import cryptsetup-2.3.3-4.el8

This commit is contained in:
CentOS Sources 2021-03-30 14:04:24 -04:00 committed by Stepan Oksanichenko
parent 11aa0f425e
commit 38d329f61e
4 changed files with 1179 additions and 1 deletions

View File

@ -0,0 +1,48 @@
From f3906957675e466bbe7fa97a725f56c7c494d4a5 Mon Sep 17 00:00:00 2001
From: Milan Broz <gmazyland@gmail.com>
Date: Tue, 21 Jul 2020 14:14:54 +0200
Subject: [PATCH] Fix crypto backend to properly handle ECB mode.
Despite it should be never used, it should still work :)
Bug introduced in version 2.3.2.
---
lib/crypto_backend/crypto_storage.c | 2 +-
tests/compat-test2 | 9 +++++++++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/lib/crypto_backend/crypto_storage.c b/lib/crypto_backend/crypto_storage.c
index 8b6c19c..92dbae7 100644
--- a/lib/crypto_backend/crypto_storage.c
+++ b/lib/crypto_backend/crypto_storage.c
@@ -64,7 +64,7 @@ static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
memset(ctx, 0, sizeof(*ctx));
ctx->iv_size = crypt_cipher_ivsize(cipher_name, mode_name);
- if (ctx->iv_size < 8)
+ if (ctx->iv_size < 0 || (strcmp(mode_name, "ecb") && ctx->iv_size < 8))
return -ENOENT;
if (!strcmp(cipher_name, "cipher_null") ||
diff --git a/tests/compat-test2 b/tests/compat-test2
index 0fad999..c3852cd 100755
--- a/tests/compat-test2
+++ b/tests/compat-test2
@@ -1023,5 +1023,14 @@ echo $PWD3 | $CRYPTSETUP luksConvertKey --key-slot 22 $LOOPDEV --keyslot-cipher
[ "$($CRYPTSETUP luksDump $IMG | grep -A8 -m1 "22: luks2" | grep "Cipher:" | sed -e 's/[[:space:]]\+Cipher:\ \+//g')" = $KEYSLOT_CIPHER ] || fail
[ "$($CRYPTSETUP luksDump $IMG | grep -A8 -m1 "22: luks2" | grep "Cipher key:"| sed -e 's/[[:space:]]\+Cipher\ key:\ \+//g')" = "128 bits" ] || fail
+prepare "[42] Some encryption compatibility mode tests" wipe
+CIPHERS="aes-ecb aes-cbc-null aes-cbc-plain64 aes-cbc-essiv:sha256 aes-xts-plain64"
+key_size=256
+for cipher in $CIPHERS ; do
+ echo -n "[$cipher/$key_size]"
+ $CRYPTSETUP -q luksFormat --type luks2 $LOOPDEV $KEY1 $FAST_PBKDF_OPT --cipher $cipher --key-size $key_size || fail
+done
+echo
+
remove_mapping
exit 0
--
1.8.3.1

View File

@ -0,0 +1,341 @@
From 52f5cb8cedf22fb3e14c744814ec8af7614146c7 Mon Sep 17 00:00:00 2001
From: Tobias Stoeckmann <tobias@stoeckmann.org>
Date: Mon, 24 Aug 2020 19:21:43 +0200
Subject: [PATCH 01/11] Check segment gaps regardless of heap space.
Segments are validated in hdr_validate_segments. Gaps in segment keys
are detected when collecting offsets. But if an invalid segment is very
large, larger than count, it could happen that cryptsetup is unable to
allocate enough memory, not giving a clue about what actually is the
problem.
Therefore check for gaps even if not enough memory is available. This
gives much more information with debug output enabled.
Obviously cryptsetup still fails if segments are perfectly fine but not
enough RAM available. But at that stage, the user knows that it's the
fault of the system, not of an invalid segment.
---
lib/luks2/luks2_json_metadata.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/lib/luks2/luks2_json_metadata.c b/lib/luks2/luks2_json_metadata.c
index 23556f2..ea5c7f7 100644
--- a/lib/luks2/luks2_json_metadata.c
+++ b/lib/luks2/luks2_json_metadata.c
@@ -679,11 +679,10 @@ static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
if (first_backup < 0)
first_backup = count;
- intervals = malloc(first_backup * sizeof(*intervals));
- if (!intervals) {
- log_dbg(cd, "Not enough memory.");
- return 1;
- }
+ if (first_backup <= count && (size_t)first_backup < SIZE_MAX / sizeof(*intervals))
+ intervals = malloc(first_backup * sizeof(*intervals));
+ else
+ intervals = NULL;
for (i = 0; i < first_backup; i++) {
jobj = json_segments_get_segment(jobj_segments, i);
@@ -692,8 +691,14 @@ static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
free(intervals);
return 1;
}
- intervals[i].offset = json_segment_get_offset(jobj, 0);
- intervals[i].length = json_segment_get_size(jobj, 0) ?: UINT64_MAX;
+ if (intervals != NULL) {
+ intervals[i].offset = json_segment_get_offset(jobj, 0);
+ intervals[i].length = json_segment_get_size(jobj, 0) ?: UINT64_MAX;
+ }
+ }
+ if (intervals == NULL) {
+ log_dbg(cd, "Not enough memory.");
+ return 1;
}
r = !validate_segment_intervals(cd, first_backup, intervals);
--
1.8.3.1
From 46ee71edcd13e1dad50815ad65c28779aa6f7503 Mon Sep 17 00:00:00 2001
From: Ondrej Kozina <okozina@redhat.com>
Date: Tue, 25 Aug 2020 19:32:48 +0200
Subject: [PATCH 07/11] Avoid needlessly large allocations in LUKS2 validation
code.
In case LUKS2 backup segment creates gap in between last regular
segment and backup segment report invalid metadata imediately. We stop
on first error so there's no need to allocate large memory on heap
(we may ran with mlock(MCL_FUTURE) set).
Example:
- total segments count is 3
- regular segments have keys "0" and "1"
- first backup segment has key "42"
---
lib/luks2/luks2_json_metadata.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/lib/luks2/luks2_json_metadata.c b/lib/luks2/luks2_json_metadata.c
index ea5c7f7..5b73b34 100644
--- a/lib/luks2/luks2_json_metadata.c
+++ b/lib/luks2/luks2_json_metadata.c
@@ -676,10 +676,16 @@ static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
return 1;
}
+ /* avoid needlessly large allocation when first backup segment is invalid */
+ if (first_backup >= count) {
+ log_dbg(cd, "Gap between last regular segment and backup segment at key %d.", first_backup);
+ return 1;
+ }
+
if (first_backup < 0)
first_backup = count;
- if (first_backup <= count && (size_t)first_backup < SIZE_MAX / sizeof(*intervals))
+ if ((size_t)first_backup < SIZE_MAX / sizeof(*intervals))
intervals = malloc(first_backup * sizeof(*intervals));
else
intervals = NULL;
--
1.8.3.1
From 752c9a52798f11d3b765b673ebaa3058eb25316e Mon Sep 17 00:00:00 2001
From: Ondrej Kozina <okozina@redhat.com>
Date: Tue, 25 Aug 2020 19:23:21 +0200
Subject: [PATCH 08/11] Simplify validation code a bit.
Keep it simple. If there's not enough memory we can't validate
segments. The LUKS2 specification does not recommend to continue
processing LUKS2 metadata if it can not be properly validated.
---
lib/luks2/luks2_json_metadata.c | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/lib/luks2/luks2_json_metadata.c b/lib/luks2/luks2_json_metadata.c
index 5b73b34..df89401 100644
--- a/lib/luks2/luks2_json_metadata.c
+++ b/lib/luks2/luks2_json_metadata.c
@@ -594,9 +594,9 @@ static bool validate_segment_intervals(struct crypt_device *cd,
static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
{
json_object *jobj_segments, *jobj_digests, *jobj_offset, *jobj_size, *jobj_type, *jobj_flags, *jobj;
- struct interval *intervals;
uint64_t offset, size;
int i, r, count, first_backup = -1;
+ struct interval *intervals = NULL;
if (!json_object_object_get_ex(hdr_jobj, "segments", &jobj_segments)) {
log_dbg(cd, "Missing segments section.");
@@ -687,8 +687,11 @@ static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
if ((size_t)first_backup < SIZE_MAX / sizeof(*intervals))
intervals = malloc(first_backup * sizeof(*intervals));
- else
- intervals = NULL;
+
+ if (!intervals) {
+ log_dbg(cd, "Not enough memory.");
+ return 1;
+ }
for (i = 0; i < first_backup; i++) {
jobj = json_segments_get_segment(jobj_segments, i);
@@ -697,14 +700,8 @@ static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
free(intervals);
return 1;
}
- if (intervals != NULL) {
- intervals[i].offset = json_segment_get_offset(jobj, 0);
- intervals[i].length = json_segment_get_size(jobj, 0) ?: UINT64_MAX;
- }
- }
- if (intervals == NULL) {
- log_dbg(cd, "Not enough memory.");
- return 1;
+ intervals[i].offset = json_segment_get_offset(jobj, 0);
+ intervals[i].length = json_segment_get_size(jobj, 0) ?: UINT64_MAX;
}
r = !validate_segment_intervals(cd, first_backup, intervals);
--
1.8.3.1
From 96da06430b6f5c2588c619082f2c5880df9cc776 Mon Sep 17 00:00:00 2001
From: Ondrej Kozina <okozina@redhat.com>
Date: Wed, 26 Aug 2020 17:24:05 +0200
Subject: [PATCH 09/11] Add test for LUKS2 segments validation code fix.
---
...enerate-luks2-segment-wrong-backup-key-0.img.sh | 67 ++++++++++++++++++++++
...enerate-luks2-segment-wrong-backup-key-1.img.sh | 67 ++++++++++++++++++++++
tests/luks2-validation-test | 2 +
3 files changed, 136 insertions(+)
create mode 100755 tests/generators/generate-luks2-segment-wrong-backup-key-0.img.sh
create mode 100755 tests/generators/generate-luks2-segment-wrong-backup-key-1.img.sh
diff --git a/tests/generators/generate-luks2-segment-wrong-backup-key-0.img.sh b/tests/generators/generate-luks2-segment-wrong-backup-key-0.img.sh
new file mode 100755
index 0000000..2499a5e
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-wrong-backup-key-0.img.sh
@@ -0,0 +1,67 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with wrong backup segment id
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function prepare()
+{
+ cp $SRC_IMG $TGT_IMG
+ test -d $TMPDIR || mkdir $TMPDIR
+ read_luks2_json0 $TGT_IMG $TMPDIR/json0
+ read_luks2_bin_hdr0 $TGT_IMG $TMPDIR/hdr0
+ read_luks2_bin_hdr1 $TGT_IMG $TMPDIR/hdr1
+}
+
+function generate()
+{
+ # create illegal backup segment key (used to be bug in 32bit implementations)
+ json_str=$(jq -c '.segments[(.segments | length + 1 | tostring)] = { "type" : "linear", "offset" : "512", "size" : "512", "flags":["backup-x"]}' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ merge_bin_hdr_with_json $TMPDIR/hdr0 $TMPDIR/json0 $TMPDIR/area0
+ erase_checksum $TMPDIR/area0
+ chks0=$(calc_sha256_checksum_file $TMPDIR/area0)
+ write_checksum $chks0 $TMPDIR/area0
+ write_luks2_hdr0 $TMPDIR/area0 $TGT_IMG
+ kill_bin_hdr $TMPDIR/hdr1
+ write_luks2_hdr1 $TMPDIR/hdr1 $TGT_IMG
+}
+
+function check()
+{
+ read_luks2_bin_hdr1 $TGT_IMG $TMPDIR/hdr_res1
+ local str_res1=$(head -c 6 $TMPDIR/hdr_res1)
+ test "$str_res1" = "VACUUM" || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments | length < 2
+ then error("Unexpected segments count") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+function cleanup()
+{
+ rm -f $TMPDIR/*
+ rm -fd $TMPDIR
+}
+
+test $# -eq 2 || exit 1
+
+TGT_IMG=$1/$(test_img_name $0)
+SRC_IMG=$2
+
+prepare
+generate
+check
+cleanup
diff --git a/tests/generators/generate-luks2-segment-wrong-backup-key-1.img.sh b/tests/generators/generate-luks2-segment-wrong-backup-key-1.img.sh
new file mode 100755
index 0000000..702fe71
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-wrong-backup-key-1.img.sh
@@ -0,0 +1,67 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with wrong backup segment id
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function prepare()
+{
+ cp $SRC_IMG $TGT_IMG
+ test -d $TMPDIR || mkdir $TMPDIR
+ read_luks2_json0 $TGT_IMG $TMPDIR/json0
+ read_luks2_bin_hdr0 $TGT_IMG $TMPDIR/hdr0
+ read_luks2_bin_hdr1 $TGT_IMG $TMPDIR/hdr1
+}
+
+function generate()
+{
+ # create illegal backup segment key (used to be bug in 32bit implementations)
+ json_str=$(jq -c '(.segments."0".offset | tonumber) as $i | .segments[range(1;65) | tostring] = { "type" : "linear", "offset" : ($i + 512 | tostring), "size" : "512" } | .segments."268435472" = { "type":"linear","offset":"512","size":"512","flags":["backup-x"]}' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ merge_bin_hdr_with_json $TMPDIR/hdr0 $TMPDIR/json0 $TMPDIR/area0
+ erase_checksum $TMPDIR/area0
+ chks0=$(calc_sha256_checksum_file $TMPDIR/area0)
+ write_checksum $chks0 $TMPDIR/area0
+ write_luks2_hdr0 $TMPDIR/area0 $TGT_IMG
+ kill_bin_hdr $TMPDIR/hdr1
+ write_luks2_hdr1 $TMPDIR/hdr1 $TGT_IMG
+}
+
+function check()
+{
+ read_luks2_bin_hdr1 $TGT_IMG $TMPDIR/hdr_res1
+ local str_res1=$(head -c 6 $TMPDIR/hdr_res1)
+ test "$str_res1" = "VACUUM" || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments | length < 64
+ then error("Unexpected segments count") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+function cleanup()
+{
+ rm -f $TMPDIR/*
+ rm -fd $TMPDIR
+}
+
+test $# -eq 2 || exit 1
+
+TGT_IMG=$1/$(test_img_name $0)
+SRC_IMG=$2
+
+prepare
+generate
+check
+cleanup
diff --git a/tests/luks2-validation-test b/tests/luks2-validation-test
index 52945ba..04183fb 100755
--- a/tests/luks2-validation-test
+++ b/tests/luks2-validation-test
@@ -199,6 +199,8 @@ RUN luks2-segment-unknown-type.img "R" "Validation rejected segment with all m
RUN luks2-segment-two.img "R" "Validation rejected two valid segments"
RUN luks2-segment-wrong-flags.img "F" "Failed to detect invalid flags field"
RUN luks2-segment-wrong-flags-element.img "F" "Failed to detect invalid flags content"
+RUN luks2-segment-wrong-backup-key-0.img "F" "Failed to detect gap in backup segments"
+RUN luks2-segment-wrong-backup-key-1.img "F" "Failed to detect gap in backup segments"
echo "[6] Test metadata size and keyslots size (config section)"
RUN luks2-invalid-keyslots-size-c0.img "F" "Failed to detect too large keyslots_size in config section"
--
1.8.3.1

View File

@ -0,0 +1,769 @@
diff -rupN cryptsetup-2.3.3.orig/tests/api-test-2.c cryptsetup-2.3.3/tests/api-test-2.c
--- cryptsetup-2.3.3.orig/tests/api-test-2.c 2021-02-17 19:48:46.483519319 +0100
+++ cryptsetup-2.3.3/tests/api-test-2.c 2021-02-17 19:49:10.527493909 +0100
@@ -2876,6 +2876,12 @@ static void Luks2KeyslotParams(void)
const char *mk_hex2 = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1e";
size_t key_size_ret, key_size = strlen(mk_hex) / 2, keyslot_key_size = 16;
uint64_t r_payload_offset;
+ const struct crypt_pbkdf_type fast_pbkdf = {
+ .type = "pbkdf2",
+ .hash = "sha256",
+ .iterations = 1000,
+ .flags = CRYPT_PBKDF_NO_BENCHMARK
+ };
crypt_decode_key(key, mk_hex, key_size);
crypt_decode_key(key2, mk_hex2, key_size);
@@ -2889,7 +2895,7 @@ static void Luks2KeyslotParams(void)
EQ_(key_size, 2 * keyslot_key_size);
/* test crypt_keyslot_add_by_key */
OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
- crypt_set_iteration_time(cd, 1);
+ OK_(crypt_set_pbkdf_type(cd, &fast_pbkdf));
OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, NULL));
NULL_(crypt_keyslot_get_encryption(cd, 0, &key_size_ret));
OK_(strcmp(crypt_keyslot_get_encryption(cd, CRYPT_ANY_SLOT, &key_size_ret), cipher_spec));
@@ -2948,7 +2954,7 @@ static void Luks2KeyslotParams(void)
OK_(strcmp(crypt_keyslot_get_encryption(cd, 7, &key_size_ret), cipher_keyslot));
EQ_(key_size_ret, keyslot_key_size);
- crypt_set_iteration_time(cd, 1);
+ OK_(crypt_set_pbkdf_type(cd, &fast_pbkdf));
EQ_(8, crypt_keyslot_change_by_passphrase(cd, 1, 8, PASSPHRASE1, strlen(PASSPHRASE1), PASSPHRASE, strlen(PASSPHRASE)));
OK_(strcmp(crypt_keyslot_get_encryption(cd, 8, &key_size_ret), cipher_spec));
EQ_(key_size_ret, key_size);
@@ -2977,7 +2983,7 @@ static void Luks2KeyslotParams(void)
/* LUKS1 compatible calls */
OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
- crypt_set_iteration_time(cd, 1);
+ OK_(crypt_set_pbkdf_type(cd, &fast_pbkdf));
OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, NULL));
NULL_(crypt_keyslot_get_encryption(cd, 0, &key_size_ret));
OK_(strcmp(crypt_keyslot_get_encryption(cd, CRYPT_ANY_SLOT, &key_size_ret), cipher_spec));
@@ -2987,6 +2993,18 @@ static void Luks2KeyslotParams(void)
EQ_(key_size_ret, key_size);
CRYPT_FREE(cd);
+ /* LUKS2 cipher null checks */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_set_pbkdf_type(cd, &fast_pbkdf));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "cipher_null", "ecb", NULL, key, key_size, NULL));
+ FAIL_(crypt_keyslot_set_encryption(cd, "null", 32), "cipher null is not allowed");
+ FAIL_(crypt_keyslot_set_encryption(cd, "cipher_null", 32), "cipher null is not allowed");
+ FAIL_(crypt_keyslot_set_encryption(cd, "cipher_null-ecb", 32), "cipher null is not allowed");
+ EQ_(0, crypt_keyslot_add_by_volume_key(cd, 0, key, key_size, PASSPHRASE, strlen(PASSPHRASE)));
+ NOTNULL_(crypt_keyslot_get_encryption(cd, 0, &key_size_ret));
+ NULL_(strstr(crypt_keyslot_get_encryption(cd, 0, &key_size_ret), "null"));
+ CRYPT_FREE(cd);
+
_cleanup_dmdevices();
_remove_keyfiles();
}
diff -rupN cryptsetup-2.3.3.orig/tests/luks2-reencryption-test cryptsetup-2.3.3/tests/luks2-reencryption-test
--- cryptsetup-2.3.3.orig/tests/luks2-reencryption-test 2021-02-17 19:48:46.493519309 +0100
+++ cryptsetup-2.3.3/tests/luks2-reencryption-test 2021-02-17 19:50:13.397427467 +0100
@@ -1365,6 +1365,33 @@ echo $PWD1 | $CRYPTSETUP luksKillSlot $D
echo -e "$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD2" | $CRYPTSETUP reencrypt $DEV -q 2>/dev/null && fail
echo $PWD1 | $CRYPTSETUP reencrypt $DEV --resume-only -q 2>/dev/null && fail
echo -e "$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1" | $CRYPTSETUP reencrypt $DEV -q || fail
+
+echo "[24] Reencryption with initial cipher_null"
+# aka custom encryption
+prepare dev_size_mb=32
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 -c cipher_null-ecb --offset 8192 $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -c aes-xts-plain64 -q $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+
+# online
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 -c cipher_null-ecb --offset 8192 $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -c aes-xts-plain64 -q $FAST_PBKDF_ARGON || fail
+check_hash_dev /dev/mapper/$DEV_NAME $HASH1
+$CRYPTSETUP status $DEV_NAME | grep -q "key location: keyring" || fail
+$CRYPTSETUP close $DEV_NAME
+
+# simulate LUKS2 device with cipher_null in both keyslot and segment (it can be created only by up conversion from LUKS1)
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 -s 128 -c cipher_null-ecb --offset 8192 $FAST_PBKDF2 $DEV || fail
+$CRYPTSETUP convert -q --type luks2 $DEV || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -c aes-xts-plain64 -q $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+# both keyslot and segment cipher must not be null
+$CRYPTSETUP luksDump $DEV | grep -q "cipher_null" && fail
remove_mapping
exit 0
diff -rupN cryptsetup-2.3.3.orig/lib/utils_crypt.c cryptsetup-2.3.3/lib/utils_crypt.c
--- cryptsetup-2.3.3.orig/lib/utils_crypt.c 2021-02-17 17:48:06.535007396 +0100
+++ cryptsetup-2.3.3/lib/utils_crypt.c 2021-02-17 17:49:07.552948180 +0100
@@ -174,3 +174,10 @@ ssize_t crypt_hex_to_bytes(const char *h
*result = bytes;
return i;
}
+
+bool crypt_is_cipher_null(const char *cipher_spec)
+{
+ if (!cipher_spec)
+ return false;
+ return (strstr(cipher_spec, "cipher_null") || !strcmp(cipher_spec, "null"));
+}
diff -rupN cryptsetup-2.3.3.orig/lib/utils_crypt.h cryptsetup-2.3.3/lib/utils_crypt.h
--- cryptsetup-2.3.3.orig/lib/utils_crypt.h 2021-02-17 17:48:06.535007396 +0100
+++ cryptsetup-2.3.3/lib/utils_crypt.h 2021-02-17 17:49:07.552948180 +0100
@@ -23,6 +23,7 @@
#ifndef _UTILS_CRYPT_H
#define _UTILS_CRYPT_H
+#include <stdbool.h>
#include <unistd.h>
#define MAX_CIPHER_LEN 32
@@ -38,4 +39,6 @@ int crypt_parse_pbkdf(const char *s, con
ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc);
+bool crypt_is_cipher_null(const char *cipher_spec);
+
#endif /* _UTILS_CRYPT_H */
diff -rupN cryptsetup-2.3.3.orig/src/cryptsetup.c cryptsetup-2.3.3/src/cryptsetup.c
--- cryptsetup-2.3.3.orig/src/cryptsetup.c 2021-02-17 17:48:06.538007393 +0100
+++ cryptsetup-2.3.3/src/cryptsetup.c 2021-02-17 17:52:54.174722763 +0100
@@ -1281,7 +1281,7 @@ static int _luksFormat(struct crypt_devi
}
/* Never call pwquality if using null cipher */
- if (tools_is_cipher_null(cipher))
+ if (crypt_is_cipher_null(cipher))
opt_force_password = 1;
if ((r = crypt_init(&cd, header_device))) {
@@ -1679,7 +1679,7 @@ static int luksAddUnboundKey(void)
goto out;
/* Never call pwquality if using null cipher */
- if (tools_is_cipher_null(crypt_get_cipher(cd)))
+ if (crypt_is_cipher_null(crypt_get_cipher(cd)))
opt_force_password = 1;
keysize = opt_key_size / 8;
@@ -1746,7 +1746,7 @@ static int action_luksAddKey(void)
goto out;
/* Never call pwquality if using null cipher */
- if (tools_is_cipher_null(crypt_get_cipher(cd)))
+ if (crypt_is_cipher_null(crypt_get_cipher(cd)))
opt_force_password = 1;
keysize = crypt_get_volume_key_size(cd);
@@ -1849,7 +1849,7 @@ static int action_luksChangeKey(void)
goto out;
/* Never call pwquality if using null cipher */
- if (tools_is_cipher_null(crypt_get_cipher(cd)))
+ if (crypt_is_cipher_null(crypt_get_cipher(cd)))
opt_force_password = 1;
r = set_pbkdf_params(cd, crypt_get_type(cd));
diff -rupN cryptsetup-2.3.3.orig/src/cryptsetup.h cryptsetup-2.3.3/src/cryptsetup.h
--- cryptsetup-2.3.3.orig/src/cryptsetup.h 2021-02-17 17:48:06.538007393 +0100
+++ cryptsetup-2.3.3/src/cryptsetup.h 2021-02-17 17:54:15.556641129 +0100
@@ -97,7 +97,6 @@ int tools_get_key(const char *prompt,
void tools_passphrase_msg(int r);
int tools_is_stdin(const char *key_file);
int tools_string_to_size(struct crypt_device *cd, const char *s, uint64_t *size);
-int tools_is_cipher_null(const char *cipher);
void tools_clear_line(void);
diff -rupN cryptsetup-2.3.3.orig/src/utils_tools.c cryptsetup-2.3.3/src/utils_tools.c
--- cryptsetup-2.3.3.orig/src/utils_tools.c 2021-02-17 17:48:06.538007393 +0100
+++ cryptsetup-2.3.3/src/utils_tools.c 2021-02-17 17:49:07.572948160 +0100
@@ -596,14 +596,6 @@ out:
return r;
}
-int tools_is_cipher_null(const char *cipher)
-{
- if (!cipher)
- return 0;
-
- return !strcmp(cipher, "cipher_null") ? 1 : 0;
-}
-
/*
* Keyfile - is standard input treated as a binary file (no EOL handling).
*/
From 03cc8a9ce4c1e04283eb0e0da658aa4509e74949 Mon Sep 17 00:00:00 2001
From: Ondrej Kozina <okozina@redhat.com>
Date: Wed, 10 Feb 2021 17:50:49 +0100
Subject: [PATCH 3/9] Fix broken detection of null cipher in LUKS2.
This bug enabled to create LUKS2 keyslots encrypted by
cipher_null when explicitely requested by user. LUKS2
was never meant to allow keyslot encryption with
cipher_null. cipher_null is meant for debug purposes
only as a segment cipher.
---
lib/luks2/luks2_keyslot.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/luks2/luks2_keyslot.c b/lib/luks2/luks2_keyslot.c
index ed51e24..414189c 100644
--- a/lib/luks2/luks2_keyslot.c
+++ b/lib/luks2/luks2_keyslot.c
@@ -155,7 +155,7 @@ int LUKS2_keyslot_cipher_incompatible(struct crypt_device *cd, const char *ciphe
{
char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
- if (!cipher_spec || !strcmp(cipher_spec, "null") || !strcmp(cipher_spec, "cipher_null"))
+ if (!cipher_spec || crypt_is_cipher_null(cipher_spec))
return 1;
if (crypt_parse_name_and_mode(cipher_spec, cipher, NULL, cipher_mode) < 0)
--
1.8.3.1
diff -rupN cryptsetup-2.3.3.orig/lib/luks2/luks2_token.c cryptsetup-2.3.3/lib/luks2/luks2_token.c
--- cryptsetup-2.3.3.orig/lib/luks2/luks2_token.c 2021-02-17 17:59:35.532320163 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_token.c 2021-02-17 18:01:49.925185354 +0100
@@ -383,6 +383,7 @@ int LUKS2_token_open_and_activate(struct
uint32_t flags,
void *usrptr)
{
+ bool use_keyring;
int keyslot, r;
char *buffer;
size_t buffer_len;
@@ -404,7 +405,13 @@ int LUKS2_token_open_and_activate(struct
keyslot = r;
- if ((name || (flags & CRYPT_ACTIVATE_KEYRING_KEY)) && crypt_use_keyring_for_vk(cd)) {
+ if (!crypt_use_keyring_for_vk(cd))
+ use_keyring = false;
+ else
+ use_keyring = ((name && !crypt_is_cipher_null(crypt_get_cipher(cd))) ||
+ (flags & CRYPT_ACTIVATE_KEYRING_KEY));
+
+ if (use_keyring) {
if (!(r = LUKS2_volume_key_load_in_keyring_by_keyslot(cd, hdr, vk, keyslot)))
flags |= CRYPT_ACTIVATE_KEYRING_KEY;
}
diff -rupN cryptsetup-2.3.3.orig/lib/setup.c cryptsetup-2.3.3/lib/setup.c
--- cryptsetup-2.3.3.orig/lib/setup.c 2021-02-17 17:59:35.529320166 +0100
+++ cryptsetup-2.3.3/lib/setup.c 2021-02-17 18:00:03.676291932 +0100
@@ -3879,6 +3879,7 @@ static int _open_and_activate(struct cry
size_t passphrase_size,
uint32_t flags)
{
+ bool use_keyring;
int r;
struct volume_key *vk = NULL;
@@ -3890,8 +3891,13 @@ static int _open_and_activate(struct cry
return r;
keyslot = r;
- if ((name || (flags & CRYPT_ACTIVATE_KEYRING_KEY)) &&
- crypt_use_keyring_for_vk(cd)) {
+ if (!crypt_use_keyring_for_vk(cd))
+ use_keyring = false;
+ else
+ use_keyring = ((name && !crypt_is_cipher_null(crypt_get_cipher(cd))) ||
+ (flags & CRYPT_ACTIVATE_KEYRING_KEY));
+
+ if (use_keyring) {
r = LUKS2_volume_key_load_in_keyring_by_keyslot(cd,
&cd->u.luks2.hdr, vk, keyslot);
if (r < 0)
@@ -4269,6 +4275,7 @@ int crypt_activate_by_volume_key(struct
size_t volume_key_size,
uint32_t flags)
{
+ bool use_keyring;
struct volume_key *vk = NULL;
int r;
@@ -4344,8 +4351,12 @@ int crypt_activate_by_volume_key(struct
if (r > 0)
r = 0;
- if (!r && (name || (flags & CRYPT_ACTIVATE_KEYRING_KEY)) &&
- crypt_use_keyring_for_vk(cd)) {
+ if (!crypt_use_keyring_for_vk(cd))
+ use_keyring = false;
+ else
+ use_keyring = (name && !crypt_is_cipher_null(crypt_get_cipher(cd))) || (flags & CRYPT_ACTIVATE_KEYRING_KEY);
+
+ if (!r && use_keyring) {
r = LUKS2_key_description_by_segment(cd,
&cd->u.luks2.hdr, vk, CRYPT_DEFAULT_SEGMENT);
if (!r)
From ed2117c72417d85c7b2f20d5859ca558eaf61c62 Mon Sep 17 00:00:00 2001
From: Ondrej Kozina <okozina@redhat.com>
Date: Thu, 11 Feb 2021 11:43:10 +0100
Subject: [PATCH 5/9] Fix device comparison for dm-crypt with cipher_null.
Do not compare volume keys if segment uses cipher_null.
The key is ignored by lower layer (internal libdevmapper)
anyway.
---
lib/setup.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/lib/setup.c b/lib/setup.c
index ffd9b7b..7286e10 100644
--- a/lib/setup.c
+++ b/lib/setup.c
@@ -2380,11 +2380,6 @@ static int _compare_crypt_devices(struct crypt_device *cd,
if (!src->u.crypt.vk || !tgt->u.crypt.vk)
return -EINVAL;
- 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;
- }
-
/* CIPHER checks */
if (!src->u.crypt.cipher || !tgt->u.crypt.cipher)
return -EINVAL;
@@ -2392,6 +2387,14 @@ static int _compare_crypt_devices(struct crypt_device *cd,
log_dbg(cd, "Cipher specs do not match.");
return -EINVAL;
}
+
+ 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;
+ }
+
if (crypt_strcmp(src->u.crypt.integrity, tgt->u.crypt.integrity)) {
log_dbg(cd, "Integrity parameters do not match.");
return -EINVAL;
--
1.8.3.1
From 01f896711ed54bff7c1ccf944d2295929af7c75c Mon Sep 17 00:00:00 2001
From: Ondrej Kozina <okozina@redhat.com>
Date: Thu, 11 Feb 2021 12:17:02 +0100
Subject: [PATCH 6/9] Replace bogus cipher_null keyslots before reencryption.
By mistake LUKS2 allowed keyslots 'not-so-encrypted' by
cipher_null (only explicitly requested by --cipher or
--keyslot-cipher parameters). If we encounter
such old key during reencryption let's replace the cipher
for new keyslot with default LUKS2 keyslot cipher.
---
src/cryptsetup.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/cryptsetup.c b/src/cryptsetup.c
index 957c24e..5e22286 100644
--- a/src/cryptsetup.c
+++ b/src/cryptsetup.c
@@ -1091,6 +1091,12 @@ static int set_keyslot_params(struct crypt_device *cd, int keyslot)
if (!cipher)
return -EINVAL;
+ if (crypt_is_cipher_null(cipher)) {
+ log_dbg("Keyslot %d uses cipher_null. Replacing with default encryption in new keyslot.", keyslot);
+ cipher = DEFAULT_LUKS2_KEYSLOT_CIPHER;
+ key_size = DEFAULT_LUKS2_KEYSLOT_KEYBITS / 8;
+ }
+
if (crypt_keyslot_set_encryption(cd, cipher, key_size))
return -EINVAL;
--
1.8.3.1
diff -rupN cryptsetup-2.3.3.orig/lib/luks2/luks2_reencrypt.c cryptsetup-2.3.3/lib/luks2/luks2_reencrypt.c
--- cryptsetup-2.3.3.orig/lib/luks2/luks2_reencrypt.c 2021-02-17 18:03:49.547065362 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_reencrypt.c 2021-02-17 18:09:43.610710202 +0100
@@ -2238,7 +2238,7 @@ static int reencrypt_verify_and_upload_k
if (LUKS2_digest_verify_by_digest(cd, hdr, digest_new, vk) != digest_new)
return -EINVAL;
- if (crypt_use_keyring_for_vk(cd) &&
+ if (crypt_use_keyring_for_vk(cd) && !crypt_is_cipher_null(reencrypt_segment_cipher_new(hdr)) &&
(r = LUKS2_volume_key_load_in_keyring_by_digest(cd, hdr, vk, crypt_volume_key_get_id(vk))))
return r;
}
@@ -2254,7 +2254,7 @@ static int reencrypt_verify_and_upload_k
r = -EINVAL;
goto err;
}
- if (crypt_use_keyring_for_vk(cd) &&
+ if (crypt_use_keyring_for_vk(cd) && !crypt_is_cipher_null(reencrypt_segment_cipher_old(hdr)) &&
(r = LUKS2_volume_key_load_in_keyring_by_digest(cd, hdr, vk, crypt_volume_key_get_id(vk))))
goto err;
}
@@ -2664,6 +2664,7 @@ static int reencrypt_load_by_passphrase(
struct luks2_hdr *hdr;
struct crypt_lock_handle *reencrypt_lock;
struct luks2_reenc_context *rh;
+ const struct volume_key *vk;
struct crypt_dm_active_device dmd_target, dmd_source = {
.uuid = crypt_get_uuid(cd),
.flags = CRYPT_ACTIVATE_SHARED /* turn off exclusive open checks */
@@ -2730,6 +2731,19 @@ static int reencrypt_load_by_passphrase(
goto err;
flags = dmd_target.flags;
+ /*
+ * By default reencryption code aims to retain flags from existing dm device.
+ * The keyring activation flag can not be inherited if original cipher is null.
+ *
+ * In this case override the flag based on decision made in reencrypt_verify_and_upload_keys
+ * above. The code checks if new VK is eligible for keyring.
+ */
+ vk = crypt_volume_key_by_id(*vks, LUKS2_reencrypt_digest_new(hdr));
+ if (vk && vk->key_description && crypt_is_cipher_null(reencrypt_segment_cipher_old(hdr))) {
+ flags |= CRYPT_ACTIVATE_KEYRING_KEY;
+ dmd_source.flags |= CRYPT_ACTIVATE_KEYRING_KEY;
+ }
+
r = LUKS2_assembly_multisegment_dmd(cd, hdr, *vks, LUKS2_get_segments_jobj(hdr), &dmd_source);
if (!r) {
r = crypt_compare_dm_devices(cd, &dmd_source, &dmd_target);
diff -rupN cryptsetup-2.3.3.orig/src/cryptsetup.c cryptsetup-2.3.3/src/cryptsetup.c
--- cryptsetup-2.3.3.orig/src/cryptsetup.c 2021-02-17 18:12:12.162561190 +0100
+++ cryptsetup-2.3.3/src/cryptsetup.c 2021-02-17 18:19:04.842147234 +0100
@@ -3142,6 +3142,11 @@ static int action_reencrypt_luks2(struct
_set_reencryption_flags(&params.flags);
+ if (!opt_cipher && crypt_is_cipher_null(crypt_get_cipher(cd))) {
+ log_std(_("Switching data encryption cipher to %s.\n"), DEFAULT_CIPHER(LUKS1));
+ opt_cipher = DEFAULT_CIPHER(LUKS1);
+ }
+
if (!opt_cipher) {
strncpy(cipher, crypt_get_cipher(cd), MAX_CIPHER_LEN - 1);
strncpy(mode, crypt_get_cipher_mode(cd), MAX_CIPHER_LEN - 1);
diff -rupN cryptsetup-2.3.3.orig/tests/luks2-reencryption-test cryptsetup-2.3.3/tests/luks2-reencryption-test
--- cryptsetup-2.3.3.orig/tests/luks2-reencryption-test 2021-02-17 18:25:01.393788684 +0100
+++ cryptsetup-2.3.3/tests/luks2-reencryption-test 2021-02-17 18:26:00.864726663 +0100
@@ -1388,9 +1388,9 @@ $CRYPTSETUP close $DEV_NAME
echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 -s 128 -c cipher_null-ecb --offset 8192 $FAST_PBKDF2 $DEV || fail
$CRYPTSETUP convert -q --type luks2 $DEV || fail
wipe $PWD1
-echo $PWD1 | $CRYPTSETUP reencrypt $DEV -c aes-xts-plain64 -q $FAST_PBKDF_ARGON || fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON >/dev/null || fail
check_hash $PWD1 $HASH1
-# both keyslot and segment cipher must not be null
+# both keyslot and segment cipher must not be null after reencryption with default params
$CRYPTSETUP luksDump $DEV | grep -q "cipher_null" && fail
remove_mapping
From 030d50f6baff62466c611c868d860c6c3a3efef9 Mon Sep 17 00:00:00 2001
From: Ondrej Kozina <okozina@redhat.com>
Date: Wed, 17 Feb 2021 15:00:19 +0100
Subject: [PATCH] Fix reencryption test on systems w/o keyring.
---
tests/luks2-reencryption-test | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/tests/luks2-reencryption-test b/tests/luks2-reencryption-test
index 51b5473..6e6b381 100755
--- a/tests/luks2-reencryption-test
+++ b/tests/luks2-reencryption-test
@@ -654,6 +654,18 @@ function reencrypt_online_fixed_size() {
fi
}
+function setup_luks2_env() {
+ echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 $FAST_PBKDF_ARGON $DEV || fail
+ echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+ HAVE_KEYRING=$($CRYPTSETUP status $DEV_NAME | grep "key location: keyring")
+ if [ -n "$HAVE_KEYRING" ]; then
+ HAVE_KEYRING=1
+ else
+ HAVE_KEYRING=0
+ fi
+ $CRYPTSETUP close $DEV_NAME || fail
+}
+
function valgrind_setup()
{
which valgrind >/dev/null 2>&1 || fail "Cannot find valgrind."
@@ -705,9 +717,11 @@ HASH7=18a393d1a505e22ccf3e29effe3005ea8627e4c36b7cca0e53f58121f49b67e1
# 60 MiBs of zeroes
HASH8=cf5ac69ca412f9b3b1a8b8de27d368c5c05ed4b1b6aa40e6c38d9cbf23711342
+prepare dev_size_mb=32
+setup_luks2_env
+
echo "[1] Reencryption"
echo -n "[512 sector]"
-prepare dev_size_mb=32
echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 -c aes-cbc-essiv:sha256 --offset 8192 $FAST_PBKDF_ARGON $DEV || fail
wipe $PWD1
check_hash $PWD1 $HASH1
@@ -1412,7 +1426,9 @@ wipe $PWD1
echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME
echo $PWD1 | $CRYPTSETUP reencrypt $DEV -c aes-xts-plain64 -q $FAST_PBKDF_ARGON || fail
check_hash_dev /dev/mapper/$DEV_NAME $HASH1
-$CRYPTSETUP status $DEV_NAME | grep -q "key location: keyring" || fail
+if [ $HAVE_KEYRING -gt 0 ]; then
+ $CRYPTSETUP status $DEV_NAME | grep -q "key location: keyring" || fail
+fi
$CRYPTSETUP close $DEV_NAME
# simulate LUKS2 device with cipher_null in both keyslot and segment (it can be created only by up conversion from LUKS1)
--
1.8.3.1
diff -rupN cryptsetup-2.3.3.orig/src/cryptsetup.c cryptsetup-2.3.3/src/cryptsetup.c
--- cryptsetup-2.3.3.orig/src/cryptsetup.c 2021-02-18 12:37:44.903909498 +0100
+++ cryptsetup-2.3.3/src/cryptsetup.c 2021-02-18 12:45:49.208492236 +0100
@@ -1196,6 +1196,21 @@ static int strcmp_or_null(const char *st
return !str ? 0 : strcmp(str, expected);
}
+static int get_adjusted_key_size(const char *cipher_mode, uint32_t default_size_bits, int integrity_keysize)
+{
+ int keysize_bits = opt_key_size;
+
+#ifdef ENABLE_LUKS_ADJUST_XTS_KEYSIZE
+ if (!opt_key_size && !strncmp(cipher_mode, "xts-", 4)) {
+ if (default_size_bits == 128)
+ keysize_bits = 256;
+ else if (default_size_bits == 256)
+ keysize_bits = 512;
+ }
+#endif
+ return (keysize_bits ?: default_size_bits) / 8 + integrity_keysize;
+}
+
static int _luksFormat(struct crypt_device **r_cd, char **r_password, size_t *r_passwordLen)
{
int r = -EINVAL, keysize, integrity_keysize = 0, fd, created = 0;
@@ -1328,15 +1343,7 @@ static int _luksFormat(struct crypt_devi
goto out;
}
-#ifdef ENABLE_LUKS_ADJUST_XTS_KEYSIZE
- if (!opt_key_size && !strncmp(cipher_mode, "xts-", 4)) {
- if (DEFAULT_LUKS1_KEYBITS == 128)
- opt_key_size = 256;
- else if (DEFAULT_LUKS1_KEYBITS == 256)
- opt_key_size = 512;
- }
-#endif
- keysize = (opt_key_size ?: DEFAULT_LUKS1_KEYBITS) / 8 + integrity_keysize;
+ keysize = get_adjusted_key_size(cipher_mode, DEFAULT_LUKS1_KEYBITS, integrity_keysize);
if (opt_random)
crypt_set_rng_type(cd, CRYPT_RNG_RANDOM);
@@ -3163,10 +3170,8 @@ static int action_reencrypt_luks2(struct
if (r)
return r;
- if (opt_key_size)
- key_size = opt_key_size / 8;
- else if (opt_cipher)
- key_size = DEFAULT_LUKS1_KEYBITS / 8;
+ if (opt_key_size || opt_cipher)
+ key_size = get_adjusted_key_size(mode, DEFAULT_LUKS1_KEYBITS, 0);
else
key_size = crypt_get_volume_key_size(cd);
diff -rupN cryptsetup-2.3.3.orig/tests/luks2-reencryption-test cryptsetup-2.3.3/tests/luks2-reencryption-test
--- cryptsetup-2.3.3.orig/tests/luks2-reencryption-test 2021-02-18 12:37:44.916909486 +0100
+++ cryptsetup-2.3.3/tests/luks2-reencryption-test 2021-02-18 12:39:33.589815857 +0100
@@ -648,7 +648,7 @@ function reencrypt_online_fixed_size() {
}
function setup_luks2_env() {
- echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 $FAST_PBKDF_ARGON $DEV || fail
+ echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 -c aes-xts-plain64 $FAST_PBKDF_ARGON $DEV || fail
echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
HAVE_KEYRING=$($CRYPTSETUP status $DEV_NAME | grep "key location: keyring")
if [ -n "$HAVE_KEYRING" ]; then
@@ -656,6 +656,8 @@ function setup_luks2_env() {
else
HAVE_KEYRING=0
fi
+ DEF_XTS_KEY=$($CRYPTSETUP status $DEV_NAME | grep "keysize:" | sed 's/\( keysize: \)\([0-9]\+\)\(.*\)/\2/')
+ [ -n "$DEF_XTS_KEY" ] || fail "Failed to parse xts mode key size."
$CRYPTSETUP close $DEV_NAME || fail
}
@@ -730,6 +732,8 @@ check_hash $PWD1 $HASH1
echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -c aes-xts-plain64 --init-only $FAST_PBKDF_ARGON || fail
echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
echo $PWD1 | $CRYPTSETUP reencrypt --active-name /dev/mapper/$DEV_NAME --resilience none -q || fail
+XTS_KEY=$($CRYPTSETUP status $DEV_NAME | grep "keysize:" | sed 's/\( keysize: \)\([0-9]\+\)\(.*\)/\2/')
+[ "$XTS_KEY" -eq "$DEF_XTS_KEY" ] || fail "xts mode has wrong key size after reencryption ($XTS_KEY != expected $DEF_XTS_KEY)"
echo $PWD1 | $CRYPTSETUP close $DEV_NAME || fail
echo -n "[OK][4096 sector]"
prepare sector_size=4096 dev_size_mb=32
diff -rupN cryptsetup-2.3.3.orig/lib/libdevmapper.c cryptsetup-2.3.3/lib/libdevmapper.c
--- cryptsetup-2.3.3.orig/lib/libdevmapper.c 2021-02-18 16:21:00.863470374 +0100
+++ cryptsetup-2.3.3/lib/libdevmapper.c 2021-02-18 16:22:36.330393562 +0100
@@ -639,11 +639,13 @@ static char *get_dm_crypt_params(const s
if (!strncmp(cipher_dm, "cipher_null-", 12))
null_cipher = 1;
- if (flags & CRYPT_ACTIVATE_KEYRING_KEY) {
+ if (null_cipher)
+ hexkey = crypt_safe_alloc(2);
+ else if (flags & CRYPT_ACTIVATE_KEYRING_KEY) {
keystr_len = strlen(tgt->u.crypt.vk->key_description) + int_log10(tgt->u.crypt.vk->keylength) + 10;
hexkey = crypt_safe_alloc(keystr_len);
} else
- hexkey = crypt_safe_alloc(null_cipher ? 2 : (tgt->u.crypt.vk->keylength * 2 + 1));
+ hexkey = crypt_safe_alloc(tgt->u.crypt.vk->keylength * 2 + 1);
if (!hexkey)
return NULL;
From 284a49443e2a833e33714f9fa0f03b8e0233d68d Mon Sep 17 00:00:00 2001
From: Ondrej Kozina <okozina@redhat.com>
Date: Thu, 18 Feb 2021 15:01:01 +0100
Subject: [PATCH 3/3] Extend LUKS2 reencryption tests w/ cipher_null.
---
tests/luks2-reencryption-test | 106 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 104 insertions(+), 2 deletions(-)
diff --git a/tests/luks2-reencryption-test b/tests/luks2-reencryption-test
index 9bdf60a..05c2151 100755
--- a/tests/luks2-reencryption-test
+++ b/tests/luks2-reencryption-test
@@ -297,7 +297,7 @@ function reencrypt_recover() { # $1 sector size, $2 resilience, $3 digest, [$4 h
test -z "$4" || _hdr="--header $4"
error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
- echo $PWD1 | $CRYPTSETUP reencrypt $DEV $_hdr --hotzone-size 1M --resilience $2 --sector-size $1 -q $FAST_PBKDF_ARGON 2>/dev/null && fail
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV $_hdr --hotzone-size 1M --resilience $2 --sector-size $1 -q $FAST_PBKDF_ARGON >/dev/null 2>&1 && fail
fix_writes $OVRDEV $OLD_DEV
echo $PWD1 | $CRYPTSETUP -q repair $DEV $_hdr || fail
@@ -318,7 +318,7 @@ function reencrypt_recover_online() { # $1 sector size, $2 resilience, $3 digest
echo $PWD1 | $CRYPTSETUP open $DEV $_hdr $DEV_NAME || fail
error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
- echo $PWD1 | $CRYPTSETUP reencrypt --active-name $DEV_NAME $_hdr --hotzone-size 1M --resilience $2 --sector-size $1 -q $FAST_PBKDF_ARGON 2>/dev/null && fail
+ echo $PWD1 | $CRYPTSETUP reencrypt --active-name $DEV_NAME $_hdr --hotzone-size 1M --resilience $2 --sector-size $1 -q $FAST_PBKDF_ARGON >/dev/null 2>&1 && fail
$CRYPTSETUP status $DEV_NAME $_hdr | grep -q "reencryption: in-progress" || fail
$CRYPTSETUP close $DEV_NAME || fail
fix_writes $OVRDEV $OLD_DEV
@@ -1444,5 +1444,107 @@ check_hash $PWD1 $HASH1
# both keyslot and segment cipher must not be null after reencryption with default params
$CRYPTSETUP luksDump $DEV | grep -q "cipher_null" && fail
+# multistep reencryption with initial cipher_null
+preparebig 64
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 $DEV -c null --offset 16384 -q $FAST_PBKDF_ARGON || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME
+wipe_dev /dev/mapper/$DEV_NAME
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --hotzone-size 1M --resilience none -q $FAST_PBKDF_ARGON >/dev/null || fail
+$CRYPTSETUP close $DEV_NAME
+check_hash $PWD1 $HASH5
+
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 $DEV -c null --offset 16384 -q $FAST_PBKDF_ARGON || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --hotzone-size 1M --resilience none -q $FAST_PBKDF_ARGON >/dev/null || fail
+check_hash $PWD1 $HASH5
+
+echo "[25] Reencryption recovery with cipher_null"
+# (check opt-io size optimization in reencryption code does not affect recovery)
+# device with opt-io size 32k
+prepare_linear_dev 32 opt_blks=64 $OPT_XFERLEN_EXP
+OFFSET=8192
+
+echo "sector size 512->512"
+
+get_error_offsets 32 $OFFSET
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+check_hash $PWD1 $HASH1
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+reencrypt_recover 512 checksum $HASH1
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+reencrypt_recover 512 journal $HASH1
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 512->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ check_hash $PWD1 $HASH1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover 4096 checksum $HASH1
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ check_hash $PWD1 $HASH1
+ reencrypt_recover 4096 journal $HASH1
+
+ echo "sector size 4096->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 4096 -c aes-cbc-essiv:sha256 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ check_hash $PWD1 $HASH1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover 4096 checksum $HASH1
+ reencrypt_recover 4096 journal $HASH1
+fi
+
+echo "[26] Reencryption recovery with cipher_null (online i/o error)"
+
+echo "sector size 512->512"
+
+get_error_offsets 32 $OFFSET
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 -c null --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+check_hash $PWD1 $HASH1
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+reencrypt_recover_online 512 checksum $HASH1
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 -c null --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+reencrypt_recover_online 512 journal $HASH1
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 512->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ check_hash $PWD1 $HASH1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover_online 4096 checksum $HASH1
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ check_hash $PWD1 $HASH1
+ reencrypt_recover_online 4096 journal $HASH1
+
+ echo "sector size 4096->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 4096 -c aes-cbc-essiv:sha256 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ check_hash $PWD1 $HASH1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover_online 4096 checksum $HASH1
+ reencrypt_recover_online 4096 journal $HASH1
+fi
+
remove_mapping
exit 0
--
1.8.3.1

View File

@ -5,7 +5,7 @@ Obsoletes: cryptsetup-python3
Summary: A utility for setting up encrypted disks Summary: A utility for setting up encrypted disks
Name: cryptsetup Name: cryptsetup
Version: 2.3.3 Version: 2.3.3
Release: 1%{?dist} Release: 4%{?dist}
License: GPLv2+ and LGPLv2+ License: GPLv2+ and LGPLv2+
Group: Applications/System Group: Applications/System
URL: https://gitlab.com/cryptsetup/cryptsetup URL: https://gitlab.com/cryptsetup/cryptsetup
@ -23,6 +23,9 @@ Source0: https://www.kernel.org/pub/linux/utils/cryptsetup/v2.0/cryptsetup-%{ups
Patch0: %{name}-add-system-library-paths.patch Patch0: %{name}-add-system-library-paths.patch
# Remove the patch when (if ever) osci infrastructure gets stable enough # Remove the patch when (if ever) osci infrastructure gets stable enough
Patch1: %{name}-disable-verity-compat-test.patch Patch1: %{name}-disable-verity-compat-test.patch
Patch2: %{name}-2.3.4-luks2-validation-32bit-fix.patch
Patch3: %{name}-2.3.4-fix-crypto-backend-to-properly-handle-ECB-mode.patch
Patch4: %{name}-2.3.5-fix-reencryption-cipher_null.patch
%description %description
The cryptsetup package contains a utility for setting up The cryptsetup package contains a utility for setting up
@ -79,6 +82,9 @@ can be used for offline reencryption of disk in situ.
%prep %prep
%setup -q -n cryptsetup-%{upstream_version} %setup -q -n cryptsetup-%{upstream_version}
%patch1 -p1 %patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch0 -p1 %patch0 -p1
chmod -x misc/dracut_90reencrypt/* chmod -x misc/dracut_90reencrypt/*
@ -138,6 +144,20 @@ rm -rf %{buildroot}/%{_libdir}/*.la
%clean %clean
%changelog %changelog
* Wed Feb 17 2021 Ondrej Kozina <okozina@redhat.com> - 2.3.3-4
- patch: Fix reencryption for custom devices with data segments
set to use cipher_null.
- Resolves: #1927409
* Wed Feb 03 2021 Ondrej Kozina <okozina@redhat.com> - 2.3.3-3
- patch: Fix crypto backend to properly handle ECB mode.
- Resolves: #1859091
* Thu Aug 27 2020 Ondrej Kozina <okozina@redhat.com> - 2.3.3-2
- patch: Fix possible memory corruption in LUKS2 validation
code in 32bit library.
- Resolves: #1872294
* Thu May 28 2020 Ondrej Kozina <okozina@redhat.com> - 2.3.3-1 * Thu May 28 2020 Ondrej Kozina <okozina@redhat.com> - 2.3.3-1
- Update to cryptsetup 2.3.3 - Update to cryptsetup 2.3.3
- Resolves: #1796826 #1743891 #1785748 - Resolves: #1796826 #1743891 #1785748