import cryptsetup-2.3.7-2.el8

This commit is contained in:
CentOS Sources 2022-05-10 03:19:28 -04:00 committed by Stepan Oksanichenko
parent e6a2c875ba
commit cd2c9eda52
26 changed files with 526 additions and 3529 deletions

View File

@ -1 +1 @@
d847934311112c7220435b94b44c2b2bb3dca0e1 SOURCES/cryptsetup-2.3.3.tar.xz
3ce643e82d52b0c0282c2754c4bfa8c15c1f567e SOURCES/cryptsetup-2.3.7.tar.xz

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/cryptsetup-2.3.3.tar.xz
SOURCES/cryptsetup-2.3.7.tar.xz

View File

@ -1,48 +0,0 @@
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

@ -1,341 +0,0 @@
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

@ -1,769 +0,0 @@
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

@ -1,206 +0,0 @@
diff -rupN cryptsetup-2.3.3.old/lib/libcryptsetup.h cryptsetup-2.3.3/lib/libcryptsetup.h
--- cryptsetup-2.3.3.old/lib/libcryptsetup.h 2022-01-18 09:15:34.523672069 +0100
+++ cryptsetup-2.3.3/lib/libcryptsetup.h 2022-01-18 09:16:43.251047191 +0100
@@ -2194,6 +2194,8 @@ int crypt_activate_by_token(struct crypt
#define CRYPT_REENCRYPT_RESUME_ONLY (1 << 2)
/** Run reencryption recovery only. (in) */
#define CRYPT_REENCRYPT_RECOVERY (1 << 3)
+/** Reencryption requires metadata protection. (in/out) */
+#define CRYPT_REENCRYPT_REPAIR_NEEDED (1 << 4)
/**
* Reencryption direction
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2.h cryptsetup-2.3.3/lib/luks2/luks2.h
--- cryptsetup-2.3.3.old/lib/luks2/luks2.h 2022-01-18 09:15:34.520672053 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2.h 2022-01-18 09:16:43.252047196 +0100
@@ -561,6 +561,8 @@ int LUKS2_config_set_flags(struct crypt_
int LUKS2_config_get_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t *reqs);
int LUKS2_config_set_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t reqs, bool commit);
+int LUKS2_config_get_reencrypt_version(struct luks2_hdr *hdr, uint32_t *version);
+
int LUKS2_unmet_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t reqs_mask, int quiet);
int LUKS2_key_description_by_segment(struct crypt_device *cd,
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_json_metadata.c cryptsetup-2.3.3/lib/luks2/luks2_json_metadata.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_json_metadata.c 2022-01-18 09:15:34.521672058 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_json_metadata.c 2022-01-18 09:16:43.253047201 +0100
@@ -1469,6 +1469,49 @@ static const struct requirement_flag *ge
return &unknown_requirement_flag;
}
+int LUKS2_config_get_reencrypt_version(struct luks2_hdr *hdr, uint32_t *version)
+{
+ json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
+ int i, len;
+ const struct requirement_flag *req;
+
+ assert(hdr && version);
+ if (!hdr || !version)
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(jobj_config, "requirements", &jobj_requirements))
+ return -ENOENT;
+
+ if (!json_object_object_get_ex(jobj_requirements, "mandatory", &jobj_mandatory))
+ return -ENOENT;
+
+ len = (int) json_object_array_length(jobj_mandatory);
+ if (len <= 0)
+ return -ENOENT;
+
+ for (i = 0; i < len; i++) {
+ jobj = json_object_array_get_idx(jobj_mandatory, i);
+
+ /* search for requirements prefixed with "online-reencrypt" */
+ if (strncmp(json_object_get_string(jobj), "online-reencrypt", 16))
+ continue;
+
+ /* check current library is aware of the requirement */
+ req = get_requirement_by_name(json_object_get_string(jobj));
+ if (req->flag == (uint32_t)CRYPT_REQUIREMENT_UNKNOWN)
+ continue;
+
+ *version = req->version;
+
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
static const struct requirement_flag *stored_requirement_name_by_id(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t req_id)
{
json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_reencrypt.c cryptsetup-2.3.3/lib/luks2/luks2_reencrypt.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_reencrypt.c 2022-01-18 09:15:34.520672053 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_reencrypt.c 2022-01-18 09:25:26.870913236 +0100
@@ -2888,6 +2888,85 @@ static int reencrypt_recovery_by_passphr
return r;
}
+static int reencrypt_repair_by_passphrase(
+ struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot_old,
+ int keyslot_new,
+ const char *passphrase,
+ size_t passphrase_size)
+{
+ int r;
+ struct crypt_lock_handle *reencrypt_lock;
+ struct luks2_reenc_context *rh;
+ crypt_reencrypt_info ri;
+ struct volume_key *vks = NULL;
+
+ log_dbg(cd, "Loading LUKS2 reencryption context for metadata repair.");
+
+ rh = crypt_get_reenc_context(cd);
+ if (rh) {
+ LUKS2_reenc_context_free(cd, rh);
+ crypt_set_reenc_context(cd, NULL);
+ rh = NULL;
+ }
+
+ ri = LUKS2_reenc_status(hdr);
+ if (ri == CRYPT_REENCRYPT_INVALID)
+ return -EINVAL;
+
+ if (ri < CRYPT_REENCRYPT_CLEAN) {
+ log_err(cd, _("Device is not in reencryption."));
+ return -EINVAL;
+ }
+
+ r = crypt_reencrypt_lock(cd, &reencrypt_lock);
+ if (r < 0) {
+ if (r == -EBUSY)
+ log_err(cd, _("Reencryption process is already running."));
+ else
+ log_err(cd, _("Failed to acquire reencryption lock."));
+ return r;
+ }
+
+ /* With reencryption lock held, reload device context and verify metadata state */
+ r = crypt_load(cd, CRYPT_LUKS2, NULL);
+ if (r)
+ goto out;
+
+ ri = LUKS2_reenc_status(hdr);
+ if (ri == CRYPT_REENCRYPT_INVALID) {
+ r = -EINVAL;
+ goto out;
+ }
+ if (ri == CRYPT_REENCRYPT_NONE) {
+ r = 0;
+ goto out;
+ }
+
+ r = LUKS2_keyslot_open_all_segments(cd, keyslot_old, keyslot_new, passphrase, passphrase_size, &vks);
+ if (r < 0)
+ goto out;
+
+ r = LUKS2_keyslot_reencrypt_digest_create(cd, hdr, vks);
+ crypt_free_volume_key(vks);
+ vks = NULL;
+ if (r < 0)
+ goto out;
+
+ /* removes online-reencrypt flag v1 */
+ if ((r = reencrypt_update_flag(cd, 0, false)))
+ goto out;
+
+ /* adds online-reencrypt flag v2 and commits metadata */
+ r = reencrypt_update_flag(cd, 1, true);
+out:
+ crypt_reencrypt_unlock(cd, reencrypt_lock);
+ crypt_free_volume_key(vks);
+ return r;
+
+}
+
static int reencrypt_init_by_passphrase(struct crypt_device *cd,
const char *name,
const char *passphrase,
@@ -2904,6 +2983,10 @@ static int reencrypt_init_by_passphrase(
uint32_t flags = params ? params->flags : 0;
struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
+ /* short-circuit in reencryption metadata update and finish immediately. */
+ if (flags & CRYPT_REENCRYPT_REPAIR_NEEDED)
+ return reencrypt_repair_by_passphrase(cd, hdr, keyslot_old, keyslot_new, passphrase, passphrase_size);
+
/* short-circuit in recovery and finish immediately. */
if (flags & CRYPT_REENCRYPT_RECOVERY)
return reencrypt_recovery_by_passphrase(cd, hdr, keyslot_old, keyslot_new, passphrase, passphrase_size);
@@ -3459,12 +3542,28 @@ err:
crypt_reencrypt_info LUKS2_reencrypt_status(struct crypt_device *cd, struct crypt_params_reencrypt *params)
{
crypt_reencrypt_info ri;
+ int digest;
+ uint32_t version;
struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
ri = LUKS2_reenc_status(hdr);
if (ri == CRYPT_REENCRYPT_NONE || ri == CRYPT_REENCRYPT_INVALID || !params)
return ri;
+ digest = LUKS2_digest_by_keyslot(hdr, LUKS2_find_keyslot(hdr, "reencrypt"));
+ if (digest < 0 && digest != -ENOENT)
+ return CRYPT_REENCRYPT_INVALID;
+
+ /*
+ * In case there's an old "online-reencrypt" requirement or reencryption
+ * keyslot digest is missing inform caller reencryption metadata requires repair.
+ */
+ if (!LUKS2_config_get_reencrypt_version(hdr, &version) &&
+ (version < 2 || digest == -ENOENT)) {
+ params->flags |= CRYPT_REENCRYPT_REPAIR_NEEDED;
+ return ri;
+ }
+
params->mode = reencrypt_mode(hdr);
params->direction = reencrypt_direction(hdr);
params->resilience = reencrypt_resilience_type(hdr);

View File

@ -1,502 +0,0 @@
diff -rupN cryptsetup-2.3.3.old/tests/luks2-reencryption-mangle-test cryptsetup-2.3.3/tests/luks2-reencryption-mangle-test
--- cryptsetup-2.3.3.old/tests/luks2-reencryption-mangle-test 1970-01-01 01:00:00.000000000 +0100
+++ cryptsetup-2.3.3/tests/luks2-reencryption-mangle-test 2022-01-13 17:01:26.605785131 +0100
@@ -0,0 +1,470 @@
+#!/bin/bash
+
+PS4='$LINENO:'
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+CRYPTSETUP_RAW=$CRYPTSETUP
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+IMG=reenc-mangle-data
+IMG_HDR=$IMG.hdr
+IMG_JSON=$IMG.json
+KEY1=key1
+DEV_NAME=reenc3492834
+
+FAST_PBKDF2="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
+CS_PWPARAMS="--disable-keyring --key-file $KEY1"
+CS_PARAMS="-q --disable-locks $CS_PWPARAMS"
+JSON_MSIZE=16384
+
+function remove_mapping()
+{
+ [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME
+ rm -f $IMG $IMG_HDR $IMG_JSON $KEY1 >/dev/null 2>&1
+}
+
+function fail()
+{
+ local frame=0
+ [ -n "$1" ] && echo "$1"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ remove_mapping
+ exit 2
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ remove_mapping
+ exit 77
+}
+
+function bin_check()
+{
+ which $1 >/dev/null 2>&1 || skip "WARNING: test require $1 binary, test skipped."
+}
+
+function img_json_save()
+{
+ # FIXME: why --json-file cannot be used?
+ #$CRYPTSETUP luksDump --dump-json-metadata $IMG | jq -c -M | tr -d '\n' >$IMG_JSON
+ local LUKS2_JSON_SIZE=$(($JSON_MSIZE - 4096))
+ _dd if=$IMG count=$LUKS2_JSON_SIZE skip=4096 | jq -c -M | tr -d '\n' >$IMG_JSON
+}
+
+function img_json_dump()
+{
+ img_json_save
+ jq . $IMG_JSON
+}
+
+function img_hash_save()
+{
+ IMG_HASH=$(sha256sum $IMG | cut -d' ' -f 1)
+}
+
+function img_hash_unchanged()
+{
+ local IMG_HASH2=$(sha256sum $IMG | cut -d' ' -f 1)
+ [ "$IMG_HASH" != "$IMG_HASH2" ] && fail "Image changed!"
+}
+
+function img_prepare_raw() # $1 options
+{
+ remove_mapping
+
+ if [ ! -e $KEY1 ]; then
+ dd if=/dev/urandom of=$KEY1 count=1 bs=32 >/dev/null 2>&1
+ fi
+
+ truncate -s 32M $IMG || fail
+ $CRYPTSETUP luksFormat $FAST_PBKDF2 $CS_PARAMS --luks2-metadata-size $JSON_MSIZE $IMG $1 || fail
+}
+
+function img_prepare() # $1 options
+{
+ img_prepare_raw
+ # FIXME: resilience is not saved here (always none)?
+ $CRYPTSETUP reencrypt $IMG $CS_PARAMS -q --init-only --resilience none $1 >/dev/null 2>&1
+ [ $? -ne 0 ] && skip "Reencryption unsupported, test skipped."
+ img_json_save
+ img_hash_save
+}
+
+function _dd()
+{
+ dd $@ status=none conv=notrunc bs=1
+}
+
+# header mangle functions
+function img_update_json()
+{
+ local LUKS2_BIN1_OFFSET=448
+ local LUKS2_BIN2_OFFSET=$((LUKS2_BIN1_OFFSET + $JSON_MSIZE))
+ local LUKS2_JSON_SIZE=$(($JSON_MSIZE - 4096))
+
+ # if present jq script, mangle JSON
+ if [ -n "$1" ]; then
+ local JSON=$(cat $IMG_JSON)
+ echo $JSON | jq -M -c "$1" >$IMG_JSON || fail
+ local JSON=$(cat $IMG_JSON)
+ echo $JSON | tr -d '\n' >$IMG_JSON || fail
+ fi
+
+ # wipe JSON areas
+ _dd if=/dev/zero of=$IMG count=$LUKS2_JSON_SIZE seek=4096
+ _dd if=/dev/zero of=$IMG count=$LUKS2_JSON_SIZE seek=$(($JSON_MSIZE + 4096))
+
+ # write JSON data
+ _dd if=$IMG_JSON of=$IMG count=$LUKS2_JSON_SIZE seek=4096
+ _dd if=$IMG_JSON of=$IMG count=$LUKS2_JSON_SIZE seek=$(($JSON_MSIZE + 4096))
+
+ # erase sha256 checksums
+ _dd if=/dev/zero of=$IMG count=64 seek=$LUKS2_BIN1_OFFSET
+ _dd if=/dev/zero of=$IMG count=64 seek=$LUKS2_BIN2_OFFSET
+
+ # calculate sha256 and write chexksums
+ local SUM1_HEX=$(_dd if=$IMG count=$JSON_MSIZE | sha256sum | cut -d ' ' -f 1)
+ echo $SUM1_HEX | xxd -r -p | _dd of=$IMG seek=$LUKS2_BIN1_OFFSET count=64 || fail
+
+ local SUM2_HEX=$(_dd if=$IMG skip=$JSON_MSIZE count=$JSON_MSIZE | sha256sum | cut -d ' ' -f 1)
+ echo $SUM2_HEX | xxd -r -p | _dd of=$IMG seek=$LUKS2_BIN2_OFFSET count=64 || fail
+
+ img_hash_save
+}
+
+function img_check_ok()
+{
+ if [ $(id -u) == 0 ]; then
+ $CRYPTSETUP open $CS_PWPARAMS $IMG $DEV_NAME || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ fi
+
+ $CRYPTSETUP repair $IMG $CS_PARAMS || fail
+}
+
+function img_check_fail()
+{
+ if [ $(id -u) == 0 ]; then
+ $CRYPTSETUP open $CS_PWPARAMS $IMG $DEV_NAME 2>/dev/null && fail
+ fi
+
+ $CRYPTSETUP repair $IMG $CS_PARAMS 2>/dev/null && fail
+ img_hash_unchanged
+}
+
+function img_run_reenc_ok()
+{
+local EXPECT_TIMEOUT=5
+[ -n "$VALG" ] && EXPECT_TIMEOUT=60
+# For now, we cannot run reencryption in batch mode for non-block device. Just fake the terminal here.
+expect_run - >/dev/null <<EOF
+proc abort {} { send_error "Timeout. "; exit 2 }
+set timeout $EXPECT_TIMEOUT
+eval spawn $CRYPTSETUP_RAW reencrypt $IMG $CS_PWPARAMS --disable-locks --resilience none
+expect timeout abort "Are you sure? (Type 'yes' in capital letters):"
+send "YES\n"
+expect timeout abort eof
+exit
+EOF
+[ $? -eq 0 ] || fail "Expect script failed."
+}
+
+function valgrind_setup()
+{
+ bin_check valgrind
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+ CRYPTSETUP=valgrind_run
+ CRYPTSETUP_RAW="./valg.sh ${CRYPTSETUP_VALGRIND}"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+function expect_run()
+{
+ export INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}"
+ expect "$@"
+}
+
+bin_check jq
+bin_check sha256sum
+bin_check xxd
+bin_check expect
+
+export LANG=C
+
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+
+#while false; do
+
+echo "[1] Reencryption with old flag is rejected"
+img_prepare
+img_update_json '.config.requirements.mandatory = ["online-reencryptx"]'
+img_check_fail
+img_update_json '.config.requirements.mandatory = ["online-reencrypt-v2"]'
+img_check_ok
+img_run_reenc_ok
+img_check_ok
+
+# Simulate old reencryption with no digest
+img_prepare
+img_update_json 'del(.digests."2") | .config.requirements.mandatory = ["online-reencrypt"]'
+img_check_fail
+
+# This must fail for new releases
+echo "[2] Old reencryption in-progress (journal)"
+img_prepare
+img_update_json '
+ del(.digests."2") |
+ .keyslots."2".area.type = "journal" |
+ .segments = {
+ "0" : (.segments."0" +
+ {"size" : .keyslots."2".area.size} +
+ {"flags" : ["in-reencryption"]}),
+ "1" : (.segments."0" +
+ {"offset" : ((.segments."0".offset|tonumber) +
+ (.keyslots."2".area.size|tonumber))|tostring}),
+ "2" : .segments."1",
+ "3" : .segments."2"
+ } |
+ .digests."0".segments = ["1","2"] |
+ .digests."1".segments = ["0","3"] |
+ .config.requirements.mandatory = ["online-reencrypt"]'
+img_check_fail
+
+echo "[3] Old reencryption in-progress (checksum)"
+img_prepare
+img_update_json '
+ del(.digests."2") |
+ .keyslots."2".area.type = "checksum" |
+ .keyslots."2".area.hash = "sha256" |
+ .keyslots."2".area.sector_size = 4096 |
+ .segments = {
+ "0" : (.segments."0" +
+ {"size" : .keyslots."2".area.size} +
+ {"flags" : ["in-reencryption"]}),
+ "1" : (.segments."0" +
+ {"offset": ((.segments."0".offset|tonumber) +
+ (.keyslots."2".area.size|tonumber))|tostring}),
+ "2" : .segments."1",
+ "3" : .segments."2"
+ } |
+ .digests."0".segments = ["1","2"] |
+ .digests."1".segments = ["0","3"] |
+ .config.requirements.mandatory = ["online-reencrypt"]'
+img_check_fail
+
+# Note: older tools cannot create this from commandline
+echo "[4] Old decryption in-progress (journal)"
+img_prepare
+img_update_json '
+ del(.digests."1") |
+ del(.digests."2") |
+ del(.keyslots."1") |
+ .keyslots."2".mode = "decrypt" |
+ .keyslots."2".area.type = "journal" |
+ .segments = {
+ "0" : {
+ "type" : "linear",
+ "offset" : .segments."0".offset,
+ "size" : .keyslots."2".area.size,
+ "flags" : ["in-reencryption"]
+ },
+ "1" : (.segments."0" +
+ {"offset" : ((.segments."0".offset|tonumber) +
+ (.keyslots."2".area.size|tonumber))|tostring}),
+ "2" : .segments."1",
+ "3" : {
+ "type" : "linear",
+ "offset" : .segments."0".offset,
+ "size" : "dynamic",
+ "flags" : ["backup-final"]
+ }
+ } |
+ .digests."0".segments = ["1","2"] |
+ .config.requirements.mandatory = ["online-reencrypt"]'
+img_check_fail
+
+echo "[5] Old decryption in-progress (checksum)"
+img_prepare
+img_update_json '
+ del(.digests."1") |
+ del(.digests."2") |
+ del(.keyslots."1") |
+ .keyslots."2".mode = "decrypt" |
+ .keyslots."2".area.type = "checksum" |
+ .keyslots."2".area.hash = "sha256" |
+ .keyslots."2".area.sector_size = 4096 |
+ .segments = {
+ "0" : {
+ "type" : "linear",
+ "offset" : .segments."0".offset,
+ "size" : .keyslots."2".area.size,
+ "flags" : ["in-reencryption"]
+ },
+ "1" : (.segments."0" +
+ {"offset" : ((.segments."0".offset|tonumber) +
+ (.keyslots."2".area.size|tonumber))|tostring}),
+ "2" : .segments."1",
+ "3" : {
+ "type" : "linear",
+ "offset" : .segments."0".offset,
+ "size" : "dynamic",
+ "flags" : ["backup-final"]
+ }
+ } |
+ .digests."0".segments = ["1","2"] |
+ .config.requirements.mandatory = ["online-reencrypt"]'
+img_check_fail
+
+# Note - offset is set to work with the old version (with a datashift bug)
+echo "[6] Old reencryption in-progress (datashift)"
+img_prepare
+img_update_json '
+ del(.digests."2") |
+ .keyslots."2".direction = "backward" |
+ .keyslots."2".area.type = "datashift" |
+ .keyslots."2".area.size = "4096" |
+ .keyslots."2".area.shift_size = ((1 * 1024 * 1024)|tostring) |
+ .segments = {
+ "0" : (.segments."0" +
+ {"size" : ((13 * 1024 * 1024)|tostring)}),
+ "1" : (.segments."0" +
+ {"offset" : ((30 * 1024 * 1024)|tostring)}),
+ "2" : .segments."1",
+ "3" : (.segments."2" +
+ {"offset" : ((17 * 1024 * 1024)|tostring)}),
+ } |
+ .digests."0".segments = ["0","2"] |
+ .digests."1".segments = ["1","3"] |
+ .config.requirements.mandatory = ["online-reencrypt"]'
+img_check_fail
+
+#
+# NEW metadata (with reenc digest)
+#
+echo "[7] Reencryption with various mangled metadata"
+
+# Normal situation
+img_prepare
+img_run_reenc_ok
+img_check_ok
+
+# The same in various steps.
+# Repair must validate not only metadata, but also reencryption digest.
+img_prepare
+img_update_json 'del(.digests."2")'
+img_check_fail
+
+img_prepare '--reduce-device-size 2M'
+img_update_json '.keyslots."2".area.shift_size = ((.keyslots."2".area.shift_size|tonumber / 2)|tostring)'
+img_check_fail
+
+#FIXME: cannot check with correct digest for now (--init-only does not store area type)
+img_prepare
+img_update_json '
+ .keyslots."2".area.type = "checksum" |
+ .keyslots."2".area.hash = "sha256" |
+ .keyslots."2".area.sector_size = 4096'
+img_check_fail
+
+img_prepare
+img_update_json '.keyslots."2".area.type = "journal"'
+img_check_fail
+
+img_prepare
+img_update_json '.keyslots."2".mode = "decrypt"'
+img_check_fail
+
+img_prepare
+img_update_json '.keyslots."2".direction = "backward"'
+img_check_fail
+
+# key_size must be 1
+img_prepare
+img_update_json '.keyslots."2".key_size = 16'
+img_check_fail
+
+# Mangling segments
+img_prepare
+img_update_json 'del(.segments."1")'
+img_check_fail
+
+img_prepare
+img_update_json '.segments."0".encryption = "aes-cbc-null"'
+img_check_fail
+
+img_prepare
+img_update_json '.segments."1".encryption = "aes-cbc-null"'
+img_check_fail
+
+img_prepare
+img_update_json '.segments."2".encryption = "aes-cbc-null"'
+img_check_fail
+
+# Mangling digests
+img_prepare
+img_update_json '
+ .digests."2" = .digests."0" |
+ .digests."2".keyslots = ["2"] |
+ .digests."2".segments = []'
+img_check_fail
+
+img_prepare
+img_update_json '.digests."2".iterations = 1111'
+img_check_fail
+
+# Simulate correct progress
+img_prepare
+img_update_json '
+ .segments = {
+ "0" : (.segments."0" +
+ {"size" : ((1 * 1024 * 1024)|tostring)}),
+ "1" : (.segments."0" +
+ {"offset" : ((17 * 1024 * 1024)|tostring)}),
+ "2" : .segments."1",
+ "3" : .segments."2"
+ } |
+ .digests."0".segments = ["1","2"] |
+ .digests."1".segments = ["0","3"]'
+img_check_ok
+
+# Mangling keyslots
+
+# Set reencrypt slot to non-ignore priority
+# This should be benign, just avoid noisy messages
+img_prepare
+img_update_json 'del(.keyslots."2".priority)'
+img_check_ok
+
+# Flags
+
+# Remove mandatory reenc flag, but keep reenc metadata
+img_prepare
+img_update_json '.config.requirements.mandatory = []'
+img_check_fail
+
+# Unknown segment flag, should be ignored
+img_prepare
+img_update_json '.segments."0".flags = ["dead-parrot"]'
+img_check_ok
+
+echo "[8] Reencryption with AEAD is not supported"
+img_prepare_raw
+img_json_save
+img_update_json '
+ .segments."0".integrity = {
+ "type" : "hmac(sha256)",
+ "journal_encryption": "none",
+ "journal_integrity": "none"
+ }'
+$CRYPTSETUP reencrypt $IMG $CS_PARAMS >/dev/null 2>&1 && fail
+
+remove_mapping
+exit 0
diff -rupN cryptsetup-2.3.3.old/tests/Makefile.am cryptsetup-2.3.3/tests/Makefile.am
--- cryptsetup-2.3.3.old/tests/Makefile.am 2022-01-13 17:01:05.450651531 +0100
+++ cryptsetup-2.3.3/tests/Makefile.am 2022-01-13 17:03:47.726676343 +0100
@@ -25,7 +25,7 @@ TESTS += verity-compat-test
endif
if REENCRYPT
-TESTS += reencryption-compat-test reencryption-compat-test2 luks2-reencryption-test
+TESTS += reencryption-compat-test reencryption-compat-test2 luks2-reencryption-test luks2-reencryption-mangle-test
endif
if INTEGRITYSETUP
@@ -57,6 +57,7 @@ EXTRA_DIST = compatimage.img.xz compatv1
reencryption-compat-test \
reencryption-compat-test2 \
luks2-reencryption-test \
+ luks2-reencryption-mangle-test \
tcrypt-compat-test \
luks1-compat-test \
luks2-validation-test generators \
@@ -119,6 +120,7 @@ valgrind-check: api-test api-test-2 diff
@INFOSTRING="api-test-000" ./valg-api.sh ./api-test
@INFOSTRING="api-test-002" ./valg-api.sh ./api-test-2
@VALG=1 ./luks2-reencryption-test
+ @VALG=1 ./luks2-reencryption-mangle-test
@VALG=1 ./compat-test
.PHONY: valgrind-check

View File

@ -1,113 +0,0 @@
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_internal.h cryptsetup-2.3.3/lib/luks2/luks2_internal.h
--- cryptsetup-2.3.3.old/lib/luks2/luks2_internal.h 2022-01-17 16:14:07.530136302 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_internal.h 2022-01-17 16:15:29.134422136 +0100
@@ -207,5 +207,6 @@ static inline const char *crypt_reencryp
}
bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len);
+bool json_segment_cmp(json_object *jobj_segment_1, json_object *jobj_segment_2);
#endif
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_json_metadata.c cryptsetup-2.3.3/lib/luks2/luks2_json_metadata.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_json_metadata.c 2022-01-17 16:14:07.530136302 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_json_metadata.c 2022-01-17 16:16:34.382650680 +0100
@@ -606,6 +606,63 @@ static int reqs_reencrypt_online(uint32_
return reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
}
+/*
+ * Config section requirements object must be valid.
+ * Also general segments section must be validated first.
+ */
+static int validate_reencrypt_segments(struct crypt_device *cd, json_object *hdr_jobj, json_object *jobj_segments, int first_backup, int segments_count)
+{
+ json_object *jobj, *jobj_backup_previous = NULL, *jobj_backup_final = NULL;
+ uint32_t reqs;
+ int i, r;
+ struct luks2_hdr dummy = {
+ .jobj = hdr_jobj
+ };
+
+ r = LUKS2_config_get_requirements(cd, &dummy, &reqs);
+ if (r)
+ return 1;
+
+ if (reqs_reencrypt_online(reqs)) {
+ for (i = first_backup; i < segments_count; i++) {
+ jobj = json_segments_get_segment(jobj_segments, i);
+ if (!jobj)
+ return 1;
+ if (json_segment_contains_flag(jobj, "backup-final", 0))
+ jobj_backup_final = jobj;
+ else if (json_segment_contains_flag(jobj, "backup-previous", 0))
+ jobj_backup_previous = jobj;
+ }
+
+ if (!jobj_backup_final || !jobj_backup_previous) {
+ log_dbg(cd, "Backup segment is missing.");
+ return 1;
+ }
+
+ for (i = 0; i < first_backup; i++) {
+ jobj = json_segments_get_segment(jobj_segments, i);
+ if (!jobj)
+ return 1;
+
+ if (json_segment_contains_flag(jobj, "in-reencryption", 0)) {
+ if (!json_segment_cmp(jobj, jobj_backup_final)) {
+ log_dbg(cd, "Segment in reencryption does not match backup final segment.");
+ return 1;
+ }
+ continue;
+ }
+
+ if (!json_segment_cmp(jobj, jobj_backup_final) &&
+ !json_segment_cmp(jobj, jobj_backup_previous)) {
+ log_dbg(cd, "Segment does not match neither backup final or backup previous segment.");
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
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;
@@ -732,7 +789,7 @@ static int hdr_validate_segments(struct
}
}
- return 0;
+ return validate_reencrypt_segments(cd, hdr_jobj, jobj_segments, first_backup, count);
}
uint64_t LUKS2_metadata_size(json_object *jobj)
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_segment.c cryptsetup-2.3.3/lib/luks2/luks2_segment.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_segment.c 2022-01-17 16:14:07.531136305 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_segment.c 2022-01-17 16:14:43.952263876 +0100
@@ -410,3 +410,23 @@ json_object *LUKS2_get_segment_by_flag(s
return jobj_segment;
}
+
+/* compares key characteristics of both segments */
+bool json_segment_cmp(json_object *jobj_segment_1, json_object *jobj_segment_2)
+{
+ const char *type = json_segment_type(jobj_segment_1);
+ const char *type2 = json_segment_type(jobj_segment_2);
+
+ if (!type || !type2)
+ return false;
+
+ if (strcmp(type, type2))
+ return false;
+
+ if (!strcmp(type, "crypt"))
+ return (json_segment_get_sector_size(jobj_segment_1) == json_segment_get_sector_size(jobj_segment_2) &&
+ !strcmp(json_segment_get_cipher(jobj_segment_1),
+ json_segment_get_cipher(jobj_segment_2)));
+
+ return true;
+}

View File

@ -1,219 +0,0 @@
diff -rupN cryptsetup-2.3.3.old/man/cryptsetup.8 cryptsetup-2.3.3/man/cryptsetup.8
--- cryptsetup-2.3.3.old/man/cryptsetup.8 2022-01-13 17:19:58.082434394 +0100
+++ cryptsetup-2.3.3/man/cryptsetup.8 2022-01-13 17:20:19.860557992 +0100
@@ -803,6 +803,13 @@ are fixable. This command will only chan
any key-slot data. You may enforce LUKS version by adding \-\-type
option.
+It also repairs (upgrades) LUKS2 reencryption metadata by adding
+metadata digest that protects it against malicious changes.
+
+If LUKS2 reencryption was interrupted in the middle of writting
+reencryption segment the repair command can be used to perform
+reencryption recovery so that reencryption can continue later.
+
\fBWARNING:\fR Always create a binary backup of the original
header before calling this command.
.PP
diff -rupN cryptsetup-2.3.3.old/src/cryptsetup.c cryptsetup-2.3.3/src/cryptsetup.c
--- cryptsetup-2.3.3.old/src/cryptsetup.c 2022-01-13 17:19:58.064434292 +0100
+++ cryptsetup-2.3.3/src/cryptsetup.c 2022-01-13 17:21:29.108950976 +0100
@@ -1072,17 +1072,59 @@ static int set_keyslot_params(struct cry
return crypt_set_pbkdf_type(cd, &pbkdf);
}
-static int _do_luks2_reencrypt_recovery(struct crypt_device *cd)
+static int reencrypt_metadata_repair(struct crypt_device *cd)
+{
+ char *password;
+ size_t passwordLen;
+ int r;
+ struct crypt_params_reencrypt params = {
+ .flags = CRYPT_REENCRYPT_REPAIR_NEEDED
+ };
+
+ if (!opt_batch_mode &&
+ !yesDialog(_("Unprotected LUKS2 reencryption metadata detected. "
+ "Please verify the reencryption operation is desirable (see luksDump output)\n"
+ "and continue (upgrade metadata) only if you acknowledge the operation as genuine."),
+ _("Operation aborted.\n")))
+ return -EINVAL;
+
+ r = tools_get_key(_("Enter passphrase to protect and uppgrade reencryption metadata: "),
+ &password, &passwordLen, opt_keyfile_offset,
+ opt_keyfile_size, opt_key_file, opt_timeout,
+ _verify_passphrase(0), 0, cd);
+ if (r < 0)
+ return r;
+
+ r = crypt_reencrypt_init_by_passphrase(cd, NULL, password, passwordLen,
+ opt_key_slot, opt_key_slot, NULL, NULL, &params);
+ tools_passphrase_msg(r);
+ if (r < 0)
+ goto out;
+
+ r = crypt_activate_by_passphrase(cd, NULL, opt_key_slot,
+ password, passwordLen, 0);
+ tools_passphrase_msg(r);
+ if (r >= 0)
+ r = 0;
+
+out:
+ crypt_safe_free(password);
+ return r;
+}
+
+static int luks2_reencrypt_repair(struct crypt_device *cd)
{
int r;
size_t passwordLen;
const char *msg;
char *password = NULL;
- struct crypt_params_reencrypt recovery_params = {
- .flags = CRYPT_REENCRYPT_RECOVERY
- };
+ struct crypt_params_reencrypt params = {};
+
+ crypt_reencrypt_info ri = crypt_reencrypt_status(cd, &params);
+
+ if (params.flags & CRYPT_REENCRYPT_REPAIR_NEEDED)
+ return reencrypt_metadata_repair(cd);
- crypt_reencrypt_info ri = crypt_reencrypt_status(cd, NULL);
switch (ri) {
case CRYPT_REENCRYPT_NONE:
return 0;
@@ -1120,7 +1162,8 @@ static int _do_luks2_reencrypt_recovery(
}
r = crypt_reencrypt_init_by_passphrase(cd, NULL, password, passwordLen,
- opt_key_slot, opt_key_slot, NULL, NULL, &recovery_params);
+ opt_key_slot, opt_key_slot, NULL, NULL,
+ &(struct crypt_params_reencrypt){ .flags = CRYPT_REENCRYPT_RECOVERY });
if (r > 0)
r = 0;
out:
@@ -1155,8 +1198,9 @@ static int action_luksRepair(void)
if (r == 0)
r = crypt_repair(cd, luksType(opt_type), NULL);
skip_repair:
+ /* Header is ok, check if reencryption metadata needs repair/recovery. */
if (!r && crypt_get_type(cd) && !strcmp(crypt_get_type(cd), CRYPT_LUKS2))
- r = _do_luks2_reencrypt_recovery(cd);
+ r = luks2_reencrypt_repair(cd);
out:
crypt_free(cd);
return r;
diff -rupN cryptsetup-2.3.3.old/tests/luks2-reencryption-mangle-test cryptsetup-2.3.3/tests/luks2-reencryption-mangle-test
--- cryptsetup-2.3.3.old/tests/luks2-reencryption-mangle-test 2022-01-13 17:19:58.073434343 +0100
+++ cryptsetup-2.3.3/tests/luks2-reencryption-mangle-test 2022-01-13 17:20:19.861557997 +0100
@@ -172,6 +172,42 @@ EOF
[ $? -eq 0 ] || fail "Expect script failed."
}
+function img_run_reenc_fail()
+{
+local EXPECT_TIMEOUT=5
+[ -n "$VALG" ] && EXPECT_TIMEOUT=60
+# For now, we cannot run reencryption in batch mode for non-block device. Just fake the terminal here.
+expect_run - >/dev/null <<EOF
+proc abort {} { send_error "Timeout. "; exit 42 }
+set timeout $EXPECT_TIMEOUT
+eval spawn $CRYPTSETUP_RAW reencrypt $IMG $CS_PWPARAMS --disable-locks
+expect timeout abort "Are you sure? (Type 'yes' in capital letters):"
+send "YES\n"
+expect timeout abort eof
+catch wait result
+exit [lindex \$result 3]
+EOF
+local ret=$?
+[ $ret -eq 0 ] && fail "Reencryption passed (should have failed)."
+[ $ret -eq 42 ] && fail "Expect script failed."
+img_hash_unchanged
+}
+
+function img_check_fail_repair_ok()
+{
+ if [ $(id -u) == 0 ]; then
+ $CRYPTSETUP open $CS_PWPARAMS $IMG $DEV_NAME 2>/dev/null && fail
+ fi
+
+ img_run_reenc_fail
+
+ # repair metadata
+ $CRYPTSETUP repair $IMG $CS_PARAMS || fail
+
+ img_check_ok
+ img_run_reenc_ok
+}
+
function valgrind_setup()
{
bin_check valgrind
@@ -212,10 +248,10 @@ img_check_ok
img_run_reenc_ok
img_check_ok
-# Simulate old reencryption with no digest
+# Simulate old reencryption with no digest (repairable)
img_prepare
img_update_json 'del(.digests."2") | .config.requirements.mandatory = ["online-reencrypt"]'
-img_check_fail
+img_check_fail_repair_ok
# This must fail for new releases
echo "[2] Old reencryption in-progress (journal)"
@@ -236,7 +272,7 @@ img_update_json '
.digests."0".segments = ["1","2"] |
.digests."1".segments = ["0","3"] |
.config.requirements.mandatory = ["online-reencrypt"]'
-img_check_fail
+img_check_fail_repair_ok
echo "[3] Old reencryption in-progress (checksum)"
img_prepare
@@ -258,7 +294,7 @@ img_update_json '
.digests."0".segments = ["1","2"] |
.digests."1".segments = ["0","3"] |
.config.requirements.mandatory = ["online-reencrypt"]'
-img_check_fail
+img_check_fail_repair_ok
# Note: older tools cannot create this from commandline
echo "[4] Old decryption in-progress (journal)"
@@ -289,7 +325,7 @@ img_update_json '
} |
.digests."0".segments = ["1","2"] |
.config.requirements.mandatory = ["online-reencrypt"]'
-img_check_fail
+img_check_fail_repair_ok
echo "[5] Old decryption in-progress (checksum)"
img_prepare
@@ -321,7 +357,7 @@ img_update_json '
} |
.digests."0".segments = ["1","2"] |
.config.requirements.mandatory = ["online-reencrypt"]'
-img_check_fail
+img_check_fail_repair_ok
# Note - offset is set to work with the old version (with a datashift bug)
echo "[6] Old reencryption in-progress (datashift)"
@@ -344,7 +380,7 @@ img_update_json '
.digests."0".segments = ["0","2"] |
.digests."1".segments = ["1","3"] |
.config.requirements.mandatory = ["online-reencrypt"]'
-img_check_fail
+img_check_fail_repair_ok
#
# NEW metadata (with reenc digest)
@@ -360,7 +396,7 @@ img_check_ok
# Repair must validate not only metadata, but also reencryption digest.
img_prepare
img_update_json 'del(.digests."2")'
-img_check_fail
+img_check_fail_repair_ok
img_prepare '--reduce-device-size 2M'
img_update_json '.keyslots."2".area.shift_size = ((.keyslots."2".area.shift_size|tonumber / 2)|tostring)'

View File

@ -1,65 +0,0 @@
From 18cb1eeeb9d320d9fb4f9bc3289a23f6694f9d60 Mon Sep 17 00:00:00 2001
From: Milan Broz <gmazyland@gmail.com>
Date: Sun, 2 Jan 2022 16:57:31 +0100
Subject: [PATCH 13/28] Do not run reencryption recovery when not needed.
---
src/cryptsetup.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/src/cryptsetup.c b/src/cryptsetup.c
index 5547b3cc..206575c7 100644
--- a/src/cryptsetup.c
+++ b/src/cryptsetup.c
@@ -1125,6 +1125,7 @@ static int _do_luks2_reencrypt_recovery(struct crypt_device *cd)
{
int r;
size_t passwordLen;
+ const char *msg;
char *password = NULL;
struct crypt_params_reencrypt recovery_params = {
.flags = CRYPT_REENCRYPT_RECOVERY
@@ -1133,12 +1134,8 @@ static int _do_luks2_reencrypt_recovery(struct crypt_device *cd)
crypt_reencrypt_info ri = crypt_reencrypt_status(cd, NULL);
switch (ri) {
case CRYPT_REENCRYPT_NONE:
- /* fall through */
+ return 0;
case CRYPT_REENCRYPT_CLEAN:
- r = noDialog(_("Seems device does not require reencryption recovery.\n"
- "Do you want to proceed anyway?"), NULL);
- if (!r)
- return 0;
break;
case CRYPT_REENCRYPT_CRASH:
r = yesDialog(_("Really proceed with LUKS2 reencryption recovery?"),
@@ -1150,8 +1147,12 @@ static int _do_luks2_reencrypt_recovery(struct crypt_device *cd)
return -EINVAL;
}
- r = tools_get_key(_("Enter passphrase for reencryption recovery: "),
- &password, &passwordLen, opt_keyfile_offset,
+ if (ri == CRYPT_REENCRYPT_CLEAN)
+ msg = _("Enter passphrase to verify reencryption metadata digest: ");
+ else
+ msg = _("Enter passphrase for reencryption recovery: ");
+
+ r = tools_get_key(msg, &password, &passwordLen, opt_keyfile_offset,
opt_keyfile_size, opt_key_file, opt_timeout,
_verify_passphrase(0), 0, cd);
if (r < 0)
@@ -1162,6 +1163,11 @@ static int _do_luks2_reencrypt_recovery(struct crypt_device *cd)
if (r < 0)
goto out;
+ if (ri == CRYPT_REENCRYPT_CLEAN) {
+ r = 0;
+ goto out;
+ }
+
r = crypt_reencrypt_init_by_passphrase(cd, NULL, password, passwordLen,
opt_key_slot, opt_key_slot, NULL, NULL, &recovery_params);
if (r > 0)
--
2.27.0

View File

@ -1,22 +0,0 @@
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_internal.h cryptsetup-2.3.3/lib/luks2/luks2_internal.h
--- cryptsetup-2.3.3.old/lib/luks2/luks2_internal.h 2022-01-17 16:10:00.756271915 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_internal.h 2022-01-17 16:11:59.845689051 +0100
@@ -206,4 +206,6 @@ static inline const char *crypt_reencryp
return "<unknown>";
}
+bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len);
+
#endif
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_segment.c cryptsetup-2.3.3/lib/luks2/luks2_segment.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_segment.c 2022-01-17 16:10:00.756271915 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_segment.c 2022-01-17 16:10:34.422389838 +0100
@@ -123,7 +123,7 @@ static json_object *json_segment_get_fla
return jobj;
}
-static bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len)
+bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len)
{
int r, i;
json_object *jobj, *jobj_flags = json_segment_get_flags(jobj_segment);

View File

@ -1,783 +0,0 @@
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2.h cryptsetup-2.3.3/lib/luks2/luks2.h
--- cryptsetup-2.3.3.old/lib/luks2/luks2.h 2022-01-17 15:03:03.689201103 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2.h 2022-01-17 15:06:42.149966321 +0100
@@ -606,4 +606,8 @@ void crypt_reencrypt_unlock(struct crypt
int luks2_check_device_size(struct crypt_device *cd, struct luks2_hdr *hdr, uint64_t check_size, uint64_t *dev_size, bool activation, bool dynamic);
+int LUKS2_reencrypt_digest_verify(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct volume_key *vks);
+
#endif
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_internal.h cryptsetup-2.3.3/lib/luks2/luks2_internal.h
--- cryptsetup-2.3.3.old/lib/luks2/luks2_internal.h 2022-01-17 15:03:03.689201103 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_internal.h 2022-01-17 15:51:20.125346606 +0100
@@ -128,6 +128,12 @@ int placeholder_keyslot_alloc(struct cry
/* validate all keyslot implementations in hdr json */
int LUKS2_keyslots_validate(struct crypt_device *cd, json_object *hdr_jobj);
+int LUKS2_keyslot_jobj_area(json_object *jobj_keyslot, uint64_t *offset, uint64_t *length);
+
+int LUKS2_keyslot_reencrypt_digest_create(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct volume_key *vks);
+
typedef struct {
const char *name;
keyslot_alloc_func alloc;
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_json_metadata.c cryptsetup-2.3.3/lib/luks2/luks2_json_metadata.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_json_metadata.c 2022-01-17 15:03:03.689201103 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_json_metadata.c 2022-01-17 15:05:48.165777220 +0100
@@ -1371,24 +1371,63 @@ int LUKS2_config_set_flags(struct crypt_
*/
/* LUKS2 library requirements */
-static const struct {
+struct requirement_flag {
uint32_t flag;
+ uint32_t version;
const char *description;
-} requirements_flags[] = {
- { CRYPT_REQUIREMENT_OFFLINE_REENCRYPT, "offline-reencrypt" },
- { CRYPT_REQUIREMENT_ONLINE_REENCRYPT, "online-reencrypt" },
- { 0, NULL }
};
-static uint32_t get_requirement_by_name(const char *requirement)
+static const struct requirement_flag unknown_requirement_flag = { CRYPT_REQUIREMENT_UNKNOWN, 0, NULL };
+
+static const struct requirement_flag requirements_flags[] = {
+ { CRYPT_REQUIREMENT_OFFLINE_REENCRYPT,1, "offline-reencrypt" },
+ { CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 2, "online-reencrypt-v2" },
+ { CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 1, "online-reencrypt" },
+ { 0, 0, NULL }
+};
+
+static const struct requirement_flag *get_requirement_by_name(const char *requirement)
{
int i;
for (i = 0; requirements_flags[i].description; i++)
if (!strcmp(requirement, requirements_flags[i].description))
- return requirements_flags[i].flag;
+ return requirements_flags + i;
+
+ return &unknown_requirement_flag;
+}
+
+static const struct requirement_flag *stored_requirement_name_by_id(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t req_id)
+{
+ json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
+ int i, len;
+ const struct requirement_flag *req;
+
+ assert(hdr);
+ if (!hdr)
+ return NULL;
+
+ if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
+ return NULL;
+
+ if (!json_object_object_get_ex(jobj_config, "requirements", &jobj_requirements))
+ return NULL;
+
+ if (!json_object_object_get_ex(jobj_requirements, "mandatory", &jobj_mandatory))
+ return NULL;
+
+ len = (int) json_object_array_length(jobj_mandatory);
+ if (len <= 0)
+ return 0;
+
+ for (i = 0; i < len; i++) {
+ jobj = json_object_array_get_idx(jobj_mandatory, i);
+ req = get_requirement_by_name(json_object_get_string(jobj));
+ if (req->flag == req_id)
+ return req;
+ }
- return CRYPT_REQUIREMENT_UNKNOWN;
+ return NULL;
}
/*
@@ -1398,7 +1437,7 @@ int LUKS2_config_get_requirements(struct
{
json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
int i, len;
- uint32_t req;
+ const struct requirement_flag *req;
assert(hdr);
if (!hdr || !reqs)
@@ -1425,8 +1464,8 @@ int LUKS2_config_get_requirements(struct
jobj = json_object_array_get_idx(jobj_mandatory, i);
req = get_requirement_by_name(json_object_get_string(jobj));
log_dbg(cd, "%s - %sknown", json_object_get_string(jobj),
- reqs_unknown(req) ? "un" : "");
- *reqs |= req;
+ reqs_unknown(req->flag) ? "un" : "");
+ *reqs |= req->flag;
}
return 0;
@@ -1436,6 +1475,8 @@ int LUKS2_config_set_requirements(struct
{
json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
int i, r = -EINVAL;
+ const struct requirement_flag *req;
+ uint32_t req_id;
if (!hdr)
return -EINVAL;
@@ -1445,8 +1486,14 @@ int LUKS2_config_set_requirements(struct
return -ENOMEM;
for (i = 0; requirements_flags[i].description; i++) {
- if (reqs & requirements_flags[i].flag) {
- jobj = json_object_new_string(requirements_flags[i].description);
+ req_id = reqs & requirements_flags[i].flag;
+ if (req_id) {
+ /* retain already stored version of requirement flag */
+ req = stored_requirement_name_by_id(cd, hdr, req_id);
+ if (req)
+ jobj = json_object_new_string(req->description);
+ else
+ jobj = json_object_new_string(requirements_flags[i].description);
if (!jobj) {
r = -ENOMEM;
goto err;
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_keyslot.c cryptsetup-2.3.3/lib/luks2/luks2_keyslot.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_keyslot.c 2022-01-17 15:03:03.689201103 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_keyslot.c 2022-01-17 15:05:48.165777220 +0100
@@ -281,19 +281,9 @@ crypt_keyslot_info LUKS2_keyslot_info(st
return CRYPT_SLOT_ACTIVE;
}
-int LUKS2_keyslot_area(struct luks2_hdr *hdr,
- int keyslot,
- uint64_t *offset,
- uint64_t *length)
+int LUKS2_keyslot_jobj_area(json_object *jobj_keyslot, uint64_t *offset, uint64_t *length)
{
- json_object *jobj_keyslot, *jobj_area, *jobj;
-
- if(LUKS2_keyslot_info(hdr, keyslot) == CRYPT_SLOT_INVALID)
- return -EINVAL;
-
- jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
- if (!jobj_keyslot)
- return -ENOENT;
+ json_object *jobj_area, *jobj;
if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
return -EINVAL;
@@ -309,6 +299,23 @@ int LUKS2_keyslot_area(struct luks2_hdr
return 0;
}
+int LUKS2_keyslot_area(struct luks2_hdr *hdr,
+ int keyslot,
+ uint64_t *offset,
+ uint64_t *length)
+{
+ json_object *jobj_keyslot;
+
+ if (LUKS2_keyslot_info(hdr, keyslot) == CRYPT_SLOT_INVALID)
+ return -EINVAL;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
+ if (!jobj_keyslot)
+ return -ENOENT;
+
+ return LUKS2_keyslot_jobj_area(jobj_keyslot, offset, length);
+}
+
static int _open_and_verify(struct crypt_device *cd,
struct luks2_hdr *hdr,
const keyslot_handler *h,
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_keyslot_reenc.c cryptsetup-2.3.3/lib/luks2/luks2_keyslot_reenc.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_keyslot_reenc.c 2022-01-17 15:03:03.689201103 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_keyslot_reenc.c 2022-01-17 15:59:15.897013127 +0100
@@ -179,6 +179,7 @@ static int reenc_keyslot_store(struct cr
int reenc_keyslot_update(struct crypt_device *cd,
const struct luks2_reenc_context *rh)
{
+ int r;
json_object *jobj_keyslot, *jobj_area, *jobj_area_type;
struct luks2_hdr *hdr;
@@ -208,11 +209,23 @@ int reenc_keyslot_update(struct crypt_de
} else
log_dbg(cd, "No update of reencrypt keyslot needed.");
- return 0;
+ r = LUKS2_keyslot_reencrypt_digest_create(cd, hdr, rh->vks);
+ if (r < 0)
+ log_err(cd, "Failed to refresh reencryption verification digest.");
+
+ return r;
}
static int reenc_keyslot_wipe(struct crypt_device *cd, int keyslot)
{
+ struct luks2_hdr *hdr;
+
+ if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
+ return -EINVAL;
+
+ /* remove reencryption verification data */
+ LUKS2_digest_assign(cd, hdr, keyslot, CRYPT_ANY_DIGEST, 0, 0);
+
return 0;
}
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_reencrypt.c cryptsetup-2.3.3/lib/luks2/luks2_reencrypt.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_reencrypt.c 2022-01-17 15:03:03.689201103 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_reencrypt.c 2022-01-17 15:57:08.906568302 +0100
@@ -2390,6 +2390,10 @@ static int reencrypt_init(struct crypt_d
if (r < 0)
goto err;
+ r = LUKS2_keyslot_reencrypt_digest_create(cd, hdr, *vks);
+ if (r < 0)
+ goto err;
+
if (name && params->mode != CRYPT_REENCRYPT_ENCRYPT) {
r = reencrypt_verify_and_upload_keys(cd, hdr, LUKS2_reencrypt_digest_old(hdr), LUKS2_reencrypt_digest_new(hdr), *vks);
if (r)
@@ -2520,20 +2524,28 @@ static int reencrypt_context_update(stru
static int reencrypt_load(struct crypt_device *cd, struct luks2_hdr *hdr,
uint64_t device_size,
const struct crypt_params_reencrypt *params,
+ struct volume_key *vks,
struct luks2_reenc_context **rh)
{
int r;
struct luks2_reenc_context *tmp = NULL;
crypt_reencrypt_info ri = LUKS2_reenc_status(hdr);
+ if (ri == CRYPT_REENCRYPT_NONE) {
+ log_err(cd, _("Device not marked for LUKS2 reencryption."));
+ return -EINVAL;
+ } else if (ri == CRYPT_REENCRYPT_INVALID)
+ return -EINVAL;
+
+ r = LUKS2_reencrypt_digest_verify(cd, hdr, vks);
+ if (r < 0)
+ return r;
+
if (ri == CRYPT_REENCRYPT_CLEAN)
r = reencrypt_load_clean(cd, hdr, device_size, &tmp, params);
else if (ri == CRYPT_REENCRYPT_CRASH)
r = reencrypt_load_crashed(cd, hdr, device_size, &tmp);
- else if (ri == CRYPT_REENCRYPT_NONE) {
- log_err(cd, _("Device not marked for LUKS2 reencryption."));
- return -EINVAL;
- } else
+ else
r = -EINVAL;
if (r < 0 || !tmp) {
@@ -2781,7 +2793,7 @@ static int reencrypt_load_by_passphrase(
rparams.device_size = required_size;
}
- r = reencrypt_load(cd, hdr, device_size, &rparams, &rh);
+ r = reencrypt_load(cd, hdr, device_size, &rparams, *vks, &rh);
if (r < 0 || !rh)
goto err;
@@ -3001,13 +3013,6 @@ static reenc_status_t reencrypt_step(str
{
int r;
- /* update reencrypt keyslot protection parameters in memory only */
- r = reenc_keyslot_update(cd, rh);
- if (r < 0) {
- log_dbg(cd, "Keyslot update failed.");
- return REENC_ERR;
- }
-
/* in memory only */
r = reencrypt_make_segments(cd, hdr, rh, device_size);
if (r)
@@ -3272,6 +3277,15 @@ int crypt_reencrypt(struct crypt_device
rs = REENC_OK;
+ /* update reencrypt keyslot protection parameters in memory only */
+ if (!quit && (rh->device_size > rh->progress)) {
+ r = reenc_keyslot_update(cd, rh);
+ if (r < 0) {
+ log_dbg(cd, "Keyslot update failed.");
+ return reencrypt_teardown(cd, hdr, rh, REENC_ERR, quit, progress);
+ }
+ }
+
while (!quit && (rh->device_size > rh->progress)) {
rs = reencrypt_step(cd, hdr, rh, rh->device_size, rh->online);
if (rs != REENC_OK)
@@ -3304,7 +3318,7 @@ static int reencrypt_recovery(struct cry
int r;
struct luks2_reenc_context *rh = NULL;
- r = reencrypt_load(cd, hdr, device_size, NULL, &rh);
+ r = reencrypt_load(cd, hdr, device_size, NULL, vks, &rh);
if (r < 0) {
log_err(cd, _("Failed to load LUKS2 reencryption context."));
return r;
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_reencrypt_digest.c cryptsetup-2.3.3/lib/luks2/luks2_reencrypt_digest.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_reencrypt_digest.c 1970-01-01 01:00:00.000000000 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_reencrypt_digest.c 2022-01-17 15:05:48.166777223 +0100
@@ -0,0 +1,381 @@
+/*
+ * LUKS - Linux Unified Key Setup v2, reencryption digest helpers
+ *
+ * Copyright (C) 2022, Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2022, Ondrej Kozina
+ * Copyright (C) 2022, Milan Broz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "luks2_internal.h"
+#include <assert.h>
+
+#define MAX_STR 64
+
+struct jtype {
+ enum { JNONE = 0, JSTR, JU64, JX64, JU32 } type;
+ json_object *jobj;
+ const char *id;
+};
+
+static size_t sr(struct jtype *j, uint8_t *ptr)
+{
+ json_object *jobj;
+ size_t len = 0;
+ uint64_t u64;
+ uint32_t u32;
+
+ if (!json_object_is_type(j->jobj, json_type_object))
+ return 0;
+
+ if (!json_object_object_get_ex(j->jobj, j->id, &jobj))
+ return 0;
+
+ switch(j->type) {
+ case JSTR: /* JSON string */
+ if (!json_object_is_type(jobj, json_type_string))
+ return 0;
+ len = strlen(json_object_get_string(jobj));
+ if (len > MAX_STR)
+ return 0;
+ if (ptr)
+ memcpy(ptr, json_object_get_string(jobj), len);
+ break;
+ case JU64: /* Unsigned 64bit integer stored as string */
+ if (!json_object_is_type(jobj, json_type_string))
+ break;
+ len = sizeof(u64);
+ if (ptr) {
+ u64 = cpu_to_be64(crypt_jobj_get_uint64(jobj));
+ memcpy(ptr, &u64, len);
+ }
+ break;
+ case JX64: /* Unsigned 64bit segment size (allows "dynamic") */
+ if (!json_object_is_type(jobj, json_type_string))
+ break;
+ if (!strcmp(json_object_get_string(jobj), "dynamic")) {
+ len = strlen("dynamic");
+ if (ptr)
+ memcpy(ptr, json_object_get_string(jobj), len);
+ } else {
+ len = sizeof(u64);
+ u64 = cpu_to_be64(crypt_jobj_get_uint64(jobj));
+ if (ptr)
+ memcpy(ptr, &u64, len);
+ }
+ break;
+ case JU32: /* Unsigned 32bit integer, stored as JSON int */
+ if (!json_object_is_type(jobj, json_type_int))
+ return 0;
+ len = sizeof(u32);
+ if (ptr) {
+ u32 = cpu_to_be32(crypt_jobj_get_uint32(jobj));
+ memcpy(ptr, &u32, len);
+ }
+ break;
+ case JNONE:
+ return 0;
+ };
+
+ return len;
+}
+
+static size_t srs(struct jtype j[], uint8_t *ptr)
+{
+ size_t l, len = 0;
+
+ while(j->jobj) {
+ l = sr(j, ptr);
+ if (!l)
+ return 0;
+ len += l;
+ if (ptr)
+ ptr += l;
+ j++;
+ }
+ return len;
+}
+
+static size_t segment_linear_serialize(json_object *jobj_segment, uint8_t *buffer)
+{
+ struct jtype j[] = {
+ { JSTR, jobj_segment, "type" },
+ { JU64, jobj_segment, "offset" },
+ { JX64, jobj_segment, "size" },
+ {}
+ };
+ return srs(j, buffer);
+}
+
+static size_t segment_crypt_serialize(json_object *jobj_segment, uint8_t *buffer)
+{
+ struct jtype j[] = {
+ { JSTR, jobj_segment, "type" },
+ { JU64, jobj_segment, "offset" },
+ { JX64, jobj_segment, "size" },
+ { JU64, jobj_segment, "iv_tweak" },
+ { JSTR, jobj_segment, "encryption" },
+ { JU32, jobj_segment, "sector_size" },
+ {}
+ };
+ return srs(j, buffer);
+}
+
+static size_t segment_serialize(json_object *jobj_segment, uint8_t *buffer)
+{
+ json_object *jobj_type;
+ const char *segment_type;
+
+ if (!json_object_object_get_ex(jobj_segment, "type", &jobj_type))
+ return 0;
+
+ if (!(segment_type = json_object_get_string(jobj_type)))
+ return 0;
+
+ if (!strcmp(segment_type, "crypt"))
+ return segment_crypt_serialize(jobj_segment, buffer);
+ else if (!strcmp(segment_type, "linear"))
+ return segment_linear_serialize(jobj_segment, buffer);
+
+ return 0;
+}
+
+static size_t backup_segments_serialize(struct luks2_hdr *hdr, uint8_t *buffer)
+{
+ json_object *jobj_segment;
+ size_t l, len = 0;
+
+ jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-previous");
+ if (!jobj_segment || !(l = segment_serialize(jobj_segment, buffer)))
+ return 0;
+ len += l;
+ if (buffer)
+ buffer += l;
+
+ jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-final");
+ if (!jobj_segment || !(l = segment_serialize(jobj_segment, buffer)))
+ return 0;
+ len += l;
+ if (buffer)
+ buffer += l;
+
+ jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-moved-segment");
+ if (jobj_segment) {
+ if (!(l = segment_serialize(jobj_segment, buffer)))
+ return 0;
+ len += l;
+ }
+
+ return len;
+}
+
+static size_t reenc_keyslot_serialize(struct luks2_hdr *hdr, uint8_t *buffer)
+{
+ json_object *jobj_keyslot, *jobj_area, *jobj_type;
+ const char *area_type;
+ int keyslot_reencrypt;
+
+ keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
+ if (keyslot_reencrypt < 0)
+ return 0;
+
+ if (!(jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot_reencrypt)))
+ return 0;
+
+ if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
+ return 0;
+
+ if (!json_object_object_get_ex(jobj_area, "type", &jobj_type))
+ return 0;
+
+ if (!(area_type = json_object_get_string(jobj_type)))
+ return 0;
+
+ struct jtype j[] = {
+ { JSTR, jobj_keyslot, "mode" },
+ { JSTR, jobj_keyslot, "direction" },
+ { JSTR, jobj_area, "type" },
+ { JU64, jobj_area, "offset" },
+ { JU64, jobj_area, "size" },
+ {}
+ };
+ struct jtype j_datashift[] = {
+ { JSTR, jobj_keyslot, "mode" },
+ { JSTR, jobj_keyslot, "direction" },
+ { JSTR, jobj_area, "type" },
+ { JU64, jobj_area, "offset" },
+ { JU64, jobj_area, "size" },
+ { JU64, jobj_area, "shift_size" },
+ {}
+ };
+ struct jtype j_checksum[] = {
+ { JSTR, jobj_keyslot, "mode" },
+ { JSTR, jobj_keyslot, "direction" },
+ { JSTR, jobj_area, "type" },
+ { JU64, jobj_area, "offset" },
+ { JU64, jobj_area, "size" },
+ { JSTR, jobj_area, "hash" },
+ { JU32, jobj_area, "sector_size" },
+ {}
+ };
+
+ if (!strcmp(area_type, "datashift"))
+ return srs(j_datashift, buffer);
+ else if (!strcmp(area_type, "checksum"))
+ return srs(j_checksum, buffer);
+
+ return srs(j, buffer);
+}
+
+static size_t blob_serialize(void *blob, size_t length, uint8_t *buffer)
+{
+ if (buffer)
+ memcpy(buffer, blob, length);
+
+ return length;
+}
+
+static int reencrypt_assembly_verification_data(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct volume_key *vks,
+ struct volume_key **verification_data)
+{
+ uint8_t *ptr;
+ int digest_new, digest_old;
+ struct volume_key *data = NULL, *vk_old = NULL, *vk_new = NULL;
+ size_t keyslot_data_len, segments_data_len, data_len = 2;
+
+ /* Keys - calculate length */
+ digest_new = LUKS2_reencrypt_digest_new(hdr);
+ digest_old = LUKS2_reencrypt_digest_old(hdr);
+
+ if (digest_old >= 0) {
+ vk_old = crypt_volume_key_by_id(vks, digest_old);
+ if (!vk_old)
+ return -EINVAL;
+ data_len += blob_serialize(vk_old->key, vk_old->keylength, NULL);
+ }
+
+ if (digest_new >= 0 && digest_old != digest_new) {
+ vk_new = crypt_volume_key_by_id(vks, digest_new);
+ if (!vk_new)
+ return -EINVAL;
+ data_len += blob_serialize(vk_new->key, vk_new->keylength, NULL);
+ }
+
+ if (data_len == 2)
+ return -EINVAL;
+
+ /* Metadata - calculate length */
+ if (!(keyslot_data_len = reenc_keyslot_serialize(hdr, NULL)))
+ return -EINVAL;
+ data_len += keyslot_data_len;
+
+ if (!(segments_data_len = backup_segments_serialize(hdr, NULL)))
+ return -EINVAL;
+ data_len += segments_data_len;
+
+ /* Alloc and fill serialization data */
+ data = crypt_alloc_volume_key(data_len, NULL);
+ if (!data)
+ return -ENOMEM;
+
+ ptr = (uint8_t*)data->key;
+
+ /* v2 */
+ *ptr++ = 0x76;
+ *ptr++ = 0x32;
+
+ if (vk_old)
+ ptr += blob_serialize(vk_old->key, vk_old->keylength, ptr);
+
+ if (vk_new)
+ ptr += blob_serialize(vk_new->key, vk_new->keylength, ptr);
+
+ if (!reenc_keyslot_serialize(hdr, ptr))
+ goto bad;
+ ptr += keyslot_data_len;
+
+ if (!backup_segments_serialize(hdr, ptr))
+ goto bad;
+ ptr += segments_data_len;
+
+ assert((size_t)(ptr - (uint8_t*)data->key) == data_len);
+
+ *verification_data = data;
+
+ return 0;
+bad:
+ crypt_free_volume_key(data);
+ return -EINVAL;
+}
+
+int LUKS2_keyslot_reencrypt_digest_create(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct volume_key *vks)
+{
+ int digest_reencrypt, keyslot_reencrypt, r;
+ struct volume_key *data;
+
+ keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
+ if (keyslot_reencrypt < 0)
+ return keyslot_reencrypt;
+
+ r = reencrypt_assembly_verification_data(cd, hdr, vks, &data);
+ if (r < 0)
+ return r;
+
+ r = LUKS2_digest_create(cd, "pbkdf2", hdr, data);
+ crypt_free_volume_key(data);
+ if (r < 0)
+ return r;
+
+ digest_reencrypt = r;
+
+ r = LUKS2_digest_assign(cd, hdr, keyslot_reencrypt, CRYPT_ANY_DIGEST, 0, 0);
+ if (r < 0)
+ return r;
+
+ return LUKS2_digest_assign(cd, hdr, keyslot_reencrypt, digest_reencrypt, 1, 0);
+}
+
+int LUKS2_reencrypt_digest_verify(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct volume_key *vks)
+{
+ int r, keyslot_reencrypt;
+ struct volume_key *data;
+
+ keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
+ if (keyslot_reencrypt < 0)
+ return keyslot_reencrypt;
+
+ r = reencrypt_assembly_verification_data(cd, hdr, vks, &data);
+ if (r < 0)
+ return r;
+
+ r = LUKS2_digest_verify(cd, hdr, data, keyslot_reencrypt);
+ crypt_free_volume_key(data);
+
+ if (r < 0) {
+ if (r == -ENOENT)
+ log_dbg(cd, "Reencryption digest is missing.");
+ log_err(cd, _("Reencryption metadata is invalid."));
+ } else
+ log_dbg(cd, "Reencryption metadata verified.");
+
+ return r;
+}
diff -rupN cryptsetup-2.3.3.old/lib/Makemodule.am cryptsetup-2.3.3/lib/Makemodule.am
--- cryptsetup-2.3.3.old/lib/Makemodule.am 2022-01-17 15:03:03.687201096 +0100
+++ cryptsetup-2.3.3/lib/Makemodule.am 2022-01-17 15:05:48.164777216 +0100
@@ -104,6 +104,7 @@ libcryptsetup_la_SOURCES = \
lib/luks2/luks2_keyslot_luks2.c \
lib/luks2/luks2_keyslot_reenc.c \
lib/luks2/luks2_reencrypt.c \
+ lib/luks2/luks2_reencrypt_digest.c \
lib/luks2/luks2_segment.c \
lib/luks2/luks2_token_keyring.c \
lib/luks2/luks2_token.c \
diff -rupN cryptsetup-2.3.3.old/lib/setup.c cryptsetup-2.3.3/lib/setup.c
--- cryptsetup-2.3.3.old/lib/setup.c 2022-01-17 15:03:03.686201093 +0100
+++ cryptsetup-2.3.3/lib/setup.c 2022-01-17 16:00:07.797194917 +0100
@@ -4032,6 +4032,12 @@ static int _open_and_activate_reencrypt_
keyslot = r;
}
+ if (r >= 0) {
+ r = LUKS2_reencrypt_digest_verify(cd, hdr, vks);
+ if (r < 0)
+ goto err;
+ }
+
log_dbg(cd, "Entering clean reencryption state mode.");
if (r >= 0)
@@ -4059,8 +4065,9 @@ static int _open_and_activate_luks2(stru
uint32_t flags)
{
crypt_reencrypt_info ri;
- int r;
+ int r, rv;
struct luks2_hdr *hdr = &cd->u.luks2.hdr;
+ struct volume_key *vks = NULL;
ri = LUKS2_reenc_status(hdr);
if (ri == CRYPT_REENCRYPT_INVALID)
@@ -4070,9 +4077,17 @@ static int _open_and_activate_luks2(stru
if (name)
r = _open_and_activate_reencrypt_device(cd, hdr, keyslot, name, passphrase,
passphrase_size, flags);
- else
+ else {
r = _open_all_keys(cd, hdr, keyslot, passphrase,
- passphrase_size, flags, NULL);
+ passphrase_size, flags, &vks);
+ if (r < 0)
+ return r;
+
+ rv = LUKS2_reencrypt_digest_verify(cd, hdr, vks);
+ crypt_free_volume_key(vks);
+ if (rv < 0)
+ return rv;
+ }
} else
r = _open_and_activate(cd, keyslot, name, passphrase,
passphrase_size, flags);
diff -rupN cryptsetup-2.3.3.old/po/POTFILES.in cryptsetup-2.3.3/po/POTFILES.in
--- cryptsetup-2.3.3.old/po/POTFILES.in 2022-01-17 15:03:03.694201121 +0100
+++ cryptsetup-2.3.3/po/POTFILES.in 2022-01-17 15:05:48.166777223 +0100
@@ -37,6 +37,7 @@ lib/luks2/luks2_keyslot_luks2.c
lib/luks2/luks2_keyslot_reenc.c
lib/luks2/luks2_luks1_convert.c
lib/luks2/luks2_reencrypt.c
+lib/luks2/luks2_reencrypt_digest.c
lib/luks2/luks2_segment.c
lib/luks2/luks2_token.c
lib/luks2/luks2_token_keyring.c

View File

@ -1,25 +0,0 @@
From b1ef7cc3cdfb708bb08c90425a7dbdef383da84c Mon Sep 17 00:00:00 2001
From: Milan Broz <gmazyland@gmail.com>
Date: Thu, 13 Jan 2022 10:12:45 +0100
Subject: [PATCH 27/28] Fix reencrypt mangle test for older jq.
---
tests/luks2-reencryption-mangle-test | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/luks2-reencryption-mangle-test b/tests/luks2-reencryption-mangle-test
index 0cca23a0..8f308f5d 100755
--- a/tests/luks2-reencryption-mangle-test
+++ b/tests/luks2-reencryption-mangle-test
@@ -51,7 +51,7 @@ function img_json_save()
# FIXME: why --json-file cannot be used?
#$CRYPTSETUP luksDump --dump-json-metadata $IMG | jq -c -M | tr -d '\n' >$IMG_JSON
local LUKS2_JSON_SIZE=$(($JSON_MSIZE - 4096))
- _dd if=$IMG count=$LUKS2_JSON_SIZE skip=4096 | jq -c -M | tr -d '\n' >$IMG_JSON
+ _dd if=$IMG count=$LUKS2_JSON_SIZE skip=4096 | jq -c -M . | tr -d '\n' >$IMG_JSON
}
function img_json_dump()
--
2.27.0

View File

@ -1,93 +0,0 @@
From c75d740f9abd8a005975517008f780b16d103b0a Mon Sep 17 00:00:00 2001
From: Ondrej Kozina <okozina@redhat.com>
Date: Thu, 6 Jan 2022 12:24:26 +0100
Subject: [PATCH 20/28] Make reencryption flag and keyslot inseparable.
LUKS2 validation code now requires reencrypt keyslot together with
online-reencryption flag or none of those.
---
lib/luks2/luks2_keyslot.c | 25 +++++++++++++++++++++++++
lib/luks2/luks2_reencrypt.c | 17 +++++++++++------
2 files changed, 36 insertions(+), 6 deletions(-)
diff --git a/lib/luks2/luks2_keyslot.c b/lib/luks2/luks2_keyslot.c
index 2ad5632c..d93f2dda 100644
--- a/lib/luks2/luks2_keyslot.c
+++ b/lib/luks2/luks2_keyslot.c
@@ -878,10 +878,17 @@ int LUKS2_keyslots_validate(struct crypt_device *cd, json_object *hdr_jobj)
const keyslot_handler *h;
int keyslot;
json_object *jobj_keyslots, *jobj_type;
+ uint32_t reqs, reencrypt_count = 0;
+ struct luks2_hdr dummy = {
+ .jobj = hdr_jobj
+ };
if (!json_object_object_get_ex(hdr_jobj, "keyslots", &jobj_keyslots))
return -EINVAL;
+ if (LUKS2_config_get_requirements(cd, &dummy, &reqs))
+ return -EINVAL;
+
json_object_object_foreach(jobj_keyslots, slot, val) {
keyslot = atoi(slot);
json_object_object_get_ex(val, "type", &jobj_type);
@@ -897,6 +904,24 @@ int LUKS2_keyslots_validate(struct crypt_device *cd, json_object *hdr_jobj)
log_dbg(cd, "Keyslot %d is not assigned to exactly 1 digest.", keyslot);
return -EINVAL;
}
+
+ if (!strcmp(h->name, "reencrypt"))
+ reencrypt_count++;
+ }
+
+ if ((reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT) && reencrypt_count == 0) {
+ log_dbg(cd, "Missing reencryption keyslot.");
+ return -EINVAL;
+ }
+
+ if (!(reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT) && reencrypt_count) {
+ log_dbg(cd, "Missing reencryption requirement flag.");
+ return -EINVAL;
+ }
+
+ if (reencrypt_count > 1) {
+ log_dbg(cd, "Too many reencryption keyslots.");
+ return -EINVAL;
}
return 0;
diff --git a/lib/luks2/luks2_reencrypt.c b/lib/luks2/luks2_reencrypt.c
index f68675de..104871a4 100644
--- a/lib/luks2/luks2_reencrypt.c
+++ b/lib/luks2/luks2_reencrypt.c
@@ -3301,15 +3301,20 @@ static int reencrypt_teardown_ok(struct crypt_device *cd, struct luks2_hdr *hdr,
log_dbg(cd, "Failed to set new keyslots area size.");
if (rh->digest_old >= 0 && rh->digest_new != rh->digest_old)
for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++)
- if (LUKS2_digest_by_keyslot(hdr, i) == rh->digest_old)
- crypt_keyslot_destroy(cd, i);
- crypt_keyslot_destroy(cd, rh->reenc_keyslot);
+ if (LUKS2_digest_by_keyslot(hdr, i) == rh->digest_old && crypt_keyslot_destroy(cd, i))
+ log_err(cd, _("Failed to remove unused (unbound) keyslot %d."), i);
+
if (reencrypt_erase_backup_segments(cd, hdr))
log_dbg(cd, "Failed to erase backup segments");
- /* do we need atomic erase? */
- if (reencrypt_update_flag(cd, 0, true))
- log_err(cd, _("Failed to disable reencryption requirement flag."));
+ if (reencrypt_update_flag(cd, 0, false))
+ log_dbg(cd, "Failed to disable reencryption requirement flag.");
+
+ /* metadata commit point also removing reencryption flag on-disk */
+ if (crypt_keyslot_destroy(cd, rh->reenc_keyslot)) {
+ log_err(cd, _("Failed to remove reencryption keyslot."));
+ return -EINVAL;
+ }
}
return 0;
--
2.27.0

View File

@ -1,60 +0,0 @@
From 4e98b65c04b624888b39216c81da17b2d0aedfb8 Mon Sep 17 00:00:00 2001
From: Ondrej Kozina <okozina@redhat.com>
Date: Thu, 6 Jan 2022 14:28:36 +0100
Subject: [PATCH 15/28] Move requirement helpers for later changes.
---
lib/luks2/luks2_json_metadata.c | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/lib/luks2/luks2_json_metadata.c b/lib/luks2/luks2_json_metadata.c
index 6071b077..e45a9739 100644
--- a/lib/luks2/luks2_json_metadata.c
+++ b/lib/luks2/luks2_json_metadata.c
@@ -591,6 +591,21 @@ static bool validate_segment_intervals(struct crypt_device *cd,
return true;
}
+static int reqs_unknown(uint32_t reqs)
+{
+ return reqs & CRYPT_REQUIREMENT_UNKNOWN;
+}
+
+static int reqs_reencrypt(uint32_t reqs)
+{
+ return reqs & CRYPT_REQUIREMENT_OFFLINE_REENCRYPT;
+}
+
+static int reqs_reencrypt_online(uint32_t reqs)
+{
+ return reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
+}
+
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;
@@ -1138,21 +1153,6 @@ int LUKS2_hdr_backup(struct crypt_device *cd, struct luks2_hdr *hdr,
return r;
}
-static int reqs_unknown(uint32_t reqs)
-{
- return reqs & CRYPT_REQUIREMENT_UNKNOWN;
-}
-
-static int reqs_reencrypt(uint32_t reqs)
-{
- return reqs & CRYPT_REQUIREMENT_OFFLINE_REENCRYPT;
-}
-
-static int reqs_reencrypt_online(uint32_t reqs)
-{
- return reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
-}
-
int LUKS2_hdr_restore(struct crypt_device *cd, struct luks2_hdr *hdr,
const char *backup_file)
{
--
2.27.0

View File

@ -1,45 +0,0 @@
From 7eeb45537af1db8a29b4e2956545ccde8ad13d32 Mon Sep 17 00:00:00 2001
From: Milan Broz <gmazyland@gmail.com>
Date: Sun, 2 Jan 2022 16:57:31 +0100
Subject: [PATCH 12/28] Reenc keyslot must have key_size == 1.
---
lib/luks2/luks2_keyslot_reenc.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/lib/luks2/luks2_keyslot_reenc.c b/lib/luks2/luks2_keyslot_reenc.c
index 1956fe27..9da7007d 100644
--- a/lib/luks2/luks2_keyslot_reenc.c
+++ b/lib/luks2/luks2_keyslot_reenc.c
@@ -230,7 +230,7 @@ static int reenc_keyslot_dump(struct crypt_device *cd, int keyslot)
static int reenc_keyslot_validate(struct crypt_device *cd, json_object *jobj_keyslot)
{
- json_object *jobj_mode, *jobj_area, *jobj_type, *jobj_shift_size, *jobj_hash, *jobj_sector_size, *jobj_direction;
+ json_object *jobj_mode, *jobj_area, *jobj_type, *jobj_shift_size, *jobj_hash, *jobj_sector_size, *jobj_direction, *jobj_key_size;
const char *mode, *type, *direction;
uint32_t sector_size;
uint64_t shift_size;
@@ -250,12 +250,18 @@ static int reenc_keyslot_validate(struct crypt_device *cd, json_object *jobj_key
!json_object_object_get_ex(jobj_area, "type", &jobj_type))
return -EINVAL;
+ jobj_key_size = json_contains(cd, jobj_keyslot, "", "reencrypt keyslot", "key_size", json_type_int);
jobj_mode = json_contains(cd, jobj_keyslot, "", "reencrypt keyslot", "mode", json_type_string);
jobj_direction = json_contains(cd, jobj_keyslot, "", "reencrypt keyslot", "direction", json_type_string);
- if (!jobj_mode || !jobj_direction)
+ if (!jobj_mode || !jobj_direction || !jobj_key_size)
return -EINVAL;
+ if (!validate_json_uint32(jobj_key_size) || crypt_jobj_get_uint32(jobj_key_size) != 1) {
+ log_dbg(cd, "Illegal reencrypt key size.");
+ return -EINVAL;
+ }
+
mode = json_object_get_string(jobj_mode);
type = json_object_get_string(jobj_type);
direction = json_object_get_string(jobj_direction);
--
2.27.0

View File

@ -1,46 +0,0 @@
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2.h cryptsetup-2.3.3/lib/luks2/luks2.h
--- cryptsetup-2.3.3.old/lib/luks2/luks2.h 2022-01-17 16:17:59.479948764 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2.h 2022-01-17 16:20:30.466477626 +0100
@@ -284,7 +284,7 @@ int LUKS2_keyslot_reencrypt_store(struct
const void *buffer,
size_t buffer_length);
-int LUKS2_keyslot_reencrypt_create(struct crypt_device *cd,
+int LUKS2_keyslot_reencrypt_allocate(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
const struct crypt_params_reencrypt *params);
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_keyslot.c cryptsetup-2.3.3/lib/luks2/luks2_keyslot.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_keyslot.c 2022-01-17 16:17:59.478948761 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_keyslot.c 2022-01-17 16:19:00.458162353 +0100
@@ -596,7 +596,7 @@ int LUKS2_keyslot_open(struct crypt_devi
return r;
}
-int LUKS2_keyslot_reencrypt_create(struct crypt_device *cd,
+int LUKS2_keyslot_reencrypt_allocate(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
const struct crypt_params_reencrypt *params)
@@ -626,9 +626,6 @@ int LUKS2_keyslot_reencrypt_create(struc
return r;
}
- if (LUKS2_hdr_validate(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN))
- return -EINVAL;
-
return 0;
}
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_reencrypt.c cryptsetup-2.3.3/lib/luks2/luks2_reencrypt.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_reencrypt.c 2022-01-17 16:17:59.478948761 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_reencrypt.c 2022-01-17 16:19:00.459162357 +0100
@@ -2375,7 +2375,7 @@ static int reencrypt_init(struct crypt_d
goto err;
}
- r = LUKS2_keyslot_reencrypt_create(cd, hdr, reencrypt_keyslot,
+ r = LUKS2_keyslot_reencrypt_allocate(cd, hdr, reencrypt_keyslot,
params);
if (r < 0)
goto err;

View File

@ -1,57 +0,0 @@
From d0169a303de017ff0c847a5f752a2449a76fdd17 Mon Sep 17 00:00:00 2001
From: Ondrej Kozina <okozina@redhat.com>
Date: Thu, 6 Jan 2022 14:47:44 +0100
Subject: [PATCH 17/28] Split requirements validation from config section
validation.
---
lib/luks2/luks2_json_metadata.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/lib/luks2/luks2_json_metadata.c b/lib/luks2/luks2_json_metadata.c
index e45a9739..9109b07a 100644
--- a/lib/luks2/luks2_json_metadata.c
+++ b/lib/luks2/luks2_json_metadata.c
@@ -855,9 +855,10 @@ static int hdr_validate_digests(struct crypt_device *cd, json_object *hdr_jobj)
return 0;
}
+/* requirements being validated in stand-alone routine */
static int hdr_validate_config(struct crypt_device *cd, json_object *hdr_jobj)
{
- json_object *jobj_config, *jobj, *jobj1;
+ json_object *jobj_config, *jobj;
int i;
uint64_t keyslots_size, metadata_size, segment_offset;
@@ -912,6 +913,19 @@ static int hdr_validate_config(struct crypt_device *cd, json_object *hdr_jobj)
return 1;
}
+ return 0;
+}
+
+static int hdr_validate_requirements(struct crypt_device *cd, json_object *hdr_jobj)
+{
+ int i;
+ json_object *jobj_config, *jobj, *jobj1;
+
+ if (!json_object_object_get_ex(hdr_jobj, "config", &jobj_config)) {
+ log_dbg(cd, "Missing config section.");
+ return 1;
+ }
+
/* Requirements object is optional */
if (json_object_object_get_ex(jobj_config, "requirements", &jobj)) {
if (!json_contains(cd, jobj_config, "section", "Config", "requirements", json_type_object))
@@ -937,6 +951,7 @@ int LUKS2_hdr_validate(struct crypt_device *cd, json_object *hdr_jobj, uint64_t
struct {
int (*validate)(struct crypt_device *, json_object *);
} checks[] = {
+ { hdr_validate_requirements },
{ hdr_validate_tokens },
{ hdr_validate_digests },
{ hdr_validate_segments },
--
2.27.0

View File

@ -0,0 +1,53 @@
From a76310b53fbb117e620f2c37350b68dd267f1088 Mon Sep 17 00:00:00 2001
From: Milan Broz <gmazyland@gmail.com>
Date: Mon, 20 Sep 2021 17:42:20 +0200
Subject: [PATCH] Do not try to set compiler optimization flag if wipe is
implemented in libc.
If zeroing memory is implemented through libc call (like memset_bzero),
compiler should never remove such call. It is not needed to set O0
optimization flag explicitly.
Various checkers like annocheck causes problems with these flags,
just remove it where it makes no sense.
(Moreover, we use the same pattern without compiler magic
in crypt_backend_memzero() already.)
---
lib/crypto_backend/argon2/core.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/lib/crypto_backend/argon2/core.c b/lib/crypto_backend/argon2/core.c
index b204ba98..db9a7741 100644
--- a/lib/crypto_backend/argon2/core.c
+++ b/lib/crypto_backend/argon2/core.c
@@ -120,18 +120,24 @@ void free_memory(const argon2_context *context, uint8_t *memory,
}
}
-void NOT_OPTIMIZED secure_wipe_memory(void *v, size_t n) {
#if defined(_MSC_VER) && VC_GE_2005(_MSC_VER)
+void secure_wipe_memory(void *v, size_t n) {
SecureZeroMemory(v, n);
+}
#elif defined memset_s
+void secure_wipe_memory(void *v, size_t n) {
memset_s(v, n, 0, n);
+}
#elif defined(HAVE_EXPLICIT_BZERO)
+void secure_wipe_memory(void *v, size_t n) {
explicit_bzero(v, n);
+}
#else
+void NOT_OPTIMIZED secure_wipe_memory(void *v, size_t n) {
static void *(*const volatile memset_sec)(void *, int, size_t) = &memset;
memset_sec(v, 0, n);
-#endif
}
+#endif
/* Memory clear flag defaults to true. */
int FLAG_clear_internal_memory = 1;
--
2.27.0

View File

@ -0,0 +1,295 @@
From 9576549fee9228cabd9ceee27739a30caab5a7f6 Mon Sep 17 00:00:00 2001
From: Milan Broz <gmazyland@gmail.com>
Date: Tue, 9 Nov 2021 11:54:27 +0100
Subject: [PATCH] Fix bogus memory allocation if LUKS2 header size is invalid.
LUKS2 code read the whole header to buffer to verify checksum,
so malloc is called on unvalidated input size parameter.
This can cause out of memory or unintentional device reads.
(Header validation will fail later anyway - the size is unsupported.)
Just do not allow too small and too big allocations here and fail quickly.
Fixes: #683.
---
lib/luks2/luks2_disk_metadata.c | 20 +++-
...ks2-metadata-size-invalid-secondary.img.sh | 96 +++++++++++++++++++
...enerate-luks2-metadata-size-invalid.img.sh | 94 ++++++++++++++++++
tests/luks2-validation-test | 2 +
4 files changed, 208 insertions(+), 4 deletions(-)
create mode 100755 tests/generators/generate-luks2-metadata-size-invalid-secondary.img.sh
create mode 100755 tests/generators/generate-luks2-metadata-size-invalid.img.sh
diff --git a/lib/luks2/luks2_disk_metadata.c b/lib/luks2/luks2_disk_metadata.c
index 502b0226..0500d5c7 100644
--- a/lib/luks2/luks2_disk_metadata.c
+++ b/lib/luks2/luks2_disk_metadata.c
@@ -195,6 +195,8 @@ static int hdr_disk_sanity_check_pre(struct crypt_device *cd,
size_t *hdr_json_size, int secondary,
uint64_t offset)
{
+ uint64_t hdr_size;
+
if (memcmp(hdr->magic, secondary ? LUKS2_MAGIC_2ND : LUKS2_MAGIC_1ST, LUKS2_MAGIC_L))
return -EINVAL;
@@ -209,19 +211,26 @@ static int hdr_disk_sanity_check_pre(struct crypt_device *cd,
return -EINVAL;
}
- if (secondary && (offset != be64_to_cpu(hdr->hdr_size))) {
+ hdr_size = be64_to_cpu(hdr->hdr_size);
+
+ if (hdr_size < LUKS2_HDR_16K_LEN || hdr_size > LUKS2_HDR_OFFSET_MAX) {
+ log_dbg(cd, "LUKS2 header has bogus size 0x%04x.", (unsigned)hdr_size);
+ return -EINVAL;
+ }
+
+ if (secondary && (offset != hdr_size)) {
log_dbg(cd, "LUKS2 offset 0x%04x in secondary header does not match size 0x%04x.",
- (unsigned)offset, (unsigned)be64_to_cpu(hdr->hdr_size));
+ (unsigned)offset, (unsigned)hdr_size);
return -EINVAL;
}
/* FIXME: sanity check checksum alg. */
log_dbg(cd, "LUKS2 header version %u of size %u bytes, checksum %s.",
- (unsigned)be16_to_cpu(hdr->version), (unsigned)be64_to_cpu(hdr->hdr_size),
+ (unsigned)be16_to_cpu(hdr->version), (unsigned)hdr_size,
hdr->checksum_alg);
- *hdr_json_size = be64_to_cpu(hdr->hdr_size) - LUKS2_HDR_BIN_LEN;
+ *hdr_json_size = hdr_size - LUKS2_HDR_BIN_LEN;
return 0;
}
@@ -252,6 +261,9 @@ static int hdr_read_disk(struct crypt_device *cd,
return -EIO;
}
+ /*
+ * hdr_json_size is validated if this call succeeds
+ */
r = hdr_disk_sanity_check_pre(cd, hdr_disk, &hdr_json_size, secondary, offset);
if (r < 0) {
return r;
diff --git a/tests/generators/generate-luks2-metadata-size-invalid-secondary.img.sh b/tests/generators/generate-luks2-metadata-size-invalid-secondary.img.sh
new file mode 100755
index 00000000..4dd484e9
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-invalid-secondary.img.sh
@@ -0,0 +1,96 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary with predefined json_size. There's only limited
+# set of values allowed as json size in config section of LUKS2
+# metadata
+#
+# 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()
+{
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_1M
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_MDA_SIZE_BOGUS_BYTES=$((TEST_MDA_SIZE*512*2*1024))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BOGUS_BYTES
+
+ write_bin_hdr_offset $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ merge_bin_hdr_with_json $TMPDIR/hdr0 $TMPDIR/json0 $TMPDIR/area0 $TEST_JSN_SIZE
+ merge_bin_hdr_with_json $TMPDIR/hdr1 $TMPDIR/json0 $TMPDIR/area1 $TEST_JSN_SIZE
+
+ erase_checksum $TMPDIR/area0
+ chks0=$(calc_sha256_checksum_file $TMPDIR/area0)
+ write_checksum $chks0 $TMPDIR/area0
+
+ erase_checksum $TMPDIR/area1
+ chks0=$(calc_sha256_checksum_file $TMPDIR/area1)
+ write_checksum $chks0 $TMPDIR/area1
+
+ kill_bin_hdr $TMPDIR/area0
+
+ write_luks2_hdr0 $TMPDIR/area0 $TGT_IMG $TEST_MDA_SIZE
+ write_luks2_hdr1 $TMPDIR/area1 $TGT_IMG $TEST_MDA_SIZE
+}
+
+function check()
+{
+ read_luks2_bin_hdr0 $TGT_IMG $TMPDIR/hdr_res0 $TEST_MDA_SIZE
+ local str_res0=$(head -c 6 $TMPDIR/hdr_res0)
+ test "$str_res0" = "VACUUM" || exit 2
+ read_luks2_json1 $TGT_IMG $TMPDIR/json_res1 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res1 || 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-metadata-size-invalid.img.sh b/tests/generators/generate-luks2-metadata-size-invalid.img.sh
new file mode 100755
index 00000000..6b9c0cf7
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-invalid.img.sh
@@ -0,0 +1,94 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary with predefined json_size. There's only limited
+# set of values allowed as json size in config section of LUKS2
+# metadata
+#
+# 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()
+{
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_1M
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_MDA_SIZE_BOGUS_BYTES=$((TEST_MDA_SIZE*512*2*1024))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BOGUS_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BOGUS_BYTES
+
+ merge_bin_hdr_with_json $TMPDIR/hdr0 $TMPDIR/json0 $TMPDIR/area0 $TEST_JSN_SIZE
+ merge_bin_hdr_with_json $TMPDIR/hdr1 $TMPDIR/json0 $TMPDIR/area1 $TEST_JSN_SIZE
+
+ erase_checksum $TMPDIR/area0
+ chks0=$(calc_sha256_checksum_file $TMPDIR/area0)
+ write_checksum $chks0 $TMPDIR/area0
+
+ erase_checksum $TMPDIR/area1
+ chks0=$(calc_sha256_checksum_file $TMPDIR/area1)
+ write_checksum $chks0 $TMPDIR/area1
+
+ kill_bin_hdr $TMPDIR/area1
+
+ write_luks2_hdr0 $TMPDIR/area0 $TGT_IMG $TEST_MDA_SIZE
+ write_luks2_hdr1 $TMPDIR/area1 $TGT_IMG $TEST_MDA_SIZE
+}
+
+function check()
+{
+ read_luks2_bin_hdr1 $TGT_IMG $TMPDIR/hdr_res1 $TEST_MDA_SIZE
+ local str_res1=$(head -c 6 $TMPDIR/hdr_res1)
+ test "$str_res1" = "VACUUM" || exit 2
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") 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 04183fbc..f771e1f9 100755
--- a/tests/luks2-validation-test
+++ b/tests/luks2-validation-test
@@ -229,6 +229,8 @@ RUN luks2-metadata-size-512k-secondary.img "R" "Valid 512KiB metadata size in s
RUN luks2-metadata-size-1m-secondary.img "R" "Valid 1MiB metadata size in secondary hdr failed to validate"
RUN luks2-metadata-size-2m-secondary.img "R" "Valid 2MiB metadata size in secondary hdr failed to validate"
RUN luks2-metadata-size-4m-secondary.img "R" "Valid 4MiB metadata size in secondary hdr failed to validate"
+RUN luks2-metadata-size-invalid.img "F" "Invalid metadata size in secondary hdr not rejected"
+RUN luks2-metadata-size-invalid-secondary.img "F" "Invalid metadata size in secondary hdr not rejected"
remove_mapping
--
2.27.0

View File

@ -0,0 +1,41 @@
From f671febe64d8f40cdcb1677a08436a8907ccbb7e Mon Sep 17 00:00:00 2001
From: Ondrej Kozina <okozina@redhat.com>
Date: Wed, 23 Feb 2022 12:27:57 +0100
Subject: [PATCH 2/3] Add more tests for --test-passphrase parameter.
---
tests/compat-test-args | 4 ++++
tests/luks2-reencryption-test | 18 ++++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/tests/luks2-reencryption-test b/tests/luks2-reencryption-test
index 6f156016..73818b5d 100755
--- a/tests/luks2-reencryption-test
+++ b/tests/luks2-reencryption-test
@@ -1606,5 +1606,23 @@ if [ -n "$DM_SECTOR_SIZE" ]; then
reencrypt_recover_online 4096 journal $HASH1
fi
+echo "[27] Verify test passphrase mode works with reencryption metadata"
+echo $PWD1 | $CRYPTSETUP -S5 -q luksFormat --type luks2 $FAST_PBKDF_ARGON $DEV || fail
+echo -e "$PWD1\n$PWD1" | $CRYPTSETUP luksAddKey --unbound -s80 -S0 $FAST_PBKDF_ARGON $DEV || fail
+echo $PWD1 | $CRYPTSETUP reencrypt --init-only $DEV || fail
+echo $PWD1 | $CRYPTSETUP open --test-passphrase $DEV || fail
+
+echo $PWD1 | $CRYPTSETUP -q luksFormat -S5 --header $IMG_HDR --type luks2 $FAST_PBKDF_ARGON $DEV || fail
+echo -e "$PWD1\n$PWD1" | $CRYPTSETUP luksAddKey --unbound -s80 -S0 $FAST_PBKDF_ARGON $IMG_HDR || fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt --init-only --header $IMG_HDR $DEV || fail
+echo $PWD1 | $CRYPTSETUP open --test-passphrase $IMG_HDR || fail
+
+echo $PWD1 | $CRYPTSETUP reencrypt -q --encrypt --init-only --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+echo $PWD1 | $CRYPTSETUP open --test-passphrase $IMG_HDR || fail
+
+wipe_dev $DEV
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --init-only --reduce-device-size 8M $FAST_PBKDF_ARGON $DEV || fail
+echo $PWD1 | $CRYPTSETUP open --test-passphrase $DEV || fail
+
remove_mapping
exit 0
--
2.27.0

View File

@ -0,0 +1,103 @@
diff -rupN cryptsetup-2.3.7.old/man/cryptsetup.8 cryptsetup-2.3.7/man/cryptsetup.8
--- cryptsetup-2.3.7.old/man/cryptsetup.8 2022-02-24 15:58:37.968167423 +0100
+++ cryptsetup-2.3.7/man/cryptsetup.8 2022-02-24 17:06:25.326217548 +0100
@@ -321,7 +321,7 @@ the command prompts for it interactively
\-\-keyfile\-size, \-\-readonly, \-\-test\-passphrase,
\-\-allow\-discards, \-\-header, \-\-key-slot, \-\-master\-key\-file, \-\-token\-id,
\-\-token\-only, \-\-disable\-keyring, \-\-disable\-locks, \-\-type, \-\-refresh,
-\-\-serialize\-memory\-hard\-pbkdf].
+\-\-serialize\-memory\-hard\-pbkdf, \-\-unbound].
.PP
\fIluksSuspend\fR <name>
.IP
@@ -1409,10 +1409,14 @@ aligned to page size and page-cache init
integrity tag.
.TP
.B "\-\-unbound"
-
Creates new or dumps existing LUKS2 unbound keyslot. See \fIluksAddKey\fR or
\fIluksDump\fR actions for more details.
+When used in \fIluksOpen\fR action (allowed only together with
+\-\-test\-passphrase parameter), it allows to test passphrase for unbound LUKS2
+keyslot. Otherwise, unbound keyslot passphrase can be tested only when specific
+keyslot is selected via \-\-key\-slot parameter.
+
.TP
.B "\-\-tcrypt\-hidden"
.B "\-\-tcrypt\-system"
diff -rupN cryptsetup-2.3.7.old/src/cryptsetup.c cryptsetup-2.3.7/src/cryptsetup.c
--- cryptsetup-2.3.7.old/src/cryptsetup.c 2022-02-24 15:58:37.969167429 +0100
+++ cryptsetup-2.3.7/src/cryptsetup.c 2022-02-24 17:10:30.947561638 +0100
@@ -230,7 +230,7 @@ static void _set_activation_flags(uint32
*flags |= CRYPT_ACTIVATE_IGNORE_PERSISTENT;
/* Only for LUKS2 but ignored elsewhere */
- if (opt_test_passphrase)
+ if (opt_test_passphrase && (opt_unbound || (opt_key_slot != CRYPT_ANY_SLOT)))
*flags |= CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY;
if (opt_serialize_memory_hard_pbkdf)
@@ -4021,6 +4021,17 @@ int main(int argc, const char **argv)
_("Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device."),
poptGetInvocationName(popt_context));
+ if (opt_unbound && !strcmp(aname, "open") && device_type &&
+ strncmp(device_type, "luks", 4))
+ usage(popt_context, EXIT_FAILURE,
+ _("Option --unbound is allowed only for open of luks device."),
+ poptGetInvocationName(popt_context));
+
+ if (opt_unbound && !opt_test_passphrase && !strcmp(aname, "open"))
+ usage(popt_context, EXIT_FAILURE,
+ _("Option --unbound cannot be used without --test-passphrase."),
+ poptGetInvocationName(popt_context));
+
if (opt_tcrypt_hidden && opt_allow_discards)
usage(popt_context, EXIT_FAILURE,
_("Option --tcrypt-hidden cannot be combined with --allow-discards."),
@@ -4103,9 +4114,9 @@ int main(int argc, const char **argv)
_("Keyslot specification is required."),
poptGetInvocationName(popt_context));
- if (opt_unbound && strcmp(aname, "luksAddKey") && strcmp(aname, "luksDump"))
+ if (opt_unbound && strcmp(aname, "luksAddKey") && strcmp(aname, "luksDump") && strcmp(aname, "open"))
usage(popt_context, EXIT_FAILURE,
- _("Option --unbound may be used only with luksAddKey and luksDump actions."),
+ _("Option --unbound may be used only with luksAddKey, luksDump and open actions."),
poptGetInvocationName(popt_context));
if (opt_refresh && strcmp(aname, "open"))
diff -rupN cryptsetup-2.3.7.old/tests/compat-test2 cryptsetup-2.3.7/tests/compat-test2
--- cryptsetup-2.3.7.old/tests/compat-test2 2022-02-24 15:58:38.013167680 +0100
+++ cryptsetup-2.3.7/tests/compat-test2 2022-02-24 17:23:23.035760517 +0100
@@ -696,7 +696,7 @@ $CRYPTSETUP luksOpen -S 5 -d $KEY1 $LOOP
# otoh it should be allowed to test for proper passphrase
prepare "" new
echo $PWD1 | $CRYPTSETUP open -S1 --test-passphrase $HEADER_KEYU || fail
-echo $PWD1 | $CRYPTSETUP open --test-passphrase $HEADER_KEYU || fail
+echo $PWD1 | $CRYPTSETUP open --unbound --test-passphrase $HEADER_KEYU || fail
echo $PWD1 | $CRYPTSETUP open -S1 $HEADER_KEYU $DEV_NAME 2>/dev/null && fail
[ -b /dev/mapper/$DEV_NAME ] && fail
echo $PWD1 | $CRYPTSETUP open $HEADER_KEYU $DEV_NAME 2>/dev/null && fail
@@ -705,7 +705,7 @@ echo $PWD0 | $CRYPTSETUP open -S1 --test
$CRYPTSETUP luksKillSlot -q $HEADER_KEYU 0
$CRYPTSETUP luksDump $HEADER_KEYU | grep -q "0: luks2" && fail
echo $PWD1 | $CRYPTSETUP open -S1 --test-passphrase $HEADER_KEYU || fail
-echo $PWD1 | $CRYPTSETUP open --test-passphrase $HEADER_KEYU || fail
+echo $PWD1 | $CRYPTSETUP open --unbound --test-passphrase $HEADER_KEYU || fail
echo $PWD1 | $CRYPTSETUP open -S1 $HEADER_KEYU $DEV_NAME 2>/dev/null && fail
prepare "[28] Detached LUKS header" wipe
@@ -952,11 +952,9 @@ echo $PWD3 | $CRYPTSETUP -q luksAddKey -
# do not allow to replace keyslot by unbound slot
echo $PWD1 | $CRYPTSETUP -q luksAddKey -S5 --unbound -s 32 $LOOPDEV 2>/dev/null && fail
echo $PWD2 | $CRYPTSETUP -q open $LOOPDEV $DEV_NAME 2> /dev/null && fail
-echo $PWD2 | $CRYPTSETUP -q open $LOOPDEV --test-passphrase || fail
echo $PWD2 | $CRYPTSETUP -q open -S2 $LOOPDEV $DEV_NAME 2> /dev/null && fail
echo $PWD2 | $CRYPTSETUP -q open -S2 $LOOPDEV --test-passphrase || fail
echo $PWD1 | $CRYPTSETUP -q open $LOOPDEV $DEV_NAME 2> /dev/null && fail
-echo $PWD1 | $CRYPTSETUP -q open $LOOPDEV --test-passphrase || fail
# check we're able to change passphrase for unbound keyslot
echo -e "$PWD2\n$PWD3" | $CRYPTSETUP luksChangeKey $FAST_PBKDF_OPT -S 2 $LOOPDEV || fail
echo $PWD3 | $CRYPTSETUP open --test-passphrase $FAST_PBKDF_OPT -S 2 $LOOPDEV || fail

View File

@ -0,0 +1,12 @@
diff -rupN cryptsetup-2.3.7.old/src/cryptsetup.c cryptsetup-2.3.7/src/cryptsetup.c
--- cryptsetup-2.3.7.old/src/cryptsetup.c 2022-01-20 14:47:13.198475734 +0100
+++ cryptsetup-2.3.7/src/cryptsetup.c 2022-01-20 14:47:24.186505625 +0100
@@ -1137,7 +1137,7 @@ static int reencrypt_metadata_repair(str
_("Operation aborted.\n")))
return -EINVAL;
- r = tools_get_key(_("Enter passphrase to protect and uppgrade reencryption metadata: "),
+ r = tools_get_key(_("Enter passphrase to protect and upgrade reencryption metadata: "),
&password, &passwordLen, opt_keyfile_offset,
opt_keyfile_size, opt_key_file, opt_timeout,
_verify_passphrase(0), 0, cd);

View File

@ -1,74 +0,0 @@
diff -rupN cryptsetup-2.3.3.old/Makefile.in cryptsetup-2.3.3/Makefile.in
--- cryptsetup-2.3.3.old/Makefile.in 2020-05-28 11:32:48.000000000 +0200
+++ cryptsetup-2.3.3/Makefile.in 2022-01-14 14:58:17.797173340 +0100
@@ -292,6 +292,7 @@ am_libcryptsetup_la_OBJECTS = lib/libcry
lib/luks2/libcryptsetup_la-luks2_keyslot_luks2.lo \
lib/luks2/libcryptsetup_la-luks2_keyslot_reenc.lo \
lib/luks2/libcryptsetup_la-luks2_reencrypt.lo \
+ lib/luks2/libcryptsetup_la-luks2_reencrypt_digest.lo \
lib/luks2/libcryptsetup_la-luks2_segment.lo \
lib/luks2/libcryptsetup_la-luks2_token_keyring.lo \
lib/luks2/libcryptsetup_la-luks2_token.lo \
@@ -530,6 +531,7 @@ am__depfiles_remade = lib/$(DEPDIR)/libc
lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_reenc.Plo \
lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_luks1_convert.Plo \
lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt.Plo \
+ lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt_digest.Plo \
lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Plo \
lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token.Plo \
lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token_keyring.Plo \
@@ -1005,6 +1009,7 @@ libcryptsetup_la_SOURCES = \
lib/luks2/luks2_keyslot_luks2.c \
lib/luks2/luks2_keyslot_reenc.c \
lib/luks2/luks2_reencrypt.c \
+ lib/luks2/luks2_reencrypt_digest.c \
lib/luks2/luks2_segment.c \
lib/luks2/luks2_token_keyring.c \
lib/luks2/luks2_token.c \
@@ -1493,6 +1498,8 @@ lib/luks2/libcryptsetup_la-luks2_keyslot
lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp)
lib/luks2/libcryptsetup_la-luks2_reencrypt.lo: \
lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp)
+lib/luks2/libcryptsetup_la-luks2_reencrypt_digest.lo: \
+ lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp)
lib/luks2/libcryptsetup_la-luks2_segment.lo: \
lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp)
lib/luks2/libcryptsetup_la-luks2_token_keyring.lo: \
@@ -1670,6 +1677,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_reenc.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_luks1_convert.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt_digest.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token_keyring.Plo@am__quote@ # am--include-marker
@@ -2138,6 +2146,13 @@ lib/luks2/libcryptsetup_la-luks2_reencry
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks2/libcryptsetup_la-luks2_reencrypt.lo `test -f 'lib/luks2/luks2_reencrypt.c' || echo '$(srcdir)/'`lib/luks2/luks2_reencrypt.c
+lib/luks2/libcryptsetup_la-luks2_reencrypt_digest.lo: lib/luks2/luks2_reencrypt_digest.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks2/libcryptsetup_la-luks2_reencrypt_digest.lo -MD -MP -MF lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt_digest.Tpo -c -o lib/luks2/libcryptsetup_la-luks2_reencrypt_digest.lo `test -f 'lib/luks2/luks2_reencrypt_digest.c' || echo '$(srcdir)/'`lib/luks2/luks2_reencrypt_digest.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt_digest.Tpo lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt_digest.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/luks2/luks2_reencrypt_digest.c' object='lib/luks2/libcryptsetup_la-luks2_reencrypt_digest.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks2/libcryptsetup_la-luks2_reencrypt_digest.lo `test -f 'lib/luks2/luks2_reencrypt_digest.c' || echo '$(srcdir)/'`lib/luks2/luks2_reencrypt_digest.c
+
lib/luks2/libcryptsetup_la-luks2_segment.lo: lib/luks2/luks2_segment.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks2/libcryptsetup_la-luks2_segment.lo -MD -MP -MF lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Tpo -c -o lib/luks2/libcryptsetup_la-luks2_segment.lo `test -f 'lib/luks2/luks2_segment.c' || echo '$(srcdir)/'`lib/luks2/luks2_segment.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Tpo lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Plo
@@ -2738,6 +2754,7 @@ distclean: distclean-recursive
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_reenc.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_luks1_convert.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt.Plo
+ -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt_digest.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token_keyring.Plo
@@ -2864,6 +2881,7 @@ maintainer-clean: maintainer-clean-recur
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_reenc.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_luks1_convert.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt.Plo
+ -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt_digest.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token_keyring.Plo

View File

@ -1,19 +0,0 @@
diff -rupN cryptsetup-2.3.3.old/tests/Makefile.in cryptsetup-2.3.3/tests/Makefile.in
--- cryptsetup-2.3.3.old/tests/Makefile.in 2022-01-14 16:25:59.283158424 +0100
+++ cryptsetup-2.3.3/tests/Makefile.in 2022-01-14 16:27:15.094215021 +0100
@@ -441,6 +441,7 @@ EXTRA_DIST = compatimage.img.xz compatv1
reencryption-compat-test \
reencryption-compat-test2 \
luks2-reencryption-test \
+ luks2-reencryption-mangle-test \
tcrypt-compat-test \
luks1-compat-test \
luks2-validation-test generators \
@@ -1023,6 +1024,7 @@ valgrind-check: api-test api-test-2 diff
@INFOSTRING="api-test-000" ./valg-api.sh ./api-test
@INFOSTRING="api-test-002" ./valg-api.sh ./api-test-2
@VALG=1 ./luks2-reencryption-test
+ @VALG=1 ./luks2-reencryption-mangle-test
@VALG=1 ./compat-test
.PHONY: valgrind-check

View File

@ -4,8 +4,8 @@ Obsoletes: cryptsetup-python3
Summary: A utility for setting up encrypted disks
Name: cryptsetup
Version: 2.3.3
Release: 4%{?dist}.1
Version: 2.3.7
Release: 2%{?dist}
License: GPLv2+ and LGPLv2+
Group: Applications/System
URL: https://gitlab.com/cryptsetup/cryptsetup
@ -23,27 +23,11 @@ Source0: https://www.kernel.org/pub/linux/utils/cryptsetup/v2.0/cryptsetup-%{ups
Patch0: %{name}-add-system-library-paths.patch
# Remove the patch when (if ever) osci infrastructure gets stable enough
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
# CVE-2021-4122 fix
Patch5: %{name}-2.3.7-Fix-CVE-2021-4122-LUKS2-reencryption-crash-recovery-.patch
Patch6: %{name}-2.3.7-Reenc-keyslot-must-have-key_size-1.patch
Patch7: %{name}-2.3.7-Do-not-run-reencryption-recovery-when-not-needed.patch
Patch8: %{name}-2.3.7-Move-requirement-helpers-for-later-changes.patch
Patch9: %{name}-2.3.7-Expose-json_segment_contains_flag-to-internal-librar.patch
Patch10: %{name}-2.3.7-Split-requirements-validation-from-config-section-va.patch
Patch11: %{name}-2.3.7-Add-segments-validation-for-reencryption.patch
Patch12: %{name}-2.3.7-Rename-LUKS2_keyslot_reencrypt_create-function.patch
Patch13: %{name}-2.3.7-Make-reencryption-flag-and-keyslot-inseparable.patch
Patch14: %{name}-2.3.7-Add-reencryption-mangle-test.patch
# cryptsetup manual repair command able to upgrade/verify reencryption metadata
Patch15: %{name}-2.3.7-Add-CRYPT_REENCRYPT_REPAIR_NEEDED-flag.patch
Patch16: %{name}-2.3.7-Allow-reencryption-metadata-repair-from-cryptsetup.patch
Patch17: %{name}-2.3.7-Fix-reencrypt-mangle-test-for-older-jq.patch
Patch18: %{name}-Makefile-in.patch
Patch19: %{name}-tests-Makefile-in.patch
Patch2: %{name}-2.4.2-Do-not-try-to-set-compiler-optimization-flag-if-wipe.patch
Patch3: %{name}-2.4.2-Fix-bogus-memory-allocation-if-LUKS2-header-size-is-.patch
Patch4: %{name}-2.5.0-Fix-typo-in-repair-prompt.patch
Patch5: %{name}-2.5.0-Fix-test-passphrase-when-device-in-reencryption.patch
Patch6: %{name}-2.5.0-Add-more-tests-for-test-passphrase-parameter.patch
%description
The cryptsetup package contains a utility for setting up
@ -105,22 +89,8 @@ can be used for offline reencryption of disk in situ.
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1
%patch19 -p1
%patch0 -p1
chmod -x misc/dracut_90reencrypt/*
chmod +x tests/luks2-reencryption-mangle-test
%build
%configure --enable-fips --enable-pwquality --enable-internal-sse-argon2 --with-crypto_backend=openssl --with-default-luks-format=LUKS2
@ -178,9 +148,19 @@ rm -rf %{buildroot}/%{_libdir}/*.la
%clean
%changelog
* Fri Jan 14 2022 Ondrej Kozina <okozina@redhat.com> - 2.3.3-4.1
- patch: fix CVE-2021-4122.
- Resolves: #2036906
* Thu Feb 24 2022 Ondrej Kozina <okozina@redhat.com> - 2.3.7-2
- patch: Fix cryptsetup --test-passphrase when device in
reencryption
- Resolves: #2058009
* Thu Jan 20 2022 Ondrej Kozina <okozina@redhat.com> - 2.3.7-1
- update to cryptsetup 2.3.7
- fixes CVE-2021-4122
- patch: Fix suboptimal optimization in bundled argon2.
- patch: Fix bogus memory allocation/device read with
invalid LUKS2 headers
- patch: Fix typo in luksRepair prompt.
- Resolves: #2021815 #2022301 #2031859
* Wed Feb 17 2021 Ondrej Kozina <okozina@redhat.com> - 2.3.3-4
- patch: Fix reencryption for custom devices with data segments