diff --git a/lib/libdevmapper.c b/lib/libdevmapper.c index 88c529aa..f2e66a42 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,16 +684,118 @@ int dm_status_verity_ok(const char *name) return r; } +static int _dm_query_crypt(uint32_t get_flags, + struct dm_info *dmi, + char *params, + struct crypt_dm_active_device *dmd) +{ + uint64_t val64; + char *rcipher, *key_, *rdevice, *endp, buffer[3], *arg; + unsigned int i; + + dmd->target = DM_CRYPT; + + rcipher = strsep(¶ms, " "); + /* cipher */ + if (get_flags & DM_ACTIVE_CIPHER) + dmd->u.crypt.cipher = strdup(rcipher); + + /* skip */ + key_ = strsep(¶ms, " "); + if (!params) + return -EINVAL; + val64 = strtoull(params, ¶ms, 10); + if (*params != ' ') + return -EINVAL; + params++; + + dmd->u.crypt.iv_offset = val64; + + /* device */ + rdevice = strsep(¶ms, " "); + if (get_flags & DM_ACTIVE_DEVICE) + dmd->u.crypt.device = crypt_lookup_dev(rdevice); + + /*offset */ + if (!params) + 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 != ' ') + return -EINVAL; + params++; + + /* Number of arguments */ + val64 = strtoull(params, ¶ms, 10); + if (*params != ' ') + return -EINVAL; + params++; + + for (i = 0; i < val64; i++) { + if (!params) + return -EINVAL; + arg = strsep(¶ms, " "); + if (!strcasecmp(arg, "allow_discards")) + dmd->flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS; + else /* unknown option */ + return -EINVAL; + } + + /* All parameters shold be processed */ + if (params) + return -EINVAL; + } + + /* Never allow to return empty key */ + if ((get_flags & DM_ACTIVE_KEY) && dmi->suspended) { + log_dbg("Cannot read volume key while suspended."); + 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) + return -ENOMEM; + + if (get_flags & DM_ACTIVE_KEY) { + buffer[2] = '\0'; + for(i = 0; i < dmd->u.crypt.vk->keylength; i++) { + memcpy(buffer, &key_[i * 2], 2); + dmd->u.crypt.vk->key[i] = strtoul(buffer, &endp, 16); + if (endp != &buffer[2]) { + crypt_free_volume_key(dmd->u.crypt.vk); + dmd->u.crypt.vk = NULL; + 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, val64; - char *target_type, *params, *rcipher, *key_, *rdevice, *endp, buffer[3], *arg; + uint64_t start, length; + char *target_type, *params; const char *tmp_uuid; void *next = NULL; - unsigned int i; int r = -EINVAL; memset(dmd, 0, sizeof(*dmd)); @@ -724,103 +819,28 @@ int dm_query_device(const char *name, uint32_t get_flags, 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) + + 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; - rcipher = strsep(¶ms, " "); - /* cipher */ - if (get_flags & DM_ACTIVE_CIPHER) - dmd->u.crypt.cipher = strdup(rcipher); - - /* skip */ - key_ = strsep(¶ms, " "); - if (!params) - goto out; - val64 = strtoull(params, ¶ms, 10); - if (*params != ' ') - goto out; - params++; - - dmd->u.crypt.iv_offset = val64; - - /* device */ - rdevice = strsep(¶ms, " "); - if (get_flags & DM_ACTIVE_DEVICE) - dmd->u.crypt.device = crypt_lookup_dev(rdevice); - - /*offset */ - if (!params) - goto out; - 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; - params++; - - /* Number of arguments */ - val64 = strtoull(params, ¶ms, 10); - if (*params != ' ') - goto out; - params++; - - for (i = 0; i < val64; i++) { - if (!params) - goto out; - arg = strsep(¶ms, " "); - if (!strcasecmp(arg, "allow_discards")) - dmd->flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS; - else /* unknown option */ - goto out; - } - - /* All parameters shold be processed */ - if (params) - goto out; - } - - /* Never allow to return empty key */ - if ((get_flags & DM_ACTIVE_KEY) && dmi.suspended) { - log_dbg("Cannot read volume key while suspended."); - r = -EINVAL; - goto out; - } - - 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 (get_flags & DM_ACTIVE_KEY) { - buffer[2] = '\0'; - for(i = 0; i < dmd->u.crypt.vk->keylength; i++) { - memcpy(buffer, &key_[i * 2], 2); - dmd->u.crypt.vk->key[i] = strtoul(buffer, &endp, 16); - if (endp != &buffer[2]) { - crypt_free_volume_key(dmd->u.crypt.vk); - dmd->u.crypt.vk = NULL; - r = -EINVAL; - goto out; - } - } - } - } - memset(key_, 0, strlen(key_)); - 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 0dd5e110..7a5f67bb 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 3b3cef84..a2e0d31c 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 e8b277e4..95a4d27b 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 115d5589..0d930efa 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 6eb24c17..7a8c8cc7 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 1bbd8d5a..589a28b9 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;