|
|
4bba8a |
From 6bc1378ddb5bbcc6ba592177c996576b0b3505f9 Mon Sep 17 00:00:00 2001
|
|
|
4bba8a |
From: Ondrej Kozina <okozina@redhat.com>
|
|
|
4bba8a |
Date: Fri, 22 Oct 2021 13:06:48 +0200
|
|
|
4bba8a |
Subject: [PATCH] Remove LUKS2 encryption data size restriction.
|
|
|
4bba8a |
|
|
|
4bba8a |
LUKS2 encryption with data shift required remaining
|
|
|
4bba8a |
data size (size remaining after substracting --reduce-data-size value)
|
|
|
4bba8a |
to be at least --reduce-data-size. This was wrong. Remaining
|
|
|
4bba8a |
data size restriction should be correctly at least single sector
|
|
|
4bba8a |
(whatever sector size is selected or auto-detected).
|
|
|
4bba8a |
---
|
|
|
4bba8a |
lib/luks2/luks2_reencrypt.c | 31 ++++++++++++-----------
|
|
|
4bba8a |
tests/api-test-2.c | 6 ++---
|
|
|
4bba8a |
tests/luks2-reencryption-test | 46 +++++++++++++++++++++++++++++------
|
|
|
4bba8a |
3 files changed, 57 insertions(+), 26 deletions(-)
|
|
|
4bba8a |
|
|
|
4bba8a |
diff --git a/lib/luks2/luks2_reencrypt.c b/lib/luks2/luks2_reencrypt.c
|
|
|
4bba8a |
index b45327ad..d0e0dc40 100644
|
|
|
4bba8a |
--- a/lib/luks2/luks2_reencrypt.c
|
|
|
4bba8a |
+++ b/lib/luks2/luks2_reencrypt.c
|
|
|
4bba8a |
@@ -825,7 +825,7 @@ static int reencrypt_offset_backward_moved(struct luks2_hdr *hdr, json_object *j
|
|
|
4bba8a |
linear_length += LUKS2_segment_size(hdr, sg, 0);
|
|
|
4bba8a |
|
|
|
4bba8a |
/* all active linear segments length */
|
|
|
4bba8a |
- if (linear_length) {
|
|
|
4bba8a |
+ if (linear_length && segs > 1) {
|
|
|
4bba8a |
if (linear_length < data_shift)
|
|
|
4bba8a |
return -EINVAL;
|
|
|
4bba8a |
tmp = linear_length - data_shift;
|
|
|
4bba8a |
@@ -1745,7 +1745,8 @@ static int reencrypt_set_encrypt_segments(struct crypt_device *cd, struct luks2_
|
|
|
4bba8a |
int r;
|
|
|
4bba8a |
uint64_t first_segment_offset, first_segment_length,
|
|
|
4bba8a |
second_segment_offset, second_segment_length,
|
|
|
4bba8a |
- data_offset = LUKS2_get_data_offset(hdr) << SECTOR_SHIFT;
|
|
|
4bba8a |
+ data_offset = LUKS2_get_data_offset(hdr) << SECTOR_SHIFT,
|
|
|
4bba8a |
+ data_size = dev_size - data_shift;
|
|
|
4bba8a |
json_object *jobj_segment_first = NULL, *jobj_segment_second = NULL, *jobj_segments;
|
|
|
4bba8a |
|
|
|
4bba8a |
if (dev_size < data_shift)
|
|
|
4bba8a |
@@ -1760,9 +1761,14 @@ static int reencrypt_set_encrypt_segments(struct crypt_device *cd, struct luks2_
|
|
|
4bba8a |
* [future LUKS2 header (data shift size)][second data segment][gap (data shift size)][first data segment (data shift size)]
|
|
|
4bba8a |
*/
|
|
|
4bba8a |
first_segment_offset = dev_size;
|
|
|
4bba8a |
- first_segment_length = data_shift;
|
|
|
4bba8a |
- second_segment_offset = data_shift;
|
|
|
4bba8a |
- second_segment_length = dev_size - 2 * data_shift;
|
|
|
4bba8a |
+ if (data_size < data_shift) {
|
|
|
4bba8a |
+ first_segment_length = data_size;
|
|
|
4bba8a |
+ second_segment_length = second_segment_offset = 0;
|
|
|
4bba8a |
+ } else {
|
|
|
4bba8a |
+ first_segment_length = data_shift;
|
|
|
4bba8a |
+ second_segment_offset = data_shift;
|
|
|
4bba8a |
+ second_segment_length = data_size - data_shift;
|
|
|
4bba8a |
+ }
|
|
|
4bba8a |
} else if (data_shift) {
|
|
|
4bba8a |
first_segment_offset = data_offset;
|
|
|
4bba8a |
first_segment_length = dev_size;
|
|
|
4bba8a |
@@ -2163,17 +2169,10 @@ static int reencrypt_move_data(struct crypt_device *cd, int devfd, uint64_t data
|
|
|
4bba8a |
|
|
|
4bba8a |
log_dbg(cd, "Going to move data from head of data device.");
|
|
|
4bba8a |
|
|
|
4bba8a |
- buffer_len = data_shift;
|
|
|
4bba8a |
- if (!buffer_len)
|
|
|
4bba8a |
- return -EINVAL;
|
|
|
4bba8a |
-
|
|
|
4bba8a |
offset = json_segment_get_offset(LUKS2_get_segment_jobj(hdr, 0), 0);
|
|
|
4bba8a |
-
|
|
|
4bba8a |
- /* this is nonsense anyway */
|
|
|
4bba8a |
- if (buffer_len != json_segment_get_size(LUKS2_get_segment_jobj(hdr, 0), 0)) {
|
|
|
4bba8a |
- log_dbg(cd, "buffer_len %" PRIu64", segment size %" PRIu64, buffer_len, json_segment_get_size(LUKS2_get_segment_jobj(hdr, 0), 0));
|
|
|
4bba8a |
+ buffer_len = json_segment_get_size(LUKS2_get_segment_jobj(hdr, 0), 0);
|
|
|
4bba8a |
+ if (!buffer_len || buffer_len > data_shift)
|
|
|
4bba8a |
return -EINVAL;
|
|
|
4bba8a |
- }
|
|
|
4bba8a |
|
|
|
4bba8a |
if (posix_memalign(&buffer, device_alignment(crypt_data_device(cd)), buffer_len))
|
|
|
4bba8a |
return -ENOMEM;
|
|
|
4bba8a |
@@ -2447,7 +2446,7 @@ static int reencrypt_init(struct crypt_device *cd,
|
|
|
4bba8a |
* encryption initialization (or mount)
|
|
|
4bba8a |
*/
|
|
|
4bba8a |
if (move_first_segment) {
|
|
|
4bba8a |
- if (dev_size < 2 * (params->data_shift << SECTOR_SHIFT)) {
|
|
|
4bba8a |
+ if (dev_size < (params->data_shift << SECTOR_SHIFT)) {
|
|
|
4bba8a |
log_err(cd, _("Device %s is too small."), device_path(crypt_data_device(cd)));
|
|
|
4bba8a |
return -EINVAL;
|
|
|
4bba8a |
}
|
|
|
4bba8a |
@@ -3484,7 +3483,7 @@ int LUKS2_reencrypt_check_device_size(struct crypt_device *cd, struct luks2_hdr
|
|
|
4bba8a |
check_size, check_size >> SECTOR_SHIFT, real_size, real_size >> SECTOR_SHIFT,
|
|
|
4bba8a |
real_size - data_offset, (real_size - data_offset) >> SECTOR_SHIFT);
|
|
|
4bba8a |
|
|
|
4bba8a |
- if (real_size < data_offset || (check_size && (real_size - data_offset) < check_size)) {
|
|
|
4bba8a |
+ if (real_size < data_offset || (check_size && real_size < check_size)) {
|
|
|
4bba8a |
log_err(cd, _("Device %s is too small."), device_path(crypt_data_device(cd)));
|
|
|
4bba8a |
return -EINVAL;
|
|
|
4bba8a |
}
|
|
|
4bba8a |
diff --git a/tests/api-test-2.c b/tests/api-test-2.c
|
|
|
4bba8a |
index a01a7a72..05ee8f94 100644
|
|
|
4bba8a |
--- a/tests/api-test-2.c
|
|
|
4bba8a |
+++ b/tests/api-test-2.c
|
|
|
4bba8a |
@@ -4238,7 +4238,7 @@ static void Luks2Reencryption(void)
|
|
|
4bba8a |
|
|
|
4bba8a |
_cleanup_dmdevices();
|
|
|
4bba8a |
OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
|
|
|
4bba8a |
- OK_(create_dmdevice_over_loop(L_DEVICE_OK, 12*1024*2+1));
|
|
|
4bba8a |
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, 8*1024*2+1));
|
|
|
4bba8a |
|
|
|
4bba8a |
/* encryption with datashift and moved segment (data shift + 1 sector) */
|
|
|
4bba8a |
OK_(crypt_init(&cd, DMDIR H_DEVICE));
|
|
|
4bba8a |
@@ -4258,11 +4258,11 @@ static void Luks2Reencryption(void)
|
|
|
4bba8a |
|
|
|
4bba8a |
_cleanup_dmdevices();
|
|
|
4bba8a |
OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
|
|
|
4bba8a |
- OK_(create_dmdevice_over_loop(L_DEVICE_OK, 12*1024*2));
|
|
|
4bba8a |
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, 2*8200));
|
|
|
4bba8a |
|
|
|
4bba8a |
OK_(crypt_init(&cd, DMDIR H_DEVICE));
|
|
|
4bba8a |
|
|
|
4bba8a |
- /* encryption with datashift and moved segment (data shift + data offset > device size) */
|
|
|
4bba8a |
+ /* encryption with datashift and moved segment (data shift + data offset <= device size) */
|
|
|
4bba8a |
memset(&rparams, 0, sizeof(rparams));
|
|
|
4bba8a |
params2.sector_size = 512;
|
|
|
4bba8a |
params2.data_device = DMDIR L_DEVICE_OK;
|
|
|
4bba8a |
diff --git a/tests/luks2-reencryption-test b/tests/luks2-reencryption-test
|
|
|
4bba8a |
index 8efb2707..bf711c15 100755
|
|
|
4bba8a |
--- a/tests/luks2-reencryption-test
|
|
|
4bba8a |
+++ b/tests/luks2-reencryption-test
|
|
|
4bba8a |
@@ -152,14 +152,30 @@ function open_crypt() # $1 pwd, $2 hdr
|
|
|
4bba8a |
fi
|
|
|
4bba8a |
}
|
|
|
4bba8a |
|
|
|
4bba8a |
+function wipe_dev_head() # $1 dev, $2 length (in MiBs)
|
|
|
4bba8a |
+{
|
|
|
4bba8a |
+ dd if=/dev/zero of=$1 bs=1M count=$2 conv=notrunc >/dev/null 2>&1
|
|
|
4bba8a |
+}
|
|
|
4bba8a |
+
|
|
|
4bba8a |
function wipe_dev() # $1 dev
|
|
|
4bba8a |
{
|
|
|
4bba8a |
if [ -b $1 ] ; then
|
|
|
4bba8a |
blkdiscard --zeroout $1 2>/dev/null || dd if=/dev/zero of=$1 bs=1M conv=notrunc >/dev/null 2>&1
|
|
|
4bba8a |
+ if [ $# -gt 2 ]; then
|
|
|
4bba8a |
+ dd if=/dev/urandom of=$1 bs=1M seek=$2 conv=notrunc >/dev/null 2>&1
|
|
|
4bba8a |
+ fi
|
|
|
4bba8a |
else
|
|
|
4bba8a |
local size=$(stat --printf="%s" $1)
|
|
|
4bba8a |
truncate -s 0 $1
|
|
|
4bba8a |
- truncate -s $size $1
|
|
|
4bba8a |
+ if [ $# -gt 2 ]; then
|
|
|
4bba8a |
+ local diff=$((size-$2*1024*1024))
|
|
|
4bba8a |
+ echo "size: $size, diff: $diff"
|
|
|
4bba8a |
+ truncate -s $diff $1
|
|
|
4bba8a |
+ # wipe_dev_head $1 $((diff/(1024*1024)))
|
|
|
4bba8a |
+ dd if=/dev/urandom of=$1 bs=1M seek=$2 size=$((diff/(1024*1024))) conv=notrunc >/dev/null 2>&1
|
|
|
4bba8a |
+ else
|
|
|
4bba8a |
+ truncate -s $size $1
|
|
|
4bba8a |
+ fi
|
|
|
4bba8a |
fi
|
|
|
4bba8a |
}
|
|
|
4bba8a |
|
|
|
4bba8a |
@@ -214,15 +230,16 @@ function check_hash() # $1 pwd, $2 hash, $3 hdr
|
|
|
4bba8a |
$CRYPTSETUP remove $DEV_NAME || fail
|
|
|
4bba8a |
}
|
|
|
4bba8a |
|
|
|
4bba8a |
+function check_hash_dev_head() # $1 dev, $2 len, $3 hash
|
|
|
4bba8a |
+{
|
|
|
4bba8a |
+ local hash=$(dd if=$1 bs=512 count=$2 2>/dev/null | sha256sum | cut -d' ' -f1)
|
|
|
4bba8a |
+ [ $hash != "$3" ] && fail "HASH differs (expected: $3) (result $hash)"
|
|
|
4bba8a |
+}
|
|
|
4bba8a |
+
|
|
|
4bba8a |
function check_hash_head() # $1 pwd, $2 len, $3 hash, $4 hdr
|
|
|
4bba8a |
{
|
|
|
4bba8a |
open_crypt $1 $4
|
|
|
4bba8a |
- if [ -n "$4" ]; then
|
|
|
4bba8a |
- echo $1 | $CRYPTSETUP resize $DEV_NAME --size $2 --header $4 || fail
|
|
|
4bba8a |
- else
|
|
|
4bba8a |
- echo $1 | $CRYPTSETUP resize $DEV_NAME --size $2 || fail
|
|
|
4bba8a |
- fi
|
|
|
4bba8a |
- check_hash_dev /dev/mapper/$DEV_NAME $3
|
|
|
4bba8a |
+ check_hash_dev_head /dev/mapper/$DEV_NAME $2 $3
|
|
|
4bba8a |
$CRYPTSETUP remove $DEV_NAME || fail
|
|
|
4bba8a |
}
|
|
|
4bba8a |
|
|
|
4bba8a |
@@ -865,6 +882,21 @@ $CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 || fail
|
|
|
4bba8a |
$CRYPTSETUP close $DEV_NAME
|
|
|
4bba8a |
echo $PWD1 | $CRYPTSETUP open $DEV --test-passphrase || fail
|
|
|
4bba8a |
|
|
|
4bba8a |
+# Small device encryption test
|
|
|
4bba8a |
+preparebig 65
|
|
|
4bba8a |
+# wipe only 1st MiB (final data size after encryption)
|
|
|
4bba8a |
+wipe_dev $DEV 1
|
|
|
4bba8a |
+check_hash_dev_head $DEV 2048 $HASH2
|
|
|
4bba8a |
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --reduce-device-size 64M -q $FAST_PBKDF_ARGON || fail
|
|
|
4bba8a |
+check_hash_head $PWD1 2048 $HASH2
|
|
|
4bba8a |
+
|
|
|
4bba8a |
+wipe_dev_head $DEV 1
|
|
|
4bba8a |
+check_hash_dev_head $DEV 2048 $HASH2
|
|
|
4bba8a |
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --reduce-device-size 64M --init-only -q $FAST_PBKDF_ARGON $DEV_NAME >/dev/null || fail
|
|
|
4bba8a |
+check_hash_dev_head /dev/mapper/$DEV_NAME 2048 $HASH2
|
|
|
4bba8a |
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q || fail
|
|
|
4bba8a |
+check_hash_dev_head /dev/mapper/$DEV_NAME 2048 $HASH2
|
|
|
4bba8a |
+
|
|
|
4bba8a |
echo "[3] Encryption with detached header"
|
|
|
4bba8a |
preparebig 256
|
|
|
4bba8a |
wipe_dev $DEV
|
|
|
4bba8a |
--
|
|
|
4bba8a |
2.38.1
|
|
|
4bba8a |
|