_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
_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, *hash_sig = NULL;
- DissectImageFlags dissect_image_flags = m->read_only ? DISSECT_IMAGE_READ_ONLY : 0;
- size_t root_hash_size = 0;
+ _cleanup_(verity_settings_done) VeritySettings verity = {};
+ DissectImageFlags dissect_image_flags;
int r;
- r = verity_metadata_load(mount_entry_source(m), NULL, &root_hash_decoded, &root_hash_size, &verity_data, &hash_sig);
+ assert(m);
+
+ r = verity_settings_load(&verity, mount_entry_source(m), NULL, NULL);
if (r < 0)
return log_debug_errno(r, "Failed to load root hash: %m");
- dissect_image_flags |= verity_data ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0;
- r = loop_device_make_by_path(mount_entry_source(m),
- m->read_only ? O_RDONLY : -1 /* < 0 means writable if possible, read-only as fallback */,
- verity_data ? 0 : LO_FLAGS_PARTSCAN,
- &loop_device);
+ dissect_image_flags =
+ (m->read_only ? DISSECT_IMAGE_READ_ONLY : 0) |
+ (verity.data_path ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0);
+
+ r = loop_device_make_by_path(
+ mount_entry_source(m),
+ m->read_only ? O_RDONLY : -1 /* < 0 means writable if possible, read-only as fallback */,
+ verity.data_path ? 0 : LO_FLAGS_PARTSCAN,
+ &loop_device);
if (r < 0)
return log_debug_errno(r, "Failed to create loop device for image: %m");
- r = dissect_image(loop_device->fd, root_hash_decoded, root_hash_size, verity_data, m->image_options, dissect_image_flags, &dissected_image);
+ r = dissect_image(
+ loop_device->fd,
+ &verity,
+ m->image_options,
+ dissect_image_flags,
+ &dissected_image);
/* No partition table? Might be a single-filesystem image, try again */
- if (!verity_data && r < 0 && r == -ENOPKG)
- r = dissect_image(loop_device->fd, root_hash_decoded, root_hash_size, verity_data, m->image_options, dissect_image_flags|DISSECT_IMAGE_NO_PARTITION_TABLE, &dissected_image);
+ if (!verity.data_path && r == -ENOPKG)
+ r = dissect_image(
+ loop_device->fd,
+ &verity,
+ m->image_options,
+ dissect_image_flags|DISSECT_IMAGE_NO_PARTITION_TABLE,
+ &dissected_image);
if (r < 0)
return log_debug_errno(r, "Failed to dissect image: %m");
- r = dissected_image_decrypt(dissected_image, NULL, root_hash_decoded, root_hash_size, verity_data, hash_sig, NULL, 0, dissect_image_flags, &decrypted_image);
+ r = dissected_image_decrypt(
+ dissected_image,
+ NULL,
+ &verity,
+ dissect_image_flags,
+ &decrypted_image);
if (r < 0)
return log_debug_errno(r, "Failed to decrypt dissected image: %m");
return false;
}
+static int verity_settings_prepare(
+ VeritySettings *verity,
+ const char *root_image,
+ const void *root_hash,
+ size_t root_hash_size,
+ const char *root_hash_path,
+ const void *root_hash_sig,
+ size_t root_hash_sig_size,
+ const char *root_hash_sig_path,
+ const char *verity_data_path) {
+
+ int r;
+
+ assert(verity);
+
+ if (root_hash) {
+ void *d;
+
+ d = memdup(root_hash, root_hash_size);
+ if (!d)
+ return -ENOMEM;
+
+ free_and_replace(verity->root_hash, d);
+ verity->root_hash_size = root_hash_size;
+ }
+
+ if (root_hash_sig) {
+ void *d;
+
+ d = memdup(root_hash_sig, root_hash_sig_size);
+ if (!d)
+ return -ENOMEM;
+
+ free_and_replace(verity->root_hash_sig, d);
+ verity->root_hash_sig_size = root_hash_sig_size;
+ }
+
+ if (verity_data_path) {
+ r = free_and_strdup(&verity->data_path, verity_data_path);
+ if (r < 0)
+ return r;
+ }
+
+ r = verity_settings_load(
+ verity,
+ root_image,
+ root_hash_path,
+ root_hash_sig_path);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to load root hash: %m");
+
+ return 0;
+}
+
int setup_namespace(
const char* root_directory,
const char* root_image,
const void *root_hash_sig,
size_t root_hash_sig_size,
const char *root_hash_sig_path,
- const char *root_verity,
+ const char *verity_data_path,
DissectImageFlags dissect_image_flags,
char **error_path) {
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
_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, *hash_sig_path = NULL;
+ _cleanup_(verity_settings_done) VeritySettings verity = {};
MountEntry *m = NULL, *mounts = NULL;
- size_t n_mounts;
bool require_prefix = false;
const char *root;
- int r = 0;
+ size_t n_mounts;
+ int r;
assert(ns_info);
strv_isempty(read_write_paths))
dissect_image_flags |= DISSECT_IMAGE_READ_ONLY;
- r = loop_device_make_by_path(root_image,
- FLAGS_SET(dissect_image_flags, DISSECT_IMAGE_READ_ONLY) ? O_RDONLY : -1 /* < 0 means writable if possible, read-only as fallback */,
- LO_FLAGS_PARTSCAN,
- &loop_device);
+ r = verity_settings_prepare(
+ &verity,
+ root_image,
+ root_hash, root_hash_size, root_hash_path,
+ root_hash_sig, root_hash_sig_size, root_hash_sig_path,
+ verity_data_path);
if (r < 0)
- return log_debug_errno(r, "Failed to create loop device for root image: %m");
+ return r;
+
+ SET_FLAG(dissect_image_flags, DISSECT_IMAGE_NO_PARTITION_TABLE, verity.data_path);
- 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,
- root_hash_sig || root_hash_sig_path ? NULL : &hash_sig_path);
+ r = loop_device_make_by_path(
+ root_image,
+ FLAGS_SET(dissect_image_flags, DISSECT_IMAGE_READ_ONLY) ? O_RDONLY : -1 /* < 0 means writable if possible, read-only as fallback */,
+ FLAGS_SET(dissect_image_flags, DISSECT_IMAGE_NO_PARTITION_TABLE) ? 0 : LO_FLAGS_PARTSCAN,
+ &loop_device);
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;
-
- r = dissect_image(loop_device->fd,
- root_hash ?: root_hash_decoded,
- root_hash_size,
- root_verity ?: verity_data,
- root_image_options,
- dissect_image_flags,
- &dissected_image);
+ return log_debug_errno(r, "Failed to create loop device for root image: %m");
+
+ r = dissect_image(
+ loop_device->fd,
+ &verity,
+ root_image_options,
+ dissect_image_flags,
+ &dissected_image);
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,
- root_hash_sig_path ?: hash_sig_path,
- root_hash_sig,
- root_hash_sig_size,
- dissect_image_flags,
- &decrypted_image);
+ r = dissected_image_decrypt(
+ dissected_image,
+ NULL,
+ &verity,
+ dissect_image_flags,
+ &decrypted_image);
if (r < 0)
return log_debug_errno(r, "Failed to decrypt dissected image: %m");
}
#include "copy.h"
#include "dissect-image.h"
#include "fd-util.h"
+#include "fileio.h"
#include "format-table.h"
#include "format-util.h"
#include "fs-util.h"
static const char *arg_source = NULL;
static const char *arg_target = NULL;
static DissectImageFlags arg_flags = DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK;
-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 VeritySettings arg_verity_settings = {};
static bool arg_json = false;
static JsonFormatFlags arg_json_format_flags = 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_DESTRUCTOR_REGISTER(arg_verity_settings, verity_settings_done);
static int help(void) {
_cleanup_free_ char *link = NULL;
enum {
ARG_VERSION = 0x100,
ARG_DISCARD,
- ARG_ROOT_HASH,
ARG_FSCK,
- ARG_VERITY_DATA,
+ ARG_ROOT_HASH,
ARG_ROOT_HASH_SIG,
+ ARG_VERITY_DATA,
ARG_MKDIR,
ARG_JSON,
};
{ "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", required_argument, NULL, ARG_ROOT_HASH },
{ "root-hash-sig", required_argument, NULL, ARG_ROOT_HASH_SIG },
+ { "verity-data", required_argument, NULL, ARG_VERITY_DATA },
{ "mkdir", no_argument, NULL, ARG_MKDIR },
{ "copy-from", no_argument, NULL, 'x' },
{ "copy-to", no_argument, NULL, 'a' },
}
case ARG_ROOT_HASH: {
- void *p;
+ _cleanup_free_ void *p = NULL;
size_t l;
r = unhexmem(optarg, strlen(optarg), &p, &l);
if (r < 0)
return log_error_errno(r, "Failed to parse root hash '%s': %m", optarg);
- if (l < sizeof(sd_id128_t)) {
- log_error("Root hash must be at least 128bit long: %s", optarg);
- free(p);
- return -EINVAL;
- }
+ if (l < sizeof(sd_id128_t))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Root hash must be at least 128bit long: %s", optarg);
- free(arg_root_hash);
- arg_root_hash = p;
- arg_root_hash_size = l;
+ free_and_replace(arg_verity_settings.root_hash, p);
+ arg_verity_settings.root_hash_size = l;
break;
}
- case ARG_VERITY_DATA:
- r = parse_path_argument_and_warn(optarg, false, &arg_verity_data);
- if (r < 0)
- return r;
- break;
-
case ARG_ROOT_HASH_SIG: {
char *value;
+ size_t l;
+ void *p;
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);
+ r = read_full_file(optarg, (char**) &p, &l);
if (r < 0)
- return r;
- arg_root_hash_sig = mfree(arg_root_hash_sig);
- arg_root_hash_sig_size = 0;
+ return log_error_errno(r, "Failed to read root hash signature file '%s': %m", optarg);
}
+ free_and_replace(arg_verity_settings.root_hash_sig, p);
+ arg_verity_settings.root_hash_sig_size = l;
break;
}
+ case ARG_VERITY_DATA:
+ r = parse_path_argument_and_warn(optarg, false, &arg_verity_settings.data_path);
+ if (r < 0)
+ return r;
+ break;
+
case ARG_FSCK:
r = parse_boolean(optarg);
if (r < 0)
if (r < 0)
return table_log_add_error(r);
- if (arg_verity_data)
+ if (arg_verity_settings.data_path)
r = table_add_cell(t, NULL, TABLE_STRING, "external");
else if (dissected_image_can_do_verity(m, i))
r = table_add_cell(t, NULL, TABLE_STRING, yes_no(dissected_image_has_verity(m, i)));
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_verity_settings,
arg_flags,
&di);
if (r < 0)
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_verity_settings,
arg_flags,
&di);
if (r < 0)
if (r <= 0)
return r;
- 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_root_hash_sig_path || arg_root_hash_sig ? NULL : &arg_root_hash_sig_path);
+ r = verity_settings_load(
+ &arg_verity_settings,
+ arg_image, NULL, NULL);
if (r < 0)
return log_error_errno(r, "Failed to read verity artifacts for %s: %m", arg_image);
+ if (arg_verity_settings.data_path)
+ arg_flags |= DISSECT_IMAGE_NO_PARTITION_TABLE; /* We only support Verity per file system,
+ * hence if there's external Verity data
+ * available we turn off partition table
+ * support */
+
r = loop_device_make_by_path(
arg_image,
- (arg_flags & DISSECT_IMAGE_READ_ONLY) ? O_RDONLY : O_RDWR,
- arg_verity_data ? 0 : LO_FLAGS_PARTSCAN,
+ FLAGS_SET(arg_flags, DISSECT_IMAGE_READ_ONLY) ? O_RDONLY : O_RDWR,
+ FLAGS_SET(arg_flags, DISSECT_IMAGE_NO_PARTITION_TABLE) ? 0 : LO_FLAGS_PARTSCAN,
&d);
if (r < 0)
return log_error_errno(r, "Failed to set up loopback device: %m");
- if (arg_verity_data)
- arg_flags |= DISSECT_IMAGE_NO_PARTITION_TABLE; /* We only support Verity per file system,
- * hence if there's external Verity data
- * available we turn off partition table
- * support */
r = dissect_image_and_warn(
d->fd,
arg_image,
- arg_root_hash,
- arg_root_hash_size,
- arg_verity_data,
+ &arg_verity_settings,
NULL,
arg_flags,
&m);
if (r <= 0)
return r;
- r = dissect_image(fd, NULL, 0, NULL, NULL, DISSECT_IMAGE_GPT_ONLY|DISSECT_IMAGE_NO_UDEV, &m);
+ r = dissect_image(fd, NULL, NULL, DISSECT_IMAGE_GPT_ONLY|DISSECT_IMAGE_NO_UDEV, &m);
if (r == -ENOPKG) {
log_debug_errno(r, "No suitable partition table found, ignoring.");
return 0;
static bool arg_use_cgns = true;
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 VeritySettings arg_verity_settings = {};
static char **arg_syscall_allow_list = NULL;
static char **arg_syscall_deny_list = NULL;
#if HAVE_SECCOMP
STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep);
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_verity_settings, verity_settings_done);
STATIC_DESTRUCTOR_REGISTER(arg_syscall_allow_list, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_syscall_deny_list, strv_freep);
#if HAVE_SECCOMP
ARG_PRIVATE_USERS_CHOWN,
ARG_NOTIFY_READY,
ARG_ROOT_HASH,
+ ARG_ROOT_HASH_SIG,
+ ARG_VERITY_DATA,
ARG_SYSTEM_CALL_FILTER,
ARG_RLIMIT,
ARG_HOSTNAME,
ARG_PIPE,
ARG_OCI_BUNDLE,
ARG_NO_PAGER,
- ARG_VERITY_DATA,
- ARG_ROOT_HASH_SIG,
ARG_SET_CREDENTIAL,
ARG_LOAD_CREDENTIAL,
};
{ "pivot-root", required_argument, NULL, ARG_PIVOT_ROOT },
{ "notify-ready", required_argument, NULL, ARG_NOTIFY_READY },
{ "root-hash", required_argument, NULL, ARG_ROOT_HASH },
+ { "root-hash-sig", required_argument, NULL, ARG_ROOT_HASH_SIG },
+ { "verity-data", required_argument, NULL, ARG_VERITY_DATA },
{ "system-call-filter", required_argument, NULL, ARG_SYSTEM_CALL_FILTER },
{ "rlimit", required_argument, NULL, ARG_RLIMIT },
{ "oom-score-adjust", required_argument, NULL, ARG_OOM_SCORE_ADJUST },
{ "pipe", no_argument, NULL, ARG_PIPE },
{ "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 },
{ "set-credential", required_argument, NULL, ARG_SET_CREDENTIAL },
{ "load-credential", required_argument, NULL, ARG_LOAD_CREDENTIAL },
{}
break;
case ARG_ROOT_HASH: {
- void *k;
+ _cleanup_free_ void *k = NULL;
size_t l;
r = unhexmem(optarg, strlen(optarg), &k, &l);
if (r < 0)
return log_error_errno(r, "Failed to parse root hash: %s", optarg);
- if (l < sizeof(sd_id128_t)) {
- free(k);
+ if (l < sizeof(sd_id128_t))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Root hash must be at least 128bit long: %s", optarg);
- }
- free(arg_root_hash);
- arg_root_hash = k;
- arg_root_hash_size = l;
+ free_and_replace(arg_verity_settings.root_hash, k);
+ arg_verity_settings.root_hash_size = l;
break;
}
- case ARG_VERITY_DATA:
- r = parse_path_argument_and_warn(optarg, false, &arg_verity_data);
- if (r < 0)
- return r;
- break;
-
case ARG_ROOT_HASH_SIG: {
char *value;
+ size_t l;
+ void *p;
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);
+ r = read_full_file(optarg, (char**) &p, &l);
if (r < 0)
- return r;
- arg_root_hash_sig = mfree(arg_root_hash_sig);
- arg_root_hash_sig_size = 0;
+ return log_error_errno(r, "Failed parse root hash signature file '%s': %m", optarg);
}
+ free_and_replace(arg_verity_settings.root_hash_sig, p);
+ arg_verity_settings.root_hash_sig_size = l;
break;
}
+ case ARG_VERITY_DATA:
+ r = parse_path_argument_and_warn(optarg, false, &arg_verity_settings.data_path);
+ if (r < 0)
+ return r;
+ break;
+
case ARG_SYSTEM_CALL_FILTER: {
bool negative;
const char *items;
goto finish;
}
- 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_root_hash_sig_path || arg_root_hash_sig ? NULL : &arg_root_hash_sig_path);
+ r = verity_settings_load(
+ &arg_verity_settings,
+ arg_image, NULL, NULL);
if (r < 0) {
log_error_errno(r, "Failed to read verity artefacts for %s: %m", arg_image);
goto finish;
}
- dissect_image_flags |= arg_verity_data ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0;
+
+ if (arg_verity_settings.data_path)
+ dissect_image_flags |= DISSECT_IMAGE_NO_PARTITION_TABLE;
}
if (!mkdtemp(tmprootdir)) {
goto finish;
}
- r = loop_device_make_by_path(arg_image, arg_read_only ? O_RDONLY : O_RDWR, LO_FLAGS_PARTSCAN, &loop);
+ r = loop_device_make_by_path(
+ arg_image,
+ arg_read_only ? O_RDONLY : O_RDWR,
+ FLAGS_SET(dissect_image_flags, DISSECT_IMAGE_NO_PARTITION_TABLE) ? 0 : LO_FLAGS_PARTSCAN,
+ &loop);
if (r < 0) {
log_error_errno(r, "Failed to set up loopback block device: %m");
goto finish;
r = dissect_image_and_warn(
loop->fd,
arg_image,
- arg_root_hash, arg_root_hash_size,
- arg_verity_data,
+ &arg_verity_settings,
NULL,
dissect_image_flags,
&dissected_image);
if (r < 0)
goto finish;
- if (!arg_root_hash && dissected_image->can_verity)
+ if (!arg_verity_settings.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, arg_root_hash_sig_path, arg_root_hash_sig, arg_root_hash_sig_size, 0, &decrypted_image);
+ r = dissected_image_decrypt_interactively(
+ dissected_image,
+ NULL,
+ &arg_verity_settings,
+ 0,
+ &decrypted_image);
if (r < 0)
goto finish;
if (r < 0)
return log_debug_errno(r, "Failed to create temporary directory: %m");
- r = dissect_image(d->fd, NULL, 0, NULL, NULL, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK, &m);
+ r = dissect_image(d->fd, NULL, NULL, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK, &m);
if (r == -ENOPKG)
sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Couldn't identify a suitable partition table or file system in '%s'.", path);
else if (r == -EADDRNOTAVAIL)
int dissect_image(
int fd,
- const void *root_hash,
- size_t root_hash_size,
- const char *verity_data,
+ const VeritySettings *verity,
const MountOptions *mount_options,
DissectImageFlags flags,
DissectedImage **ret) {
assert(fd >= 0);
assert(ret);
- assert(root_hash || root_hash_size == 0);
+ assert(!verity || verity->root_hash || verity->root_hash_size == 0);
assert(!((flags & DISSECT_IMAGE_GPT_ONLY) && (flags & DISSECT_IMAGE_NO_PARTITION_TABLE)));
/* Probes a disk image, and returns information about what it found in *ret.
* Returns -ENOPKG if no suitable partition table or file system could be found.
* Returns -EADDRNOTAVAIL if a root hash was specified but no matching root/verity partitions found. */
- if (root_hash) {
+ if (verity && verity->root_hash) {
/* If a root hash is supplied, then we use the root partition that has a UUID that match the first
* 128bit of the root hash. And we use the verity partition that has a UUID that match the final
* 128bit. */
- if (root_hash_size < sizeof(sd_id128_t))
+ if (verity->root_hash_size < sizeof(sd_id128_t))
return -EINVAL;
- memcpy(&root_uuid, root_hash, sizeof(sd_id128_t));
- memcpy(&verity_uuid, (const uint8_t*) root_hash + root_hash_size - sizeof(sd_id128_t), sizeof(sd_id128_t));
+ memcpy(&root_uuid, verity->root_hash, sizeof(sd_id128_t));
+ memcpy(&verity_uuid, (const uint8_t*) verity->root_hash + verity->root_hash_size - sizeof(sd_id128_t), sizeof(sd_id128_t));
if (sd_id128_is_null(root_uuid))
return -EINVAL;
return r;
m->single_file_system = true;
- m->verity = root_hash && verity_data;
- m->can_verity = !!verity_data;
+ m->verity = verity && verity->root_hash && verity->data_path;
+ m->can_verity = verity && verity->data_path;
options = mount_options_from_designator(mount_options, PARTITION_ROOT);
if (options) {
/* If the root hash was set, then we won't fall back to a generic node, because the
* root hash decides. */
- if (root_hash)
+ if (verity && verity->root_hash)
return -EADDRNOTAVAIL;
/* If we didn't find a generic node, then we can't fix this up either */
}
}
- if (root_hash) {
+ if (verity && verity->root_hash) {
if (!m->partitions[PARTITION_ROOT_VERITY].found || !m->partitions[PARTITION_ROOT].found)
return -EADDRNOTAVAIL;
return 0;
}
-static int verity_can_reuse(const void *root_hash, size_t root_hash_size, bool has_sig, const char *name, struct crypt_device **ret_cd) {
+static int verity_can_reuse(
+ const VeritySettings *verity,
+ const char *name,
+ struct crypt_device **ret_cd) {
+
/* If the same volume was already open, check that the root hashes match, and reuse it if they do */
_cleanup_free_ char *root_hash_existing = NULL;
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
struct crypt_params_verity crypt_params = {};
- size_t root_hash_existing_size = root_hash_size;
+ size_t root_hash_existing_size;
int r;
+ assert(verity);
+ assert(name);
assert(ret_cd);
r = sym_crypt_init_by_name(&cd, name);
if (r < 0)
return log_debug_errno(r, "Error opening verity device, crypt_get_verity_info failed: %m");
- root_hash_existing = malloc0(root_hash_size);
+ root_hash_existing_size = verity->root_hash_size;
+ root_hash_existing = malloc0(root_hash_existing_size);
if (!root_hash_existing)
return -ENOMEM;
r = sym_crypt_volume_key_get(cd, CRYPT_ANY_SLOT, root_hash_existing, &root_hash_existing_size, NULL, 0);
if (r < 0)
return log_debug_errno(r, "Error opening verity device, crypt_volume_key_get failed: %m");
- if (root_hash_size != root_hash_existing_size || memcmp(root_hash_existing, root_hash, root_hash_size) != 0)
+ if (verity->root_hash_size != root_hash_existing_size ||
+ memcmp(root_hash_existing, verity->root_hash, verity->root_hash_size) != 0)
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Error opening verity device, it already exists but root hashes are different.");
+
#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
- /* Ensure that, if signatures are supported, we only reuse the device if the previous mount
- * used the same settings, so that a previous unsigned mount will not be reused if the user
- * asks to use signing for the new one, and viceversa. */
- if (has_sig != !!(crypt_params.flags & CRYPT_VERITY_ROOT_HASH_SIGNATURE))
+ /* Ensure that, if signatures are supported, we only reuse the device if the previous mount used the
+ * same settings, so that a previous unsigned mount will not be reused if the user asks to use
+ * signing for the new one, and viceversa. */
+ if (!!verity->root_hash_sig != !!(crypt_params.flags & CRYPT_VERITY_ROOT_HASH_SIGNATURE))
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Error opening verity device, it already exists but signature settings are not the same.");
#endif
static int verity_partition(
DissectedPartition *m,
DissectedPartition *v,
- 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,
+ const VeritySettings *verity,
DissectImageFlags flags,
DecryptedImage *d) {
- _cleanup_free_ char *node = NULL, *name = NULL, *hash_sig_from_file = NULL;
_cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
_cleanup_(dm_deferred_remove_cleanp) char *restore_deferred_remove = NULL;
+ _cleanup_free_ char *node = NULL, *name = NULL;
int r;
assert(m);
- assert(v || verity_data);
+ assert(v || (verity && verity->data_path));
- if (!root_hash)
+ if (!verity || !verity->root_hash)
return 0;
if (!m->found || !m->node || !m->fstype)
return 0;
- if (!verity_data) {
+ if (!verity->data_path) {
if (!v->found || !v->node || !v->fstype)
return 0;
/* Use the roothash, which is unique per volume, as the device node name, so that it can be reused */
_cleanup_free_ char *root_hash_encoded = NULL;
- root_hash_encoded = hexmem(root_hash, root_hash_size);
+ root_hash_encoded = hexmem(verity->root_hash, verity->root_hash_size);
if (!root_hash_encoded)
return -ENOMEM;
if (r < 0)
return r;
- if (!root_hash_sig && root_hash_sig_path) {
- r = read_full_file_full(AT_FDCWD, root_hash_sig_path, 0, &hash_sig_from_file, &root_hash_sig_size);
- if (r < 0)
- return r;
- }
-
- r = sym_crypt_init(&cd, verity_data ?: v->node);
+ r = sym_crypt_init(&cd, verity->data_path ?: v->node);
if (r < 0)
return r;
* In case of ENODEV/ENOENT, which can happen if another process is activating at the exact same time,
* retry a few times before giving up. */
for (unsigned i = 0; i < N_DEVICE_NODE_LIST_ATTEMPTS; i++) {
- if (root_hash_sig || hash_sig_from_file) {
+ if (verity->root_hash_sig) {
#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
- r = sym_crypt_activate_by_signed_key(cd, name, root_hash, root_hash_size, root_hash_sig ?: hash_sig_from_file, root_hash_sig_size, CRYPT_ACTIVATE_READONLY);
+ r = sym_crypt_activate_by_signed_key(
+ cd,
+ name,
+ verity->root_hash,
+ verity->root_hash_size,
+ verity->root_hash_sig,
+ verity->root_hash_sig_size,
+ CRYPT_ACTIVATE_READONLY);
#else
r = log_debug_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 = sym_crypt_activate_by_volume_key(cd, name, root_hash, root_hash_size, CRYPT_ACTIVATE_READONLY);
+ r = sym_crypt_activate_by_volume_key(
+ cd,
+ name,
+ verity->root_hash,
+ verity->root_hash_size,
+ CRYPT_ACTIVATE_READONLY);
/* libdevmapper can return EINVAL when the device is already in the activation stage.
* There's no way to distinguish this situation from a genuine error due to invalid
* parameters, so immediately fall back to activating the device with a unique name.
- * Improvements in libcrypsetup can ensure this never happens: https://gitlab.com/cryptsetup/cryptsetup/-/merge_requests/96 */
+ * Improvements in libcrypsetup can ensure this never happens:
+ * https://gitlab.com/cryptsetup/cryptsetup/-/merge_requests/96 */
if (r == -EINVAL && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE))
- return verity_partition(m, v, root_hash, root_hash_size, verity_data, NULL, root_hash_sig ?: hash_sig_from_file, root_hash_sig_size, flags & ~DISSECT_IMAGE_VERITY_SHARE, d);
+ return verity_partition(m, v, verity, flags & ~DISSECT_IMAGE_VERITY_SHARE, d);
if (!IN_SET(r,
0, /* Success */
-EEXIST, /* Volume is already open and ready to be used */
}
}
- r = verity_can_reuse(root_hash, root_hash_size, !!root_hash_sig || !!hash_sig_from_file, name, &existing_cd);
+ r = verity_can_reuse(verity, name, &existing_cd);
/* Same as above, -EINVAL can randomly happen when it actually means -EEXIST */
if (r == -EINVAL && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE))
- return verity_partition(m, v, root_hash, root_hash_size, verity_data, NULL, root_hash_sig ?: hash_sig_from_file, root_hash_sig_size, flags & ~DISSECT_IMAGE_VERITY_SHARE, d);
+ return verity_partition(m, v, verity, flags & ~DISSECT_IMAGE_VERITY_SHARE, d);
if (!IN_SET(r, 0, -ENODEV, -ENOENT, -EBUSY))
return log_debug_errno(r, "Checking whether existing verity device %s can be reused failed: %m", node);
if (r == 0) {
/* An existing verity device was reported by libcryptsetup/libdevmapper, but we can't use it at this time.
* Fall back to activating it with a unique device name. */
if (r != 0 && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE))
- return verity_partition(m, v, root_hash, root_hash_size, verity_data, NULL, root_hash_sig ?: hash_sig_from_file, root_hash_sig_size, flags & ~DISSECT_IMAGE_VERITY_SHARE, d);
+ return verity_partition(m, v, verity, flags & ~DISSECT_IMAGE_VERITY_SHARE, d);
/* Everything looks good and we'll be able to mount the device, so deferred remove will be re-enabled at that point. */
restore_deferred_remove = mfree(restore_deferred_remove);
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,
+ const VeritySettings *verity,
DissectImageFlags flags,
DecryptedImage **ret) {
#endif
assert(m);
- assert(root_hash || root_hash_size == 0);
+ assert(!verity || verity->root_hash || verity->root_hash_size == 0);
/* Returns:
*
* -EKEYREJECTED → Passed key was not correct
*/
- if (root_hash && root_hash_size < sizeof(sd_id128_t))
+ if (verity && verity->root_hash && verity->root_hash_size < sizeof(sd_id128_t))
return -EINVAL;
if (!m->encrypted && !m->verity) {
k = PARTITION_VERITY_OF(i);
if (k >= 0) {
- 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 | DISSECT_IMAGE_VERITY_SHARE, d);
+ r = verity_partition(p, m->partitions + k, verity, flags | DISSECT_IMAGE_VERITY_SHARE, d);
if (r < 0)
return r;
}
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,
+ const VeritySettings *verity,
DissectImageFlags flags,
DecryptedImage **ret) {
n--;
for (;;) {
- 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);
+ r = dissected_image_decrypt(m, passphrase, verity, flags, ret);
if (r >= 0)
return r;
if (r == -EKEYREJECTED)
return 0;
}
-int verity_metadata_load(
+static char *build_auxiliary_path(const char *image, const char *suffix) {
+ const char *e;
+ char *n;
+
+ assert(image);
+ assert(suffix);
+
+ e = endswith(image, ".raw");
+ if (!e)
+ return strjoin(e, suffix);
+
+ n = new(char, e - image + strlen(suffix) + 1);
+ if (!n)
+ return NULL;
+
+ strcpy(mempcpy(n, image, e - image), suffix);
+ return n;
+}
+
+void verity_settings_done(VeritySettings *v) {
+ assert(v);
+
+ v->root_hash = mfree(v->root_hash);
+ v->root_hash_size = 0;
+
+ v->root_hash_sig = mfree(v->root_hash_sig);
+ v->root_hash_sig_size = 0;
+
+ v->data_path = mfree(v->data_path);
+}
+
+int verity_settings_load(
+ VeritySettings *verity,
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;
+ const char *root_hash_sig_path) {
+
+ _cleanup_free_ void *root_hash = NULL, *root_hash_sig = NULL;
+ size_t root_hash_size = 0, root_hash_sig_size = 0;
+ _cleanup_free_ char *verity_data_path = NULL;
int r;
+ assert(verity);
assert(image);
- if (is_device_path(image)) {
- /* If we are asked to load the root hash for a device node, exit early */
- if (ret_roothash)
- *ret_roothash = NULL;
- if (ret_roothash_size)
- *ret_roothash_size = 0;
- if (ret_verity_data)
- *ret_verity_data = NULL;
- if (ret_roothashsig)
- *ret_roothashsig = NULL;
+ /* If we are asked to load the root hash for a device node, exit early */
+ if (is_device_path(image))
return 0;
- }
-
- if (ret_verity_data) {
- char *e;
-
- verity_filename = new(char, strlen(image) + STRLEN(".verity") + 1);
- if (!verity_filename)
- return -ENOMEM;
- strcpy(verity_filename, image);
- e = endswith(verity_filename, ".raw");
- if (e)
- strcpy(e, ".verity");
- else
- strcat(verity_filename, ".verity");
-
- r = access(verity_filename, F_OK);
- if (r < 0) {
- if (errno != ENOENT)
- return -errno;
- verity_filename = mfree(verity_filename);
- }
- }
- if (ret_roothashsig) {
- char *e;
+ /* We only fill in what isn't already filled in */
- /* 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) {
+ if (!verity->root_hash) {
_cleanup_free_ char *text = NULL;
- assert(ret_roothash_size);
if (root_hash_path) {
- /* We have the path to a roothash to load and decode, eg: RootHash=/foo/bar.roothash */
r = read_one_line_file(root_hash_path, &text);
if (r < 0)
return r;
} else {
r = getxattr_malloc(image, "user.verity.roothash", &text, true);
if (r < 0) {
- char *fn, *e, *n;
+ _cleanup_free_ char *p = NULL;
- if (!IN_SET(r, -ENODATA, -EOPNOTSUPP, -ENOENT))
+ if (!IN_SET(r, -ENODATA, -ENOENT) && !ERRNO_IS_NOT_SUPPORTED(r))
return r;
- fn = newa(char, strlen(image) + STRLEN(".roothash") + 1);
- n = stpcpy(fn, image);
- e = endswith(fn, ".raw");
- if (e)
- n = e;
-
- strcpy(n, ".roothash");
+ p = build_auxiliary_path(image, ".roothash");
+ if (!p)
+ return -ENOMEM;
- r = read_one_line_file(fn, &text);
+ r = read_one_line_file(p, &text);
if (r < 0 && r != -ENOENT)
return r;
}
}
if (text) {
- r = unhexmem(text, strlen(text), &roothash_decoded, &roothash_decoded_size);
+ r = unhexmem(text, strlen(text), &root_hash, &root_hash_size);
if (r < 0)
return r;
- if (roothash_decoded_size < sizeof(sd_id128_t))
+ if (root_hash_size < sizeof(sd_id128_t))
return -EINVAL;
}
}
- if (ret_roothash) {
- *ret_roothash = TAKE_PTR(roothash_decoded);
- *ret_roothash_size = roothash_decoded_size;
+ if (!verity->root_hash_sig) {
+ _cleanup_free_ char *p = NULL;
+
+ if (!root_hash_sig_path) {
+ /* Follow naming convention recommended by the relevant RFC:
+ * https://tools.ietf.org/html/rfc5751#section-3.2.1 */
+ p = build_auxiliary_path(image, ".roothash.p7s");
+ if (!p)
+ return -ENOMEM;
+
+ root_hash_sig_path = p;
+ }
+
+ r = read_full_file_full(AT_FDCWD, root_hash_sig_path, 0, (char**) &root_hash_sig, &root_hash_sig_size);
+ if (r < 0) {
+ if (r != -ENOENT)
+ return r;
+ } else if (root_hash_sig_size == 0) /* refuse empty size signatures */
+ return -EINVAL;
+ }
+
+ if (!verity->data_path) {
+ _cleanup_free_ char *p = NULL;
+
+ p = build_auxiliary_path(image, ".verity");
+ if (!p)
+ return -ENOMEM;
+
+ if (access(p, F_OK) < 0) {
+ if (errno != ENOENT)
+ return -errno;
+ } else
+ verity_data_path = TAKE_PTR(p);
+ }
+
+ if (root_hash) {
+ verity->root_hash = TAKE_PTR(root_hash);
+ verity->root_hash_size = root_hash_size;
+ }
+
+ if (root_hash_sig) {
+ verity->root_hash_sig = TAKE_PTR(root_hash_sig);
+ verity->root_hash_sig_size = root_hash_sig_size;
}
- if (ret_verity_data)
- *ret_verity_data = TAKE_PTR(verity_filename);
- if (roothashsig_filename)
- *ret_roothashsig = TAKE_PTR(roothashsig_filename);
+
+ if (verity_data_path)
+ verity->data_path = TAKE_PTR(verity_data_path);
return 1;
}
int dissect_image_and_warn(
int fd,
const char *name,
- const void *root_hash,
- size_t root_hash_size,
- const char *verity_data,
+ const VeritySettings *verity,
const MountOptions *mount_options,
DissectImageFlags flags,
DissectedImage **ret) {
name = buffer;
}
- r = dissect_image(fd, root_hash, root_hash_size, verity_data, mount_options, flags, ret);
+ r = dissect_image(fd, verity, mount_options, flags, ret);
switch (r) {
if (r < 0)
return log_error_errno(r, "Failed to set up loopback device: %m");
- r = dissect_image_and_warn(d->fd, image, NULL, 0, NULL, NULL, flags, &dissected_image);
+ r = dissect_image_and_warn(d->fd, image, NULL, NULL, flags, &dissected_image);
if (r < 0)
return r;
- r = dissected_image_decrypt_interactively(dissected_image, NULL, NULL, 0, NULL, NULL, NULL, 0, flags, &decrypted_image);
+ r = dissected_image_decrypt_interactively(dissected_image, NULL, NULL, flags, &decrypted_image);
if (r < 0)
return r;
typedef struct DissectedPartition DissectedPartition;
typedef struct DecryptedImage DecryptedImage;
typedef struct MountOptions MountOptions;
+typedef struct VeritySettings VeritySettings;
struct DissectedPartition {
bool found:1;
LIST_FIELDS(MountOptions, mount_options);
};
+struct VeritySettings {
+ /* Binary root hash for the Verity Merkle tree */
+ void *root_hash;
+ size_t root_hash_size;
+
+ /* PKCS#7 signature of the above */
+ void *root_hash_sig;
+ size_t root_hash_sig_size;
+
+ /* Path to the verity data file, if stored externally */
+ char *data_path;
+};
+
MountOptions* mount_options_free_all(MountOptions *options);
DEFINE_TRIVIAL_CLEANUP_FUNC(MountOptions*, mount_options_free_all);
const char* mount_options_from_designator(const MountOptions *options, PartitionDesignator designator);
int probe_filesystem(const char *node, char **ret_fstype);
-int dissect_image(int fd, const void *root_hash, size_t root_hash_size, const char *verity_data, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret);
-int dissect_image_and_warn(int fd, const char *name, const void *root_hash, size_t root_hash_size, const char *verity_data, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret);
+int dissect_image(int fd, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret);
+int dissect_image_and_warn(int fd, const char *name, const VeritySettings *verity, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret);
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, 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_decrypt(DissectedImage *m, const char *passphrase, const VeritySettings *verity, DissectImageFlags flags, DecryptedImage **ret);
+int dissected_image_decrypt_interactively(DissectedImage *m, const char *passphrase, const VeritySettings *verity, DissectImageFlags flags, DecryptedImage **ret);
int dissected_image_mount(DissectedImage *m, const char *dest, uid_t uid_shift, DissectImageFlags flags);
int dissected_image_mount_and_warn(DissectedImage *m, const char *where, uid_t uid_shift, DissectImageFlags flags);
const char* partition_designator_to_string(PartitionDesignator d) _const_;
PartitionDesignator 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, char **ret_roothashsig);
+int verity_settings_load(VeritySettings *verity, const char *image, const char *root_hash_path, const char *root_hash_sig_path);
+void verity_settings_done(VeritySettings *verity);
+
bool dissected_image_can_do_verity(const DissectedImage *image, PartitionDesignator d);
bool dissected_image_has_verity(const DissectedImage *image, PartitionDesignator d);
if (r < 0)
return r;
- r = dissect_image(d->fd, NULL, 0, NULL, NULL, DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_RELAX_VAR_CHECK, &m);
+ r = dissect_image(d->fd, NULL, NULL, DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_RELAX_VAR_CHECK, &m);
if (r < 0)
return r;