From 3e4c69a01709d35322ffa17c5360608907a207d7 Mon Sep 17 00:00:00 2001 From: Ondrej Kozina Date: Tue, 11 Oct 2022 11:48:13 +0200 Subject: [PATCH 5/5] Fix internal crypt segment compare routine. The function is supposed to check if manipulated active dm-crypt device matches the on-disk metadata. Unfortunately it did not take into account differences between normal cipher specification (aes-xts-plain64) and capi format specification (capi:xts(aes)-plain64). The internal query function always converted capi format in normal format and therefor failed if capi format was used in metadata. Fixes: #759. --- lib/setup.c | 36 ++++++++++++++++++++++++++---------- tests/api-test-2.c | 14 ++++++++++++-- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/lib/setup.c b/lib/setup.c index 6d7411b5..809049b9 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -2458,6 +2458,9 @@ static int _compare_crypt_devices(struct crypt_device *cd, const struct dm_target *src, const struct dm_target *tgt) { + char *src_cipher = NULL, *src_integrity = NULL; + int r = -EINVAL; + /* for crypt devices keys are mandatory */ if (!src->u.crypt.vk || !tgt->u.crypt.vk) return -EINVAL; @@ -2465,21 +2468,30 @@ static int _compare_crypt_devices(struct crypt_device *cd, /* CIPHER checks */ if (!src->u.crypt.cipher || !tgt->u.crypt.cipher) return -EINVAL; - if (strcmp(src->u.crypt.cipher, tgt->u.crypt.cipher)) { - log_dbg(cd, "Cipher specs do not match."); + + /* + * dm_query_target converts capi cipher specification to dm-crypt format. + * We need to do same for cipher specification requested in source + * device. + */ + if (crypt_capi_to_cipher(&src_cipher, &src_integrity, src->u.crypt.cipher, src->u.crypt.integrity)) return -EINVAL; + + if (strcmp(src_cipher, tgt->u.crypt.cipher)) { + log_dbg(cd, "Cipher specs do not match."); + goto out; } if (tgt->u.crypt.vk->keylength == 0 && crypt_is_cipher_null(tgt->u.crypt.cipher)) log_dbg(cd, "Existing device uses cipher null. Skipping key comparison."); else if (_compare_volume_keys(src->u.crypt.vk, 0, tgt->u.crypt.vk, tgt->u.crypt.vk->key_description != NULL)) { log_dbg(cd, "Keys in context and target device do not match."); - return -EINVAL; + goto out; } - if (crypt_strcmp(src->u.crypt.integrity, tgt->u.crypt.integrity)) { + if (crypt_strcmp(src_integrity, tgt->u.crypt.integrity)) { log_dbg(cd, "Integrity parameters do not match."); - return -EINVAL; + goto out; } if (src->u.crypt.offset != tgt->u.crypt.offset || @@ -2487,15 +2499,19 @@ static int _compare_crypt_devices(struct crypt_device *cd, src->u.crypt.iv_offset != tgt->u.crypt.iv_offset || src->u.crypt.tag_size != tgt->u.crypt.tag_size) { log_dbg(cd, "Integer parameters do not match."); - return -EINVAL; + goto out; } - if (device_is_identical(src->data_device, tgt->data_device) <= 0) { + if (device_is_identical(src->data_device, tgt->data_device) <= 0) log_dbg(cd, "Data devices do not match."); - return -EINVAL; - } + else + r = 0; - return 0; +out: + free(src_cipher); + free(src_integrity); + + return r; } static int _compare_integrity_devices(struct crypt_device *cd, diff --git a/tests/api-test-2.c b/tests/api-test-2.c index 0534677a..34002d1a 100644 --- a/tests/api-test-2.c +++ b/tests/api-test-2.c @@ -1585,8 +1585,8 @@ static void ResizeDeviceLuks2(void) const char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a"; size_t key_size = strlen(mk_hex) / 2; - const char *cipher = "aes"; - const char *cipher_mode = "cbc-essiv:sha256"; + const char *cipher = "aes", *capi_cipher = "capi:cbc(aes)"; + const char *cipher_mode = "cbc-essiv:sha256", *capi_cipher_mode = "essiv:sha256"; uint64_t r_payload_offset, r_header_size, r_size; /* Cannot use Argon2 in FIPS */ @@ -1728,6 +1728,16 @@ static void ResizeDeviceLuks2(void) OK_(crypt_deactivate(cd, CDEVICE_1)); CRYPT_FREE(cd); + OK_(crypt_init(&cd, DMDIR L_DEVICE_OK)); + OK_(crypt_set_pbkdf_type(cd, &pbkdf)); + OK_(crypt_format(cd, CRYPT_LUKS2, capi_cipher, capi_cipher_mode, NULL, key, key_size, NULL)); + OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0)); + OK_(crypt_resize(cd, CDEVICE_1, 8)); + if (!t_device_size(DMDIR CDEVICE_1, &r_size)) + EQ_(8, r_size >> SECTOR_SHIFT); + OK_(crypt_deactivate(cd, CDEVICE_1)); + CRYPT_FREE(cd); + _cleanup_dmdevices(); } -- 2.38.1