From d3079c2fb3bc3efcd29c4a9b095e32b2991a24fb Mon Sep 17 00:00:00 2001 From: Ondrej Kozina Date: Wed, 30 Mar 2022 13:00:57 +0200 Subject: [PATCH] Do not resume reencryption with conflicting parameters. Do not resume reencryption operation with conflicting parameters. For example if operation was initialized as --encrypt do not allow resume with oposing parameter --decrypt and vice versa. Also checks for conflicting --resilience parameters (datashift cannot be changed after initialization). Previously, conflicting reencryption parameters were silently ignored. So, for example operation initialized with mode --encrypt and resumed with mode --decrypt simply finished --encrypt operation and did not report any error. This could lead to impresion different type of operation was perfomed instead. Fixes: #570. --- src/utils_reencrypt.c | 32 +++++++++++++++++++++++++++- tests/luks2-reencryption-mangle-test | 22 +++++++++++++++---- tests/luks2-reencryption-test | 22 +++++++++++++++++++ 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/src/utils_reencrypt.c b/src/utils_reencrypt.c index dfb80a88..54f74003 100644 --- a/src/utils_reencrypt.c +++ b/src/utils_reencrypt.c @@ -141,10 +141,11 @@ static int reencrypt_get_active_name(struct crypt_device *cd, const char *data_d static int reencrypt_luks2_load(struct crypt_device *cd, const char *data_device) { + crypt_reencrypt_info ri; int r; size_t passwordLen; char *active_name = NULL, *password = NULL; - struct crypt_params_reencrypt params = { + struct crypt_params_reencrypt ret_params, params = { .resilience = ARG_STR(OPT_RESILIENCE_ID) ?: "checksum", .hash = ARG_STR(OPT_RESILIENCE_HASH_ID) ?: "sha256", .max_hotzone_size = ARG_UINT64(OPT_HOTZONE_SIZE_ID) / SECTOR_SIZE, @@ -152,6 +153,35 @@ static int reencrypt_luks2_load(struct crypt_device *cd, const char *data_device .flags = CRYPT_REENCRYPT_RESUME_ONLY }; + ri = crypt_reencrypt_status(cd, &ret_params); + if (ri == CRYPT_REENCRYPT_CRASH) + log_err(_("Device requires reencryption recovery. Run repair first.")); + + if (ri != CRYPT_REENCRYPT_CLEAN) + return -EINVAL; + + if (ARG_SET(OPT_ENCRYPT_ID) && ret_params.mode != CRYPT_REENCRYPT_ENCRYPT) { + log_err(_("Device is not in LUKS2 encryption. Conflicting option --encrypt.")); + return -EINVAL; + } + + if (ARG_SET(OPT_DECRYPT_ID) && ret_params.mode != CRYPT_REENCRYPT_DECRYPT) { + log_err(_("Device is not in LUKS2 decryption. Conflicting option --decrypt.")); + return -EINVAL; + } + + if (ARG_SET(OPT_RESILIENCE_ID) && + !strcmp(ret_params.resilience, "datashift") && strcmp(ARG_STR(OPT_RESILIENCE_ID), "datashift")) { + log_err(_("Device is in reencryption using datashift resilience. Requested --resilience option cannot be applied.")); + return -EINVAL; + } + + if (ARG_SET(OPT_RESILIENCE_ID) && + strcmp(ret_params.resilience, "datashift") && !strcmp(ARG_STR(OPT_RESILIENCE_ID), "datashift")) { + log_err(_("Requested --resilience option cannot be applied to current reencryption operation.")); + return -EINVAL; + } + r = tools_get_key(NULL, &password, &passwordLen, ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID), ARG_UINT32(OPT_TIMEOUT_ID), verify_passphrase(0), 0, cd); diff --git a/tests/luks2-reencryption-mangle-test b/tests/luks2-reencryption-mangle-test index 3e6ab69b..1a7049d1 100755 --- a/tests/luks2-reencryption-mangle-test +++ b/tests/luks2-reencryption-mangle-test @@ -158,13 +158,18 @@ function img_run_reenc_ok() $CRYPTSETUP_RAW reencrypt $IMG $CS_PWPARAMS -q --disable-locks --force-offline-reencrypt --resilience none || fail } +function img_run_reenc_ok_data_shift() +{ + $CRYPTSETUP_RAW reencrypt $IMG $CS_PWPARAMS -q --disable-locks --force-offline-reencrypt || fail +} + function img_run_reenc_fail() { $CRYPTSETUP_RAW reencrypt $IMG $CS_PWPARAMS --force-offline-reencrypt --disable-locks -q 2>/dev/null && fail "Reencryption passed (should have failed)." img_hash_unchanged } -function img_check_fail_repair_ok() +function img_check_fail_repair() { if [ $(id -u) == 0 ]; then $CRYPTSETUP open $CS_PWPARAMS $IMG $DEV_NAME 2>/dev/null && fail @@ -176,9 +181,20 @@ function img_check_fail_repair_ok() $CRYPTSETUP repair $IMG $CS_PARAMS || fail img_check_ok +} + +function img_check_fail_repair_ok() +{ + img_check_fail_repair img_run_reenc_ok } +function img_check_fail_repair_ok_data_shift() +{ + img_check_fail_repair + img_run_reenc_ok_data_shift +} + function valgrind_setup() { bin_check valgrind @@ -203,8 +219,6 @@ 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"]' @@ -346,7 +360,7 @@ img_update_json ' .digests."0".segments = ["0","2"] | .digests."1".segments = ["1","3"] | .config.requirements.mandatory = ["online-reencrypt"]' -img_check_fail_repair_ok +img_check_fail_repair_ok_data_shift # # NEW metadata (with reenc digest) diff --git a/tests/luks2-reencryption-test b/tests/luks2-reencryption-test index 793713ad..1d45cb82 100755 --- a/tests/luks2-reencryption-test +++ b/tests/luks2-reencryption-test @@ -1686,5 +1686,27 @@ rm -f $IMG_HDR echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --init-only --type luks2 --header $IMG_HDR $FAST_PBKDF2 $DEV || fail echo $PWD1 | $CRYPTSETUP reencrypt -q --encrypt --type luks1 --header $IMG_HDR $FAST_PBKDF2 $DEV 2>/dev/null && fail +echo "[29] Conflicting reencryption parameters" +echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 $FAST_PBKDF2 $DEV || fail +echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --init-only $FAST_PBKDF_ARGON || fail +echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --reduce-device-size 4M $DEV -q $FAST_PBKDF_ARGON 2> /dev/null && fail +echo $PWD1 | $CRYPTSETUP reencrypt --decrypt $DEV -q $FAST_PBKDF_ARGON 2> /dev/null && fail +echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience datashift 2> /dev/null && fail +wipe_dev_head $DEV 1 +echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --init-only --reduce-device-size 16M $DEV -q $FAST_PBKDF_ARGON 2> /dev/null || fail +echo $PWD1 | $CRYPTSETUP reencrypt --decrypt $DEV -q $FAST_PBKDF_ARGON 2> /dev/null && fail +echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience journal 2> /dev/null && fail +wipe_dev_head $DEV 1 +echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --header $IMG_HDR $FAST_PBKDF2 $DEV || fail +echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --header $IMG_HDR --init-only $FAST_PBKDF_ARGON || fail +echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --header $IMG_HDR $DEV -q $FAST_PBKDF_ARGON 2> /dev/null && fail +echo $PWD1 | $CRYPTSETUP reencrypt --decrypt --header $IMG_HDR $DEV -q $FAST_PBKDF_ARGON 2> /dev/null && fail +rm -f $IMG_HDR +echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --encrypt --header $IMG_HDR --init-only $FAST_PBKDF_ARGON || fail +echo $PWD1 | $CRYPTSETUP reencrypt --decrypt --header $IMG_HDR $DEV -q $FAST_PBKDF_ARGON 2> /dev/null && fail +echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --header $IMG_HDR $FAST_PBKDF2 $DEV || fail +echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR --init-only $FAST_PBKDF_ARGON || fail +echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --header $IMG_HDR $DEV -q $FAST_PBKDF_ARGON 2> /dev/null && fail + remove_mapping exit 0