From c4b16923bbb12149cc8df5624821ab07a1e42920 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Fri, 8 Jun 2012 10:12:12 +0200 Subject: [PATCH] Unify dm backend for crypt/verity. --- lib/libdevmapper.c | 182 ++++++++++++++++++++++++---------------------- lib/loopaes/loopaes.c | 2 +- lib/luks1/keyencryption.c | 2 +- lib/luks1/keymanage.c | 2 +- lib/setup.c | 4 +- lib/utils_dm.h | 18 +---- lib/verity/verity.c | 18 +++-- 7 files changed, 113 insertions(+), 115 deletions(-) diff --git a/lib/libdevmapper.c b/lib/libdevmapper.c index 88c529a..f2e66a4 100644 --- a/lib/libdevmapper.c +++ b/lib/libdevmapper.c @@ -300,15 +300,15 @@ out: return params; } static char *get_dm_verity_params(struct crypt_params_verity *vp, - struct crypt_dm_active_verity *dmd) + struct crypt_dm_active_device *dmd) { int max_size, r; char *params = NULL, *hexroot = NULL, *hexsalt = NULL; - hexroot = crypt_safe_alloc(dmd->root_hash_size * 2 + 1); + hexroot = crypt_safe_alloc(dmd->u.verity.root_hash_size * 2 + 1); if (!hexroot) goto out; - hex_key(hexroot, dmd->root_hash_size, dmd->root_hash); + hex_key(hexroot, dmd->u.verity.root_hash_size, dmd->u.verity.root_hash); hexsalt = crypt_safe_alloc(vp->salt_size * 2 + 1); if (!hexsalt) @@ -316,7 +316,8 @@ static char *get_dm_verity_params(struct crypt_params_verity *vp, hex_key(hexsalt, vp->salt_size, vp->salt); max_size = strlen(hexroot) + strlen(hexsalt) + - strlen(dmd->data_device) + strlen(dmd->hash_device) + + strlen(dmd->u.verity.data_device) + + strlen(dmd->u.verity.hash_device) + strlen(vp->hash_name) + 128; params = crypt_safe_alloc(max_size); @@ -325,9 +326,10 @@ static char *get_dm_verity_params(struct crypt_params_verity *vp, r = snprintf(params, max_size, "%u %s %s %u %u %" PRIu64 " %" PRIu64 " %s %s %s", - vp->version, dmd->data_device, dmd->hash_device, + vp->version, dmd->u.verity.data_device, + dmd->u.verity.hash_device, vp->data_block_size, vp->hash_block_size, - vp->data_size, dmd->hash_offset, + vp->data_size, dmd->u.verity.hash_offset, vp->hash_name, hexroot, hexsalt); if (r < 0 || r >= max_size) { crypt_safe_free(params); @@ -579,11 +581,16 @@ out_no_removal: int dm_create_device(const char *name, const char *type, struct crypt_dm_active_device *dmd, + void *params, int reload) { char *table_params = NULL; - table_params = get_dm_crypt_params(dmd); + if (dmd->target == DM_CRYPT) + table_params = get_dm_crypt_params(dmd); + else if (dmd->target == DM_VERITY) + table_params = get_dm_verity_params(params, dmd); + if (!table_params) return -EINVAL; @@ -591,20 +598,6 @@ int dm_create_device(const char *name, dmd->uuid, dmd->size, table_params, reload); } -int dm_create_verity(const char *name, - struct crypt_params_verity *params, - struct crypt_dm_active_verity *dmd) -{ - char *table_params = NULL; - - table_params = get_dm_verity_params(params, dmd); - if (!table_params) - return -EINVAL; - - return _dm_create_device(name, CRYPT_VERITY, dmd->data_device, dmd->flags, - NULL, dmd->size, table_params, 0); -} - static int dm_status_dmi(const char *name, struct dm_info *dmi, const char *target, char **status_line) { @@ -691,48 +684,16 @@ int dm_status_verity_ok(const char *name) return r; } -int dm_query_device(const char *name, uint32_t get_flags, - struct crypt_dm_active_device *dmd) +static int _dm_query_crypt(uint32_t get_flags, + struct dm_info *dmi, + char *params, + struct crypt_dm_active_device *dmd) { - struct dm_task *dmt; - struct dm_info dmi; - uint64_t start, length, val64; - char *target_type, *params, *rcipher, *key_, *rdevice, *endp, buffer[3], *arg; - const char *tmp_uuid; - void *next = NULL; + uint64_t val64; + char *rcipher, *key_, *rdevice, *endp, buffer[3], *arg; unsigned int i; - int r = -EINVAL; - - memset(dmd, 0, sizeof(*dmd)); - - if (!(dmt = dm_task_create(DM_DEVICE_TABLE))) - goto out; - if ((dm_flags() & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt)) - goto out; - if (!dm_task_set_name(dmt, name)) - goto out; - r = -ENODEV; - if (!dm_task_run(dmt)) - goto out; - - r = -EINVAL; - if (!dm_task_get_info(dmt, &dmi)) - goto out; - if (!dmi.exists) { - r = -ENODEV; - goto out; - } - - tmp_uuid = dm_task_get_uuid(dmt); - - next = dm_get_next_target(dmt, next, &start, &length, - &target_type, ¶ms); - if (!target_type || strcmp(target_type, DM_CRYPT_TARGET) != 0 || - start != 0 || next) - goto out; - - dmd->size = length; + dmd->target = DM_CRYPT; rcipher = strsep(¶ms, " "); /* cipher */ @@ -742,10 +703,10 @@ int dm_query_device(const char *name, uint32_t get_flags, /* skip */ key_ = strsep(¶ms, " "); if (!params) - goto out; + return -EINVAL; val64 = strtoull(params, ¶ms, 10); if (*params != ' ') - goto out; + return -EINVAL; params++; dmd->u.crypt.iv_offset = val64; @@ -757,50 +718,47 @@ int dm_query_device(const char *name, uint32_t get_flags, /*offset */ if (!params) - goto out; + return -EINVAL; val64 = strtoull(params, ¶ms, 10); dmd->u.crypt.offset = val64; /* Features section, available since crypt target version 1.11 */ if (*params) { if (*params != ' ') - goto out; + return -EINVAL; params++; /* Number of arguments */ val64 = strtoull(params, ¶ms, 10); if (*params != ' ') - goto out; + return -EINVAL; params++; for (i = 0; i < val64; i++) { if (!params) - goto out; + return -EINVAL; arg = strsep(¶ms, " "); if (!strcasecmp(arg, "allow_discards")) dmd->flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS; else /* unknown option */ - goto out; + return -EINVAL; } /* All parameters shold be processed */ if (params) - goto out; + return -EINVAL; } /* Never allow to return empty key */ - if ((get_flags & DM_ACTIVE_KEY) && dmi.suspended) { + if ((get_flags & DM_ACTIVE_KEY) && dmi->suspended) { log_dbg("Cannot read volume key while suspended."); - r = -EINVAL; - goto out; + return -EINVAL; } if (get_flags & DM_ACTIVE_KEYSIZE) { dmd->u.crypt.vk = crypt_alloc_volume_key(strlen(key_) / 2, NULL); - if (!dmd->u.crypt.vk) { - r = -ENOMEM; - goto out; - } + if (!dmd->u.crypt.vk) + return -ENOMEM; if (get_flags & DM_ACTIVE_KEY) { buffer[2] = '\0'; @@ -810,17 +768,79 @@ int dm_query_device(const char *name, uint32_t get_flags, if (endp != &buffer[2]) { crypt_free_volume_key(dmd->u.crypt.vk); dmd->u.crypt.vk = NULL; - r = -EINVAL; - goto out; + return -EINVAL; } } } } memset(key_, 0, strlen(key_)); + return 0; +} + +static int _dm_query_verity(uint32_t get_flags, + struct dm_info *dmi, + char *params, + struct crypt_dm_active_device *dmd) +{ + dmd->target = DM_VERITY; + return -EINVAL; +} + +int dm_query_device(const char *name, uint32_t get_flags, + struct crypt_dm_active_device *dmd) +{ + struct dm_task *dmt; + struct dm_info dmi; + uint64_t start, length; + char *target_type, *params; + const char *tmp_uuid; + void *next = NULL; + int r = -EINVAL; + + memset(dmd, 0, sizeof(*dmd)); + + if (!(dmt = dm_task_create(DM_DEVICE_TABLE))) + goto out; + if ((dm_flags() & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt)) + goto out; + if (!dm_task_set_name(dmt, name)) + goto out; + r = -ENODEV; + if (!dm_task_run(dmt)) + goto out; + + r = -EINVAL; + if (!dm_task_get_info(dmt, &dmi)) + goto out; + + if (!dmi.exists) { + r = -ENODEV; + goto out; + } + + next = dm_get_next_target(dmt, next, &start, &length, + &target_type, ¶ms); + + if (!target_type || start != 0 || next) + goto out; + + if (!strcmp(target_type, DM_CRYPT_TARGET)) + r = _dm_query_crypt(get_flags, &dmi, params, dmd); + else if (!strcmp(target_type, DM_VERITY_TARGET)) + r = _dm_query_verity(get_flags, &dmi, params, dmd); + else + r = -EINVAL; + + if (r < 0) + goto out; + + dmd->size = length; + if (dmi.read_only) dmd->flags |= CRYPT_ACTIVATE_READONLY; + tmp_uuid = dm_task_get_uuid(dmt); if (!tmp_uuid) dmd->flags |= CRYPT_ACTIVATE_NO_UUID; else if (get_flags & DM_ACTIVE_UUID) { @@ -836,14 +856,6 @@ out: return r; } -int dm_query_verity(const char *name, - struct crypt_dm_active_verity *dmd) -{ - int r = -EINVAL; - - return r; -} - static int _dm_message(const char *name, const char *msg) { int r = 0; diff --git a/lib/loopaes/loopaes.c b/lib/loopaes/loopaes.c index 0dd5e11..7a5f67b 100644 --- a/lib/loopaes/loopaes.c +++ b/lib/loopaes/loopaes.c @@ -225,7 +225,7 @@ int LOOPAES_activate(struct crypt_device *cd, log_dbg("Trying to activate loop-AES device %s using cipher %s.", name, dmd.u.crypt.cipher); - r = dm_create_device(name, CRYPT_LOOPAES, &dmd, 0); + r = dm_create_device(name, CRYPT_LOOPAES, &dmd, NULL, 0); if (!r && !(dm_flags() & req_flags)) { log_err(cd, _("Kernel doesn't support loop-AES compatible mapping.\n")); diff --git a/lib/luks1/keyencryption.c b/lib/luks1/keyencryption.c index 3b3cef8..a2e0d31 100644 --- a/lib/luks1/keyencryption.c +++ b/lib/luks1/keyencryption.c @@ -86,7 +86,7 @@ static int setup_mapping(const char *cipher, const char *name, dmd.size = round_up_modulo(srcLength,device_sector_size)/SECTOR_SIZE; cleaner_size = dmd.size; - return dm_create_device(name, "TEMP", &dmd, 0); + return dm_create_device(name, "TEMP", &dmd, NULL, 0); } static void sigint_handler(int sig __attribute__((unused))) diff --git a/lib/luks1/keymanage.c b/lib/luks1/keymanage.c index e8b277e..95a4d27 100644 --- a/lib/luks1/keymanage.c +++ b/lib/luks1/keymanage.c @@ -1062,7 +1062,7 @@ int LUKS1_activate(struct crypt_device *cd, return -ENOMEM; dmd.u.crypt.cipher = dm_cipher; - r = dm_create_device(name, CRYPT_LUKS1, &dmd, 0); + r = dm_create_device(name, CRYPT_LUKS1, &dmd, NULL, 0); free(dm_cipher); return r; diff --git a/lib/setup.c b/lib/setup.c index 115d558..0d930ef 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -335,7 +335,7 @@ int PLAIN_activate(struct crypt_device *cd, log_dbg("Trying to activate PLAIN device %s using cipher %s.", name, dmd.u.crypt.cipher); - r = dm_create_device(name, CRYPT_PLAIN, &dmd, 0); + r = dm_create_device(name, CRYPT_PLAIN, &dmd, NULL, 0); // FIXME if (!cd->plain_uuid && dm_query_device(name, DM_ACTIVE_UUID, &dmd) >= 0) @@ -1195,7 +1195,7 @@ int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size) r = 0; } else { dmd.size = new_size; - r = dm_create_device(name, cd->type, &dmd, 1); + r = dm_create_device(name, cd->type, &dmd, NULL, 1); } out: crypt_free_volume_key(dmd.u.crypt.vk); diff --git a/lib/utils_dm.h b/lib/utils_dm.h index 6eb24c1..7a8c8cc 100644 --- a/lib/utils_dm.h +++ b/lib/utils_dm.h @@ -73,18 +73,6 @@ struct crypt_dm_active_device { } u; }; -struct crypt_dm_active_verity { - const char *data_device; - const char *hash_device; - - const char *root_hash; - size_t root_hash_size; - - uint64_t hash_offset; /* hash offset (not header) */ - uint64_t size; /* active device size */ - uint32_t flags; /* activation flags */ -}; - const char *dm_get_dir(void); int dm_init(struct crypt_device *context, int check_kernel); void dm_exit(void); @@ -94,15 +82,11 @@ int dm_status_suspended(const char *name); int dm_status_verity_ok(const char *name); int dm_query_device(const char *name, uint32_t get_flags, struct crypt_dm_active_device *dmd); -int dm_query_verity(const char *name, - struct crypt_dm_active_verity *dmd); int dm_create_device(const char *name, const char *type, struct crypt_dm_active_device *dmd, + void *params, int reload); -int dm_create_verity(const char *name, - struct crypt_params_verity *params, - struct crypt_dm_active_verity *dmd); int dm_suspend_and_wipe_key(const char *name); int dm_resume_and_reinstate_key(const char *name, size_t key_size, diff --git a/lib/verity/verity.c b/lib/verity/verity.c index 1bbd8d5..589a28b 100644 --- a/lib/verity/verity.c +++ b/lib/verity/verity.c @@ -155,7 +155,7 @@ int VERITY_activate(struct crypt_device *cd, struct crypt_params_verity *verity_hdr, uint32_t flags) { - struct crypt_dm_active_verity dmd; + struct crypt_dm_active_device dmd; uint64_t offset = 0; int r; @@ -173,20 +173,22 @@ int VERITY_activate(struct crypt_device *cd, if (!name) return 0; - dmd.data_device = crypt_get_device_name(cd); - dmd.hash_device = hash_device; - dmd.root_hash = root_hash; - dmd.root_hash_size = root_hash_size; - dmd.hash_offset = VERITY_hash_offset_block(verity_hdr), + dmd.target = DM_VERITY; + dmd.u.verity.data_device = crypt_get_device_name(cd); + dmd.u.verity.hash_device = hash_device; + dmd.u.verity.root_hash = root_hash; + dmd.u.verity.root_hash_size = root_hash_size; + dmd.u.verity.hash_offset = VERITY_hash_offset_block(verity_hdr), dmd.flags = CRYPT_ACTIVATE_READONLY; dmd.size = verity_hdr->data_size * verity_hdr->data_block_size / 512; + dmd.uuid = NULL; - r = device_check_and_adjust(cd, dmd.data_device, DEV_EXCL, + r = device_check_and_adjust(cd, dmd.u.verity.data_device, DEV_EXCL, &dmd.size, &offset, &dmd.flags); if (r) return r; - r = dm_create_verity(name, verity_hdr, &dmd); + r = dm_create_device(name, CRYPT_VERITY, &dmd, verity_hdr, 0); if (!r && !(dm_flags() & DM_VERITY_SUPPORTED)) { log_err(cd, _("Kernel doesn't support dm-verity mapping.\n")); return -ENOTSUP; -- 2.7.4