]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect/nspawn: add support for dm-verity root hash signature
authorLuca Boccassi <luca.boccassi@microsoft.com>
Tue, 2 Jun 2020 14:35:58 +0000 (15:35 +0100)
committerLuca Boccassi <luca.boccassi@microsoft.com>
Thu, 25 Jun 2020 07:45:21 +0000 (08:45 +0100)
Since cryptsetup 2.3.0 a new API to verify dm-verity volumes by a
pkcs7 signature, with the public key in the kernel keyring,
is available. Use it if libcryptsetup supports it.

README
man/systemd-nspawn.xml
meson.build
shell-completion/bash/systemd-nspawn
src/core/namespace.c
src/dissect/dissect.c
src/nspawn/nspawn.c
src/shared/dissect-image.c
src/shared/dissect-image.h

diff --git a/README b/README
index 4f4a21eeca7ea1e824542b3eda148d54ee88cfa8..4269f0c73df1c2937902d4ab89e744ba48dcae19 100644 (file)
--- a/README
+++ b/README
@@ -35,6 +35,7 @@ LICENSE:
 REQUIREMENTS:
         Linux kernel >= 3.13
         Linux kernel >= 4.2 for unified cgroup hierarchy support
+        Linux kernel >= 5.4 for signed Verity images support
 
         Kernel Config Options:
           CONFIG_DEVTMPFS
@@ -102,6 +103,9 @@ REQUIREMENTS:
           CONFIG_EFIVAR_FS
           CONFIG_EFI_PARTITION
 
+        Required for signed Verity images support:
+          CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG
+
         We recommend to turn off Real-Time group scheduling in the
         kernel when using systemd. RT group scheduling effectively
         makes RT scheduling unavailable for most userspace, since it
@@ -144,7 +148,7 @@ REQUIREMENTS:
         libblkid >= 2.24 (from util-linux) (optional)
         libkmod >= 15 (optional)
         PAM >= 1.1.2 (optional)
-        libcryptsetup (optional)
+        libcryptsetup (optional), >= 2.3.0 required for signed Verity images support
         libaudit (optional)
         libacl (optional)
         libselinux (optional)
index abcddbf00a42c2496ed7ac81b50f44f4d67e1ac8..e28572db6ddffec3d1ca9e87a5e14ba5ea800645 100644 (file)
 
         <para>Single file system images (i.e. file systems without a surrounding partition table) can be opened using
         dm-verity if the integrity data is passed using the <option>--root-hash=</option> and
-        <option>--verity-data=</option> options.</para>
+        <option>--verity-data=</option> (and optionally <option>--root-hash-sig=</option>) options.</para>
 
         <para>Any other partitions, such as foreign partitions or swap partitions are not mounted. May not be specified
         together with <option>--directory=</option>, <option>--template=</option>.</para></listitem>
         is read from it and automatically used, also as formatted hexadecimal characters.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--root-hash-sig=</option></term>
+
+        <listitem><para>Takes a PKCS7 formatted binary signature of the <option>--root-hash=</option> option as a path
+        to a DER encoded signature file or as an ASCII base64 string encoding of the DER encoded signature, prefixed
+        by <literal>base64:</literal>. The dm-verity volume will only be opened if the signature of the root hash hex
+        string is valid and done by a public key present in the kernel keyring. If this option is not specified, but a
+        file with the <filename>.roothash.p7s</filename> suffix is found next to the image file, bearing otherwise the
+        same name (except if the image has the <filename>.raw</filename> suffix, in which case the signature file must
+        not have it in its name), the signature is read from it and automatically used.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>--verity-data=</option></term>
 
index 8f1d1b58971beb6b017065a2d17e5fdc1dd909cb..827fdfc8cfef0facba641222ced76be871f65092 100644 (file)
@@ -1035,6 +1035,8 @@ if want_libcryptsetup != 'false' and not skip_deps
 
         conf.set10('HAVE_CRYPT_SET_METADATA_SIZE',
                    have and cc.has_function('crypt_set_metadata_size', dependencies : libcryptsetup))
+        conf.set10('HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY',
+                   have and cc.has_function('crypt_activate_by_signed_key', dependencies : libcryptsetup))
 else
         have = false
         libcryptsetup = []
