diff --git a/SOURCES/cryptsetup-2.5.0-Remove-LUKS2-encryption-data-size-restriction.patch b/SOURCES/cryptsetup-2.5.0-Remove-LUKS2-encryption-data-size-restriction.patch new file mode 100644 index 0000000..bf522bf --- /dev/null +++ b/SOURCES/cryptsetup-2.5.0-Remove-LUKS2-encryption-data-size-restriction.patch @@ -0,0 +1,206 @@ +From 6bc1378ddb5bbcc6ba592177c996576b0b3505f9 Mon Sep 17 00:00:00 2001 +From: Ondrej Kozina +Date: Fri, 22 Oct 2021 13:06:48 +0200 +Subject: [PATCH] Remove LUKS2 encryption data size restriction. + +LUKS2 encryption with data shift required remaining +data size (size remaining after substracting --reduce-data-size value) +to be at least --reduce-data-size. This was wrong. Remaining +data size restriction should be correctly at least single sector +(whatever sector size is selected or auto-detected). +--- + lib/luks2/luks2_reencrypt.c | 31 ++++++++++++----------- + tests/api-test-2.c | 6 ++--- + tests/luks2-reencryption-test | 46 +++++++++++++++++++++++++++++------ + 3 files changed, 57 insertions(+), 26 deletions(-) + +diff --git a/lib/luks2/luks2_reencrypt.c b/lib/luks2/luks2_reencrypt.c +index b45327ad..d0e0dc40 100644 +--- a/lib/luks2/luks2_reencrypt.c ++++ b/lib/luks2/luks2_reencrypt.c +@@ -825,7 +825,7 @@ static int reencrypt_offset_backward_moved(struct luks2_hdr *hdr, json_object *j + linear_length += LUKS2_segment_size(hdr, sg, 0); + + /* all active linear segments length */ +- if (linear_length) { ++ if (linear_length && segs > 1) { + if (linear_length < data_shift) + return -EINVAL; + tmp = linear_length - data_shift; +@@ -1745,7 +1745,8 @@ static int reencrypt_set_encrypt_segments(struct crypt_device *cd, struct luks2_ + int r; + uint64_t first_segment_offset, first_segment_length, + second_segment_offset, second_segment_length, +- data_offset = LUKS2_get_data_offset(hdr) << SECTOR_SHIFT; ++ data_offset = LUKS2_get_data_offset(hdr) << SECTOR_SHIFT, ++ data_size = dev_size - data_shift; + json_object *jobj_segment_first = NULL, *jobj_segment_second = NULL, *jobj_segments; + + if (dev_size < data_shift) +@@ -1760,9 +1761,14 @@ static int reencrypt_set_encrypt_segments(struct crypt_device *cd, struct luks2_ + * [future LUKS2 header (data shift size)][second data segment][gap (data shift size)][first data segment (data shift size)] + */ + first_segment_offset = dev_size; +- first_segment_length = data_shift; +- second_segment_offset = data_shift; +- second_segment_length = dev_size - 2 * data_shift; ++ if (data_size < data_shift) { ++ first_segment_length = data_size; ++ second_segment_length = second_segment_offset = 0; ++ } else { ++ first_segment_length = data_shift; ++ second_segment_offset = data_shift; ++ second_segment_length = data_size - data_shift; ++ } + } else if (data_shift) { + first_segment_offset = data_offset; + first_segment_length = dev_size; +@@ -2163,17 +2169,10 @@ static int reencrypt_move_data(struct crypt_device *cd, int devfd, uint64_t data + + log_dbg(cd, "Going to move data from head of data device."); + +- buffer_len = data_shift; +- if (!buffer_len) +- return -EINVAL; +- + offset = json_segment_get_offset(LUKS2_get_segment_jobj(hdr, 0), 0); +- +- /* this is nonsense anyway */ +- if (buffer_len != json_segment_get_size(LUKS2_get_segment_jobj(hdr, 0), 0)) { +- log_dbg(cd, "buffer_len %" PRIu64", segment size %" PRIu64, buffer_len, json_segment_get_size(LUKS2_get_segment_jobj(hdr, 0), 0)); ++ buffer_len = json_segment_get_size(LUKS2_get_segment_jobj(hdr, 0), 0); ++ if (!buffer_len || buffer_len > data_shift) + return -EINVAL; +- } + + if (posix_memalign(&buffer, device_alignment(crypt_data_device(cd)), buffer_len)) + return -ENOMEM; +@@ -2447,7 +2446,7 @@ static int reencrypt_init(struct crypt_device *cd, + * encryption initialization (or mount) + */ + if (move_first_segment) { +- if (dev_size < 2 * (params->data_shift << SECTOR_SHIFT)) { ++ if (dev_size < (params->data_shift << SECTOR_SHIFT)) { + log_err(cd, _("Device %s is too small."), device_path(crypt_data_device(cd))); + return -EINVAL; + } +@@ -3484,7 +3483,7 @@ int LUKS2_reencrypt_check_device_size(struct crypt_device *cd, struct luks2_hdr + check_size, check_size >> SECTOR_SHIFT, real_size, real_size >> SECTOR_SHIFT, + real_size - data_offset, (real_size - data_offset) >> SECTOR_SHIFT); + +- if (real_size < data_offset || (check_size && (real_size - data_offset) < check_size)) { ++ if (real_size < data_offset || (check_size && real_size < check_size)) { + log_err(cd, _("Device %s is too small."), device_path(crypt_data_device(cd))); + return -EINVAL; + } +diff --git a/tests/api-test-2.c b/tests/api-test-2.c +index a01a7a72..05ee8f94 100644 +--- a/tests/api-test-2.c ++++ b/tests/api-test-2.c +@@ -4238,7 +4238,7 @@ static void Luks2Reencryption(void) + + _cleanup_dmdevices(); + OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size)); +- OK_(create_dmdevice_over_loop(L_DEVICE_OK, 12*1024*2+1)); ++ OK_(create_dmdevice_over_loop(L_DEVICE_OK, 8*1024*2+1)); + + /* encryption with datashift and moved segment (data shift + 1 sector) */ + OK_(crypt_init(&cd, DMDIR H_DEVICE)); +@@ -4258,11 +4258,11 @@ static void Luks2Reencryption(void) + + _cleanup_dmdevices(); + OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size)); +- OK_(create_dmdevice_over_loop(L_DEVICE_OK, 12*1024*2)); ++ OK_(create_dmdevice_over_loop(L_DEVICE_OK, 2*8200)); + + OK_(crypt_init(&cd, DMDIR H_DEVICE)); + +- /* encryption with datashift and moved segment (data shift + data offset > device size) */ ++ /* encryption with datashift and moved segment (data shift + data offset <= device size) */ + memset(&rparams, 0, sizeof(rparams)); + params2.sector_size = 512; + params2.data_device = DMDIR L_DEVICE_OK; +diff --git a/tests/luks2-reencryption-test b/tests/luks2-reencryption-test +index 8efb2707..bf711c15 100755 +--- a/tests/luks2-reencryption-test ++++ b/tests/luks2-reencryption-test +@@ -152,14 +152,30 @@ function open_crypt() # $1 pwd, $2 hdr + fi + } + ++function wipe_dev_head() # $1 dev, $2 length (in MiBs) ++{ ++ dd if=/dev/zero of=$1 bs=1M count=$2 conv=notrunc >/dev/null 2>&1 ++} ++ + function wipe_dev() # $1 dev + { + if [ -b $1 ] ; then + blkdiscard --zeroout $1 2>/dev/null || dd if=/dev/zero of=$1 bs=1M conv=notrunc >/dev/null 2>&1 ++ if [ $# -gt 2 ]; then ++ dd if=/dev/urandom of=$1 bs=1M seek=$2 conv=notrunc >/dev/null 2>&1 ++ fi + else + local size=$(stat --printf="%s" $1) + truncate -s 0 $1 +- truncate -s $size $1 ++ if [ $# -gt 2 ]; then ++ local diff=$((size-$2*1024*1024)) ++ echo "size: $size, diff: $diff" ++ truncate -s $diff $1 ++ # wipe_dev_head $1 $((diff/(1024*1024))) ++ dd if=/dev/urandom of=$1 bs=1M seek=$2 size=$((diff/(1024*1024))) conv=notrunc >/dev/null 2>&1 ++ else ++ truncate -s $size $1 ++ fi + fi + } + +@@ -214,15 +230,16 @@ function check_hash() # $1 pwd, $2 hash, $3 hdr + $CRYPTSETUP remove $DEV_NAME || fail + } + ++function check_hash_dev_head() # $1 dev, $2 len, $3 hash ++{ ++ local hash=$(dd if=$1 bs=512 count=$2 2>/dev/null | sha256sum | cut -d' ' -f1) ++ [ $hash != "$3" ] && fail "HASH differs (expected: $3) (result $hash)" ++} ++ + function check_hash_head() # $1 pwd, $2 len, $3 hash, $4 hdr + { + open_crypt $1 $4 +- if [ -n "$4" ]; then +- echo $1 | $CRYPTSETUP resize $DEV_NAME --size $2 --header $4 || fail +- else +- echo $1 | $CRYPTSETUP resize $DEV_NAME --size $2 || fail +- fi +- check_hash_dev /dev/mapper/$DEV_NAME $3 ++ check_hash_dev_head /dev/mapper/$DEV_NAME $2 $3 + $CRYPTSETUP remove $DEV_NAME || fail + } + +@@ -865,6 +882,21 @@ $CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 || fail + $CRYPTSETUP close $DEV_NAME + echo $PWD1 | $CRYPTSETUP open $DEV --test-passphrase || fail + ++# Small device encryption test ++preparebig 65 ++# wipe only 1st MiB (final data size after encryption) ++wipe_dev $DEV 1 ++check_hash_dev_head $DEV 2048 $HASH2 ++echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --reduce-device-size 64M -q $FAST_PBKDF_ARGON || fail ++check_hash_head $PWD1 2048 $HASH2 ++ ++wipe_dev_head $DEV 1 ++check_hash_dev_head $DEV 2048 $HASH2 ++echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --reduce-device-size 64M --init-only -q $FAST_PBKDF_ARGON $DEV_NAME >/dev/null || fail ++check_hash_dev_head /dev/mapper/$DEV_NAME 2048 $HASH2 ++echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q || fail ++check_hash_dev_head /dev/mapper/$DEV_NAME 2048 $HASH2 ++ + echo "[3] Encryption with detached header" + preparebig 256 + wipe_dev $DEV +-- +2.38.1 + diff --git a/SOURCES/cryptsetup-2.6.1-Abort-encryption-when-header-and-data-devices-are-sa.patch b/SOURCES/cryptsetup-2.6.1-Abort-encryption-when-header-and-data-devices-are-sa.patch new file mode 100644 index 0000000..b8c056d --- /dev/null +++ b/SOURCES/cryptsetup-2.6.1-Abort-encryption-when-header-and-data-devices-are-sa.patch @@ -0,0 +1,154 @@ +From c18dcfaa0b91eb48006232fbfadce9e6a9b4a790 Mon Sep 17 00:00:00 2001 +From: Ondrej Kozina +Date: Fri, 2 Dec 2022 15:39:36 +0100 +Subject: [PATCH 2/2] Abort encryption when header and data devices are same. + +If data device reduction is not requsted this led +to data corruption since LUKS metadata was written +over the data device. +--- + src/utils_reencrypt.c | 42 ++++++++++++++++++++++++++++++---- + tests/luks2-reencryption-test | 16 +++++++++++++ + tests/reencryption-compat-test | 20 +++++++++++++--- + 3 files changed, 70 insertions(+), 8 deletions(-) + +diff --git a/src/utils_tools.c b/src/utils_tools.c +--- a/src/utils_tools.c ++++ b/src/utils_tools.c +@@ -624,3 +624,23 @@ int tools_reencrypt_progress(uint64_t si + + return r; + } ++ ++int reencrypt_is_header_detached(const char *header_device, const char *data_device) ++{ ++ int r; ++ struct stat st; ++ struct crypt_device *cd; ++ ++ if (!header_device) ++ return 0; ++ ++ if (header_device && stat(header_device, &st) < 0 && errno == ENOENT) ++ return 1; ++ ++ if ((r = crypt_init_data_device(&cd, header_device, data_device))) ++ return r; ++ ++ r = crypt_get_metadata_device_name(cd) && crypt_get_device_name(cd) && strcmp(crypt_get_metadata_device_name(cd), crypt_get_device_name(cd)); ++ crypt_free(cd); ++ return r; ++} +diff --git a/src/cryptsetup.h b/src/cryptsetup.h +--- a/src/cryptsetup.h ++++ b/src/cryptsetup.h +@@ -103,6 +103,7 @@ void tools_clear_line(void); + + int tools_wipe_progress(uint64_t size, uint64_t offset, void *usrptr); + int tools_reencrypt_progress(uint64_t size, uint64_t offset, void *usrptr); ++int reencrypt_is_header_detached(const char *header_device, const char *data_device); + + int tools_read_mk(const char *file, char **key, int keysize); + int tools_write_mk(const char *file, const char *key, int keysize); +diff --git a/src/cryptsetup.c b/src/cryptsetup.c +--- a/src/cryptsetup.c ++++ b/src/cryptsetup.c +@@ -2892,6 +2892,16 @@ static int action_encrypt_luks2(struct c + return -ENOTSUP; + } + ++ if (!opt_data_shift) { ++ r = reencrypt_is_header_detached(opt_header_device, action_argv[0]); ++ if (r < 0) ++ return r; ++ if (!r) { ++ log_err(_("Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size).")); ++ return -ENOTSUP; ++ } ++ } ++ + if (!opt_header_device && opt_offset && opt_data_shift && (opt_offset > (imaxabs(opt_data_shift) / (2 * SECTOR_SIZE)))) { + log_err(_("Requested data offset must be less than or equal to half of --reduce-device-size parameter.")); + return -EINVAL; +diff --git a/src/cryptsetup_reencrypt.c b/src/cryptsetup_reencrypt.c +--- a/src/cryptsetup_reencrypt.c ++++ b/src/cryptsetup_reencrypt.c +@@ -1553,6 +1553,17 @@ static int run_reencrypt(const char *dev + goto out; + } + ++ if (rc.reencrypt_mode == ENCRYPT) { ++ r = reencrypt_is_header_detached(opt_header_device, action_argv[0]); ++ if (r < 0) ++ goto out; ++ if (!r && !opt_reduce_size) { ++ log_err(_("Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size).")); ++ r = -ENOTSUP; ++ goto out; ++ } ++ } ++ + log_dbg("Running reencryption."); + + if (!rc.in_progress) { +diff --git a/tests/luks2-reencryption-test b/tests/luks2-reencryption-test +index bab54353..a647a8c2 100755 +--- a/tests/luks2-reencryption-test ++++ b/tests/luks2-reencryption-test +@@ -1080,6 +1080,15 @@ $CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 || fail + $CRYPTSETUP close $DEV_NAME + echo $PWD1 | $CRYPTSETUP open --header $IMG_HDR $DEV --test-passphrase || fail + ++# Encrypt without size reduction must not allow header device same as data device ++wipe_dev_head $DEV 1 ++echo $PWD1 | $CRYPTSETUP reencrypt $DEV --type luks2 --encrypt --header $DEV -q $FAST_PBKDF_ARGON 2>/dev/null && fail ++$CRYPTSETUP isLUKS $DEV 2>/dev/null && fail ++ ++dd if=/dev/zero of=$IMG bs=4k count=1 >/dev/null 2>&1 ++echo $PWD1 | $CRYPTSETUP reencrypt $IMG --type luks2 --encrypt --header $IMG -q $FAST_PBKDF_ARGON 2>/dev/null && fail ++$CRYPTSETUP isLUKS $IMG 2>/dev/null && fail ++ + echo "[4] Reencryption with detached header" + wipe $PWD1 $IMG_HDR + echo $PWD1 | $CRYPTSETUP reencrypt -c aes-cbc-essiv:sha256 -s 128 --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail +diff --git a/tests/reencryption-compat-test b/tests/reencryption-compat-test +index f6a84137..453831d1 100755 +--- a/tests/reencryption-compat-test ++++ b/tests/reencryption-compat-test +@@ -11,5 +11,6 @@ IMG=reenc-data + IMG_HDR=$IMG.hdr + ORIG_IMG=reenc-data-orig ++DEV_LINK="reenc-test-link" + KEY1=key1 + PWD1="93R4P4pIqAH8" + PWD2="1cND4319812f" +@@ -40,7 +41,7 @@ function remove_mapping() + [ -b /dev/mapper/$DEV_NAME2 ] && dmsetup remove --retry $DEV_NAME2 + [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME + [ ! -z "$LOOPDEV1" ] && losetup -d $LOOPDEV1 >/dev/null 2>&1 +- rm -f $IMG $IMG_HDR $ORIG_IMG $KEY1 >/dev/null 2>&1 ++ rm -f $IMG $IMG_HDR $ORIG_IMG $KEY1 $DEV_LINK >/dev/null 2>&1 + umount $MNT_DIR > /dev/null 2>&1 + rmdir $MNT_DIR > /dev/null 2>&1 + LOOPDEV1="" +@@ -265,10 +265,16 @@ $REENC $LOOPDEV1 -d $KEY1 $FAST_PBKDF -q + # FIXME echo $PWD1 | $REENC ... + + echo "[4] Encryption of not yet encrypted device" ++# Encrypt without size reduction must not allow header device same as data device ++wipe_dev $LOOPDEV1 ++echo $PWD1 | $REENC $LOOPDEV1 --type luks1 --new --header $LOOPDEV1 -q $FAST_PBKDF_ARGON 2>/dev/null && fail ++$CRYPTSETUP isLUKS $LOOPDEV1 2>/dev/null && fail ++echo $PWD1 | $REENC $IMG --type luks1 --new --header $IMG -q $FAST_PBKDF_ARGON 2>/dev/null && fail ++$CRYPTSETUP isLUKS $IMG 2>/dev/null && fail ++ + # well, movin' zeroes :-) + OFFSET=2048 + SIZE=$(blockdev --getsz $LOOPDEV1) +-wipe_dev $LOOPDEV1 + dmsetup create $DEV_NAME2 --table "0 $(($SIZE - $OFFSET)) linear $LOOPDEV1 0" || fail + check_hash_dev /dev/mapper/$DEV_NAME2 $HASH3 + dmsetup remove --retry $DEV_NAME2 || fail +-- +2.38.1 + diff --git a/SPECS/cryptsetup.spec b/SPECS/cryptsetup.spec index 48b5db4..1f790e7 100644 --- a/SPECS/cryptsetup.spec +++ b/SPECS/cryptsetup.spec @@ -5,7 +5,7 @@ Obsoletes: cryptsetup-python3 Summary: A utility for setting up encrypted disks Name: cryptsetup Version: 2.3.7 -Release: 3%{?dist} +Release: 5%{?dist} License: GPLv2+ and LGPLv2+ Group: Applications/System URL: https://gitlab.com/cryptsetup/cryptsetup @@ -28,11 +28,13 @@ Patch3: %{name}-2.4.2-Fix-bogus-memory-allocation-if-LUKS2-header-size-is-.patc 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 -Patch7: %{name}-2.6.0-Fix-cipher-convert-routines-naming-confusion.patch -Patch8: %{name}-2.6.0-Move-cipher_dm2c-to-crypto-utilities.patch -Patch9: %{name}-2.6.0-Code-cleanup.patch -Patch10: %{name}-2.6.0-Copy-also-integrity-string-in-legacy-mode.patch -Patch11: %{name}-2.6.0-Fix-internal-crypt-segment-compare-routine.patch +Patch7: %{name}-2.5.0-Remove-LUKS2-encryption-data-size-restriction.patch +Patch8: %{name}-2.6.0-Fix-cipher-convert-routines-naming-confusion.patch +Patch9: %{name}-2.6.0-Move-cipher_dm2c-to-crypto-utilities.patch +Patch10: %{name}-2.6.0-Code-cleanup.patch +Patch11: %{name}-2.6.0-Copy-also-integrity-string-in-legacy-mode.patch +Patch12: %{name}-2.6.0-Fix-internal-crypt-segment-compare-routine.patch +Patch13: %{name}-2.6.1-Abort-encryption-when-header-and-data-devices-are-sa.patch %description The cryptsetup package contains a utility for setting up @@ -40,7 +42,7 @@ disk encryption using dm-crypt kernel module. %package devel Group: Development/Libraries -Requires: %{name} = %{version}-%{release} +Requires: %{name}-libs%{?_isa} = %{version}-%{release} Requires: pkgconfig Summary: Headers and libraries for using encrypted file systems Provides: cryptsetup-luks-devel = %{version}-%{release} @@ -99,6 +101,8 @@ can be used for offline reencryption of disk in situ. %patch9 -p1 %patch10 -p1 %patch11 -p1 +%patch12 -p1 +%patch13 -p1 %patch0 -p1 chmod -x misc/dracut_90reencrypt/* @@ -158,6 +162,15 @@ rm -rf %{buildroot}/%{_libdir}/*.la %clean %changelog +* Tue Jan 10 2023 Daniel Zatovic - 2.3.7-5 +- change cryptsetup-devel dependency from cryptsetup to cryptsetup-libs +- Resolves: #2150254 + +* Wed Dec 21 2022 Daniel Zatovic - 2.3.7-4 +- patch: Remove LUKS2 encryption data size restriction. +- patch: Abort encryption when header and data devices are same. +- Resolves: #2150254 + * Fri Nov 4 2022 Daniel Zatovic - 2.3.7-3 - patch: Fix internal crypt segment compare routine - Resolves: #2110810