From 98d94734f0405ca7b22629274cdc43a6e534911e Mon Sep 17 00:00:00 2001 From: Daniel Zatovic Date: Wed, 10 Jan 2024 16:56:50 +0100 Subject: [PATCH] Add tests for device activation using multiple VKs. --- tests/api-test-2.c | 150 +++++++++++++++++++++++++++++++++- tests/compat-test2 | 58 +++++++++++-- tests/luks2-reencryption-test | 72 ++++++++++++++++ 3 files changed, 273 insertions(+), 7 deletions(-) diff --git a/tests/api-test-2.c b/tests/api-test-2.c index 611239366..dd99f593b 100644 --- a/tests/api-test-2.c +++ b/tests/api-test-2.c @@ -94,7 +94,7 @@ typedef int32_t key_serial_t; #define TEST_KEY_VK_LOGON "cs_api_test_prefix:api_test_logon_vk1" #define TEST_KEY_VK_LOGON_NAME "\%logon:" TEST_KEY_VK_LOGON #define TEST_KEY_VK_USER2 "api_test_user_vk2" -#define TEST_KEY_VK_USER2_NAME "\%user:" TEST_KEY_VK_USER +#define TEST_KEY_VK_USER2_NAME "\%user:" TEST_KEY_VK_USER2 #define TEST_KEY_VK_LOGON2 "cs_api_test_prefix:api_test_logon_vk2" #define TEST_KEY_VK_LOGON2_NAME "\%logon:" TEST_KEY_VK_LOGON @@ -5267,7 +5267,7 @@ static void KeyslotContextAndKeyringLink(void) #ifdef KERNEL_KEYRING const char *cipher = "aes"; const char *cipher_mode = "xts-plain64"; - struct crypt_keyslot_context *kc; + struct crypt_keyslot_context *kc, *kc2; uint64_t r_payload_offset; char key[128]; size_t key_size = 128; @@ -5318,6 +5318,7 @@ static void KeyslotContextAndKeyringLink(void) NOTFAIL_(keyring_in_session_id, "Test or kernel keyring are broken."); // test passphrase + EQ_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, NULL, CRYPT_ANY_SLOT, NULL, 0), -EINVAL); OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &kc)); EQ_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), 0); crypt_keyslot_context_free(kc); @@ -5570,8 +5571,153 @@ static void KeyslotContextAndKeyringLink(void) EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), 0); NOTFAIL_((linked_kid = request_key("user", TEST_KEY_VK_USER, NULL, 0)), "VK was not linked to custom keyring."); FAIL_((linked_kid2 = request_key("user", TEST_KEY_VK_USER2, NULL, 0)), "VK was not linked to custom keyring."); + OK_(crypt_deactivate(cd, CDEVICE_1)); + CRYPT_FREE(cd); + + // Reenncryption: test reactivation using linked keys + OK_(crypt_init(&cd, DMDIR L_DEVICE_OK)); + OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, ¶ms2)); + OK_(crypt_set_pbkdf_type(cd, &pbkdf)); + EQ_(crypt_keyslot_add_by_volume_key(cd, 1, NULL, 64, PASSPHRASE, strlen(PASSPHRASE)), 1); + EQ_(crypt_keyslot_add_by_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 0); + rparams.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY; + + EQ_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 1, 0, "aes", "xts-plain64", &rparams), 2); + EQ_(crypt_set_keyring_to_link(cd, TEST_KEY_VK_USER, TEST_KEY_VK_USER2, "user", keyring_in_user_str_id), 0); + EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), 0); + NOTFAIL_((linked_kid = request_key("user", TEST_KEY_VK_USER, NULL, 0)), "VK was not linked to custom keyring."); + NOTFAIL_((linked_kid2 = request_key("user", TEST_KEY_VK_USER2, NULL, 0)), "VK was not linked to custom keyring."); + OK_(crypt_deactivate(cd, CDEVICE_1)); + OK_(crypt_keyslot_context_init_by_vk_in_keyring(cd, TEST_KEY_VK_USER_NAME , &kc)); + OK_(crypt_keyslot_context_init_by_vk_in_keyring(cd, TEST_KEY_VK_USER2_NAME, &kc2)); + + EQ_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), -ENOKEY); + EQ_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc2, CRYPT_ANY_SLOT, NULL, 0), -ENOKEY); + EQ_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, NULL, CRYPT_ANY_SLOT, kc, 0), -EINVAL); + EQ_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, NULL, CRYPT_ANY_SLOT, kc2, 0), -EINVAL); + + EQ_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, kc2, 0), 0); + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, kc2, 0), 0); + OK_(crypt_deactivate(cd, CDEVICE_1)); + + OK_(_drop_keyring_key_from_keyring_name(TEST_KEY_VK_USER, keyring_in_user_id, "user")); + OK_(_drop_keyring_key_from_keyring_name(TEST_KEY_VK_USER2, keyring_in_user_id, "user")); + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, kc2, 0), -EINVAL); + + EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), 0); + NOTFAIL_((linked_kid = request_key("user", TEST_KEY_VK_USER, NULL, 0)), "VK was not linked to custom keyring."); + NOTFAIL_((linked_kid2 = request_key("user", TEST_KEY_VK_USER2, NULL, 0)), "VK was not linked to custom keyring."); + OK_(crypt_deactivate(cd, CDEVICE_1)); + + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, kc2, 0), 0); + OK_(crypt_deactivate(cd, CDEVICE_1)); + GE_((vk_len = keyctl_read(linked_kid, vk_buf, sizeof(vk_buf))), 0); + vk_buf[0] = ~vk_buf[0]; + OK_(keyctl_update(linked_kid, vk_buf, vk_len)); + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, kc2, 0), -EINVAL); + OK_(_drop_keyring_key_from_keyring_name(TEST_KEY_VK_USER, keyring_in_user_id, "user")); + OK_(_drop_keyring_key_from_keyring_name(TEST_KEY_VK_USER2, keyring_in_user_id, "user")); CRYPT_FREE(cd); + + // Decryption: test reactivation using linked keys + OK_(crypt_init(&cd, DMDIR L_DEVICE_OK)); + OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, ¶ms2)); + OK_(crypt_set_pbkdf_type(cd, &pbkdf)); + EQ_(crypt_keyslot_add_by_volume_key(cd, 1, NULL, 64, PASSPHRASE, strlen(PASSPHRASE)), 1); + rparams.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY; + rparams.mode = CRYPT_REENCRYPT_DECRYPT; + EQ_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 1, CRYPT_ANY_SLOT, NULL, NULL, &rparams), 0); + EQ_(crypt_set_keyring_to_link(cd, TEST_KEY_VK_USER, TEST_KEY_VK_USER2, "user", keyring_in_user_str_id), 0); + EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), 1); + NOTFAIL_((linked_kid = request_key("user", TEST_KEY_VK_USER, NULL, 0)), "VK was not linked to custom keyring."); + FAIL_((linked_kid2 = request_key("user", TEST_KEY_VK_USER2, NULL, 0)), "second VK was linked to custom keyring."); + OK_(crypt_deactivate(cd, CDEVICE_1)); + + OK_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0)); + OK_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, kc, 0)); + // lazy evaluation, if the first context supplies key and only one key is required, the second (invalid) context is not invoked + OK_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, kc2, 0)); + // first context takes precedence, if t fails, the second is not tried + EQ_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc2, CRYPT_ANY_SLOT, kc, 0), -EINVAL); + + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, kc2, 0), 0); + OK_(crypt_deactivate(cd, CDEVICE_1)); + + OK_(_drop_keyring_key_from_keyring_name(TEST_KEY_VK_USER, keyring_in_user_id, "user")); + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, kc2, 0), -EINVAL); + + EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), 1); + NOTFAIL_((linked_kid = request_key("user", TEST_KEY_VK_USER, NULL, 0)), "VK was not linked to custom keyring."); + FAIL_((linked_kid2 = request_key("user", TEST_KEY_VK_USER2, NULL, 0)), "VK was not linked to custom keyring."); + OK_(crypt_deactivate(cd, CDEVICE_1)); + + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, kc2, 0), 0); + OK_(crypt_deactivate(cd, CDEVICE_1)); + GE_((vk_len = keyctl_read(linked_kid, vk_buf, sizeof(vk_buf))), 0); + vk_buf[0] = ~vk_buf[0]; + OK_(keyctl_update(linked_kid, vk_buf, vk_len)); + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, kc2, 0), -EINVAL); + + OK_(_drop_keyring_key_from_keyring_name(TEST_KEY_VK_USER, keyring_in_user_id, "user")); + CRYPT_FREE(cd); + + // Encryption: test reactivation using linked keys + _cleanup_dmdevices(); + OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size)); + OK_(create_dmdevice_over_loop(L_DEVICE_OK, 12*1024*2)); + + OK_(crypt_init(&cd, DMDIR H_DEVICE)); + + memset(&rparams, 0, sizeof(rparams)); + params2.sector_size = 512; + params2.data_device = DMDIR L_DEVICE_OK; + rparams.mode = CRYPT_REENCRYPT_ENCRYPT; + rparams.luks2 = ¶ms2; + rparams.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY; + rparams.resilience = "checksum"; + rparams.hash = "sha256"; + OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "xts-plain64", NULL, NULL, 64, ¶ms2)); + EQ_(crypt_keyslot_add_by_volume_key(cd, 1, NULL, 64, PASSPHRASE, strlen(PASSPHRASE)), 1); + EQ_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ANY_SLOT, 1, "aes", "xts-plain64", &rparams), 0); + + EQ_(crypt_set_keyring_to_link(cd, TEST_KEY_VK_USER, TEST_KEY_VK_USER2, "user", keyring_in_user_str_id), 0); + EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), 1); + NOTFAIL_((linked_kid = request_key("user", TEST_KEY_VK_USER, NULL, 0)), "VK was not linked to custom keyring."); + FAIL_((linked_kid2 = request_key("user", TEST_KEY_VK_USER2, NULL, 0)), "second VK was linked to custom keyring."); + OK_(crypt_deactivate(cd, CDEVICE_1)); + + OK_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0)); + OK_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, kc, 0)); + // lazy evaluation, if the first context supplies key and only one key is required, the second (invalid) context is not invoked + OK_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, kc2, 0)); + // first context takes precedence, if t fails, the second is not tried + EQ_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc2, CRYPT_ANY_SLOT, kc, 0), -EINVAL); + + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, kc2, 0), 0); + OK_(crypt_deactivate(cd, CDEVICE_1)); + + OK_(_drop_keyring_key_from_keyring_name(TEST_KEY_VK_USER, keyring_in_user_id, "user")); + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, kc2, 0), -EINVAL); + + EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), 1); + NOTFAIL_((linked_kid = request_key("user", TEST_KEY_VK_USER, NULL, 0)), "VK was not linked to custom keyring."); + FAIL_((linked_kid2 = request_key("user", TEST_KEY_VK_USER2, NULL, 0)), "VK was not linked to custom keyring."); + OK_(crypt_deactivate(cd, CDEVICE_1)); + + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, kc2, 0), 0); + OK_(crypt_deactivate(cd, CDEVICE_1)); + GE_((vk_len = keyctl_read(linked_kid, vk_buf, sizeof(vk_buf))), 0); + vk_buf[0] = ~vk_buf[0]; + OK_(keyctl_update(linked_kid, vk_buf, vk_len)); + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, kc2, 0), -EINVAL); + + OK_(_drop_keyring_key_from_keyring_name(TEST_KEY_VK_USER, keyring_in_user_id, "user")); + CRYPT_FREE(cd); + + crypt_keyslot_context_free(kc); + crypt_keyslot_context_free(kc2); + _cleanup_dmdevices(); #else printf("WARNING: cryptsetup compiled with kernel keyring service disabled, skipping test.\n"); diff --git a/tests/compat-test2 b/tests/compat-test2 index e4a8f6e4b..aa2ac15a3 100755 --- a/tests/compat-test2 +++ b/tests/compat-test2 @@ -316,7 +316,7 @@ test_vk_link() { echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME || fail keyctl search "$2" $KEY_TYPE $1 > /dev/null 2>&1 && fail "VK is linked to the specified keyring before resume with linking." - $CRYPTSETUP luksSuspend $DEV_NAME || fail + $CRYPTSETUP luksSuspend $DEV_NAME || fail echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME --link-vk-to-keyring "$2"::"$KEY_DESC" || fail keyctl search "$2" $KEY_TYPE $1 > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after activation." $CRYPTSETUP close $DEV_NAME @@ -392,6 +392,44 @@ test_reencrypt_vk_link() { keyctl unlink $KEYCTL_KEY_NAME2 "$3" || fail } +# $1 first key name +# $2 second key name +# $3 keyring to link VK to +# $4 key type (optional) +test_reencrypt_vk_link_and_reactivate() { + KEY_TYPE=${4:-user} + if [ -z "$4" ]; then + KEY_DESC=$1 + else + KEY_DESC="%$4:$1" + fi + if [ -z "$4" ]; then + KEY_DESC2=$2 + else + KEY_DESC2="%$4:$2" + fi + + KEYCTL_KEY_NAME="%$KEY_TYPE:$1" + KEYCTL_KEY_NAME2="%$KEY_TYPE:$2" + + echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring "$3"::"$KEY_DESC" --link-vk-to-keyring "$3"::"$KEY_DESC2" || fail + keyctl search "$3" $KEY_TYPE $1 > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after activation." + + keyctl search "$3" $KEY_TYPE $1 > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after activation." + keyctl search "$3" $KEY_TYPE $2 > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after activation." + $CRYPTSETUP close $DEV_NAME || fail + keyctl search "$3" $KEY_TYPE $1 > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after deactivation." + keyctl search "$3" $KEY_TYPE $2 > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after deactivation." + + echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --volume-key-keyring "$KEY_DESC" --volume-key-keyring "$KEY_DESC2" || fail + $CRYPTSETUP close $DEV_NAME || fail + + keyctl unlink $KEYCTL_KEY_NAME "$3" || fail + echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --volume-key-keyring "$KEY_DESC" --volume-key-keyring "$KEY_DESC2" > /dev/null 2>&1 && fail + keyctl unlink $KEYCTL_KEY_NAME2 "$3" || fail + echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --volume-key-keyring "$KEY_DESC" --volume-key-keyring "$KEY_DESC2" > /dev/null 2>&1 && fail +} + function expect_run() { export INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" @@ -1457,13 +1495,13 @@ if [ $HAVE_KEYRING -gt 0 -a -d /proc/sys/kernel/keys ]; then echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring "@t::%blah:$KEY_NAME" > /dev/null 2>&1 && fail echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring "@t::%userlogon:$KEY_NAME" > /dev/null 2>&1 && fail - # test that only one VK name is used, when the device is not in reencryption + # test that only one VK name is used, when the device is not in reencryption echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring "@u::%user:$KEY_NAME" --link-vk-to-keyring "@u::%user:$KEY_NAME2" > /dev/null 2>&1 || fail keyctl unlink "%user:$KEY_NAME" @u || fail keyctl unlink "%user:$KEY_NAME2" @u > /dev/null 2>&1 && fail $CRYPTSETUP close $DEV_NAME || fail - # test linkning multiple VKs during reencryption + # test linkning multiple VKs during reencryption echo $PWD1 | $CRYPTSETUP -q reencrypt $LOOPDEV --init-only test_reencrypt_vk_link $KEY_NAME $KEY_NAME2 "@u" @@ -1477,12 +1515,22 @@ if [ $HAVE_KEYRING -gt 0 -a -d /proc/sys/kernel/keys ]; then # explicitly specify keyring key type test_reencrypt_vk_link $KEY_NAME $KEY_NAME2 "%keyring:$TEST_KEYRING_NAME" - # the keyring and key type have to be the same for both keys + test_reencrypt_vk_link_and_reactivate $KEY_NAME $KEY_NAME2 "@u" + test_reencrypt_vk_link_and_reactivate $KEY_NAME $KEY_NAME2 "@u" "user" + [[ ! -z "$SESSION_KEYRING_WORKS" ]] && test_reencrypt_vk_link_and_reactivate $KEY_NAME $KEY_NAME2 "@s" + [[ ! -z "$SESSION_KEYRING_WORKS" ]] && test_reencrypt_vk_link_and_reactivate $KEY_NAME $KEY_NAME2 "@s" "user" + test_reencrypt_vk_link_and_reactivate $KEY_NAME $KEY_NAME2 "%:$TEST_KEYRING_NAME" + test_reencrypt_vk_link_and_reactivate $KEY_NAME $KEY_NAME2 "%:$TEST_KEYRING_NAME" "user" + + # explicitly specify keyring key type + test_reencrypt_vk_link $KEY_NAME $KEY_NAME2 "%keyring:$TEST_KEYRING_NAME" + + # the keyring and key type have to be the same for both keys echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring "@s::%user:$KEY_NAME" --link-vk-to-keyring "@u::%user:$KEY_NAME2" > /dev/null 2>&1 && fail echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring "@u::%logon:$KEY_NAME" --link-vk-to-keyring "@u::%user:$KEY_NAME2" > /dev/null 2>&1 && fail echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring "@s::%logon:$KEY_NAME" --link-vk-to-keyring "@u::%user:$KEY_NAME2" > /dev/null 2>&1 && fail - # supply one/three key name(s) when two names are required + # supply one/three key name(s) when two names are required echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring "@s::%logon:$KEY_NAME" > /dev/null 2>&1 && fail echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring "@s::%logon:$KEY_NAME" --link-vk-to-keyring "@s::%logon:$KEY_NAME2" --link-vk-to-keyring "@s::%logon:$KEY_NAME3" > /dev/null 2>&1 && fail fi diff --git a/tests/luks2-reencryption-test b/tests/luks2-reencryption-test index 653204479..61f0d2cbe 100755 --- a/tests/luks2-reencryption-test +++ b/tests/luks2-reencryption-test @@ -30,6 +30,12 @@ PWD1="93R4P4pIqAH8" PWD2="1cND4319812f" PWD3="1-9Qu5Ejfnqv" DEV_LINK="reenc-test-link" +KEYRING="@u" +KEY_TYPE="user" +KEY_NAME1="luks2-reencryption-test1" +KEY_NAME2="luks2-reencryption-test2" +KEY_SPEC1="${KEYRING}::%${KEY_TYPE}:${KEY_NAME1}" +KEY_SPEC2="${KEYRING}::%${KEY_TYPE}:${KEY_NAME2}" FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null) @@ -366,6 +372,38 @@ function reencrypt_recover_online() { # $1 sector size, $2 resilience, $3 digest echo "[OK]" } +function reencrypt_recover_online_vk() { # $1 sector size, $2 resilience, $3 digest, [$4 header] + echo -n "resilience mode: $2 ..." + local _hdr="" + test -z "$4" || _hdr="--header $4" + + echo $PWD1 | $CRYPTSETUP open $DEV $_hdr $DEV_NAME || fail + echo $PWD1 | $CRYPTSETUP reencrypt --active-name $DEV_NAME $_hdr --hotzone-size 1M --resilience $2 --sector-size $1 -q $FAST_PBKDF_ARGON --init-only >/dev/null 2>&1 || fail + $CRYPTSETUP close $DEV_NAME || fail + + echo $PWD1 | $CRYPTSETUP open --link-vk-to-keyring $KEY_SPEC1 --link-vk-to-keyring $KEY_SPEC2 $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 >/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 + + # recovery during activation + $CRYPTSETUP open --volume-key-keyring $KEY_NAME1 --volume-key-keyring $KEY_NAME2 $DEV $_hdr $DEV_NAME || fail + check_hash_dev /dev/mapper/$DEV_NAME $3 + + $CRYPTSETUP luksDump ${4:-$DEV} | grep -q "online-reencrypt" + if [ $? -eq 0 ]; then + $CRYPTSETUP status $DEV_NAME $_hdr | grep -q "reencryption: in-progress" || fail + echo $PWD1 | $CRYPTSETUP reencrypt --active-name $DEV_NAME $_hdr --resilience $2 --resume-only -q || fail + check_hash_dev /dev/mapper/$DEV_NAME $3 + fi + + $CRYPTSETUP close $DEV_NAME || fail + echo "[OK]" +} + function encrypt_recover() { # $1 sector size, $2 reduce size, $3 digest, $4 device size in sectors, $5 origin digest wipe_dev $DEV check_hash_dev $DEV $5 @@ -1261,6 +1299,40 @@ if [ -n "$DM_SECTOR_SIZE" ]; then reencrypt_recover_online 4096 journal $HASH1 fi +echo "sector size 512->512 (recovery by VK)" + +get_error_offsets 32 $OFFSET +echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail +wipe $PWD1 + +echo "ERR writes to sectors (recovery by VK) [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]" +reencrypt_recover_online_vk 512 checksum $HASH1 +reencrypt_recover_online_vk 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 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail + wipe $PWD1 + + echo "ERR writes to sectors (recovery by VK) [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]" + reencrypt_recover_online_vk 4096 checksum $HASH1 + echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail + wipe $PWD1 + reencrypt_recover_online_vk 4096 journal $HASH1 + + echo "sector size 4096->4096" + + get_error_offsets 32 $OFFSET 4096 + echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 --sector-size 4096 -c aes-cbc-essiv:sha256 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail + wipe $PWD1 + + echo "ERR writes to sectors (recovery by VK) [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]" + reencrypt_recover_online_vk 4096 checksum $HASH1 + reencrypt_recover_online_vk 4096 journal $HASH1 +fi + echo "[8] Reencryption with detached header recovery" prepare_linear_dev 31 opt_blks=64 $OPT_XFERLEN_EXP