index a731167680fbf6908c7b5e6316dfb7d753114576..a8bd406fb3118a11fd1dafc1b1c94e843324a367 100644 (file)
@@ -71,7 +71,7 @@ _systemd_nspawn() {
                       --pivot-root --property --private-users --network-namespace-path --network-ipvlan
                       --network-veth-extra --network-zone -p --port --system-call-filter --overlay --overlay-ro
                       --settings --rlimit --hostname --no-new-privileges --oom-score-adjust --cpu-affinity
-                      --resolv-conf --timezone'
+                      --resolv-conf --timezone --root-hash-sig'
     )
 
     _init_completion || return
@@ -183,6 +183,10 @@ _systemd_nspawn() {
             --timezone)
                 comps=$( systemd-nspawn --timezone=help 2>/dev/null )
                 ;;
+            --root-hash-sig)
+                compopt -o nospace
+                comps=$( compgen -A file -- "$cur" )
+                ;;
         esac
         COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
         return 0
index 7bb444074784ee805ff318a337528bbecec655ba..a9985c56572b31d98fb0a522ca112a9b8feb1b67 100644 (file)
@@ -1268,7 +1268,7 @@ int setup_namespace(
         _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
         _cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL;
         _cleanup_free_ void *root_hash_decoded = NULL;
-        _cleanup_free_ char *verity_data = NULL;
+        _cleanup_free_ char *verity_data = NULL, *hash_sig_path = NULL;
         MountEntry *m = NULL, *mounts = NULL;
         size_t n_mounts;
         bool require_prefix = false;
@@ -1299,7 +1299,7 @@ int setup_namespace(
                 if (r < 0)
                         return log_debug_errno(r, "Failed to create loop device for root image: %m");
 
-                r = verity_metadata_load(root_image, root_hash_path, root_hash ? NULL : &root_hash_decoded, root_hash ? NULL : &root_hash_size, root_verity ? NULL : &verity_data);
+                r = verity_metadata_load(root_image, root_hash_path, root_hash ? NULL : &root_hash_decoded, root_hash ? NULL : &root_hash_size, root_verity ? NULL : &verity_data, &hash_sig_path);
                 if (r < 0)
                         return log_debug_errno(r, "Failed to load root hash: %m");
                 dissect_image_flags |= root_verity || verity_data ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0;
@@ -1308,7 +1308,7 @@ int setup_namespace(
                 if (r < 0)
                         return log_debug_errno(r, "Failed to dissect image: %m");
 
-                r = dissected_image_decrypt(dissected_image, NULL, root_hash ?: root_hash_decoded, root_hash_size, root_verity ?: verity_data, dissect_image_flags, &decrypted_image);
+                r = dissected_image_decrypt(dissected_image, NULL, root_hash ?: root_hash_decoded, root_hash_size, root_verity ?: verity_data, hash_sig_path, NULL, 0, dissect_image_flags, &decrypted_image);
                 if (r < 0)
                         return log_debug_errno(r, "Failed to decrypt dissected image: %m");
         }
index 2a8eaca5bd10945de87700b4792ccbb8791c28fa..66ac638401cf50d8c19fceda7073a37df7833d71 100644 (file)
@@ -28,9 +28,14 @@ static DissectImageFlags arg_flags = DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DI
 static void *arg_root_hash = NULL;
 static char *arg_verity_data = NULL;
 static size_t arg_root_hash_size = 0;
+static char *arg_root_hash_sig_path = NULL;
+static void *arg_root_hash_sig = NULL;
+static size_t arg_root_hash_sig_size = 0;
 
 STATIC_DESTRUCTOR_REGISTER(arg_root_hash, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_verity_data, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_root_hash_sig_path, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_root_hash_sig, freep);
 
 static void help(void) {
         printf("%s [OPTIONS...] IMAGE\n"
@@ -43,6 +48,10 @@ static void help(void) {
                "     --fsck=BOOL          Run fsck before mounting\n"
                "     --discard=MODE       Choose 'discard' mode (disabled, loop, all, crypto)\n"
                "     --root-hash=HASH     Specify root hash for verity\n"
+               "     --root-hash-sig=SIG  Specify pkcs7 signature of root hash for verity\n"
+               "                          as a DER encoded PKCS7, either as a path to a file\n"
+               "                          or as an ASCII base64 encoded string prefixed by\n"
+               "                          'base64:'\n"
                "     --verity-data=PATH   Specify data file with hash tree for verity if it is\n"
                "                          not embedded in IMAGE\n",
                program_invocation_short_name,
@@ -57,17 +66,19 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_ROOT_HASH,
                 ARG_FSCK,
                 ARG_VERITY_DATA,
+                ARG_ROOT_HASH_SIG,
         };
 
         static const struct option options[] = {
-                { "help",          no_argument,       NULL, 'h'              },
-                { "version",       no_argument,       NULL, ARG_VERSION      },
-                { "mount",         no_argument,       NULL, 'm'              },
-                { "read-only",     no_argument,       NULL, 'r'              },
-                { "discard",       required_argument, NULL, ARG_DISCARD      },
-                { "root-hash",     required_argument, NULL, ARG_ROOT_HASH    },
-                { "fsck",          required_argument, NULL, ARG_FSCK         },
-                { "verity-data",   required_argument, NULL, ARG_VERITY_DATA  },
+                { "help",          no_argument,       NULL, 'h'               },
+                { "version",       no_argument,       NULL, ARG_VERSION       },
+                { "mount",         no_argument,       NULL, 'm'               },
+                { "read-only",     no_argument,       NULL, 'r'               },
+                { "discard",       required_argument, NULL, ARG_DISCARD       },
+                { "root-hash",     required_argument, NULL, ARG_ROOT_HASH     },
+                { "fsck",          required_argument, NULL, ARG_FSCK          },
+                { "verity-data",   required_argument, NULL, ARG_VERITY_DATA   },
+                { "root-hash-sig", required_argument, NULL, ARG_ROOT_HASH_SIG },
                 {}
         };
 
@@ -140,6 +151,31 @@ static int parse_argv(int argc, char *argv[]) {
                                 return r;
                         break;
 
+                case ARG_ROOT_HASH_SIG: {
+                        char *value;
+
+                        if ((value = startswith(optarg, "base64:"))) {
+                                void *p;
+                                size_t l;
+
+                                r = unbase64mem(value, strlen(value), &p, &l);
+                                if (r < 0)
+                                        return log_error_errno(r, "Failed to parse root hash signature '%s': %m", optarg);
+
+                                free_and_replace(arg_root_hash_sig, p);
+                                arg_root_hash_sig_size = l;
+                                arg_root_hash_sig_path = mfree(arg_root_hash_sig_path);
+                        } else {
+                                r = parse_path_argument_and_warn(optarg, false, &arg_root_hash_sig_path);
+                                if (r < 0)
+                                        return r;
+                                arg_root_hash_sig = mfree(arg_root_hash_sig);
+                                arg_root_hash_sig_size = 0;
+                        }
+
+                        break;
+                }
+
                 case ARG_FSCK:
                         r = parse_boolean(optarg);
                         if (r < 0)
@@ -202,7 +238,8 @@ static int run(int argc, char *argv[]) {
                 return log_error_errno(r, "Failed to set up loopback device: %m");
 
         r = verity_metadata_load(arg_image, NULL, arg_root_hash ? NULL : &arg_root_hash, &arg_root_hash_size,
-                           arg_verity_data ? NULL : &arg_verity_data);
+                           arg_verity_data ? NULL : &arg_verity_data,
+                           arg_root_hash_sig_path || arg_root_hash_sig ? NULL : &arg_root_hash_sig_path);
         if (r < 0)
                 return log_error_errno(r, "Failed to read verity artefacts for %s: %m", arg_image);
         arg_flags |= arg_verity_data ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0;
@@ -279,7 +316,7 @@ static int run(int argc, char *argv[]) {
         }
 
         case ACTION_MOUNT:
-                r = dissected_image_decrypt_interactively(m, NULL, arg_root_hash, arg_root_hash_size, arg_verity_data, arg_flags, &di);
+                r = dissected_image_decrypt_interactively(m, NULL, arg_root_hash, arg_root_hash_size, arg_verity_data, arg_root_hash_sig_path, arg_root_hash_sig, arg_root_hash_sig_size, arg_flags, &di);
                 if (r < 0)
                         return r;
 
index 2f86d4094d593b101e58e1487a13b7e0b965567d..0f2d01c0aa8872928ff3d1a61e33f92ef9444988 100644 (file)
@@ -200,6 +200,9 @@ static unsigned long arg_clone_ns_flags = CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS
 static MountSettingsMask arg_mount_settings = MOUNT_APPLY_APIVFS_RO|MOUNT_APPLY_TMPFS_TMP;
 static void *arg_root_hash = NULL;
 static char *arg_verity_data = NULL;
+static char *arg_root_hash_sig_path = NULL;
+static void *arg_root_hash_sig = NULL;
+static size_t arg_root_hash_sig_size = 0;
 static size_t arg_root_hash_size = 0;
 static char **arg_syscall_allow_list = NULL;
 static char **arg_syscall_deny_list = NULL;
@@ -244,6 +247,8 @@ STATIC_DESTRUCTOR_REGISTER(arg_property_message, sd_bus_message_unrefp);
 STATIC_DESTRUCTOR_REGISTER(arg_parameters, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_root_hash, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_verity_data, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_root_hash_sig_path, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_root_hash_sig, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_syscall_allow_list, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_syscall_deny_list, strv_freep);
 #if HAVE_SECCOMP
@@ -305,6 +310,10 @@ static int help(void) {
                "     --read-only            Mount the root directory read-only\n"
                "     --volatile[=MODE]      Run the system in volatile mode\n"
                "     --root-hash=HASH       Specify verity root hash for root disk image\n"
+               "     --root-hash-sig=SIG    Specify pkcs7 signature of root hash for verity\n"
+               "                            as a DER encoded PKCS7, either as a path to a file\n"
+               "                            or as an ASCII base64 encoded string prefixed by\n"
+               "                            'base64:'\n"
                "     --verity-data=PATH     Specify hash device for verity\n"
                "     --pivot-root=PATH[:PATH]\n"
                "                            Pivot root to given directory in the container\n\n"
@@ -667,6 +676,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_OCI_BUNDLE,
                 ARG_NO_PAGER,
                 ARG_VERITY_DATA,
+                ARG_ROOT_HASH_SIG,
         };
 
         static const struct option options[] = {
@@ -733,6 +743,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "oci-bundle",             required_argument, NULL, ARG_OCI_BUNDLE             },
                 { "no-pager",               no_argument,       NULL, ARG_NO_PAGER               },
                 { "verity-data",            required_argument, NULL, ARG_VERITY_DATA            },
+                { "root-hash-sig",          required_argument, NULL, ARG_ROOT_HASH_SIG          },
                 {}
         };
 
@@ -1327,6 +1338,31 @@ static int parse_argv(int argc, char *argv[]) {
                                 return r;
                         break;
 
+                case ARG_ROOT_HASH_SIG: {
+                        char *value;
+
+                        if ((value = startswith(optarg, "base64:"))) {
+                                void *p;
+                                size_t l;
+
+                                r = unbase64mem(value, strlen(value), &p, &l);
+                                if (r < 0)
+                                        return log_error_errno(r, "Failed to parse root hash signature '%s': %m", optarg);
+
+                                free_and_replace(arg_root_hash_sig, p);
+                                arg_root_hash_sig_size = l;
+                                arg_root_hash_sig_path = mfree(arg_root_hash_sig_path);
+                        } else {
+                                r = parse_path_argument_and_warn(optarg, false, &arg_root_hash_sig_path);
+                                if (r < 0)
+                                        return r;
+                                arg_root_hash_sig = mfree(arg_root_hash_sig);
+                                arg_root_hash_sig_size = 0;
+                        }
+
+                        break;
+                }
+
                 case ARG_SYSTEM_CALL_FILTER: {
                         bool negative;
                         const char *items;
@@ -5143,7 +5179,8 @@ static int run(int argc, char *argv[]) {
                         }
 
                         r = verity_metadata_load(arg_image, NULL, arg_root_hash ? NULL : &arg_root_hash, &arg_root_hash_size,
-                                        arg_verity_data ? NULL : &arg_verity_data);
+                                        arg_verity_data ? NULL : &arg_verity_data,
+                                        arg_root_hash_sig_path || arg_root_hash_sig ? NULL : &arg_root_hash_sig_path);
                         if (r < 0) {
                                 log_error_errno(r, "Failed to read verity artefacts for %s: %m", arg_image);
                                 goto finish;
@@ -5193,7 +5230,7 @@ static int run(int argc, char *argv[]) {
                 if (!arg_root_hash && dissected_image->can_verity)
                         log_notice("Note: image %s contains verity information, but no root hash specified! Proceeding without integrity checking.", arg_image);
 
-                r = dissected_image_decrypt_interactively(dissected_image, NULL, arg_root_hash, arg_root_hash_size, arg_verity_data, 0, &decrypted_image);
+                r = dissected_image_decrypt_interactively(dissected_image, NULL, arg_root_hash, arg_root_hash_size, arg_verity_data, arg_root_hash_sig_path, arg_root_hash_sig, arg_root_hash_sig_size, 0, &decrypted_image);
                 if (r < 0)
                         goto finish;
 
index e576518c6b8e4aa5c566aad3df5d5e187b3fa679..fdf4d481f6545805d93560244c110c507fc69fa3 100644 (file)
@@ -1223,6 +1223,9 @@ static int verity_partition(
                 const void *root_hash,
                 size_t root_hash_size,
                 const char *verity_data,
+                const char *root_hash_sig_path,
+                const void *root_hash_sig,
+                size_t root_hash_sig_size,
                 DissectImageFlags flags,
                 DecryptedImage *d) {
 
@@ -1267,7 +1270,25 @@ static int verity_partition(
         if (r < 0)
                 return r;
 
-        r = crypt_activate_by_volume_key(cd, name, root_hash, root_hash_size, CRYPT_ACTIVATE_READONLY);
+        if (root_hash_sig || root_hash_sig_path) {
+#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
+                if (root_hash_sig)
+                        r = crypt_activate_by_signed_key(cd, name, root_hash, root_hash_size, root_hash_sig, root_hash_sig_size, CRYPT_ACTIVATE_READONLY);
+                else {
+                        _cleanup_free_ char *hash_sig = NULL;
+                        size_t hash_sig_size;
+
+                        r = read_full_file_full(AT_FDCWD, root_hash_sig_path, 0, &hash_sig, &hash_sig_size);
+                        if (r < 0)
+                                return r;
+
+                        r = crypt_activate_by_signed_key(cd, name, root_hash, root_hash_size, hash_sig, hash_sig_size, CRYPT_ACTIVATE_READONLY);
+                }
+#else
+                r = log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "activation of verity device with signature requested, but not supported by cryptsetup due to missing crypt_activate_by_signed_key()");
+#endif
+        } else
+                r = crypt_activate_by_volume_key(cd, name, root_hash, root_hash_size, CRYPT_ACTIVATE_READONLY);
         if (r < 0)
                 return r;
 
@@ -1287,6 +1308,9 @@ int dissected_image_decrypt(
                 const void *root_hash,
                 size_t root_hash_size,
                 const char *verity_data,
+                const char *root_hash_sig_path,
+                const void *root_hash_sig,
+                size_t root_hash_sig_size,
                 DissectImageFlags flags,
                 DecryptedImage **ret) {
 
@@ -1333,7 +1357,7 @@ int dissected_image_decrypt(
 
                 k = PARTITION_VERITY_OF(i);
                 if (k >= 0) {
-                        r = verity_partition(p, m->partitions + k, root_hash, root_hash_size, verity_data, flags, d);
+                        r = verity_partition(p, m->partitions + k, root_hash, root_hash_size, verity_data, root_hash_sig_path, root_hash_sig, root_hash_sig_size, flags, d);
                         if (r < 0)
                                 return r;
                 }
@@ -1359,6 +1383,9 @@ int dissected_image_decrypt_interactively(
                 const void *root_hash,
                 size_t root_hash_size,
                 const char *verity_data,
+                const char *root_hash_sig_path,
+                const void *root_hash_sig,
+                size_t root_hash_sig_size,
                 DissectImageFlags flags,
                 DecryptedImage **ret) {
 
@@ -1369,7 +1396,7 @@ int dissected_image_decrypt_interactively(
                 n--;
 
         for (;;) {
-                r = dissected_image_decrypt(m, passphrase, root_hash, root_hash_size, verity_data, flags, ret);
+                r = dissected_image_decrypt(m, passphrase, root_hash, root_hash_size, verity_data, root_hash_sig_path, root_hash_sig, root_hash_sig_size, flags, ret);
                 if (r >= 0)
                         return r;
                 if (r == -EKEYREJECTED)
@@ -1421,8 +1448,8 @@ int decrypted_image_relinquish(DecryptedImage *d) {
         return 0;
 }
 
-int verity_metadata_load(const char *image, const char *root_hash_path, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data) {
-        _cleanup_free_ char *verity_filename = NULL;
+int verity_metadata_load(const char *image, const char *root_hash_path, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data, char **ret_roothashsig) {
+        _cleanup_free_ char *verity_filename = NULL, *roothashsig_filename = NULL;
         _cleanup_free_ void *roothash_decoded = NULL;
         size_t roothash_decoded_size = 0;
         int r;
@@ -1437,6 +1464,8 @@ int verity_metadata_load(const char *image, const char *root_hash_path, void **r
                         *ret_roothash_size = 0;
                 if (ret_verity_data)
                         *ret_verity_data = NULL;
+                if (ret_roothashsig)
+                        *ret_roothashsig = NULL;
                 return 0;
         }
 
@@ -1461,6 +1490,29 @@ int verity_metadata_load(const char *image, const char *root_hash_path, void **r
                 }
         }
 
+        if (ret_roothashsig) {
+                char *e;
+
+                /* Follow naming convention recommended by the relevant RFC:
+                 * https://tools.ietf.org/html/rfc5751#section-3.2.1 */
+                roothashsig_filename = new(char, strlen(image) + STRLEN(".roothash.p7s") + 1);
+                if (!roothashsig_filename)
+                        return -ENOMEM;
+                strcpy(roothashsig_filename, image);
+                e = endswith(roothashsig_filename, ".raw");
+                if (e)
+                        strcpy(e, ".roothash.p7s");
+                else
+                        strcat(roothashsig_filename, ".roothash.p7s");
+
+                r = access(roothashsig_filename, R_OK);
+                if (r < 0) {
+                        if (errno != ENOENT)
+                                return -errno;
+                        roothashsig_filename = mfree(roothashsig_filename);
+                }
+        }
+
         if (ret_roothash) {
                 _cleanup_free_ char *text = NULL;
                 assert(ret_roothash_size);
@@ -1507,6 +1559,8 @@ int verity_metadata_load(const char *image, const char *root_hash_path, void **r
         }
         if (ret_verity_data)
                 *ret_verity_data = TAKE_PTR(verity_filename);
+        if (roothashsig_filename)
+                *ret_roothashsig = TAKE_PTR(roothashsig_filename);
 
         return 1;
 }
index 6a53b949486fb52ee55f3004d969745da97bc592..c7d078f4b7b5d9028823bda626ef1b96d40be2fe 100644 (file)
@@ -87,8 +87,8 @@ int dissect_image_and_warn(int fd, const char *name, const void *root_hash, size
 DissectedImage* dissected_image_unref(DissectedImage *m);
 DEFINE_TRIVIAL_CLEANUP_FUNC(DissectedImage*, dissected_image_unref);
 
-int dissected_image_decrypt(DissectedImage *m, const char *passphrase, const void *root_hash, size_t root_hash_size, const char *verity_data, DissectImageFlags flags, DecryptedImage **ret);
-int dissected_image_decrypt_interactively(DissectedImage *m, const char *passphrase, const void *root_hash, size_t root_hash_size, const char *verity_data, DissectImageFlags flags, DecryptedImage **ret);
+int dissected_image_decrypt(DissectedImage *m, const char *passphrase, const void *root_hash, size_t root_hash_size, const char *verity_data, const char *root_hash_sig_path, const void *root_hash_sig, size_t root_hash_sig_size, DissectImageFlags flags, DecryptedImage **ret);
+int dissected_image_decrypt_interactively(DissectedImage *m, const char *passphrase, const void *root_hash, size_t root_hash_size, const char *verity_data, const char *root_hash_sig_path, const void *root_hash_sig, size_t root_hash_sig_size, DissectImageFlags flags, DecryptedImage **ret);
 int dissected_image_mount(DissectedImage *m, const char *dest, uid_t uid_shift, DissectImageFlags flags);
 
 int dissected_image_acquire_metadata(DissectedImage *m);
@@ -100,6 +100,6 @@ int decrypted_image_relinquish(DecryptedImage *d);
 const char* partition_designator_to_string(int i) _const_;
 int partition_designator_from_string(const char *name) _pure_;
 
-int verity_metadata_load(const char *image, const char *root_hash_path, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data);
+int verity_metadata_load(const char *image, const char *root_hash_path, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data, char **ret_roothashsig);
 bool dissected_image_can_do_verity(const DissectedImage *image, unsigned partition_designator);
 bool dissected_image_has_verity(const DissectedImage *image, unsigned partition_designator);