Blame SOURCES/cryptsetup-2.6.0-Fix-internal-crypt-segment-compare-routine.patch

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