diff options
Diffstat (limited to 'tests')
57 files changed, 3840 insertions, 455 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index c8a46a8..75c1d3d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,6 +4,7 @@ TESTS = 00modules-test \ compat-args-test \ compat-test \ compat-test2 \ + compat-test-opal \ loopaes-test \ align-test \ align-test2 \ @@ -44,15 +45,7 @@ if EXTERNAL_TOKENS TESTS += systemd-test-plugin endif -ssh-test-plugin: fake_token_path.so -systemd-test-plugin: fake_token_path.so fake_systemd_tpm_path.so - -# Do not use global CFLAGS here as the *.so link does not support sanitizers -fake_token_path.so: fake_token_path.c - $(CC) $(LDFLAGS) -I $(top_srcdir)/lib -fPIC -shared -D_GNU_SOURCE \ - -Wl,--version-script=$(top_srcdir)/lib/libcryptsetup.sym \ - -o fake_token_path.so $(top_srcdir)/tests/fake_token_path.c \ - -DBUILD_DIR=\"$(abs_top_srcdir)/.libs/\" +systemd-test-plugin: fake_systemd_tpm_path.so fake_systemd_tpm_path.so: fake_systemd_tpm_path.c $(CC) $(LDFLAGS) -fPIC -shared -D_GNU_SOURCE -o fake_systemd_tpm_path.so \ @@ -68,6 +61,7 @@ EXTRA_DIST = compatimage.img.xz compatv10image.img.xz \ luks2_valid_hdr.img.xz \ luks2_header_requirements.tar.xz \ luks2_mda_images.tar.xz \ + luks2_invalid_cipher.img.xz \ evil_hdr-payload_overwrite.xz \ evil_hdr-stripes_payload_dmg.xz \ evil_hdr-luks_hdr_damage.xz \ @@ -79,6 +73,7 @@ EXTRA_DIST = compatimage.img.xz compatv10image.img.xz \ compat-args-test \ compat-test \ compat-test2 \ + compat-test-opal \ loopaes-test align-test discards-test mode-test password-hash-test \ align-test2 verity-compat-test \ reencryption-compat-test \ @@ -103,14 +98,14 @@ EXTRA_DIST = compatimage.img.xz compatv10image.img.xz \ ssh-test-plugin \ generate-symbols-list \ run-all-symbols \ - fake_token_path.c \ fake_systemd_tpm_path.c \ unit-wipe-test \ systemd-test-plugin -CLEANFILES = cryptsetup-tst* valglog* *-fail-*.log test-symbols-list.h fake_token_path.so fake_systemd_tpm_path.so +CLEANFILES = cryptsetup-tst* valglog* *-fail-*.log test-symbols-list.h fake_systemd_tpm_path.so clean-local: - -rm -rf tcrypt-images luks1-images luks2-images bitlk-images fvault2-images conversion_imgs luks2_valid_hdr.img blkid-luks2-pv-img blkid-luks2-pv-img.bcp external-tokens + -rm -rf tcrypt-images luks1-images luks2-images bitlk-images fvault2-images conversion_imgs \ + luks2_valid_hdr.img blkid-luks2-pv-img blkid-luks2-pv-img.bcp external-tokens luks2_invalid_cipher.img differ_SOURCES = differ.c differ_CFLAGS = $(AM_CFLAGS) -Wall -O2 @@ -165,7 +160,7 @@ all_symbols_test_CPPFLAGS = $(AM_CPPFLAGS) -D_GNU_SOURCE check_PROGRAMS = api-test api-test-2 differ vectors-test unit-utils-io unit-utils-crypt-test unit-wipe all-symbols-test -check-programs: test-symbols-list.h $(check_PROGRAMS) fake_token_path.so fake_systemd_tpm_path.so +check-programs: test-symbols-list.h $(check_PROGRAMS) fake_systemd_tpm_path.so conversion_imgs: @tar xJf conversion_imgs.tar.xz @@ -177,6 +172,7 @@ valgrind-check: api-test api-test-2 differ @VALG=1 ./compat-args-test @VALG=1 ./compat-test @VALG=1 ./compat-test2 + @[ -z "$(OPAL2_PSID_FILE)" ] || VALG=1 ./compat-test-opal @VALG=1 ./luks2-validation-test @VALG=1 ./verity-compat-test @VALG=1 ./integrity-compat-test @@ -198,7 +194,7 @@ valgrind-check: api-test api-test-2 differ @VALG=1 ./password-hash-test @VALG=1 ./reencryption-compat-test @VALG=1 ./fvault2-compat-test - @[ -z "$RUN_SSH_PLUGIN_TEST" ] || VALG=1 ./ssh-test-plugin + @[ -z "$(RUN_SSH_PLUGIN_TEST)" ] || VALG=1 ./ssh-test-plugin @INFOSTRING="unit-utils-crypt-test" ./valg-api.sh ./unit-utils-crypt-test @INFOSTRING="vectors-test" ./valg-api.sh ./vectors-test @grep -l "ERROR SUMMARY: [^0][0-9]* errors" valglog* || echo "No leaks detected." diff --git a/tests/align-test b/tests/align-test index 5941cde..d2932ae 100755 --- a/tests/align-test +++ b/tests/align-test @@ -12,8 +12,13 @@ FAST_PBKDF="--pbkdf-force-iterations 1000" FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null) -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi + function fips_mode() { @@ -54,7 +59,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() @@ -92,7 +100,7 @@ add_device() { exit 77 fi - sleep 2 + sleep 1 DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /) if [ ! -e /sys/block/$DEV/alignment_offset ] ; then @@ -176,7 +184,7 @@ format_plain() # sector size { echo -n "Formatting plain device (sector size $1)..." if [ -n "$DM_SECTOR_SIZE" ] ; then - echo $PWD1 | $CRYPTSETUP open --type plain --hash sha256 --sector-size $1 $DEV $DEV_NAME || fail + echo $PWD1 | $CRYPTSETUP open --type plain --cipher aes-cbc-essiv:sha256 --key-size 256 --hash sha256 --sector-size $1 $DEV $DEV_NAME || fail $CRYPTSETUP close $DEV_NAME || fail echo "PASSED" else diff --git a/tests/align-test2 b/tests/align-test2 index 33126a4..23d418a 100755 --- a/tests/align-test2 +++ b/tests/align-test2 @@ -11,8 +11,12 @@ PWD1="93R4P4pIqAH8" PWD2="mymJeD8ivEhE" FAST_PBKDF="--pbkdf pbkdf2 --pbkdf-force-iterations 1000" -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi cleanup() { udevadm settle >/dev/null 2>&1 @@ -49,7 +53,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() @@ -87,7 +94,7 @@ add_device() { exit 77 fi - sleep 2 + sleep 1 DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /) if [ ! -e /sys/block/$DEV/alignment_offset ] ; then diff --git a/tests/all-symbols-test.c b/tests/all-symbols-test.c index 10c7fe2..8d75044 100644 --- a/tests/all-symbols-test.c +++ b/tests/all-symbols-test.c @@ -1,7 +1,7 @@ /* * Test utility checking symbol versions in libcryptsetup. * - * Copyright (C) 2021-2023 Red Hat, Inc. All rights reserved. + * Copyright (C) 2021-2024 Red Hat, Inc. All rights reserved. * * This file is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -85,6 +85,10 @@ static int check_dlvsym(void *h, const char *symbol, const char *version) } log_dbg("OK\n"); +#else + UNUSED(h); + UNUSED(symbol); + UNUSED(version); #endif return 0; } diff --git a/tests/api-test-2.c b/tests/api-test-2.c index 824ae65..8a7a60e 100644 --- a/tests/api-test-2.c +++ b/tests/api-test-2.c @@ -1,9 +1,9 @@ /* * cryptsetup library LUKS2 API check functions * - * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2023 Milan Broz - * Copyright (C) 2016-2023 Ondrej Kozina + * Copyright (C) 2009-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2024 Milan Broz + * Copyright (C) 2016-2024 Ondrej Kozina * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -59,10 +59,12 @@ typedef int32_t key_serial_t; #define L_DEVICE_0S "luks_zerosec" #define L_DEVICE_WRONG "luks_wr" #define L_DEVICE_OK "luks_ok" +#define L_PLACEHOLDER "bdev_reference_placeholder" #define REQS_LUKS2_HEADER "luks2_header_requirements" #define NO_REQS_LUKS2_HEADER "luks2_header_requirements_free" #define BACKUP_FILE "csetup_backup_file" #define IMAGE1 "compatimage2.img" +#define EMPTY_HEADER "empty.hdr" #define IMAGE_EMPTY "empty.img" #define IMAGE_EMPTY_SMALL "empty_small.img" #define IMAGE_EMPTY_SMALL_2 "empty_small2.img" @@ -83,6 +85,19 @@ typedef int32_t key_serial_t; #define DEVICE_CHAR "/dev/zero" #define THE_LFILE_TEMPLATE "cryptsetup-tstlp.XXXXXX" +#define TEST_KEYRING_USER "cs_apitest2_keyring_in_user" +#define TEST_KEYRING_USER_NAME "%keyring:" TEST_KEYRING_USER +#define TEST_KEYRING_SESSION "cs_apitest2_keyring_in_session" +#define TEST_KEYRING_SESSION_NAME "%keyring:" TEST_KEYRING_SESSION +#define TEST_KEY_VK_USER "api_test_user_vk1" +#define TEST_KEY_VK_USER_NAME "\%user:" TEST_KEY_VK_USER +#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_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 + #define KEY_DESC_TEST0 "cs_token_test:test_key0" #define KEY_DESC_TEST1 "cs_token_test:test_key1" @@ -141,6 +156,10 @@ static uint32_t default_luks2_iter_time = 0; static uint32_t default_luks2_memory_kb = 0; static uint32_t default_luks2_parallel_threads = 0; +#ifdef KERNEL_KEYRING +static char keyring_in_user_str_id[32] = {0}; +#endif + static struct crypt_pbkdf_type min_pbkdf2 = { .type = "pbkdf2", .iterations = 1000, @@ -196,7 +215,7 @@ static int get_luks2_offsets(int metadata_device, uint64_t *r_header_size, uint64_t *r_payload_offset) { - struct crypt_device *cd = NULL; + struct crypt_device *_cd = NULL; static uint64_t default_header_size = 0; if (r_header_size) @@ -205,16 +224,16 @@ static int get_luks2_offsets(int metadata_device, *r_payload_offset = 0; if (!default_header_size) { - if (crypt_init(&cd, THE_LOOP_DEV)) + if (crypt_init(&_cd, THE_LOOP_DEV)) return -EINVAL; - if (crypt_format(cd, CRYPT_LUKS2, "aes", "xts-plain64", NULL, NULL, 64, NULL)) { - crypt_free(cd); + if (crypt_format(_cd, CRYPT_LUKS2, "aes", "xts-plain64", NULL, NULL, 64, NULL)) { + crypt_free(_cd); return -EINVAL; } - default_header_size = crypt_get_data_offset(cd); + default_header_size = crypt_get_data_offset(_cd); - crypt_free(cd); + crypt_free(_cd); } if (!sector_size) @@ -225,7 +244,7 @@ static int get_luks2_offsets(int metadata_device, if (r_payload_offset) { if (metadata_device) - *r_payload_offset = alignpayload_sec * sector_size; + *r_payload_offset = (uint64_t)alignpayload_sec * sector_size; else *r_payload_offset = DIV_ROUND_UP_MODULO(default_header_size * 512, (alignpayload_sec ?: 1) * sector_size); @@ -278,6 +297,9 @@ static void _cleanup_dmdevices(void) { struct stat st; + if (!stat(DMDIR L_PLACEHOLDER, &st)) + _system("dmsetup remove " DM_RETRY L_PLACEHOLDER DM_NOSTDERR, 0); + if (!stat(DMDIR H_DEVICE, &st)) _system("dmsetup remove " DM_RETRY H_DEVICE DM_NOSTDERR, 0); @@ -299,80 +321,6 @@ static void _cleanup_dmdevices(void) t_dev_offset = 0; } -static void _cleanup(void) -{ - struct stat st; - - CRYPT_FREE(cd); - CRYPT_FREE(cd2); - - //_system("udevadm settle", 0); - - if (!stat(DMDIR CDEVICE_1, &st)) - _system("dmsetup remove " DM_RETRY CDEVICE_1 DM_NOSTDERR, 0); - - if (!stat(DMDIR CDEVICE_2, &st)) - _system("dmsetup remove " DM_RETRY CDEVICE_2 DM_NOSTDERR, 0); - - if (!stat(DEVICE_EMPTY, &st)) - _system("dmsetup remove " DM_RETRY DEVICE_EMPTY_name DM_NOSTDERR, 0); - - if (!stat(DEVICE_ERROR, &st)) - _system("dmsetup remove " DM_RETRY DEVICE_ERROR_name DM_NOSTDERR, 0); - - _cleanup_dmdevices(); - - if (loop_device(THE_LOOP_DEV)) - loop_detach(THE_LOOP_DEV); - - if (loop_device(DEVICE_1)) - loop_detach(DEVICE_1); - - if (loop_device(DEVICE_2)) - loop_detach(DEVICE_2); - - if (loop_device(DEVICE_3)) - loop_detach(DEVICE_3); - - if (loop_device(DEVICE_4)) - loop_detach(DEVICE_4); - - if (loop_device(DEVICE_5)) - loop_detach(DEVICE_5); - - if (loop_device(DEVICE_6)) - loop_detach(DEVICE_6); - - _system("rm -f " IMAGE_EMPTY, 0); - _system("rm -f " IMAGE1, 0); - _system("rm -rf " CONV_DIR, 0); - - if (test_loop_file) - remove(test_loop_file); - if (tmp_file_1) - remove(tmp_file_1); - - remove(REQS_LUKS2_HEADER); - remove(NO_REQS_LUKS2_HEADER); - remove(BACKUP_FILE); - remove(IMAGE_PV_LUKS2_SEC); - remove(IMAGE_PV_LUKS2_SEC ".bcp"); - remove(IMAGE_EMPTY_SMALL); - remove(IMAGE_EMPTY_SMALL_2); - - _remove_keyfiles(); - - free(tmp_file_1); - free(test_loop_file); - free(THE_LOOP_DEV); - free(DEVICE_1); - free(DEVICE_2); - free(DEVICE_3); - free(DEVICE_4); - free(DEVICE_5); - free(DEVICE_6); -} - static int _setup(void) { int fd, ro = 0; @@ -429,6 +377,8 @@ static int _setup(void) _system("dd if=/dev/zero of=" IMAGE_EMPTY_SMALL_2 " bs=512 count=2050 2>/dev/null", 1); + _system("dd if=/dev/zero of=" EMPTY_HEADER " bs=4K count=1 2>/dev/null", 1); + _system(" [ ! -e " NO_REQS_LUKS2_HEADER " ] && tar xJf " REQS_LUKS2_HEADER ".tar.xz", 1); fd = loop_attach(&DEVICE_4, NO_REQS_LUKS2_HEADER, 0, 0, &ro); close(fd); @@ -467,7 +417,7 @@ static int _setup(void) return 0; } -static int set_fast_pbkdf(struct crypt_device *cd) +static int set_fast_pbkdf(struct crypt_device *_cd) { const struct crypt_pbkdf_type *pbkdf = &min_argon2; @@ -475,7 +425,7 @@ static int set_fast_pbkdf(struct crypt_device *cd) if (_fips_mode) pbkdf = &min_pbkdf2; - return crypt_set_pbkdf_type(cd, pbkdf); + return crypt_set_pbkdf_type(_cd, pbkdf); } #ifdef KERNEL_KEYRING @@ -489,6 +439,21 @@ static key_serial_t keyctl_unlink(key_serial_t key, key_serial_t keyring) return syscall(__NR_keyctl, KEYCTL_UNLINK, key, keyring); } +static key_serial_t keyctl_link(key_serial_t key, key_serial_t keyring) +{ + return syscall(__NR_keyctl, KEYCTL_LINK, key, keyring); +} + +static long keyctl_update(key_serial_t id, const void *payload, size_t plen) +{ + return syscall(__NR_keyctl, KEYCTL_UPDATE, id, payload, plen); +} + +static long keyctl_read(key_serial_t id, char *buffer, size_t buflen) +{ + return syscall(__NR_keyctl, KEYCTL_READ, id, buffer, buflen); +} + static key_serial_t request_key(const char *type, const char *description, const char *callout_info, @@ -497,33 +462,168 @@ static key_serial_t request_key(const char *type, return syscall(__NR_request_key, type, description, callout_info, keyring); } -static key_serial_t _kernel_key_by_segment(struct crypt_device *cd, int segment) +/* key handle permissions mask */ +typedef uint32_t key_perm_t; +#define KEY_POS_ALL 0x3f000000 +#define KEY_USR_ALL 0x003f0000 + +static key_serial_t add_key_set_perm(const char *type, const char *description, const void *payload, size_t plen, key_serial_t keyring, key_perm_t perm) +{ + long l; + key_serial_t kid = syscall(__NR_add_key, type, description, payload, plen, KEY_SPEC_THREAD_KEYRING); + + if (kid < 0) + return kid; + + l = syscall(__NR_keyctl, KEYCTL_SETPERM, kid, perm); + if (l == 0) + l = syscall(__NR_keyctl, KEYCTL_LINK, kid, keyring); + + syscall(__NR_keyctl, KEYCTL_UNLINK, kid, KEY_SPEC_THREAD_KEYRING); + + return l == 0 ? kid : -EINVAL; +} + +static key_serial_t _kernel_key_by_segment_and_type(struct crypt_device *_cd, int segment, + const char* type) { char key_description[1024]; - if (snprintf(key_description, sizeof(key_description), "cryptsetup:%s-d%u", crypt_get_uuid(cd), segment) < 1) + if (snprintf(key_description, sizeof(key_description), "cryptsetup:%s-d%u", crypt_get_uuid(_cd), segment) < 1) return -1; - return request_key("logon", key_description, NULL, 0); + return request_key(type, key_description, NULL, 0); } -static int _volume_key_in_keyring(struct crypt_device *cd, int segment) +static key_serial_t _kernel_key_by_segment(struct crypt_device *_cd, int segment) { - return _kernel_key_by_segment(cd, segment) >= 0 ? 0 : -1; + return _kernel_key_by_segment_and_type(_cd, segment, "logon"); +} + +static int _volume_key_in_keyring(struct crypt_device *_cd, int segment) +{ + return _kernel_key_by_segment(_cd, segment) >= 0 ? 0 : -1; +} + +static int _drop_keyring_key_from_keyring_name(const char *key_description, key_serial_t keyring, const char* type) +{ + //key_serial_t kid = request_key(type, key_description, NULL, keyring); + key_serial_t kid = request_key(type, key_description, NULL, 0); + + if (kid < 0) + return -2; + + return keyctl_unlink(kid, keyring); } -static int _drop_keyring_key(struct crypt_device *cd, int segment) +static int _drop_keyring_key_from_keyring_type(struct crypt_device *_cd, int segment, + key_serial_t keyring, const char* type) { - key_serial_t kid = _kernel_key_by_segment(cd, segment); + key_serial_t kid = _kernel_key_by_segment_and_type(_cd, segment, type); if (kid < 0) return -1; - return keyctl_unlink(kid, KEY_SPEC_THREAD_KEYRING); + return keyctl_unlink(kid, keyring); +} + +static int _drop_keyring_key(struct crypt_device *_cd, int segment) +{ + return _drop_keyring_key_from_keyring_type(_cd, segment, KEY_SPEC_THREAD_KEYRING, "logon"); } #endif -static int test_open(struct crypt_device *cd __attribute__((unused)), +static void _cleanup(void) +{ + struct stat st; + + CRYPT_FREE(cd); + CRYPT_FREE(cd2); + + //_system("udevadm settle", 0); + + if (!stat(DMDIR CDEVICE_1, &st)) + _system("dmsetup remove " DM_RETRY CDEVICE_1 DM_NOSTDERR, 0); + + if (!stat(DMDIR CDEVICE_2, &st)) + _system("dmsetup remove " DM_RETRY CDEVICE_2 DM_NOSTDERR, 0); + + if (!stat(DEVICE_EMPTY, &st)) + _system("dmsetup remove " DM_RETRY DEVICE_EMPTY_name DM_NOSTDERR, 0); + + if (!stat(DEVICE_ERROR, &st)) + _system("dmsetup remove " DM_RETRY DEVICE_ERROR_name DM_NOSTDERR, 0); + + _cleanup_dmdevices(); + + if (loop_device(THE_LOOP_DEV)) + loop_detach(THE_LOOP_DEV); + + if (loop_device(DEVICE_1)) + loop_detach(DEVICE_1); + + if (loop_device(DEVICE_2)) + loop_detach(DEVICE_2); + + if (loop_device(DEVICE_3)) + loop_detach(DEVICE_3); + + if (loop_device(DEVICE_4)) + loop_detach(DEVICE_4); + + if (loop_device(DEVICE_5)) + loop_detach(DEVICE_5); + + if (loop_device(DEVICE_6)) + loop_detach(DEVICE_6); + + _system("rm -f " IMAGE_EMPTY, 0); + _system("rm -f " IMAGE1, 0); + _system("rm -rf " CONV_DIR, 0); + _system("rm -f " EMPTY_HEADER, 0); + + if (test_loop_file) + remove(test_loop_file); + if (tmp_file_1) + remove(tmp_file_1); + + remove(REQS_LUKS2_HEADER); + remove(NO_REQS_LUKS2_HEADER); + remove(BACKUP_FILE); + remove(IMAGE_PV_LUKS2_SEC); + remove(IMAGE_PV_LUKS2_SEC ".bcp"); + remove(IMAGE_EMPTY_SMALL); + remove(IMAGE_EMPTY_SMALL_2); + + _remove_keyfiles(); + + free(tmp_file_1); + free(test_loop_file); + free(THE_LOOP_DEV); + free(DEVICE_1); + free(DEVICE_2); + free(DEVICE_3); + free(DEVICE_4); + free(DEVICE_5); + free(DEVICE_6); + +#ifdef KERNEL_KEYRING + char *end; + key_serial_t krid; + + if (keyring_in_user_str_id[0] != '\0') { + krid = strtoul(keyring_in_user_str_id, &end, 0); + if (!*end) + (void)keyctl_unlink(krid, KEY_SPEC_USER_KEYRING); + } + + krid = request_key("keyring", TEST_KEYRING_SESSION, NULL, 0); + if (krid > 0) + (void)keyctl_unlink(krid, KEY_SPEC_SESSION_KEYRING); +#endif +} + +static int test_open(struct crypt_device *_cd __attribute__((unused)), int token __attribute__((unused)), char **buffer, size_t *buffer_len, @@ -539,7 +639,35 @@ static int test_open(struct crypt_device *cd __attribute__((unused)), return 0; } -static int test_validate(struct crypt_device *cd __attribute__((unused)), const char *json) +static int test_open_pass(struct crypt_device *_cd __attribute__((unused)), + int token __attribute__((unused)), + char **buffer, + size_t *buffer_len, + void *usrptr __attribute__((unused))) +{ + *buffer = strdup(PASSPHRASE); + if (!*buffer) + return -ENOMEM; + *buffer_len = strlen(*buffer); + + return 0; +} + +static int test_open_pass1(struct crypt_device *_cd __attribute__((unused)), + int token __attribute__((unused)), + char **buffer, + size_t *buffer_len, + void *usrptr __attribute__((unused))) +{ + *buffer = strdup(PASSPHRASE1); + if (!*buffer) + return -ENOMEM; + *buffer_len = strlen(*buffer); + + return 0; +} + +static int test_validate(struct crypt_device *_cd __attribute__((unused)), const char *json) { return (strstr(json, "magic_string") == NULL); } @@ -1925,6 +2053,10 @@ static void Tokens(void) #define LUKS2_KEYRING_TOKEN_JSON_BAD(x, y) "{\"type\":\"luks2-keyring\",\"keyslots\":[" x "]," \ "\"key_description\":" y ", \"some_field\":\"some_value\"}" +#define TEST_TOKEN2_JSON(x) "{\"type\":\"test_token2\",\"keyslots\":[" x "] }" + +#define TEST_TOKEN3_JSON(x) "{\"type\":\"test_token3\",\"keyslots\":[" x "] }" + int ks, token_max; const char *dummy; @@ -1933,6 +2065,7 @@ static void Tokens(void) char passptr[] = PASSPHRASE; char passptr1[] = PASSPHRASE1; struct crypt_active_device cad; + struct crypt_keyslot_context *kc; static const crypt_token_handler th = { .name = "test_token", @@ -1948,6 +2081,12 @@ static void Tokens(void) }, th_reserved = { .name = "luks2-prefix", .open = test_open + }, th4 = { + .name = "test_token2", + .open = test_open_pass, // PASSPHRASE + }, th5 = { + .name = "test_token3", + .open = test_open_pass1, // PASSPHRASE1 }; struct crypt_token_params_luks2_keyring params = { @@ -2153,6 +2292,60 @@ static void Tokens(void) OK_(crypt_deactivate(cd, CDEVICE_1)); CRYPT_FREE(cd); + // test token based API with keyslot parameter + OK_(crypt_token_register(&th4)); // PASSPHRASE + OK_(crypt_token_register(&th5)); // PASSPHRASE1 + OK_(crypt_init(&cd, DMDIR L_DEVICE_1S)); + OK_(set_fast_pbkdf(cd)); + OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, 32, NULL)); + EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0); + EQ_(crypt_keyslot_add_by_volume_key(cd, 1, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 1); + EQ_(crypt_keyslot_add_by_volume_key(cd, 2, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 2); + + EQ_(crypt_keyslot_add_by_volume_key(cd, 3, NULL, 32, PASSPHRASE1, strlen(PASSPHRASE1)), 3); + EQ_(crypt_keyslot_add_by_volume_key(cd, 4, NULL, 32, PASSPHRASE1, strlen(PASSPHRASE1)), 4); + EQ_(crypt_keyslot_add_by_volume_key(cd, 5, NULL, 32, PASSPHRASE1, strlen(PASSPHRASE1)), 5); + + OK_(crypt_keyslot_set_priority(cd, 0, CRYPT_SLOT_PRIORITY_IGNORE)); + OK_(crypt_keyslot_set_priority(cd, 3, CRYPT_SLOT_PRIORITY_IGNORE)); + + OK_(crypt_keyslot_set_priority(cd, 2, CRYPT_SLOT_PRIORITY_PREFER)); + OK_(crypt_keyslot_set_priority(cd, 5, CRYPT_SLOT_PRIORITY_PREFER)); + + EQ_(crypt_keyslot_add_by_key(cd, 6, NULL, 32, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 6); + EQ_(crypt_keyslot_add_by_key(cd, 7, NULL, 32, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT), 7); + + OK_(crypt_keyslot_set_priority(cd, 6, CRYPT_SLOT_PRIORITY_PREFER)); + OK_(crypt_keyslot_set_priority(cd, 7, CRYPT_SLOT_PRIORITY_PREFER)); + + EQ_(crypt_token_json_set(cd, 0, TEST_TOKEN2_JSON("\"0\", \"5\", \"1\", \"6\"")), 0); // PASSPHRASE + EQ_(crypt_token_json_set(cd, 1, TEST_TOKEN3_JSON("\"4\", \"6\", \"0\", \"5\"")), 1); // PASSPHRASE1 + + /* keyslots: + * + * 0 ignore (token 0) + * 1 normal (token 0) + * 2 prefer - + * 3 ignore - + * 4 normal (token 1) + * 5 prefer (token 1, token 0 wrong passphrase) + * 6 prefer (unbound, token 0, token 1 wrong passphrase) + * 7 prefer (unbound) + */ + + OK_(crypt_keyslot_context_init_by_token(cd, 0, NULL, NULL, 0, NULL, &kc)); + EQ_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), 1); + EQ_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY), 6); + EQ_(crypt_activate_by_keyslot_context(cd, NULL, 7, kc, CRYPT_ANY_SLOT, NULL, CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY), -ENOENT); + EQ_(crypt_activate_by_keyslot_context(cd, NULL, 5, kc, CRYPT_ANY_SLOT, NULL, CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY), -EPERM); + crypt_keyslot_context_free(kc); + + OK_(crypt_keyslot_context_init_by_token(cd, CRYPT_ANY_TOKEN, NULL, NULL, 0, NULL, &kc)); + EQ_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), 5); + crypt_keyslot_context_free(kc); + + CRYPT_FREE(cd); + EQ_(crypt_token_max(CRYPT_LUKS2), 32); FAIL_(crypt_token_max(CRYPT_LUKS1), "No token support in LUKS1"); FAIL_(crypt_token_max(NULL), "No LUKS format specified"); @@ -2802,7 +2995,8 @@ static void Pbkdf(void) OK_(strcmp(pbkdf->type, default_luks2_pbkdf)); OK_(strcmp(pbkdf->hash, default_luks1_hash)); EQ_(pbkdf->time_ms, default_luks2_iter_time); - EQ_(pbkdf->max_memory_kb, adjusted_pbkdf_memory()); + GE_(pbkdf->max_memory_kb, 64 * 1024); + GE_(adjusted_pbkdf_memory(), pbkdf->max_memory_kb); EQ_(pbkdf->parallel_threads, _min(cpus_online(), default_luks2_parallel_threads)); // set and verify argon2 type OK_(crypt_set_pbkdf_type(cd, &argon2)); @@ -2827,7 +3021,8 @@ static void Pbkdf(void) OK_(strcmp(pbkdf->type, default_luks2_pbkdf)); OK_(strcmp(pbkdf->hash, default_luks1_hash)); EQ_(pbkdf->time_ms, default_luks2_iter_time); - EQ_(pbkdf->max_memory_kb, adjusted_pbkdf_memory()); + GE_(pbkdf->max_memory_kb, 64 * 1024); + GE_(adjusted_pbkdf_memory(), pbkdf->max_memory_kb); EQ_(pbkdf->parallel_threads, _min(cpus_online(), default_luks2_parallel_threads)); // try to pass illegal values argon2.parallel_threads = 0; @@ -2858,14 +3053,16 @@ static void Pbkdf(void) OK_(strcmp(pbkdf->type, default_luks2_pbkdf)); OK_(strcmp(pbkdf->hash, default_luks1_hash)); EQ_(pbkdf->time_ms, default_luks2_iter_time); - EQ_(pbkdf->max_memory_kb, adjusted_pbkdf_memory()); + GE_(pbkdf->max_memory_kb, 64 * 1024); + GE_(adjusted_pbkdf_memory(), pbkdf->max_memory_kb); EQ_(pbkdf->parallel_threads, _min(cpus_online(), default_luks2_parallel_threads)); crypt_set_iteration_time(cd, 1); OK_(crypt_load(cd, CRYPT_LUKS, NULL)); OK_(strcmp(pbkdf->type, default_luks2_pbkdf)); OK_(strcmp(pbkdf->hash, default_luks1_hash)); EQ_(pbkdf->time_ms, 1); - EQ_(pbkdf->max_memory_kb, adjusted_pbkdf_memory()); + GE_(pbkdf->max_memory_kb, 64 * 1024); + GE_(adjusted_pbkdf_memory(), pbkdf->max_memory_kb); EQ_(pbkdf->parallel_threads, _min(cpus_online(), default_luks2_parallel_threads)); CRYPT_FREE(cd); @@ -2913,6 +3110,17 @@ static void Pbkdf(void) argon2.hash = NULL; OK_(crypt_set_pbkdf_type(cd, &argon2)); + argon2.flags = CRYPT_PBKDF_NO_BENCHMARK; + argon2.max_memory_kb = 2 * 1024 * 1024; + argon2.iterations = 6; + argon2.parallel_threads = 8; + OK_(crypt_set_pbkdf_type(cd, &argon2)); + NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd)); + EQ_(pbkdf->iterations, 6); + EQ_(pbkdf->max_memory_kb, 2 * 1024 *1024); + EQ_(pbkdf->parallel_threads, 4); /* hard maximum*/ + EQ_(pbkdf->flags, CRYPT_PBKDF_NO_BENCHMARK); + CRYPT_FREE(cd); NOTNULL_(pbkdf = crypt_get_pbkdf_default(CRYPT_LUKS1)); @@ -3015,6 +3223,9 @@ static void Luks2KeyslotAdd(void) OK_(crypt_deactivate(cd, CDEVICE_1)); EQ_(crypt_activate_by_passphrase(cd, NULL, 1, PASSPHRASE1, strlen(PASSPHRASE1), 0), 1); EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 1, PASSPHRASE1, strlen(PASSPHRASE1), 0), 1); + /* check we can resume device with new volume key */ + OK_(crypt_suspend(cd, CDEVICE_1)); + EQ_(crypt_resume_by_passphrase(cd, CDEVICE_1, 1, PASSPHRASE1, strlen(PASSPHRASE1)), 1); OK_(crypt_deactivate(cd, CDEVICE_1)); /* old keyslot must be unusable */ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "Key doesn't match volume key digest"); @@ -4332,6 +4543,52 @@ static void Luks2Reencryption(void) CRYPT_FREE(cd); _cleanup_dmdevices(); + OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_header_size + 1)); + + /* offline in-place encryption with reserved space in the head of data device */ + OK_(crypt_init(&cd, DMDIR L_DEVICE_OK)); + memset(&rparams, 0, sizeof(rparams)); + params2.sector_size = 512; + rparams.mode = CRYPT_REENCRYPT_ENCRYPT; + rparams.direction = CRYPT_REENCRYPT_FORWARD; + rparams.resilience = "checksum"; + rparams.hash = "sha256"; + rparams.luks2 = ¶ms2; + rparams.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY; + OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "xts-plain64", NULL, NULL, 64, ¶ms2)); + EQ_(crypt_keyslot_add_by_volume_key(cd, 30, NULL, 64, PASSPHRASE, strlen(PASSPHRASE)), 30); + OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ANY_SLOT, 30, "aes", "xts-plain64", &rparams)); + FAIL_(crypt_reencrypt_run(cd, NULL, NULL), "context not initialized"); + rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY; + OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ANY_SLOT, 30, "aes", "xts-plain64", &rparams)); + OK_(crypt_reencrypt_run(cd, NULL, NULL)); + EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE); + CRYPT_FREE(cd); + + /* wipe existing header from previous run */ + _system("dd if=/dev/zero of=" DMDIR L_DEVICE_OK " bs=4K count=5 2>/dev/null", 1); + /* open existing device from kernel (simulate active filesystem) */ + OK_(create_dmdevice_over_device(L_PLACEHOLDER, DMDIR L_DEVICE_OK, 1, r_header_size)); + + /* online in-place encryption with reserved space */ + rparams.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY; + OK_(crypt_init(&cd, EMPTY_HEADER)); + OK_(crypt_set_data_offset(cd, r_header_size)); + OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "xts-plain64", NULL, NULL, 64, ¶ms2)); + EQ_(crypt_keyslot_add_by_volume_key(cd, 30, NULL, 64, PASSPHRASE, strlen(PASSPHRASE)), 30); + OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ANY_SLOT, 30, "aes", "xts-plain64", &rparams)); + CRYPT_FREE(cd); + OK_(crypt_init(&cd, DMDIR L_DEVICE_OK)); + OK_(crypt_header_restore(cd, CRYPT_LUKS2, EMPTY_HEADER)); + NOTFAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_SHARED), "Failed to activate device in reencryption with shared flag."); + rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY; + OK_(crypt_reencrypt_init_by_passphrase(cd, CDEVICE_1, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ANY_SLOT, 30, "aes", "xts-plain64", &rparams)); + OK_(crypt_reencrypt_run(cd, NULL, NULL)); + EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE); + OK_(crypt_deactivate(cd, CDEVICE_1)); + CRYPT_FREE(cd); + + _cleanup_dmdevices(); OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size)); OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_header_size + 1)); @@ -5005,10 +5262,479 @@ static void VolumeKeyGet(void) _cleanup_dmdevices(); } -static int _crypt_load_check(struct crypt_device *cd) +static void KeyslotContextAndKeyringLink(void) +{ +#ifdef KERNEL_KEYRING + const char *cipher = "aes"; + const char *cipher_mode = "xts-plain64"; + struct crypt_keyslot_context *kc, *kc2; + uint64_t r_payload_offset; + char key[128]; + size_t key_size = 128; + key_serial_t kid, keyring_in_user_id, keyring_in_session_id, linked_kid, linked_kid2; + int suspend_status; + struct crypt_active_device cad; + char vk_buf[1024]; + long vk_len; + + struct crypt_pbkdf_type pbkdf = { + .type = CRYPT_KDF_ARGON2I, + .hash = "sha256", + .parallel_threads = 1, + .max_memory_kb = 128, + .iterations = 4, + .flags = CRYPT_PBKDF_NO_BENCHMARK + }; + struct crypt_params_luks2 params2 = { + .pbkdf = &pbkdf, + .sector_size = 4096 + }; + struct crypt_params_reencrypt rparams = { + .direction = CRYPT_REENCRYPT_FORWARD, + .resilience = "checksum", + .hash = "sha256", + .luks2 = ¶ms2, + }; + uint64_t r_header_size; + + if (_fips_mode) { + pbkdf.type = CRYPT_KDF_PBKDF2; + pbkdf.parallel_threads = 0; + pbkdf.max_memory_kb = 0; + pbkdf.iterations = 1000; + } + + OK_(get_luks2_offsets(0, 0, 0, NULL, &r_payload_offset)); + OK_(create_dmdevice_over_loop(L_DEVICE_1S, r_payload_offset + 1)); + + // prepare the device + OK_(crypt_init(&cd, DMDIR L_DEVICE_1S)); + OK_(set_fast_pbkdf(cd)); + OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, 32, NULL)); + EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0); + EQ_(crypt_keyslot_add_by_volume_key(cd, 1, NULL, 32, KEY1, strlen(KEY1)), 1); + EQ_(0, crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, NULL, 0)); + + kid = add_key("user", KEY_DESC_TEST0, PASSPHRASE, strlen(PASSPHRASE), KEY_SPEC_THREAD_KEYRING); + NOTFAIL_(kid, "Test or kernel keyring are broken."); + + keyring_in_user_id = add_key_set_perm("keyring", TEST_KEYRING_USER, NULL, 0, KEY_SPEC_USER_KEYRING, KEY_POS_ALL | KEY_USR_ALL); + NOTFAIL_(keyring_in_user_id, "Test or kernel keyring are broken."); + NOTFAIL_(snprintf(keyring_in_user_str_id, sizeof(keyring_in_user_str_id)-1, "%u", keyring_in_user_id), "Failed to get string id."); + keyring_in_session_id = add_key_set_perm("keyring", TEST_KEYRING_SESSION, NULL, 0, KEY_SPEC_SESSION_KEYRING, KEY_POS_ALL | KEY_USR_ALL); + 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); + + OK_(crypt_keyslot_context_init_by_passphrase(cd, KEY1, strlen(KEY1), &kc)); + EQ_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), 1); + crypt_keyslot_context_free(kc); + + OK_(crypt_keyslot_context_init_by_volume_key(cd, key, key_size, &kc)); + EQ_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), 0); + crypt_keyslot_context_free(kc); + + OK_(prepare_keyfile(KEYFILE1, KEY1, strlen(KEY1))); + OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &kc)); + EQ_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), 1); + crypt_keyslot_context_free(kc); + + OK_(crypt_keyslot_context_init_by_keyring(cd, KEY_DESC_TEST0, &kc)); + EQ_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), 0); + crypt_keyslot_context_free(kc); + + // test activation + OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &kc)); + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), 0); + FAIL_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), "already active"); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_keyslot_context_free(kc); + + OK_(crypt_keyslot_context_init_by_volume_key(cd, key, key_size, &kc)); + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), 0); + FAIL_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), "already active"); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_keyslot_context_free(kc); + + OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &kc)); + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), 1); + FAIL_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), "already active"); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_keyslot_context_free(kc); + + OK_(crypt_keyslot_context_init_by_keyring(cd, KEY_DESC_TEST0, &kc)); + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), 0); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_keyslot_context_free(kc); + + // test linking to a custom keyring linked in user keyring + OK_(crypt_set_keyring_to_link(cd, TEST_KEY_VK_USER, NULL, "user", keyring_in_user_str_id /* TEST_KEYRING_USER_NAME */)); + OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0)); + + /* + * Otherwise we will not be able to search the TEST_KEYRING_USER in current context (see request_key(2): + * "The keyrings are searched in the order: thread-specific keyring, process-specific keyring, and then session keyring." + */ + NOTFAIL_(keyctl_link(keyring_in_user_id, KEY_SPEC_THREAD_KEYRING), "Failed to link in thread keyring."); + + FAIL_((linked_kid = request_key("logon", TEST_KEY_VK_USER, NULL, 0)), "VK was linked to custom keyring under wrong key type."); + NOTFAIL_((linked_kid = request_key("user", TEST_KEY_VK_USER, NULL, 0)), "VK was not linked to custom keyring."); + NOTFAIL_(_kernel_key_by_segment_and_type(cd, 0, "logon"), "dm-crypt VK was not uploaded in thread kernel keyring."); + OK_(crypt_deactivate(cd, CDEVICE_1)); + NOTFAIL_(keyctl_unlink(linked_kid, keyring_in_user_id), "VK was not linked to custom keyring after deactivation."); + FAIL_(_kernel_key_by_segment_and_type(cd, 0, "logon"), "dm-crypt VK remain linked in thread keyring."); + + OK_(crypt_set_keyring_to_link(cd, TEST_KEY_VK_LOGON, NULL, "logon", keyring_in_user_str_id /* TEST_KEYRING_USER_NAME */)); + OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0)); + NOTFAIL_((linked_kid = request_key("logon", TEST_KEY_VK_LOGON, NULL, 0)), "VK was not linked to custom keyring."); + NOTFAIL_(_kernel_key_by_segment_and_type(cd, 0, "logon"), "dm-crypt VK was not uploaded in thread kernel keyring."); + OK_(crypt_deactivate(cd, CDEVICE_1)); + NOTFAIL_(keyctl_unlink(linked_kid, keyring_in_user_id), "VK was not linked to custom keyring after deactivation."); + FAIL_(_kernel_key_by_segment_and_type(cd, 0, "logon"), "dm-crypt VK remain linked in thread keyring."); + + OK_(crypt_set_keyring_to_link(cd, TEST_KEY_VK_LOGON, NULL, "logon", TEST_KEYRING_SESSION_NAME)); + OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0)); + NOTFAIL_((linked_kid = request_key("logon", TEST_KEY_VK_LOGON, NULL, 0)), "VK was not linked to custom keyring."); + NOTFAIL_(_kernel_key_by_segment_and_type(cd, 0, "logon"), "dm-crypt VK was not uploaded in thread kernel keyring."); + OK_(crypt_deactivate(cd, CDEVICE_1)); + NOTFAIL_(keyctl_unlink(linked_kid, keyring_in_session_id), "VK was not linked to custom keyring after deactivation."); + FAIL_(_kernel_key_by_segment_and_type(cd, 0, "logon"), "dm-crypt VK remain linked in thread keyring."); + + // test repeated activation + OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0)); + NOTFAIL_((linked_kid = request_key("logon", TEST_KEY_VK_LOGON, NULL, 0)), "VK was not linked to custom keyring after repeated activation."); + OK_(crypt_deactivate(cd, CDEVICE_1)); + NOTFAIL_(request_key("logon", TEST_KEY_VK_LOGON, NULL, 0), "VK was not linked to custom keyring after deactivation."); + NOTFAIL_(keyctl_unlink(linked_kid, keyring_in_session_id), "VK was not linked to custom keyring after deactivation."); + FAIL_(request_key("logon", TEST_KEY_VK_LOGON, NULL, 0), "VK was probably wrongly linked in yet another keyring "); + + // change key type to default (user) + OK_(crypt_set_keyring_to_link(cd, TEST_KEY_VK_USER, NULL, NULL, TEST_KEYRING_USER_NAME)); + OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0)); + NOTFAIL_((linked_kid = request_key("user", TEST_KEY_VK_USER, NULL, 0)), "VK was not linked to custom keyring after resetting key type."); + OK_(crypt_deactivate(cd, CDEVICE_1)); + //NOTFAIL_(request_key("user", TEST_KEY_VK_USER, NULL, 0), "VK was not linked to custom keyring after deactivation."); + NOTFAIL_(keyctl_unlink(linked_kid, keyring_in_user_id), "VK was not linked to custom keyring after deactivation."); + FAIL_(request_key("user", TEST_KEY_VK_USER, NULL, 0), "VK was probably wrongly linked in yet another keyring "); + + // disable linking to session keyring + crypt_set_keyring_to_link(cd, NULL, NULL, NULL, NULL); + OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0)); + FAIL_(request_key("user", TEST_KEY_VK_USER, NULL, 0), "VK was probably wrongly linked in yet another keyring "); + FAIL_(request_key("logon", TEST_KEY_VK_LOGON, NULL, 0), "VK was probably wrongly linked in yet another keyring "); + NOTFAIL_(_kernel_key_by_segment_and_type(cd, 0, "logon"), "VK was not found in thread keyring"); + OK_(crypt_deactivate(cd, CDEVICE_1)); + FAIL_(_kernel_key_by_segment_and_type(cd, 0, "logon"), "failed to unlink the key from thread keyring"); + + // link VK to keyring and re-activate by the linked VK + crypt_set_keyring_to_link(cd, TEST_KEY_VK_USER, NULL, "user", TEST_KEYRING_SESSION_NAME); + OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0)); + OK_(crypt_deactivate(cd, CDEVICE_1)); + NOTFAIL_(request_key("user", TEST_KEY_VK_USER, NULL, 0), "VK was not linked to session keyring."); + OK_(crypt_keyslot_context_init_by_vk_in_keyring(cd, TEST_KEY_VK_USER_NAME, &kc)); + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), 0); + OK_(crypt_deactivate(cd, CDEVICE_1)); + NOTFAIL_(request_key("user", TEST_KEY_VK_USER, NULL, 0), "VK was not linked to session keyring after deactivation."); + OK_(_drop_keyring_key_from_keyring_name(TEST_KEY_VK_USER, keyring_in_session_id, "user")); + FAIL_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), "activation via VK in keyring after dropping the key"); + + // load VK back to keyring by activating + OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0)); + OK_(crypt_deactivate(cd, CDEVICE_1)); + + // activate by bad VK in keyring (test if VK digest is verified) + NOTFAIL_((linked_kid = request_key("user", TEST_KEY_VK_USER, NULL, 0)), "VK was not linked to session keyring after activation."); + 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)); + FAIL_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), 0); + OK_(_drop_keyring_key_from_keyring_name(TEST_KEY_VK_USER, keyring_in_session_id, "user")); + crypt_keyslot_context_free(kc); + + // After this point put resume tests only! + OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &kc)); + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), 0); + suspend_status = crypt_suspend(cd, CDEVICE_1); + if (suspend_status == -ENOTSUP) { + printf("WARNING: Suspend/Resume not supported, skipping test.\n"); + OK_(crypt_deactivate(cd, CDEVICE_1)); + + NOTFAIL_(keyctl_unlink(kid, KEY_SPEC_THREAD_KEYRING), "Test or kernel keyring are broken."); + CRYPT_FREE(cd); + _cleanup_dmdevices(); + return; + } + OK_(suspend_status); + OK_(crypt_get_active_device(cd, CDEVICE_1, &cad)); + EQ_(CRYPT_ACTIVATE_SUSPENDED, cad.flags & CRYPT_ACTIVATE_SUSPENDED); + OK_(crypt_resume_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc)); + OK_(crypt_get_active_device(cd, CDEVICE_1, &cad)); + EQ_(0, cad.flags & CRYPT_ACTIVATE_SUSPENDED); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_keyslot_context_free(kc); + + OK_(crypt_keyslot_context_init_by_volume_key(cd, key, key_size, &kc)); + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), 0); + OK_(crypt_suspend(cd, CDEVICE_1)); + EQ_(crypt_resume_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc), 0); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_keyslot_context_free(kc); + + OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &kc)); + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), 1); + OK_(crypt_suspend(cd, CDEVICE_1)); + OK_(crypt_get_active_device(cd, CDEVICE_1, &cad)); + EQ_(CRYPT_ACTIVATE_SUSPENDED, cad.flags & CRYPT_ACTIVATE_SUSPENDED); + EQ_(crypt_resume_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc), 1); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_keyslot_context_free(kc); + + OK_(crypt_keyslot_context_init_by_keyring(cd, KEY_DESC_TEST0, &kc)); + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), 0); + OK_(crypt_suspend(cd, CDEVICE_1)); + EQ_(crypt_resume_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc), 0); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_keyslot_context_free(kc); + + // resume by VK keyring context + crypt_set_keyring_to_link(cd, TEST_KEY_VK_USER, NULL, "user", TEST_KEYRING_SESSION_NAME); + OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0)); + NOTFAIL_(request_key("user", TEST_KEY_VK_USER, NULL, 0), "VK was not linked to session keyring."); + OK_(crypt_suspend(cd, CDEVICE_1)); + OK_(crypt_keyslot_context_init_by_vk_in_keyring(cd, TEST_KEY_VK_USER_NAME, &kc)); + EQ_(crypt_resume_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc), 0); + OK_(crypt_deactivate(cd, CDEVICE_1)); + EQ_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), 0); + OK_(crypt_deactivate(cd, CDEVICE_1)); + NOTFAIL_(request_key("user", TEST_KEY_VK_USER, NULL, 0), "VK was not linked to session keyring after deactivation."); + OK_(_drop_keyring_key_from_keyring_name(TEST_KEY_VK_USER, keyring_in_session_id, "user")); + FAIL_(crypt_activate_by_keyslot_context(cd, CDEVICE_1, CRYPT_ANY_SLOT, kc, CRYPT_ANY_SLOT, NULL, 0), "activation via VK in keyring after dropping the key"); + crypt_keyslot_context_free(kc); + + NOTFAIL_(keyctl_unlink(kid, KEY_SPEC_THREAD_KEYRING), "Test or kernel keyring are broken."); + CRYPT_FREE(cd); + + // test storing two VKs in keyring during reencryption + OK_(get_luks2_offsets(1, 0, 0, &r_header_size, NULL)); + OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_header_size + 16)); + + 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); + + // when no key name is specified, don't allow specifying type and keyring + EQ_(crypt_set_keyring_to_link(cd, NULL, NULL, NULL, keyring_in_user_str_id), -EINVAL); + EQ_(crypt_set_keyring_to_link(cd, NULL, NULL, "user", NULL), -EINVAL); + EQ_(crypt_set_keyring_to_link(cd, NULL, NULL, "user", keyring_in_user_str_id), -EINVAL); + + // key names have to be specified starting from the first + EQ_(crypt_set_keyring_to_link(cd, NULL, TEST_KEY_VK_USER, "user", keyring_in_user_str_id), -EINVAL); + EQ_(crypt_set_keyring_to_link(cd, TEST_KEY_VK_USER, NULL, "user", keyring_in_user_str_id), -ESRCH); + + 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); + FAIL_((linked_kid = request_key("logon", TEST_KEY_VK_USER, NULL, 0)), "VK was linked to custom keyring under wrong key type."); + FAIL_((linked_kid2 = request_key("logon", TEST_KEY_VK_USER2, NULL, 0)), "VK was linked to custom keyring under wrong key type."); + 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."); + NOTFAIL_(_kernel_key_by_segment_and_type(cd, 0, "logon"), "dm-crypt VK was not uploaded in thread kernel keyring."); + NOTFAIL_(_kernel_key_by_segment_and_type(cd, 1, "logon"), "dm-crypt VK was not uploaded in thread kernel keyring."); + + OK_(crypt_deactivate(cd, CDEVICE_1)); + NOTFAIL_(keyctl_unlink(linked_kid, keyring_in_user_id), "VK was not linked to custom keyring after deactivation."); + NOTFAIL_(keyctl_unlink(linked_kid2, keyring_in_user_id), "VK was not linked to custom keyring after deactivation."); + FAIL_(_kernel_key_by_segment_and_type(cd, 0, "logon"), "dm-crypt VK remain linked in thread keyring."); + // BUG: Reencryption code does not unlink the second VK + // FAIL_(_kernel_key_by_segment_and_type(cd, 1, "logon"), "dm-crypt VK remain linked in thread keyring."); + + // check that VKs are linked without calling crypt_activate_by_passphrase again, when activate is called on the same context + 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)); + NOTFAIL_(keyctl_unlink(linked_kid, keyring_in_user_id), "VK was not linked to custom keyring after deactivation."); + NOTFAIL_(keyctl_unlink(linked_kid2, keyring_in_user_id), "VK was not linked to custom keyring after deactivation."); + + // verify that the VK is no longer stored in a custom keyring + EQ_(crypt_set_keyring_to_link(cd, NULL, NULL, NULL, NULL), 0); + EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), 0); + FAIL_((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)); + + // test that after reencryption finishes (and there is only one VK), only one VK name is used + EQ_(crypt_set_keyring_to_link(cd, TEST_KEY_VK_USER, TEST_KEY_VK_USER2, "user", keyring_in_user_str_id), 0); + rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY; + EQ_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 1, 0, "aes", "xts-plain64", &rparams), 2); + OK_(crypt_reencrypt_run(cd, NULL, NULL)); + 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), -ESRCH); + EQ_(crypt_activate_by_keyslot_context(cd, NULL, CRYPT_ANY_SLOT, kc2, CRYPT_ANY_SLOT, NULL, 0), -ESRCH); + 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"); +#endif +} + +static int _crypt_load_check(struct crypt_device *_cd) { #ifdef HAVE_BLKID - return crypt_load(cd, CRYPT_LUKS, NULL); + return crypt_load(_cd, CRYPT_LUKS, NULL); #else return -ENOTSUP; #endif @@ -5132,6 +5858,7 @@ int main(int argc, char *argv[]) #endif RUN_(LuksKeyslotAdd, "Adding keyslot via new API"); RUN_(VolumeKeyGet, "Getting volume key via keyslot context API"); + RUN_(KeyslotContextAndKeyringLink, "Activate via keyslot context API and linking VK to a keyring"); RUN_(Luks2Repair, "LUKS2 repair"); // test disables metadata locking. Run always last! _cleanup(); diff --git a/tests/api-test.c b/tests/api-test.c index aa430dd..71f1270 100644 --- a/tests/api-test.c +++ b/tests/api-test.c @@ -1,9 +1,9 @@ /* * cryptsetup library API check functions * - * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2023 Milan Broz - * Copyright (C) 2016-2023 Ondrej Kozina + * Copyright (C) 2009-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2024 Milan Broz + * Copyright (C) 2016-2024 Ondrej Kozina * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/tests/api_test.h b/tests/api_test.h index 14efead..462c9aa 100644 --- a/tests/api_test.h +++ b/tests/api_test.h @@ -1,9 +1,9 @@ /* * cryptsetup library API check functions * - * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2023 Milan Broz - * Copyright (C) 2016-2023 Ondrej Kozina + * Copyright (C) 2009-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2024 Milan Broz + * Copyright (C) 2016-2024 Ondrej Kozina * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -45,6 +45,8 @@ int t_set_readahead(const char *device, unsigned value); int fips_mode(void); +int create_dmdevice_over_device(const char *dm_name, const char *device, uint64_t size, uint64_t offset); + int create_dmdevice_over_loop(const char *dm_name, const uint64_t size); int get_key_dm(const char *name, char *buffer, unsigned int buffer_size); @@ -138,7 +140,7 @@ void xlog(const char *msg, const char *tst, const char *func, int line, const ch #define T_DM_INTEGRITY_DISCARDS_SUPPORTED (1 << 23) /* dm-integrity discards/TRIM option is supported */ #define T_DM_INTEGRITY_RESIZE_SUPPORTED (1 << 23) /* dm-integrity resize of the integrity device supported (introduced in the same version as discards)*/ #define T_DM_VERITY_PANIC_CORRUPTION_SUPPORTED (1 << 24) /* dm-verity panic on corruption */ -#define T_DM_CRYPT_NO_WORKQUEUE_SUPPORTED (1 << 25) /* dm-crypt suppot for bypassing workqueues */ +#define T_DM_CRYPT_NO_WORKQUEUE_SUPPORTED (1 << 25) /* dm-crypt support for bypassing workqueues */ #define T_DM_INTEGRITY_FIX_HMAC_SUPPORTED (1 << 26) /* hmac covers also superblock */ #define T_DM_INTEGRITY_RESET_RECALC_SUPPORTED (1 << 27) /* dm-integrity automatic recalculation supported */ #define T_DM_VERITY_TASKLETS_SUPPORTED (1 << 28) /* dm-verity tasklets supported */ diff --git a/tests/bitlk-compat-test b/tests/bitlk-compat-test index 8559e06..aa4a71f 100755 --- a/tests/bitlk-compat-test +++ b/tests/bitlk-compat-test @@ -8,8 +8,12 @@ TST_DIR=bitlk-images MAP=bitlktst DUMP_VK_FILE=bitlk-test-vk -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi [ -z "$srcdir" ] && srcdir="." @@ -93,7 +97,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() @@ -156,6 +163,9 @@ for file in $(ls $TST_DIR/bitlk-*) ; do echo $PASSPHRASE | $CRYPTSETUP bitlkDump -r $file --dump-volume-key --volume-key-file $DUMP_VK_FILE >/dev/null 2>&1 ret=$? [ $ret -eq 0 ] || fail " failed to dump volume key" + $CRYPTSETUP bitlkOpen -r $file $MAP --volume-key-file $DUMP_VK_FILE --test-passphrase >/dev/null 2>&1 + ret=$? + [ $ret -eq 1 ] || fail " test passphrase with volume key unexpectedly succeeded" $CRYPTSETUP bitlkOpen -r $file $MAP --volume-key-file $DUMP_VK_FILE >/dev/null 2>&1 ret=$? [ $ret -eq 1 ] && ( echo "$file" | grep -q -e "aes-cbc" ) && echo " [N/A]" && continue diff --git a/tests/blockwise-compat-test b/tests/blockwise-compat-test index 11db493..8db91c9 100755 --- a/tests/blockwise-compat-test +++ b/tests/blockwise-compat-test @@ -68,7 +68,7 @@ add_device() { if [ $? -ne 0 ] ; then skip "This kernel seems to not support proper scsi_debug module." fi - grep -q scsi_debug /sys/block/*/device/model || sleep 2 + sleep 1 DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /) DEV="/dev/$DEV" [ -b $DEV ] || fail "Cannot find $DEV." diff --git a/tests/compat-args-test b/tests/compat-args-test index c41e942..788cc7c 100755 --- a/tests/compat-args-test +++ b/tests/compat-args-test @@ -4,8 +4,12 @@ PS4='$LINENO:' [ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".." CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi TEST_UUID="12345678-1234-1234-1234-123456789abc" @@ -37,7 +41,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() diff --git a/tests/compat-test b/tests/compat-test index 6dc8004..433beb2 100755 --- a/tests/compat-test +++ b/tests/compat-test @@ -5,8 +5,12 @@ PS4='$LINENO:' CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup CRYPTSETUP_RAW=$CRYPTSETUP -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi DIFFER=./differ DEV_NAME=dummy @@ -28,6 +32,7 @@ PWDW="rUkL4RUryBom" VK_FILE="compattest_vkfile" FAST_PBKDF_OPT="--pbkdf pbkdf2 --pbkdf-force-iterations 1000" +PLAIN_OPT="--hash sha256 --cipher aes-cbc-essiv:sha256 --key-size 256" LUKS_HEADER="S0-5 S6-7 S8-39 S40-71 S72-103 S104-107 S108-111 R112-131 R132-163 S164-167 S168-207 A0-591" KEY_SLOT0="S208-211 S212-215 R216-247 A248-251 A251-255" @@ -198,7 +203,10 @@ function valgrind_setup() [ -n "$VALG" ] || return command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi CRYPTSETUP=valgrind_run CRYPTSETUP_RAW="./valg.sh ${CRYPTSETUP_VALGRIND}" } @@ -538,8 +546,8 @@ $CRYPTSETUP luksKillSlot -q $LOOPDEV 1 || fail $CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 1: DISABLED" || fail prepare "[19] create & status & resize" wipe -echo $PWD1 | $CRYPTSETUP create $DEV_NAME $LOOPDEV --hash xxx 2>/dev/null && fail -echo $PWD1 | $CRYPTSETUP create $DEV_NAME $LOOPDEV --hash sha256 --cipher aes-cbc-essiv:sha256 --offset 3 --skip 4 --readonly || fail +echo $PWD1 | $CRYPTSETUP create $DEV_NAME $LOOPDEV --hash xxx --cipher aes-cbc-essiv:sha256 --key-size 256 2>/dev/null && fail +echo $PWD1 | $CRYPTSETUP create $DEV_NAME $LOOPDEV $PLAIN_OPT --offset 3 --skip 4 --readonly || fail $CRYPTSETUP -q status $DEV_NAME | grep "offset:" | grep -q "3 sectors" || fail $CRYPTSETUP -q status $DEV_NAME | grep "skipped:" | grep -q "4 sectors" || fail $CRYPTSETUP -q status $DEV_NAME | grep "mode:" | grep -q "readonly" || fail @@ -559,15 +567,15 @@ $CRYPTSETUP -q resize $DEV_NAME || fail $CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "32765 sectors" || fail $CRYPTSETUP -q remove $DEV_NAME || fail $CRYPTSETUP -q status $DEV_NAME >/dev/null && fail -echo $PWD1 | $CRYPTSETUP create $DEV_NAME --hash sha256 $LOOPDEV || fail +echo $PWD1 | $CRYPTSETUP create $DEV_NAME $PLAIN_OPT $LOOPDEV || fail $CRYPTSETUP -q remove $DEV_NAME || fail -echo $PWD1 | $CRYPTSETUP -q create $DEV_NAME --hash sha256 $LOOPDEV || fail +echo $PWD1 | $CRYPTSETUP -q create $DEV_NAME $PLAIN_OPT $LOOPDEV || fail $CRYPTSETUP -q remove $DEV_NAME || fail -echo $PWD1 | $CRYPTSETUP -q create $DEV_NAME --hash sha256 --size 100 $LOOPDEV || fail +echo $PWD1 | $CRYPTSETUP -q create $DEV_NAME $PLAIN_OPT --size 100 $LOOPDEV || fail $CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "100 sectors" || fail $CRYPTSETUP -q remove $DEV_NAME || fail # 4k sector resize (if kernel supports it) -echo $PWD1 | $CRYPTSETUP -q open --type plain --hash sha256 $LOOPDEV $DEV_NAME --sector-size 4096 --size 8 >/dev/null 2>&1 +echo $PWD1 | $CRYPTSETUP -q open --type plain $PLAIN_OPT $LOOPDEV $DEV_NAME --sector-size 4096 --size 8 >/dev/null 2>&1 if [ $? -eq 0 ] ; then $CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "8 sectors" || fail $CRYPTSETUP -q resize $DEV_NAME --size 16 || fail @@ -580,7 +588,7 @@ if [ $? -eq 0 ] ; then fi # Resize not aligned to logical block size add_scsi_device dev_size_mb=32 sector_size=4096 -echo $PWD1 | $CRYPTSETUP create $DEV_NAME --hash sha256 $DEV || fail +echo $PWD1 | $CRYPTSETUP create $DEV_NAME $PLAIN_OPT $DEV || fail OLD_SIZE=$($CRYPTSETUP status $DEV_NAME | grep "^ \+size:" | sed 's/.* \([0-9]\+\) .*/\1/') $CRYPTSETUP resize $DEV_NAME -b 7 2> /dev/null && fail dmsetup info $DEV_NAME | grep -q SUSPENDED && fail @@ -588,25 +596,25 @@ NEW_SIZE=$($CRYPTSETUP status $DEV_NAME | grep "^ \+size:" | sed 's/.* \([0-9]\+ test $OLD_SIZE -eq $NEW_SIZE || fail $CRYPTSETUP close $DEV_NAME || fail # Add check for unaligned plain crypt activation -echo $PWD1 | $CRYPTSETUP create $DEV_NAME --hash sha256 $DEV -b 7 2>/dev/null && fail +echo $PWD1 | $CRYPTSETUP create $DEV_NAME $PLAIN_OPT $DEV -b 7 2>/dev/null && fail $CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 && fail # verify is ignored on non-tty input echo $PWD1 | $CRYPTSETUP create $DEV_NAME $LOOPDEV --hash sha256 --verify-passphrase 2>/dev/null || fail $CRYPTSETUP -q remove $DEV_NAME || fail -$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 --key-size 255 2>/dev/null && fail -$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 --key-size -1 2>/dev/null && fail -$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 -l -1 2>/dev/null && fail -$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 || fail -$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 2>/dev/null && fail -$CRYPTSETUP create $DEV_NAME $LOOPDEV -d blah 2>/dev/null && fail +$CRYPTSETUP create --cipher aes-cbc-essiv:sha256 --key-size 256 $DEV_NAME $LOOPDEV -d $KEY1 --key-size 255 2>/dev/null && fail +$CRYPTSETUP create --cipher aes-cbc-essiv:sha256 --key-size 256 $DEV_NAME $LOOPDEV -d $KEY1 --key-size -1 2>/dev/null && fail +$CRYPTSETUP create --cipher aes-cbc-essiv:sha256 --key-size 256 $DEV_NAME $LOOPDEV -d $KEY1 -l -1 2>/dev/null && fail +$CRYPTSETUP create --cipher aes-cbc-essiv:sha256 --key-size 256 $DEV_NAME $LOOPDEV -d $KEY1 || fail +$CRYPTSETUP create --cipher aes-cbc-essiv:sha256 --key-size 256 $DEV_NAME $LOOPDEV -d $KEY1 2>/dev/null && fail +$CRYPTSETUP create --cipher aes-cbc-essiv:sha256 --key-size 256 $DEV_NAME $LOOPDEV -d blah 2>/dev/null && fail $CRYPTSETUP -q remove $DEV_NAME || fail -$CRYPTSETUP create $DEV_NAME $LOOPDEV -d /dev/urandom || fail +$CRYPTSETUP create --cipher aes-cbc-essiv:sha256 --key-size 256 $DEV_NAME $LOOPDEV -d /dev/urandom || fail $CRYPTSETUP -q remove $DEV_NAME || fail prepare "[20] Disallow open/create if already mapped." wipe -$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 || fail -$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 2>/dev/null && fail -$CRYPTSETUP create $DEV_NAME2 $LOOPDEV -d $KEY1 2>/dev/null && fail +$CRYPTSETUP create --cipher aes-cbc-essiv:sha256 --key-size 256 $DEV_NAME $LOOPDEV -d $KEY1 || fail +$CRYPTSETUP create --cipher aes-cbc-essiv:sha256 --key-size 256 $DEV_NAME $LOOPDEV -d $KEY1 2>/dev/null && fail +$CRYPTSETUP create --cipher aes-cbc-essiv:sha256 --key-size 256 $DEV_NAME2 $LOOPDEV -d $KEY1 2>/dev/null && fail echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $LOOPDEV 2>/dev/null && fail $CRYPTSETUP remove $DEV_NAME || fail echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $LOOPDEV || fail @@ -708,15 +716,15 @@ $CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d /dev/mapper/$DEV_NAME2 \ dmsetup remove --retry $DEV_NAME2 prepare "[25] Create shared segments" wipe -echo $PWD1 | $CRYPTSETUP create $DEV_NAME $LOOPDEV --hash sha256 --offset 0 --size 256 || fail -echo $PWD1 | $CRYPTSETUP create $DEV_NAME2 $LOOPDEV --hash sha256 --offset 512 --size 256 2>/dev/null && fail -echo $PWD1 | $CRYPTSETUP create $DEV_NAME2 $LOOPDEV --hash sha256 --offset 512 --size 256 --shared || fail +echo $PWD1 | $CRYPTSETUP create $DEV_NAME $LOOPDEV $PLAIN_OPT --offset 0 --size 256 || fail +echo $PWD1 | $CRYPTSETUP create $DEV_NAME2 $LOOPDEV $PLAIN_OPT --offset 512 --size 256 2>/dev/null && fail +echo $PWD1 | $CRYPTSETUP create $DEV_NAME2 $LOOPDEV $PLAIN_OPT --offset 512 --size 256 --shared || fail $CRYPTSETUP -q remove $DEV_NAME2 || fail $CRYPTSETUP -q remove $DEV_NAME || fail prepare "[26] Suspend/Resume" wipe # only LUKS is supported -echo $PWD1 | $CRYPTSETUP create $DEV_NAME --hash sha256 $LOOPDEV || fail +echo $PWD1 | $CRYPTSETUP create $DEV_NAME $PLAIN_OPT $LOOPDEV || fail $CRYPTSETUP luksSuspend $DEV_NAME 2>/dev/null && fail $CRYPTSETUP luksResume $DEV_NAME 2>/dev/null && fail $CRYPTSETUP -q remove $DEV_NAME || fail @@ -836,8 +844,8 @@ $CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 1: DISABLED" || fail $CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 5: DISABLED" || fail prepare "[31] Deferred removal of device" wipe -echo $PWD1 | $CRYPTSETUP open --type plain --hash sha256 $LOOPDEV $DEV_NAME || fail -echo $PWD2 | $CRYPTSETUP open --type plain --hash sha256 /dev/mapper/$DEV_NAME $DEV_NAME2 || fail +echo $PWD1 | $CRYPTSETUP open --type plain $PLAIN_OPT $LOOPDEV $DEV_NAME || fail +echo $PWD2 | $CRYPTSETUP open --type plain $PLAIN_OPT /dev/mapper/$DEV_NAME $DEV_NAME2 || fail $CRYPTSETUP close $DEV_NAME >/dev/null 2>&1 && fail $CRYPTSETUP -q status $DEV_NAME >/dev/null 2>&1 || fail $CRYPTSETUP close --deferred $DEV_NAME >/dev/null 2>&1 diff --git a/tests/compat-test-opal b/tests/compat-test-opal new file mode 100755 index 0000000..3d5c07c --- /dev/null +++ b/tests/compat-test-opal @@ -0,0 +1,1329 @@ +#!/bin/bash + +PS4='$LINENO:' +[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".." +CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup +CRYPTSETUP_RAW=$CRYPTSETUP + +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi + +DEV_NAME=dummy +DEV_NAME2=dummy2 +NO_HEADER_IMG=missing-header +HEADER_IMG=luks-header +HEADER_LUKS2_INV=luks2_invalid_cipher.img +KEY1=key1 +KEY2=key2 +KEY5=key5 +KEYE=keye +KEY_PWD1=key_pwd1 +OPAL2_ADMIN_PIN="adminPin01" +PWD1="93R4P4pIqAH8" +PWD2="mymJeD8ivEhE" +PWD3="ocMakf3fAcQO" +PWD4="Qx3qn46vq0v" +PWDW="rUkL4RUryBom" +TEST_KEYRING_NAME="compattest2_keyring" +TEST_TOKEN0="compattest2_desc0" +TEST_TOKEN1="compattest2_desc1" +VK_FILE="compattest2_vkfile" +IMPORT_TOKEN="{\"type\":\"some_type\",\"keyslots\":[],\"base64_data\":\"zxI7vKB1Qwl4VPB4D-N-OgcC14hPCG0IDu8O7eCqaQ\"}" +TOKEN_FILE0=test-token-file0 +TOKEN_FILE1=test-token-file1 +KEY_FILE0=test-key-file0 +KEY_FILE1=test-key-file1 + +FAST_PBKDF_OPT="--pbkdf pbkdf2 --pbkdf-force-iterations 1000" + +TEST_UUID="12345678-1234-1234-1234-123456789abc" + +FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null) + +function remove_mapping() +{ + [ -b /dev/mapper/$DEV_NAME2 ] && dmsetup remove --retry $DEV_NAME2 + [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME + [ -b /dev/mapper/"$DEV_NAME"_dif ] && dmsetup remove --retry "$DEV_NAME"_dif + rm -f $KEY1 $KEY2 $KEY5 $KEYE $HEADER_IMG $VK_FILE \ + $HEADER_LUKS2_INV missing-file $TOKEN_FILE0 $TOKEN_FILE1 test_image_* \ + $KEY_FILE0 $KEY_FILE1 $KEY_PWD1 $NO_HEADER_IMG >/dev/null 2>&1 + + # unlink whole test keyring + [ -n "$TEST_KEYRING" ] && keyctl unlink $TEST_KEYRING "@u" >/dev/null + unset TEST_KEYRING +} + +function fail() +{ + [ -n "$1" ] && echo "$1" + remove_mapping + reset_device_psid_nofail + echo "FAILED backtrace:" + while caller $frame; do ((frame++)); done + exit 2 +} + +function fips_mode() +{ + [ -n "$FIPS_MODE" ] && [ "$FIPS_MODE" -gt 0 ] +} + +function can_fail_fips() +{ + # Ignore this fail if running in FIPS mode + fips_mode || fail $1 +} + +function skip() +{ + [ -n "$1" ] && echo "$1" + remove_mapping + exit 77 +} + +function reset_device_psid() +{ + $CRYPTSETUP_RAW luksErase --hw-opal-factory-reset --key-file $OPAL2_PSID_FILE $OPAL2_DEV -q || \ + fail "PSID reset fail, wrong device used?" +} + +function reset_device_psid_nofail() +{ + $CRYPTSETUP_RAW luksErase --hw-opal-factory-reset --key-file $OPAL2_PSID_FILE $OPAL2_DEV -q 2>/dev/null +} + +function prepare() +{ + [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME + + case "$2" in + reset) + remove_mapping + reset_device_psid + ;; + wipe) + $CRYPTSETUP_RAW isLuks --type luks2 $HEADER_IMG -q 2>/dev/null + if [ $? -eq 0 ]; then + echo $OPAL2_ADMIN_PIN | $CRYPTSETUP_RAW luksErase $OPAL2_DEV -q --header $HEADER_IMG + else + echo $OPAL2_ADMIN_PIN | $CRYPTSETUP_RAW luksErase $OPAL2_DEV -q 2>/dev/null + fi + remove_mapping + ;; + new) + remove_mapping + ;; + reuse | *) + ;; + esac + + if [ ! -e $KEY1 ]; then + echo -n $'\x48\xc6\x74\x4f\x41\x4e\x50\xc0\x79\xc2\x2d\x5b\x5f\x68\x84\x17' >$KEY1 + echo -n $'\x9c\x03\x5e\x1b\x4d\x0f\x9a\x75\xb3\x90\x70\x32\x0a\xf8\xae\xc4'>>$KEY1 + fi + + if [ ! -e $KEY2 ]; then + dd if=/dev/urandom of=$KEY2 count=1 bs=64 >/dev/null 2>&1 + fi + + if [ ! -e $KEY5 ]; then + dd if=/dev/urandom of=$KEY5 count=1 bs=16 >/dev/null 2>&1 + fi + + if [ ! -e $KEY_PWD1 ]; then + echo -n "$PWD1" > $KEY_PWD1 + fi + + if [ ! -e $KEYE ]; then + touch $KEYE + fi + + [ -n "$1" ] && echo "CASE: $1" +} + +function check_exists() +{ + [ -b /dev/mapper/$DEV_NAME ] || fail +} + +function valgrind_setup() +{ + command -v valgrind >/dev/null || fail "Cannot find valgrind." + [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi +} + +function valgrind_run() +{ + INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@" +} + +function dm_crypt_keyring_support() +{ + VER_STR=$(dmsetup targets | grep crypt | cut -f2 -dv) + [ -z "$VER_STR" ] && fail "Failed to parse dm-crypt version." + + VER_MAJ=$(echo $VER_STR | cut -f 1 -d.) + VER_MIN=$(echo $VER_STR | cut -f 2 -d.) + VER_PTC=$(echo $VER_STR | cut -f 3 -d.) + + test -d /proc/sys/kernel/keys || return 1 + + [ $VER_MAJ -gt 1 ] && return 0 + [ $VER_MAJ -eq 1 -a $VER_MIN -gt 18 ] && return 0 + [ $VER_MAJ -eq 1 -a $VER_MIN -eq 18 -a $VER_PTC -ge 1 ] && return 0 + return 1 +} + +function dm_crypt_keyring_new_kernel() +{ + KER_STR=$(uname -r) + [ -z "$KER_STR" ] && fail "Failed to parse kernel version." + KER_MAJ=$(echo $KER_STR | cut -f 1 -d.) + KER_MIN=$(echo $KER_STR | cut -f 2 -d.) + + [ $KER_MAJ -ge 5 ] && return 0 + [ $KER_MAJ -eq 4 -a $KER_MIN -ge 15 ] && return 0 + return 1 +} + +function test_and_prepare_keyring() { + command -v keyctl >/dev/null || skip "Cannot find keyctl, test skipped" + keyctl list "@s" > /dev/null || skip "Current session keyring is unreachable, test skipped" + TEST_KEYRING=$(keyctl newring $TEST_KEYRING_NAME "@u" 2> /dev/null) + test -n "$TEST_KEYRING" || skip "Failed to create keyring in user keyring" + keyctl search "@s" keyring "$TEST_KEYRING" > /dev/null 2>&1 || keyctl link "@u" "@s" > /dev/null 2>&1 + load_key user test_key test_data "$TEST_KEYRING" || skip "Kernel keyring service is useless on this system, test skipped." +} + +# $1 type +# $2 description +# $3 payload +# $4 keyring +function load_key() +{ + keyctl add $@ >/dev/null +} + +function setup_luks2_env() { + echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 $FAST_PBKDF_OPT $OPAL2_DEV || fail + $CRYPTSETUP luksDump $OPAL2_DEV >/dev/null || fail + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV $DEV_NAME || fail + HAVE_KEYRING=$($CRYPTSETUP status $DEV_NAME | grep "keyring") + if [ -n "$HAVE_KEYRING" ]; then + HAVE_KEYRING=1 + else + HAVE_KEYRING=0 + fi + if $($CRYPTSETUP --version | grep -q "BLKID"); then + HAVE_BLKID=1 + else + HAVE_BLKID=0 + fi + $CRYPTSETUP close $DEV_NAME || fail +} + +# $1 key name +# $2 keyring to link VK to +# $3 key type (optional) +test_vk_link() { + KEY_TYPE=${3:-user} + if [ -z "$3" ]; then + KEY_DESC=$1 + else + KEY_DESC="%$3:$1" + fi + + KEYCTL_KEY_NAME="%$KEY_TYPE:$1" + + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV $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 + keyctl search "$2" $KEY_TYPE $1 > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after deactivation." + keyctl unlink "$KEYCTL_KEY_NAME" "$2" || fail +} + +# $1 key name +# $2 keyring to link VK to +# $3 key type (optional) +test_vk_link_and_reactivate() { + KEY_TYPE=${3:-user} + if [ -z "$3" ]; then + KEY_DESC=$1 + else + KEY_DESC="%$3:$1" + fi + + KEYCTL_KEY_NAME="%$KEY_TYPE:$1" + + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV $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 || fail + keyctl search "$2" $KEY_TYPE $1 > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after deactivation." + $CRYPTSETUP open $OPAL2_DEV $DEV_NAME --volume-key-keyring $KEY_DESC <&-|| fail "Failed to unlock volume via a VK in keyring." + $CRYPTSETUP luksSuspend $DEV_NAME || fail "Failed to suspend device." + $CRYPTSETUP luksResume $DEV_NAME --volume-key-keyring $KEY_DESC <&- || fail "Failed to resume via a VK in keyring." + + echo $PWD1 | $CRYPTSETUP luksOpen $OPAL2_DEV --test-passphrase 2>/dev/null || fail + echo $PWD2 | $CRYPTSETUP luksOpen $OPAL2_DEV --test-passphrase 2>/dev/null && fail + echo $PWD2 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT --volume-key-keyring $KEY_DESC $OPAL2_DEV --new-key-slot 1 || fail "Failed to add passphrase by VK in keyring." + echo $PWD2 | $CRYPTSETUP luksOpen $OPAL2_DEV --test-passphrase 2>/dev/null || fail + $CRYPTSETUP luksKillSlot -q $OPAL2_DEV 1 2>/dev/null || fail + + $CRYPTSETUP close $DEV_NAME || fail + # zero-out the key in keyring + keyctl pipe $KEYCTL_KEY_NAME | tr -c '\0' '\0' | keyctl pupdate $KEYCTL_KEY_NAME + $CRYPTSETUP open $OPAL2_DEV $DEV_NAME --volume-key-keyring $KEY_DESC <&- > /dev/null 2>&1 && fail "Unlocked volume via a bad VK in keyring." + keyctl search "$2" $KEY_TYPE $1 > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after bad activation." + keyctl unlink $KEYCTL_KEY_NAME "$2" || fail +} + +function test_reencryption_does_not_init() +{ + local _hdr="" + local _hdrdev=$NO_HEADER_IMG + if [ -n "$1" ]; then + _hdr="--header $1" + _hdrdev=$1 + fi + local _dumpdev=${1:-$OPAL2_DEV} + + # store sequence id to check if reencryption was aborted without metadata modifications + OLD_SEQID=0"$($CRYPTSETUP luksDump $_dumpdev | grep "Epoch:" | cut -d: -f 2 | sed -e 's/[[:space:]]*//g')" + [ 0$OLD_SEQID -gt 0 ] || fail + + echo $PWD1 | $CRYPTSETUP reencrypt $_hdr -q --init-only $OPAL2_DEV 2>/dev/null && fail + NEW_SEQID=0"$($CRYPTSETUP luksDump $_dumpdev | grep "Epoch:" | cut -d: -f 2 | sed -e 's/[[:space:]]*//g')" + [ 0$NEW_SEQID -gt 0 ] || fail + test $OLD_SEQID -eq $NEW_SEQID || fail "LUKS2 metadata was modified." + + echo $PWD1 | $CRYPTSETUP reencrypt $_hdr -q $OPAL2_DEV 2>/dev/null && fail + NEW_SEQID=0"$($CRYPTSETUP luksDump $_dumpdev | grep "Epoch:" | cut -d: -f 2 | sed -e 's/[[:space:]]*//g')" + [ 0$NEW_SEQID -gt 0 ] || fail + test $OLD_SEQID -eq $NEW_SEQID || fail "LUKS2 metadata was modified." + + echo $PWD1 |$CRYPTSETUP reencrypt -q --decrypt --header $_hdrdev --init-only $OPAL2_DEV 2>/dev/null && fail + if [ $_hdrdev = $NO_HEADER_IMG ]; then + test -e $_hdrdev && fail "Decryption header was created." + fi + NEW_SEQID=0"$($CRYPTSETUP luksDump $_dumpdev | grep "Epoch:" | cut -d: -f 2 | sed -e 's/[[:space:]]*//g')" + [ 0$NEW_SEQID -gt 0 ] || fail + test $OLD_SEQID -eq $NEW_SEQID || fail "LUKS2 metadata was modified." + + echo $PWD1 |$CRYPTSETUP reencrypt -q --decrypt --header $_hdrdev $OPAL2_DEV 2>/dev/null && fail + if [ $_hdrdev = $NO_HEADER_IMG ]; then + test -e $_hdrdev && fail "Decryption header was created." + fi + NEW_SEQID=0"$($CRYPTSETUP luksDump $_dumpdev | grep "Epoch:" | cut -d: -f 2 | sed -e 's/[[:space:]]*//g')" + [ 0$NEW_SEQID -gt 0 ] || fail + test $OLD_SEQID -eq $NEW_SEQID || fail "LUKS2 metadata was modified." + + # repeat the test with active device + echo $PWD1 | $CRYPTSETUP open $_hdr $OPAL2_DEV $DEV_NAME -q || fail + + echo $PWD1 | $CRYPTSETUP reencrypt $_hdr -q --init-only --active-name $DEV_NAME 2>/dev/null && fail + NEW_SEQID=0"$($CRYPTSETUP luksDump $_dumpdev | grep "Epoch:" | cut -d: -f 2 | sed -e 's/[[:space:]]*//g')" + [ 0$NEW_SEQID -gt 0 ] || fail + test $OLD_SEQID -eq $NEW_SEQID || fail "LUKS2 metadata was modified." + + echo $PWD1 | $CRYPTSETUP reencrypt $_hdr -q --active-name $DEV_NAME 2>/dev/null && fail + NEW_SEQID=0"$($CRYPTSETUP luksDump $_dumpdev | grep "Epoch:" | cut -d: -f 2 | sed -e 's/[[:space:]]*//g')" + [ 0$NEW_SEQID -gt 0 ] || fail + test $OLD_SEQID -eq $NEW_SEQID || fail "LUKS2 metadata was modified." + + echo $PWD1 |$CRYPTSETUP reencrypt -q --decrypt --header $_hdrdev --init-only --active-name $DEV_NAME 2>/dev/null && fail + if [ $_hdrdev = $NO_HEADER_IMG ]; then + test -e $_hdrdev && fail "Decryption header was created." + fi + NEW_SEQID=0"$($CRYPTSETUP luksDump $_dumpdev | grep "Epoch:" | cut -d: -f 2 | sed -e 's/[[:space:]]*//g')" + [ 0$NEW_SEQID -gt 0 ] || fail + test $OLD_SEQID -eq $NEW_SEQID || fail "LUKS2 metadata was modified." + + echo $PWD1 |$CRYPTSETUP reencrypt -q --decrypt --header $_hdrdev --active-name $DEV_NAME 2>/dev/null && fail + if [ $_hdrdev = $NO_HEADER_IMG ]; then + test -e $_hdrdev && fail "Decryption header was created." + fi + NEW_SEQID=0"$($CRYPTSETUP luksDump $_dumpdev | grep "Epoch:" | cut -d: -f 2 | sed -e 's/[[:space:]]*//g')" + [ 0$NEW_SEQID -gt 0 ] || fail + test $OLD_SEQID -eq $NEW_SEQID || fail "LUKS2 metadata was modified." + + $CRYPTSETUP close $DEV_NAME || fail +} + +function test_device() #opal_mode, #format_params, #--integrity-no-wipe +{ + echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat --type luks2 $1 $2 $3 -q $FAST_PBKDF_OPT $OPAL2_DEV || fail + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV $DEV_NAME || fail + test -z "$3" || dd if=/dev/zero of=/dev/mapper/$DEV_NAME bs=1M count=1 oflag=direct >/dev/null 2>&1 || fail + $CRYPTSETUP luksSuspend $DEV_NAME || fail + dd if=$OPAL2_DEV of=/dev/zero bs=1M skip=16 count=1 iflag=direct >/dev/null 2>&1 && fail + echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME || fail + dd if=/dev/mapper/$DEV_NAME of=/dev/zero bs=1M count=1 iflag=direct >/dev/null 2>&1 || fail + $CRYPTSETUP close $DEV_NAME || fail + dd if=$OPAL2_DEV of=/dev/zero bs=1M skip=16 count=1 iflag=direct >/dev/null 2>&1 && fail + echo $OPAL2_ADMIN_PIN | $CRYPTSETUP luksErase $OPAL2_DEV -q || fail +} + +function test_device_detached_header() #hdr, #opal_mode, #format_params, #--integrity-no-wipe +{ + echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat --type luks2 --header $1 $2 $3 $4 -q $FAST_PBKDF_OPT $OPAL2_DEV || fail + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV $DEV_NAME --header $1 || fail + test -z "$4" || dd if=/dev/zero of=/dev/mapper/$DEV_NAME bs=1M count=1 oflag=direct >/dev/null 2>&1 || fail + $CRYPTSETUP luksSuspend $DEV_NAME || fail + dd if=$OPAL2_DEV of=/dev/zero bs=1M count=1 iflag=direct >/dev/null 2>&1 && fail + echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME 2>/dev/null && fail + echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME --header $1 || fail + dd if=/dev/mapper/$DEV_NAME of=/dev/zero bs=1M count=1 iflag=direct >/dev/null 2>&1 || fail + $CRYPTSETUP close $DEV_NAME || fail + dd if=$OPAL2_DEV of=/dev/zero bs=1M count=1 iflag=direct >/dev/null 2>&1 && fail + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV $DEV_NAME --header $1 || fail + $CRYPTSETUP close $DEV_NAME --header $1 || fail + dd if=$OPAL2_DEV of=/dev/zero bs=1M count=1 iflag=direct >/dev/null 2>&1 && fail + echo $OPAL2_ADMIN_PIN | $CRYPTSETUP luksErase $OPAL2_DEV -q --header $1 || fail + rm -f $1 +} + +export LANG=C + +[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped." +[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped." + +# Do not run automatically. +[ -z "$OPAL2_DEV" ] && skip "WARNING: Variable OPAL2_DEV must be defined (partition or block dev), test skipped." +[ -z "$OPAL2_PSID_FILE" ] && skip "WARNING: Variable OPAL2_PSID_FILE must be defined, test skipped." +[ -f "$OPAL2_PSID_FILE" ] || skip "WARNING: $OPAL2_PSID_FILE is not reachable, test skipped." + +prepare "[0] Detect LUKS2 environment" reset +setup_luks2_env + +[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run + +prepare "[1] Data offset" +echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV -q --offset 1 2>/dev/null && fail + +prepare "[2] Sector size and old payload alignment" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV -q --sector-size 511 2>/dev/null && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV -q --sector-size 256 2>/dev/null && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV -q --sector-size 8192 2>/dev/null && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV -q --sector-size 512 || fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV -q --sector-size 4096 >/dev/null || fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV -q --sector-size 2048 >/dev/null || fail + +prepare "[3] format" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q $FAST_PBKDF_OPT -c aes-cbc-essiv:sha256 -s 128 luksFormat --type luks2 --hw-opal $OPAL2_DEV || fail +# FIXME: BUG (--hw-opal-only should reject --cipher, --key-size & co) +#echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q $FAST_PBKDF_OPT --hw-opal-only -c aes-cbc-essiv:sha256 -s 128 luksFormat --type luks2 $OPAL2_DEV 2> /dev/null && fail +prepare "[4] format using hash sha512" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP $FAST_PBKDF_OPT -h sha512 -c aes-cbc-essiv:sha256 -s 128 luksFormat --type luks2 --hw-opal $OPAL2_DEV || fail +$CRYPTSETUP -q luksDump $OPAL2_DEV | grep "0: pbkdf2" -A2 | grep "Hash:" | grep -qe sha512 || fail +# Check JSON dump for some mandatory section +$CRYPTSETUP -q luksDump $OPAL2_DEV --dump-json-metadata | grep -q '"tokens":' || fail + +prepare "[5] open" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q $FAST_PBKDF_OPT luksFormat --type luks2 --hw-opal $OPAL2_DEV || fail +echo $PWD1 | $CRYPTSETUP luksOpen $OPAL2_DEV $DEV_NAME --test-passphrase || fail +echo $PWDW | $CRYPTSETUP luksOpen $OPAL2_DEV $DEV_NAME --test-passphrase 2>/dev/null && fail +[ $? -ne 2 ] && fail "luksOpen should return EPERM exit code" +echo $PWD1 | $CRYPTSETUP luksOpen $OPAL2_DEV $DEV_NAME || fail +check_exists + +prepare "" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q $FAST_PBKDF_OPT luksFormat --type luks2 --hw-opal-only $OPAL2_DEV || fail +echo $PWD1 | $CRYPTSETUP luksOpen $OPAL2_DEV $DEV_NAME --test-passphrase || fail +echo $PWDW | $CRYPTSETUP luksOpen $OPAL2_DEV $DEV_NAME --test-passphrase 2>/dev/null && fail +[ $? -ne 2 ] && fail "luksOpen should return EPERM exit code" +echo $PWD1 | $CRYPTSETUP luksOpen $OPAL2_DEV $DEV_NAME || fail +check_exists + +# Key Slot 1 and key material section 1 must change, the rest must not. +prepare "[6] add key" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q $FAST_PBKDF_OPT luksFormat --type luks2 --hw-opal $OPAL2_DEV || fail +echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey $OPAL2_DEV $FAST_PBKDF_OPT || fail +echo $PWD2 | $CRYPTSETUP luksOpen $OPAL2_DEV $DEV_NAME || fail +$CRYPTSETUP close $DEV_NAME || fail + +# Unsuccessful Key Delete - nothing may change +prepare "[7] unsuccessful delete" new +echo $PWDW | $CRYPTSETUP luksKillSlot $OPAL2_DEV 1 2>/dev/null && fail +[ $? -ne 2 ] && fail "luksKillSlot should return EPERM exit code" + +# Delete Key Test +# Key Slot 1 and key material section 1 must change, the rest must not +prepare "[8] successful delete" +$CRYPTSETUP -q luksKillSlot $OPAL2_DEV 1 || fail +echo $PWD2 | $CRYPTSETUP luksOpen $OPAL2_DEV $DEV_NAME 2> /dev/null && fail +[ $? -ne 2 ] && fail "luksOpen should return EPERM exit code" +echo $PWD1 | $CRYPTSETUP luksOpen $OPAL2_DEV $DEV_NAME || fail +$CRYPTSETUP close $DEV_NAME || fail + +# Key Slot 1 and key material section 1 must change, the rest must not +prepare "[9] add key test for key files" new +echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT $OPAL2_DEV $KEY1 || fail +$CRYPTSETUP -d $KEY1 luksOpen $OPAL2_DEV $DEV_NAME || fail +$CRYPTSETUP close $DEV_NAME || fail + +# Key Slot 1 and key material section 1 must change, the rest must not +prepare "[10] delete key test with key1 as remaining key" new +$CRYPTSETUP -d $KEY1 luksKillSlot $OPAL2_DEV 0 || fail +echo $PWD1 | $CRYPTSETUP luksOpen $OPAL2_DEV $DEV_NAME 2>/dev/null && fail +$CRYPTSETUP luksOpen -d $KEY1 $OPAL2_DEV $DEV_NAME || fail + +# Delete last slot +prepare "[11] delete last key" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat --type luks2 --hw-opal $OPAL2_DEV $FAST_PBKDF_OPT || fail +echo $PWD1 | $CRYPTSETUP luksKillSlot $OPAL2_DEV 0 || fail +echo $PWD1 | $CRYPTSETUP luksOpen $OPAL2_DEV $DEV_NAME 2>/dev/null && fail + +prepare "[12] open/close - stacked devices" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat --type luks2 --hw-opal $OPAL2_DEV $FAST_PBKDF_OPT || fail +echo $PWD1 | $CRYPTSETUP -q luksOpen $OPAL2_DEV $DEV_NAME || fail +echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 /dev/mapper/$DEV_NAME $FAST_PBKDF_OPT || fail +echo $PWD1 | $CRYPTSETUP -q luksOpen /dev/mapper/$DEV_NAME $DEV_NAME2 || fail +$CRYPTSETUP -q luksClose $DEV_NAME2 || fail +$CRYPTSETUP -q luksClose $DEV_NAME || fail + +prepare "[13] UUID - use and report provided UUID" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --uuid blah --type luks2 --hw-opal $OPAL2_DEV 2>/dev/null && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --uuid $TEST_UUID --type luks2 --hw-opal $OPAL2_DEV || fail +tst=$($CRYPTSETUP -q luksUUID $OPAL2_DEV) +[ "$tst"x = "$TEST_UUID"x ] || fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV || fail +$CRYPTSETUP -q luksUUID --uuid $TEST_UUID $OPAL2_DEV || fail +tst=$($CRYPTSETUP -q luksUUID $OPAL2_DEV) +[ "$tst"x = "$TEST_UUID"x ] || fail + +prepare "[14] luksFormat" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --volume-key-file /dev/urandom --type luks2 --hw-opal $OPAL2_DEV || fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --volume-key-file /dev/urandom -s 512 --uuid $TEST_UUID --type luks2 --hw-opal $OPAL2_DEV || fail +$CRYPTSETUP luksOpen -d $KEY_PWD1 $OPAL2_DEV $DEV_NAME || fail +$CRYPTSETUP -q luksClose $DEV_NAME || fail +# open by UUID +if [ -d /dev/disk/by-uuid ] ; then + $CRYPTSETUP luksOpen -d $KEY_PWD1 UUID=X$TEST_UUID $DEV_NAME 2>/dev/null && fail + $CRYPTSETUP luksOpen -d $KEY_PWD1 UUID=$TEST_UUID $DEV_NAME || fail + $CRYPTSETUP -q luksClose $DEV_NAME || fail +fi +# skip tests using empty passphrases +if [ ! fips_mode ]; then +# empty passphrase (OPAL admin pin cannot be empty) +echo -e "\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV || fail +$CRYPTSETUP luksOpen -d $KEYE $OPAL2_DEV $DEV_NAME || fail +$CRYPTSETUP -q luksClose $DEV_NAME || fail +fi + +# format hw-opal-only +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --volume-key-file /dev/urandom --type luks2 --hw-opal-only $OPAL2_DEV || fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --volume-key-file /dev/urandom -s 512 --uuid $TEST_UUID --type luks2 --hw-opal-only $OPAL2_DEV || fail +$CRYPTSETUP luksOpen -d $KEY_PWD1 $OPAL2_DEV $DEV_NAME || fail +$CRYPTSETUP -q luksClose $DEV_NAME || fail +# open by UUID +if [ -d /dev/disk/by-uuid ] ; then + $CRYPTSETUP luksOpen -d $KEY_PWD1 UUID=X$TEST_UUID $DEV_NAME 2>/dev/null && fail + $CRYPTSETUP luksOpen -d $KEY_PWD1 UUID=$TEST_UUID $DEV_NAME || fail + $CRYPTSETUP -q luksClose $DEV_NAME || fail +fi +# skip tests using empty passphrases +if [ ! fips_mode ]; then +# empty passphrase (OPAL admin pin cannot be empty) +echo -e "\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal-only $OPAL2_DEV || fail +$CRYPTSETUP luksOpen -d $KEYE $OPAL2_DEV $DEV_NAME || fail +$CRYPTSETUP -q luksClose $DEV_NAME || fail +fi + +# open by volume key +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT -s 256 --volume-key-file $KEY2 --type luks2 --hw-opal $OPAL2_DEV || fail +$CRYPTSETUP luksOpen --volume-key-file /dev/urandom $OPAL2_DEV $DEV_NAME 2>/dev/null && fail +$CRYPTSETUP luksOpen --volume-key-file $KEY2 $OPAL2_DEV $DEV_NAME || fail +$CRYPTSETUP -q luksClose $DEV_NAME || fail + +prepare "[15] AddKey volume key, passphrase and keyfile" wipe +# volumekey +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV --volume-key-file /dev/zero --key-slot 3 || fail +echo $PWD1 | $CRYPTSETUP luksOpen $OPAL2_DEV --test-passphrase || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "3: luks2" || fail +echo $PWD2 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $OPAL2_DEV --volume-key-file /dev/zero --key-slot 4 || fail +echo $PWD2 | $CRYPTSETUP luksOpen $OPAL2_DEV --test-passphrase --key-slot 4 || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "4: luks2" || fail +echo $PWD3 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $OPAL2_DEV --volume-key-file /dev/null --key-slot 5 2>/dev/null && fail +$CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $OPAL2_DEV --volume-key-file /dev/zero --key-slot 5 $KEY1 || fail +$CRYPTSETUP luksOpen $OPAL2_DEV --test-passphrase --key-slot 5 -d $KEY1 || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "5: luks2" || fail + +# special "-" handling +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV --key-slot 3 || fail +echo $PWD2 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT $OPAL2_DEV -d $KEY_PWD1 - || fail +echo $PWD2 | $CRYPTSETUP luksOpen $OPAL2_DEV --test-passphrase 2>/dev/null && fail +echo $PWD2 | $CRYPTSETUP luksOpen $OPAL2_DEV -d - --test-passphrase || fail +echo $PWD2 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT $OPAL2_DEV -d - $KEY2 || fail +$CRYPTSETUP luksOpen $OPAL2_DEV -d $KEY2 --test-passphrase || fail +echo $PWD2 | $CRYPTSETUP luksOpen $OPAL2_DEV -d - -d $KEY1 --test-passphrase 2>/dev/null && fail +echo $PWD2 | $CRYPTSETUP luksOpen $OPAL2_DEV -d $KEY1 -d $KEY1 --test-passphrase 2>/dev/null && fail + +# [0]PWD3 [1]PWD2 [3]PWD1 [4]KEY2 +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV --key-slot 3 || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "3: luks2" || fail +$CRYPTSETUP luksAddKey -q $OPAL2_DEV $FAST_PBKDF_OPT -d $KEY_PWD1 $KEY2 --key-slot 3 2>/dev/null && fail +# keyfile/keyfile +$CRYPTSETUP luksAddKey -q $OPAL2_DEV $FAST_PBKDF_OPT -d $KEY_PWD1 $KEY2 --key-slot 4 || fail +$CRYPTSETUP luksOpen $OPAL2_DEV -d $KEY2 --test-passphrase --key-slot 4 || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "4: luks2" || fail +# passphrase/keyfile +echo $PWD3 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $OPAL2_DEV -d $KEY_PWD1 --key-slot 0 || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "0: luks2" || fail +echo $PWD3 | $CRYPTSETUP luksOpen $OPAL2_DEV --test-passphrase --key-slot 0 || fail +# passphrase/passphrase +echo -e "$PWD1\n$PWD2\n" | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $OPAL2_DEV --key-slot 1 || fail +echo $PWD2 | $CRYPTSETUP luksOpen $OPAL2_DEV --test-passphrase --key-slot 1 || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "1: luks2" || fail +# keyfile/passphrase +echo -e "$PWD2\n" | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $OPAL2_DEV $KEY_PWD1 --key-slot 2 --new-keyfile-size 8 || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "2: luks2" || fail + +prepare "[16] RemoveKey passphrase and keyfile" reuse +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "3: luks2" || fail +$CRYPTSETUP luksRemoveKey $OPAL2_DEV $KEY_PWD1 || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "3: luks2" && fail +$CRYPTSETUP luksRemoveKey $OPAL2_DEV $KEY_PWD1 2>/dev/null && fail +[ $? -ne 2 ] && fail "luksRemoveKey should return EPERM exit code" +$CRYPTSETUP luksRemoveKey $OPAL2_DEV $KEY2 --keyfile-size 1 2>/dev/null && fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "4: luks2" || fail +$CRYPTSETUP luksRemoveKey $OPAL2_DEV $KEY2 || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "4: luks2" && fail +# if password or keyfile is provided, batch mode must not suppress it +echo "badpw" | $CRYPTSETUP luksKillSlot $OPAL2_DEV 2 2>/dev/null && fail +echo "badpw" | $CRYPTSETUP luksKillSlot $OPAL2_DEV 2 -q 2>/dev/null && fail +echo "badpw" | $CRYPTSETUP luksKillSlot $OPAL2_DEV 2 --key-file=- 2>/dev/null && fail +echo "badpw" | $CRYPTSETUP luksKillSlot $OPAL2_DEV 2 --key-file=- -q 2>/dev/null && fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "2: luks2" || fail +# kill slot using passphrase from 1 +echo $PWD2 | $CRYPTSETUP luksKillSlot $OPAL2_DEV 2 2>/dev/null || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "2: luks2" && fail +# remove key0 / slot 0 +echo $PWD3 | $CRYPTSETUP luksRemoveKey $OPAL2_DEV || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "0: luks2" && fail +# last keyslot, in batch mode no passphrase needed... +$CRYPTSETUP luksKillSlot -q $OPAL2_DEV 1 || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "1: luks2" && fail + +prepare "[17] create & resize" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV || fail +echo $PWD1 | $CRYPTSETUP luksOpen $OPAL2_DEV $DEV_NAME || fail +# OPAL2 devices cannot be resized +$CRYPTSETUP -q resize --size 99 $DEV_NAME <&- 2>/dev/null && fail +echo $PWD1 | $CRYPTSETUP -q resize --size 99 $DEV_NAME 2>/dev/null && fail +$CRYPTSETUP close $DEV_NAME || fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT -q --type luks2 --hw-opal-only $OPAL2_DEV || fail +echo $PWD1 | $CRYPTSETUP luksOpen $OPAL2_DEV $DEV_NAME || fail +# OPAL2 devices cannot be resized +$CRYPTSETUP -q resize --size 99 $DEV_NAME <&- 2>/dev/null && fail +echo $PWD1 | $CRYPTSETUP -q resize --size 99 $DEV_NAME 2>/dev/null && fail +$CRYPTSETUP close $DEV_NAME || fail +echo $OPAL2_ADMIN_PIN | $CRYPTSETUP luksErase $OPAL2_DEV -q || fail + +prepare "[18] Disallow open/create if already mapped." wipe +$CRYPTSETUP create -q $DEV_NAME $OPAL2_DEV -d $KEY1 2>/dev/null || fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV 2>/dev/null && fail +$CRYPTSETUP remove $DEV_NAME || fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV || fail +echo $PWD1 | $CRYPTSETUP luksOpen $OPAL2_DEV $DEV_NAME || fail +echo $PWD1 | $CRYPTSETUP luksOpen -q $OPAL2_DEV $DEV_NAME2 >/dev/null 2>&1 && fail +dd if=$OPAL2_DEV of=/dev/zero bs=1M skip=16 count=1 iflag=direct >/dev/null 2>&1 || fail "OPAL segment perhaps locked after failed activation over already active device." +$CRYPTSETUP luksClose $DEV_NAME || fail + +prepare "[19] luksDump" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat --key-size 256 $FAST_PBKDF_OPT --uuid $TEST_UUID --type luks2 --hw-opal $OPAL2_DEV || fail +echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT $OPAL2_DEV -d $KEY_PWD1 || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "0: luks2" || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q $TEST_UUID || fail +echo $PWDW | $CRYPTSETUP luksDump $OPAL2_DEV --dump-volume-key 2>/dev/null && fail +echo $PWD1 | $CRYPTSETUP luksDump $OPAL2_DEV --dump-volume-key | grep -q "MK dump:" || fail +$CRYPTSETUP luksDump -q $OPAL2_DEV --dump-volume-key -d $KEY_PWD1 | grep -q "MK dump:" || fail +echo $PWD1 | $CRYPTSETUP luksDump -q $OPAL2_DEV --dump-master-key --master-key-file $VK_FILE >/dev/null || fail +rm -f $VK_FILE +echo $PWD1 | $CRYPTSETUP luksDump -q $OPAL2_DEV --dump-volume-key --volume-key-file $VK_FILE >/dev/null || fail +echo $PWD1 | $CRYPTSETUP luksDump -q $OPAL2_DEV --dump-volume-key --volume-key-file $VK_FILE 2>/dev/null && fail +echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT --volume-key-file $VK_FILE $OPAL2_DEV || fail +# Use volume key file without keyslots +echo $PWD1 | $CRYPTSETUP luksRemoveKey -q $OPAL2_DEV || fail +echo $PWD1 | $CRYPTSETUP luksRemoveKey -q $OPAL2_DEV || fail +echo $PWD1 | $CRYPTSETUP luksRemoveKey -q $OPAL2_DEV || fail +$CRYPTSETUP luksOpen --volume-key-file $VK_FILE --key-size 512 --test-passphrase $OPAL2_DEV || fail +echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT --volume-key-file $VK_FILE --key-size 512 $OPAL2_DEV || fail +echo $PWD1 | $CRYPTSETUP luksOpen --test-passphrase $OPAL2_DEV || fail + +prepare "[20] ChangeKey passphrase and keyfile" wipe +# [0]PWD1 [1]PWD2 +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat --type luks2 --hw-opal $OPAL2_DEV $FAST_PBKDF_OPT --key-slot 0 --key-size 256 --luks2-keyslots-size 756k >/dev/null || fail +echo $PWD2 | $CRYPTSETUP luksAddKey -q $OPAL2_DEV $FAST_PBKDF_OPT -d $KEY_PWD1 --key-slot 1 || fail +# [0]KEY2 [1]PWD2 +$CRYPTSETUP luksChangeKey $OPAL2_DEV $FAST_PBKDF_OPT -d $KEY_PWD1 $KEY2 --key-slot 0 || fail +# [0]KEY2 [1]PWD1 +echo -e "$PWD2\n$PWD1" | $CRYPTSETUP luksChangeKey $OPAL2_DEV $FAST_PBKDF_OPT --key-slot 1 || fail +# [0]KEY1 [1]PWD1 - with LUKS2 it should stay +$CRYPTSETUP luksChangeKey $OPAL2_DEV $FAST_PBKDF_OPT -d $KEY2 $KEY1 || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "0: luks2" || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "2: luks2" && fail +# [0]KEY1 [1]PWD2 +echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksChangeKey $FAST_PBKDF_OPT $OPAL2_DEV || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "1: luks2" || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "2: luks2" && fail +# test out of raw area, change in-place (space only for 2 keyslots) +$CRYPTSETUP luksChangeKey $OPAL2_DEV $FAST_PBKDF_OPT -d $KEY1 $KEY2 || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "0: luks2" || fail +$CRYPTSETUP luksChangeKey $OPAL2_DEV $FAST_PBKDF_OPT -d $KEY1 $KEY2 2>/dev/null && fail +# make a free space in keyslot area +echo $PWD2 | $CRYPTSETUP luksKillSlot -q $OPAL2_DEV 0 || fail + +# assert LUKS2 does not overwrite existing area with specific keyslot id +AREA_OFFSET_OLD=$($CRYPTSETUP luksDump $OPAL2_DEV | grep -e "1: luks2" -A12 | grep -e "Area offset:" | cut -d: -f 2 | sed -e 's/[[:space:]]*\[bytes\]//g') +[ 0$AREA_OFFSET_OLD -gt 0 ] || fail +echo -e "$PWD2\n$PWD1\n" | $CRYPTSETUP luksChangeKey --key-slot 1 $OPAL2_DEV $FAST_PBKDF_OPT || fail +AREA_OFFSET_NEW=$($CRYPTSETUP luksDump $OPAL2_DEV | grep -e "1: luks2" -A12 | grep -e "Area offset:" | cut -d: -f 2 | sed -e 's/[[:space:]]*\[bytes\]//g') +[ 0$AREA_OFFSET_NEW -gt 0 ] || fail +[ $AREA_OFFSET_OLD -ne $AREA_OFFSET_NEW ] || fail "Area offsets remained same: old area $AREA_OFFSET_OLD, new area $AREA_OFFSET_NEW" + +# assert LUKS2 does not overwrite existing area with any sklot +AREA_OFFSET_OLD=$($CRYPTSETUP luksDump $OPAL2_DEV | grep -e "1: luks2" -A12 | grep -e "Area offset:" | cut -d: -f 2 | sed -e 's/[[:space:]]*\[bytes\]//g') +[ 0$AREA_OFFSET_OLD -gt 0 ] || fail +echo -e "$PWD1\n$PWD2\n" | $CRYPTSETUP luksChangeKey $OPAL2_DEV $FAST_PBKDF_OPT || fail +AREA_OFFSET_NEW=$($CRYPTSETUP luksDump $OPAL2_DEV | grep -e "1: luks2" -A12 | grep -e "Area offset:" | cut -d: -f 2 | sed -e 's/[[:space:]]*\[bytes\]//g') +[ 0$AREA_OFFSET_NEW -gt 0 ] || fail +[ $AREA_OFFSET_OLD -ne $AREA_OFFSET_NEW ] || fail "Area offsets remained same: old area $AREA_OFFSET_OLD, new area $AREA_OFFSET_NEW" + +prepare "[21] Keyfile limit" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV --key-slot 0 || fail +echo $PWD1 | $CRYPTSETUP luksChangeKey $OPAL2_DEV $KEY1 --new-keyfile-size 13 $FAST_PBKDF_OPT || fail +echo $PWD1 | $CRYPTSETUP open --test-passphrase $OPAL2_DEV -q 2>/dev/null && fail +$CRYPTSETUP --key-file=$KEY1 luksOpen $OPAL2_DEV $DEV_NAME 2>/dev/null && fail +$CRYPTSETUP --key-file=$KEY1 -l 0 luksOpen $OPAL2_DEV $DEV_NAME 2>/dev/null && fail +$CRYPTSETUP --key-file=$KEY1 -l -1 luksOpen $OPAL2_DEV $DEV_NAME 2>/dev/null && fail +$CRYPTSETUP --key-file=$KEY1 -l 14 luksOpen $OPAL2_DEV $DEV_NAME 2>/dev/null && fail +$CRYPTSETUP --key-file=$KEY1 -l 13 --keyfile-offset 1 luksOpen $OPAL2_DEV $DEV_NAME 2>/dev/null && fail +$CRYPTSETUP --key-file=$KEY1 -l 13 --keyfile-offset -1 luksOpen $OPAL2_DEV $DEV_NAME 2>/dev/null && fail +$CRYPTSETUP --key-file=$KEY1 -l 13 luksOpen $OPAL2_DEV $DEV_NAME || fail +$CRYPTSETUP luksClose $DEV_NAME || fail +$CRYPTSETUP luksAddKey $OPAL2_DEV -d $KEY1 $KEY2 2>/dev/null && fail +$CRYPTSETUP luksAddKey $OPAL2_DEV -d $KEY1 $KEY2 -l 14 2>/dev/null && fail +$CRYPTSETUP luksAddKey $OPAL2_DEV -d $KEY1 $KEY2 -l -1 2>/dev/null && fail +$CRYPTSETUP luksAddKey $OPAL2_DEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT -l 13 --new-keyfile-size 12 || fail +$CRYPTSETUP luksRemoveKey $OPAL2_DEV $KEY2 2>/dev/null && fail +$CRYPTSETUP luksRemoveKey $OPAL2_DEV $KEY2 -l 12 || fail +$CRYPTSETUP luksChangeKey $OPAL2_DEV -d $KEY1 $KEY2 2>/dev/null && fail +[ $? -ne 2 ] && fail "luksChangeKey should return EPERM exit code" +$CRYPTSETUP luksChangeKey $OPAL2_DEV -d $KEY1 $KEY2 -l 14 2>/dev/null && fail +$CRYPTSETUP luksChangeKey $OPAL2_DEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT -l 13 || fail +# -l is ignored for stdin if _only_ passphrase is used +echo $PWD1 | $CRYPTSETUP luksAddKey $OPAL2_DEV -d $KEY2 $FAST_PBKDF_OPT || fail +# this is stupid, but expected +echo $PWD1 | $CRYPTSETUP luksRemoveKey $OPAL2_DEV -l 11 2>/dev/null && fail +echo $PWDW"0" | $CRYPTSETUP luksRemoveKey $OPAL2_DEV -l 12 2>/dev/null && fail +echo -e "$PWD1\n" | $CRYPTSETUP luksRemoveKey $OPAL2_DEV -d- -l 12 || fail +# offset +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV --key-slot 0 || fail +echo $PWD1 | $CRYPTSETUP luksChangeKey $OPAL2_DEV $KEY1 --new-keyfile-offset 16 --new-keyfile-size 13 $FAST_PBKDF_OPT || fail +$CRYPTSETUP --key-file=$KEY1 -l 13 --keyfile-offset 15 luksOpen $OPAL2_DEV $DEV_NAME 2>/dev/null && fail +$CRYPTSETUP --key-file=$KEY1 -l 13 --keyfile-offset 16 luksOpen $OPAL2_DEV $DEV_NAME || fail +$CRYPTSETUP luksClose $DEV_NAME || fail +$CRYPTSETUP luksAddKey $OPAL2_DEV $FAST_PBKDF_OPT -d $KEY1 -l 13 --keyfile-offset 16 $KEY2 --new-keyfile-offset 1 || fail +$CRYPTSETUP --key-file=$KEY2 --keyfile-offset 11 luksOpen $OPAL2_DEV $DEV_NAME 2>/dev/null && fail +$CRYPTSETUP --key-file=$KEY2 --keyfile-offset 1 luksOpen $OPAL2_DEV $DEV_NAME || fail +$CRYPTSETUP luksClose $DEV_NAME || fail +$CRYPTSETUP luksChangeKey $OPAL2_DEV $FAST_PBKDF_OPT -d $KEY2 --keyfile-offset 1 $KEY2 --new-keyfile-offset 0 || fail +$CRYPTSETUP luksOpen -d $KEY2 $OPAL2_DEV $DEV_NAME || fail +$CRYPTSETUP luksClose $DEV_NAME || fail + +prepare "[22] Suspend/Resume" wipe +# OPAL+dm-crypt +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV || fail +echo $PWD1 | $CRYPTSETUP -q luksOpen $OPAL2_DEV $DEV_NAME || fail +$CRYPTSETUP luksSuspend $DEV_NAME || fail +$CRYPTSETUP -q status $DEV_NAME | grep -q "(suspended)" || fail +dd if=$OPAL2_DEV of=/dev/zero bs=1M skip=16 count=1 iflag=direct >/dev/null 2>&1 && fail +$CRYPTSETUP -q resize $DEV_NAME 2>/dev/null && fail +echo $PWDW | $CRYPTSETUP luksResume $DEV_NAME 2>/dev/null && fail +[ $? -ne 2 ] && fail "luksResume should return EPERM exit code" +echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME || fail +dd if=/dev/mapper/$DEV_NAME of=/dev/zero bs=4K count=1 iflag=direct >/dev/null 2>&1 || fail +$CRYPTSETUP -q luksClose $DEV_NAME || fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat -c null $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV || fail +echo $PWD1 | $CRYPTSETUP -q luksOpen $OPAL2_DEV $DEV_NAME || fail +$CRYPTSETUP luksSuspend $DEV_NAME || fail +$CRYPTSETUP -q status $DEV_NAME | grep -q "(suspended)" || fail +dd if=$OPAL2_DEV of=/dev/zero bs=1M skip=16 count=1 iflag=direct >/dev/null 2>&1 && fail +echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME || fail +dd if=/dev/mapper/$DEV_NAME of=/dev/zero bs=4K count=1 iflag=direct >/dev/null 2>&1 || fail +$CRYPTSETUP -q luksClose $DEV_NAME || fail + +# OPAL only +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal-only $OPAL2_DEV || fail +echo $PWD1 | $CRYPTSETUP -q luksOpen $OPAL2_DEV $DEV_NAME || fail +$CRYPTSETUP luksSuspend $DEV_NAME || fail +$CRYPTSETUP -q status $DEV_NAME | grep -q "(suspended)" || fail +dd if=$OPAL2_DEV of=/dev/zero bs=1M skip=16 count=1 iflag=direct >/dev/null 2>&1 && fail +$CRYPTSETUP -q resize $DEV_NAME 2>/dev/null && fail +echo $PWDW | $CRYPTSETUP luksResume $DEV_NAME 2>/dev/null && fail +[ $? -ne 2 ] && fail "luksResume should return EPERM exit code" +echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME || fail +dd if=/dev/mapper/$DEV_NAME of=/dev/zero bs=4K count=1 iflag=direct >/dev/null 2>&1 || fail +$CRYPTSETUP -q luksClose $DEV_NAME || fail + +prepare "[23] luksOpen/Resume with specified key slot number" wipe +# first, let's try passphrase option +echo -e "$PWD3\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT -S 5 --type luks2 --hw-opal $OPAL2_DEV || fail +echo $PWD3 | $CRYPTSETUP luksOpen -S 4 $OPAL2_DEV $DEV_NAME 2>/dev/null && fail +[ -b /dev/mapper/$DEV_NAME ] && fail +echo $PWD3 | $CRYPTSETUP luksOpen -S 5 $OPAL2_DEV $DEV_NAME || fail +check_exists +$CRYPTSETUP luksSuspend $DEV_NAME || fail +echo $PWD3 | $CRYPTSETUP luksResume -S 4 $DEV_NAME 2>/dev/null && fail +$CRYPTSETUP -q status $DEV_NAME | grep -q "(suspended)" || fail +dd if=$OPAL2_DEV of=/dev/zero bs=1M skip=16 count=1 iflag=direct >/dev/null 2>&1 && fail +echo $PWD3 | $CRYPTSETUP luksResume -S 5 $DEV_NAME || fail +dd if=/dev/mapper/$DEV_NAME of=/dev/zero bs=4K count=1 iflag=direct >/dev/null 2>&1 || fail +$CRYPTSETUP luksClose $DEV_NAME || fail +echo -e "$PWD3\n$PWD1" | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S 0 $OPAL2_DEV || fail +echo $PWD3 | $CRYPTSETUP luksOpen -S 0 $OPAL2_DEV $DEV_NAME 2>/dev/null && fail +[ -b /dev/mapper/$DEV_NAME ] && fail +echo $PWD1 | $CRYPTSETUP luksOpen -S 5 $OPAL2_DEV $DEV_NAME 2>/dev/null && fail +[ -b /dev/mapper/$DEV_NAME ] && fail +# second, try it with keyfiles +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat -q -S 5 $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV || fail +echo "$PWD1" | $CRYPTSETUP luksChangeKey -q -S 5 $FAST_PBKDF_OPT $OPAL2_DEV $KEY5 || fail +$CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S 1 -d $KEY5 $OPAL2_DEV $KEY1 || fail +$CRYPTSETUP luksOpen -S 5 -d $KEY5 $OPAL2_DEV $DEV_NAME || fail +check_exists +$CRYPTSETUP luksSuspend $DEV_NAME || fail +dd if=$OPAL2_DEV of=/dev/zero bs=1M skip=16 count=1 iflag=direct >/dev/null 2>&1 && fail +$CRYPTSETUP luksResume -S 1 -d $KEY5 $DEV_NAME 2>/dev/null && fail +$CRYPTSETUP -q status $DEV_NAME | grep -q "(suspended)" || fail +$CRYPTSETUP luksResume -S 5 -d $KEY5 $DEV_NAME || fail +dd if=/dev/mapper/$DEV_NAME of=/dev/zero bs=4K count=1 iflag=direct >/dev/null 2>&1 || fail +$CRYPTSETUP luksClose $DEV_NAME || fail +$CRYPTSETUP luksOpen -S 1 -d $KEY5 $OPAL2_DEV $DEV_NAME 2>/dev/null && fail +[ -b /dev/mapper/$DEV_NAME ] && fail +$CRYPTSETUP luksOpen -S 5 -d $KEY1 $OPAL2_DEV $DEV_NAME 2>/dev/null && fail +[ -b /dev/mapper/$DEV_NAME ] && fail + +prepare "[24] Detached LUKS header" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV --header $HEADER_IMG || fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV --header $HEADER_IMG --align-payload 1 >/dev/null 2>&1 && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV --header $HEADER_IMG --align-payload 8192 || fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV --header $HEADER_IMG --align-payload 4096 >/dev/null || fail +$CRYPTSETUP luksDump $HEADER_IMG | grep -e "0: hw-opal-crypt" -A1 | grep -qe $((4096*512)) || fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV --header $HEADER_IMG --align-payload 0 --sector-size 512 || fail +echo $PWD1 | $CRYPTSETUP luksOpen $OPAL2_DEV-missing --header $HEADER_IMG $DEV_NAME 2>/dev/null && fail +echo $PWD1 | $CRYPTSETUP luksOpen $OPAL2_DEV --header $HEADER_IMG $DEV_NAME || fail +$CRYPTSETUP -q status $DEV_NAME | grep "type:" | grep -q "n/a" || fail +$CRYPTSETUP luksSuspend $DEV_NAME --header $HEADER_IMG || fail +dd if=$OPAL2_DEV of=/dev/zero bs=4K count=1 iflag=direct >/dev/null 2>&1 && fail +echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME --header $HEADER_IMG || fail +dd if=/dev/mapper/$DEV_NAME of=/dev/zero bs=4K count=1 iflag=direct >/dev/null 2>&1 || fail +$CRYPTSETUP luksSuspend $DEV_NAME || fail +dd if=$OPAL2_DEV of=/dev/zero bs=4K count=1 iflag=direct >/dev/null 2>&1 && fail +echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME 2>/dev/null && fail +echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME --header $HEADER_IMG || fail +dd if=/dev/mapper/$DEV_NAME of=/dev/zero bs=4K count=1 iflag=direct >/dev/null 2>&1 || fail +$CRYPTSETUP luksClose $DEV_NAME || fail +echo $PWD1 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S 5 _fakedev_ --header $HEADER_IMG $KEY5 || fail +$CRYPTSETUP luksDump _fakedev_ --header $HEADER_IMG | grep -q "5: luks2" || fail +$CRYPTSETUP luksKillSlot -q _fakedev_ --header $HEADER_IMG 5 || fail +$CRYPTSETUP luksDump _fakedev_ --header $HEADER_IMG | grep -q "5: luks2" && fail +echo $PWD1 | $CRYPTSETUP open --test-passphrase $HEADER_IMG || fail +rm $HEADER_IMG || fail +# create exactly 16 MiBs LUKS2 header +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV --header $HEADER_IMG --luks2-keyslots-size 16352k --luks2-metadata-size 16k --offset 131072 >/dev/null || fail +SIZE=$(stat --printf=%s $HEADER_IMG) +test $SIZE -eq 16777216 || fail +$CRYPTSETUP -q luksDump $HEADER_IMG | grep -q "offset: $((512 * 131072)) \[bytes\]" || fail + +prepare "[25] LUKS erase" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV || fail +echo $OPAL2_ADMIN_PIN | $CRYPTSETUP luksErase -q $OPAL2_DEV || fail +$CRYPTSETUP isLuks -q $OPAL2_DEV && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal-only $OPAL2_DEV || fail +echo $OPAL2_ADMIN_PIN | $CRYPTSETUP luksErase -q $OPAL2_DEV || fail +$CRYPTSETUP isLuks -q $OPAL2_DEV && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV || fail +# test psid reset once with valgrind +$CRYPTSETUP luksErase --hw-opal-factory-reset --key-file $OPAL2_PSID_FILE $OPAL2_DEV -q || fail + +prepare "[26] LUKS convert" wipe +# create almost compatible LUKS2 device except OPAL segment +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --sector-size 512 -s256 --hw-opal $OPAL2_DEV || fail +$CRYPTSETUP -q convert --type luks1 $OPAL2_DEV >/dev/null 2>&1 && fail +$CRYPTSETUP isLuks --type luks2 $OPAL2_DEV || fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --sector-size 512 -s256 --hw-opal-only $OPAL2_DEV || fail +$CRYPTSETUP -q convert --type luks1 $OPAL2_DEV >/dev/null 2>&1 && fail +$CRYPTSETUP isLuks --type luks2 $OPAL2_DEV || fail + +if dm_crypt_keyring_support && dm_crypt_keyring_new_kernel; then + prepare "[27] LUKS2 key in keyring" wipe + echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV --header $HEADER_IMG || fail + + # check keyring support detection works as expected + rmmod dm-crypt >/dev/null 2>&1 || true + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV --header $HEADER_IMG $DEV_NAME || fail + $CRYPTSETUP -q status $DEV_NAME | grep "key location:" | grep -q "keyring" || fail + $CRYPTSETUP close $DEV_NAME || fail + + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV --disable-keyring --header $HEADER_IMG $DEV_NAME || fail + $CRYPTSETUP -q status $DEV_NAME | grep "key location:" | grep -q "dm-crypt" || fail + $CRYPTSETUP close $DEV_NAME || fail + + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV --disable-keyring --header $HEADER_IMG $DEV_NAME || fail + $CRYPTSETUP luksSuspend $DEV_NAME || fail + echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME --header $HEADER_IMG || fail + $CRYPTSETUP -q status $DEV_NAME | grep "key location:" | grep -q "keyring" || fail + $CRYPTSETUP close $DEV_NAME || fail + + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV --header $HEADER_IMG $DEV_NAME || fail + $CRYPTSETUP luksSuspend $DEV_NAME || fail + echo $PWD1 | $CRYPTSETUP luksResume --disable-keyring $DEV_NAME --header $HEADER_IMG || fail + $CRYPTSETUP -q status $DEV_NAME | grep "key location:" | grep -q "dm-crypt" || fail + $CRYPTSETUP close $DEV_NAME || fail +fi + +prepare "[28] tokens" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV || fail +if [ $HAVE_KEYRING -gt 0 -a -d /proc/sys/kernel/keys ]; then + + test_and_prepare_keyring + + $CRYPTSETUP token add $OPAL2_DEV --key-description $TEST_TOKEN0 --token-id 3 || fail + $CRYPTSETUP luksDump $OPAL2_DEV | grep -q -e "3: luks2-keyring" || fail + # keyslot 5 is inactive + $CRYPTSETUP token add $OPAL2_DEV --key-description $TEST_TOKEN1 --key-slot 5 2> /dev/null && fail + # key description is not reachable + $CRYPTSETUP open --token-only $OPAL2_DEV --test-passphrase && fail + # wrong passphrase + load_key user $TEST_TOKEN0 "blabla" "$TEST_KEYRING" || fail "Cannot load 32 byte user key type" + $CRYPTSETUP open --token-only $OPAL2_DEV --test-passphrase 2>/dev/null && fail + load_key user $TEST_TOKEN0 $PWD1 "$TEST_KEYRING" || fail "Cannot load 32 byte user key type" + $CRYPTSETUP open --token-only $OPAL2_DEV --test-passphrase || fail + $CRYPTSETUP open --token-only $OPAL2_DEV $DEV_NAME || fail + $CRYPTSETUP status $DEV_NAME > /dev/null || fail + $CRYPTSETUP luksSuspend $DEV_NAME || fail + $CRYPTSETUP luksResume $DEV_NAME <&- || fail + $CRYPTSETUP -q status $DEV_NAME | grep -q "(suspended)" && fail + $CRYPTSETUP luksSuspend $DEV_NAME || fail + $CRYPTSETUP luksResume $DEV_NAME --token-type luks2-keyring <&- || fail + $CRYPTSETUP close $DEV_NAME || fail + + # check --token-type sort of works (TODO: extend tests when native systemd tokens are available) + echo -n "$IMPORT_TOKEN" | $CRYPTSETUP token import $OPAL2_DEV --token-id 22 || fail + # this excludes keyring tokens from unlocking device + $CRYPTSETUP open --token-only --token-type some_type $OPAL2_DEV --test-passphrase && fail + $CRYPTSETUP open --token-only --token-type some_type $OPAL2_DEV $DEV_NAME && fail + $CRYPTSETUP status $DEV_NAME > /dev/null && fail + + $CRYPTSETUP token remove --token-id 3 $OPAL2_DEV || fail + $CRYPTSETUP luksDump $OPAL2_DEV | grep -q -e "3: luks2-keyring" && fail + + # test we can remove keyslot with token + echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey -q -S4 $FAST_PBKDF_OPT $OPAL2_DEV || fail + $CRYPTSETUP token add $OPAL2_DEV --key-description $TEST_TOKEN1 --key-slot 4 --token-id 0 || fail + $CRYPTSETUP -q luksKillSlot $OPAL2_DEV 4 || fail + $CRYPTSETUP token remove --token-id 0 $OPAL2_DEV || fail + + # test we can add unassigned token + $CRYPTSETUP token add $OPAL2_DEV --key-description $TEST_TOKEN0 --unbound --token-id 0 || fail + $CRYPTSETUP open --token-only --token-id 0 --test-passphrase $OPAL2_DEV && fail + $CRYPTSETUP token remove --token-id 0 $OPAL2_DEV || fail + + # test token unassign works + $CRYPTSETUP token add $OPAL2_DEV --key-description $TEST_TOKEN0 -S0 --token-id 0 || fail + $CRYPTSETUP open --token-only --token-id 0 --test-passphrase $OPAL2_DEV || fail + $CRYPTSETUP token unassign --token-id 0 $OPAL2_DEV 2>/dev/null && fail + $CRYPTSETUP token unassign -S0 $OPAL2_DEV 2>/dev/null && fail + $CRYPTSETUP token unassign --token-id 0 -S0 $OPAL2_DEV || fail + $CRYPTSETUP open --token-only --token-id 0 --test-passphrase $OPAL2_DEV && fail + $CRYPTSETUP token unassign --token-id 0 -S0 $OPAL2_DEV 2>/dev/null && fail + $CRYPTSETUP token unassign --token-id 0 -S44 $OPAL2_DEV 2>/dev/null && fail + $CRYPTSETUP token unassign --token-id 44 -S0 $OPAL2_DEV 2>/dev/null && fail +fi +echo -n "$IMPORT_TOKEN" | $CRYPTSETUP token import $OPAL2_DEV --token-id 10 || fail +echo -n "$IMPORT_TOKEN" | $CRYPTSETUP token import $OPAL2_DEV --token-id 11 --json-file - || fail +echo -n "$IMPORT_TOKEN" > $TOKEN_FILE0 +$CRYPTSETUP token import $OPAL2_DEV --token-id 12 --json-file $TOKEN_FILE0 || fail +$CRYPTSETUP token import $OPAL2_DEV --token-id 12 --json-file $TOKEN_FILE0 2>/dev/null && fail +$CRYPTSETUP token export $OPAL2_DEV --token-id 10 >$TOKEN_FILE1 || fail +diff $TOKEN_FILE0 $TOKEN_FILE1 || fail +$CRYPTSETUP token export $OPAL2_DEV --token-id 11 >$TOKEN_FILE1 || fail +diff $TOKEN_FILE0 $TOKEN_FILE1 || fail +$CRYPTSETUP token export $OPAL2_DEV --token-id 12 >$TOKEN_FILE1 || fail +diff $TOKEN_FILE0 $TOKEN_FILE1 || fail +$CRYPTSETUP token export $OPAL2_DEV --token-id 12 --json-file $TOKEN_FILE1 || fail +diff $TOKEN_FILE0 $TOKEN_FILE1 || fail +$CRYPTSETUP token export $OPAL2_DEV --token-id 12 > $TOKEN_FILE1 || fail +diff $TOKEN_FILE0 $TOKEN_FILE1 || fail + +prepare "[29] LUKS keyslot priority" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV -S 1 || fail +echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey -q $OPAL2_DEV $FAST_PBKDF_OPT -S 5 || fail +$CRYPTSETUP config $OPAL2_DEV -S 0 --priority prefer && fail +$CRYPTSETUP config $OPAL2_DEV -S 1 --priority bla >/dev/null 2>&1 && fail +$CRYPTSETUP config $OPAL2_DEV -S 1 --priority ignore || fail +echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV --test-passphrase 2>/dev/null && fail +echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV --test-passphrase -S 1 || fail +echo $PWD2 | $CRYPTSETUP open $OPAL2_DEV --test-passphrase || fail +$CRYPTSETUP config $OPAL2_DEV -S 1 --priority normal || fail +echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV --test-passphrase || fail +$CRYPTSETUP config $OPAL2_DEV -S 1 --priority ignore || fail +echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV --test-passphrase 2>/dev/null && fail + +prepare "[30] LUKS label and subsystem" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Subsystem:" | grep -q "HW-OPAL" || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Label:" | grep -q "(no label)" || fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV --subsystem SatelliteTwo --label TheLabel || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Subsystem:" | grep -q "SatelliteTwo" || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Label:" | grep -q "TheLabel" || fail +$CRYPTSETUP config $OPAL2_DEV --subsystem SatelliteThree +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Subsystem:" | grep -q "SatelliteThree" || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Label:" | grep -q "(no label)" || fail +$CRYPTSETUP config $OPAL2_DEV --subsystem SatelliteThree --label TheLabel +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Subsystem:" | grep -q "SatelliteThree" || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Label:" | grep -q "TheLabel" || fail + +prepare "[31] LUKS PBKDF setting" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat --type luks2 --hw-opal --pbkdf bla $OPAL2_DEV >/dev/null 2>&1 && fail +# Force setting, no benchmark. PBKDF2 has 1000 iterations as a minimum +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" |$CRYPTSETUP luksFormat --type luks2 --hw-opal --pbkdf pbkdf2 --pbkdf-force-iterations 999 $OPAL2_DEV 2>/dev/null && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat --type luks2 --hw-opal --pbkdf pbkdf2 --pbkdf-force-iterations 1234 $OPAL2_DEV || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Iterations:" | grep -q "1234" || fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat --type luks2 --hw-opal --pbkdf argon2id --pbkdf-force-iterations 3 $OPAL2_DEV 2>/dev/null && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat --type luks2 --hw-opal --pbkdf argon2id --pbkdf-force-iterations 4 --pbkdf-memory 100000 $OPAL2_DEV || can_fail_fips +$CRYPTSETUP luksDump $OPAL2_DEV | grep "PBKDF:" | grep -q "argon2id" || can_fail_fips +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat --type luks2 --hw-opal --pbkdf argon2i --pbkdf-force-iterations 4 \ + --pbkdf-memory 1234 --pbkdf-parallel 1 $OPAL2_DEV || can_fail_fips +$CRYPTSETUP luksDump $OPAL2_DEV | grep "PBKDF:" | grep -q "argon2i" || can_fail_fips +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Time cost:" | grep -q "4" || can_fail_fips +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Memory:" | grep -q "1234" || can_fail_fips +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Threads:" | grep -q "1" || can_fail_fips +# Benchmark +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat --type luks2 --hw-opal --pbkdf argon2i -i 500 --pbkdf-memory 1234 --pbkdf-parallel 1 $OPAL2_DEV || can_fail_fips +[ 0"$($CRYPTSETUP luksDump $OPAL2_DEV | grep "Time cost:" | cut -d: -f 2 | sed -e 's/\ //g')" -gt 0 ] || can_fail_fips +[ 0"$($CRYPTSETUP luksDump $OPAL2_DEV | grep "Memory:" | cut -d: -f 2 | sed -e 's/\ //g')" -gt 0 ] || can_fail_fips +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat --type luks2 --hw-opal --pbkdf pbkdf2 -i 500 $OPAL2_DEV || fail +[ 0"$($CRYPTSETUP luksDump $OPAL2_DEV | grep -m1 "Iterations:" | cut -d' ' -f 2 | sed -e 's/\ //g')" -gt 1000 ] || fail + +prepare "[32] LUKS Keyslot convert" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV --key-slot 0 || fail +echo "$PWD1" | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S0 --new-key-slot 5 $OPAL2_DEV $KEY5 || fail +$CRYPTSETUP -q luksKillSlot $OPAL2_DEV 0 || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "5: luks2" || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep "PBKDF:" | grep -q "pbkdf2" || fail +$CRYPTSETUP -q luksConvertKey $OPAL2_DEV -S 5 --key-file $KEY5 --pbkdf argon2i -i1 --pbkdf-memory 32 || can_fail_fips +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "5: luks2" || can_fail_fips +echo $PWD1 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $OPAL2_DEV -S 1 --key-file $KEY5 || fail +$CRYPTSETUP -q luksKillSlot $OPAL2_DEV 5 || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "1: luks2" || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep "PBKDF:" | grep -q "pbkdf2" || fail +echo $PWD1 | $CRYPTSETUP -q luksConvertKey $OPAL2_DEV -S 1 --pbkdf argon2i -i1 --pbkdf-memory 32 || can_fail_fips +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "1: luks2" || can_fail_fips +echo $PWD3 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S 21 --unbound -s 72 $OPAL2_DEV || fail +echo $PWD3 | $CRYPTSETUP luksConvertKey --pbkdf-force-iterations 1001 --pbkdf pbkdf2 -S 21 $OPAL2_DEV || fail + +prepare "[33] luksAddKey unbound tests" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV --key-slot 5 || fail +# unbound key may have arbitrary size +echo $PWD1 | $CRYPTSETUP luksChangeKey -q $OPAL2_DEV $FAST_PBKDF_OPT -S5 $KEY5 || fail +echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT --unbound -s 72 $OPAL2_DEV || fail +echo $PWD2 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT --unbound -s 72 -S 2 $OPAL2_DEV || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "2: luks2 (unbound)" || fail +dd if=/dev/urandom of=$KEY_FILE0 bs=64 count=1 > /dev/null 2>&1 || fail +echo $PWD3 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT --unbound -s 512 -S 3 --volume-key-file $KEY_FILE0 $OPAL2_DEV || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "3: luks2 (unbound)" || fail +# unbound key size is required +echo $PWD1 | $CRYPTSETUP -q luksAddKey --unbound $OPAL2_DEV 2>/dev/null && fail +echo $PWD3 | $CRYPTSETUP -q luksAddKey --unbound --volume-key-file /dev/urandom $OPAL2_DEV 2> /dev/null && fail +# do not allow one to replace keyslot by unbound slot +echo $PWD1 | $CRYPTSETUP -q luksAddKey -S5 --unbound -s 32 $OPAL2_DEV 2>/dev/null && fail +echo $PWD2 | $CRYPTSETUP -q open $OPAL2_DEV $DEV_NAME 2> /dev/null && fail +echo $PWD2 | $CRYPTSETUP -q open -S2 $OPAL2_DEV $DEV_NAME 2> /dev/null && fail +echo $PWD2 | $CRYPTSETUP -q open -S2 $OPAL2_DEV --test-passphrase || fail +echo $PWD1 | $CRYPTSETUP -q open $OPAL2_DEV $DEV_NAME 2> /dev/null && fail +# check we're able to change passphrase for unbound keyslot +echo -e "$PWD2\n$PWD3" | $CRYPTSETUP luksChangeKey $FAST_PBKDF_OPT -S 2 $OPAL2_DEV || fail +echo $PWD3 | $CRYPTSETUP open --test-passphrase -S 2 $OPAL2_DEV || fail +echo $PWD3 | $CRYPTSETUP -q open -S 2 $OPAL2_DEV $DEV_NAME 2> /dev/null && fail +# do not allow adding keyslot by unbound keyslot +echo -e "$PWD3\n$PWD1" | $CRYPTSETUP -q luksAddKey $OPAL2_DEV 2> /dev/null && fail +# check adding keyslot works when there's unbound keyslot +echo $PWD1 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $OPAL2_DEV --key-file $KEY5 -S8 || fail +echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV $DEV_NAME || fail +$CRYPTSETUP close $DEV_NAME || fail +$CRYPTSETUP luksKillSlot -q $OPAL2_DEV 2 +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "2: luks2 (unbound)" && fail +echo $PWD3 | $CRYPTSETUP luksDump --unbound --volume-key-file $KEY_FILE1 $OPAL2_DEV 2> /dev/null && fail +echo $PWD3 | $CRYPTSETUP luksDump --unbound 2> /dev/null $OPAL2_DEV 2> /dev/null && fail +echo $PWD3 | $CRYPTSETUP luksDump --unbound --volume-key-file $KEY_FILE1 -S3 $OPAL2_DEV > /dev/null || fail +diff $KEY_FILE0 $KEY_FILE1 || fail +echo $PWD3 | $CRYPTSETUP luksDump --unbound --volume-key-file $KEY_FILE1 -S3 $OPAL2_DEV 2> /dev/null && fail +diff $KEY_FILE0 $KEY_FILE1 || fail +rm $KEY_FILE1 || fail +echo $PWD3 | $CRYPTSETUP luksDump --unbound --volume-key-file $KEY_FILE1 -S3 $OPAL2_DEV | grep -q "Unbound Key:" && fail +echo $PWD3 | $CRYPTSETUP luksDump --unbound -S3 $OPAL2_DEV | grep -q "Unbound Key:" || fail +$CRYPTSETUP luksKillSlot -q $OPAL2_DEV 3 || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep -q "3: luks2 (unbound)" && fail + +prepare "[34] LUKS2 metadata areas" wipe +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV 2> /dev/null || fail +DEFAULT_OFFSET=$($CRYPTSETUP luksDump $OPAL2_DEV | grep "offset: " | cut -f 2 -d ' ') +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal-only $OPAL2_DEV --key-size 256 --luks2-metadata-size=128k --luks2-keyslots-size=127k 2> /dev/null && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal-only $OPAL2_DEV --key-size 256 --luks2-metadata-size=127k --luks2-keyslots-size=128k 2> /dev/null && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal-only $OPAL2_DEV --key-size 256 --luks2-metadata-size=128k --luks2-keyslots-size=128M >/dev/null 2>&1 && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal-only $OPAL2_DEV --key-size 256 --luks2-metadata-size=128k --luks2-keyslots-size=128k >/dev/null || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Metadata area:" | grep -q "131072 \[bytes\]" || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Keyslots area:" | grep -q "131072 \[bytes\]" || fail +echo $OPAL2_ADMIN_PIN | $CRYPTSETUP luksErase $OPAL2_DEV -q || fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal $OPAL2_DEV --key-size 256 --luks2-metadata-size=128k || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Metadata area:" | grep -q "131072 \[bytes\]" || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Keyslots area:" | grep -q "$((DEFAULT_OFFSET-2*131072)) \[bytes\]" || fail +echo $OPAL2_ADMIN_PIN | $CRYPTSETUP luksErase $OPAL2_DEV -q || fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal-only $OPAL2_DEV --key-size 256 --luks2-keyslots-size=128k >/dev/null || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Metadata area:" | grep -q "16384 \[bytes\]" || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Keyslots area:" | grep -q "131072 \[bytes\]" || fail +echo $OPAL2_ADMIN_PIN | $CRYPTSETUP luksErase $OPAL2_DEV -q || fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal-only $OPAL2_DEV --key-size 256 --offset 16384 || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Metadata area:" | grep -q "16384 \[bytes\]" || fail +$CRYPTSETUP luksDump $OPAL2_DEV | grep "Keyslots area:" | grep -q "8355840 \[bytes\]" || fail +echo $OPAL2_ADMIN_PIN | $CRYPTSETUP luksErase $OPAL2_DEV -q || fail +# data offset vs area size +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal-only $OPAL2_DEV --key-size 256 --offset 64 --luks2-keyslots-size=8192 >/dev/null 2>&1 && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal-only $OPAL2_DEV --key-size 256 --offset $((256+56)) >/dev/null 2>&1 && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --hw-opal-only $OPAL2_DEV --key-size 256 --offset $((256+64)) >/dev/null || fail + +prepare "[35] Per-keyslot encryption parameters" wipe +KEYSLOT_CIPHER="aes-cbc-plain64" +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat --type luks2 --hw-opal-only $OPAL2_DEV $FAST_PBKDF_OPT --key-slot 0 --keyslot-cipher $KEYSLOT_CIPHER --keyslot-key-size 128 || fail +echo $PWD1 | $CRYPTSETUP luksChangeKey $OPAL2_DEV $FAST_PBKDF_OPT --key-slot 0 --keyslot-cipher $KEYSLOT_CIPHER --keyslot-key-size 128 $KEY1 || fail +[ "$($CRYPTSETUP luksDump $OPAL2_DEV | grep -A8 -m1 "0: luks2" | grep "Cipher:" | sed -e 's/[[:space:]]\+Cipher:\ \+//g')" = $KEYSLOT_CIPHER ] || fail +[ "$($CRYPTSETUP luksDump $OPAL2_DEV | grep -A8 -m1 "0: luks2" | grep "Cipher key:"| sed -e 's/[[:space:]]\+Cipher\ key:\ \+//g')" = "128 bits" ] || fail +$CRYPTSETUP luksAddKey -q $OPAL2_DEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT --key-slot 1 --keyslot-cipher $KEYSLOT_CIPHER --keyslot-key-size 128 || fail +[ "$($CRYPTSETUP luksDump $OPAL2_DEV | grep -A8 -m1 "1: luks2" | grep "Cipher:" | sed -e 's/[[:space:]]\+Cipher:\ \+//g')" = $KEYSLOT_CIPHER ] || fail +[ "$($CRYPTSETUP luksDump $OPAL2_DEV | grep -A8 -m1 "1: luks2" | grep "Cipher key:"| sed -e 's/[[:space:]]\+Cipher\ key:\ \+//g')" = "128 bits" ] || fail +$CRYPTSETUP luksAddKey -q $OPAL2_DEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT --key-slot 2 || fail +$CRYPTSETUP luksChangeKey $OPAL2_DEV $FAST_PBKDF_OPT -d $KEY2 $KEY1 --key-slot 2 --keyslot-cipher $KEYSLOT_CIPHER --keyslot-key-size 128 || fail +[ "$($CRYPTSETUP luksDump $OPAL2_DEV | grep -A8 -m1 "2: luks2" | grep "Cipher:" | sed -e 's/[[:space:]]\+Cipher:\ \+//g')" = $KEYSLOT_CIPHER ] || fail +[ "$($CRYPTSETUP luksDump $OPAL2_DEV | grep -A8 -m1 "2: luks2" | grep "Cipher key:"| sed -e 's/[[:space:]]\+Cipher\ key:\ \+//g')" = "128 bits" ] || fail +# unbound keyslot +echo $PWD3 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT --key-slot 21 --unbound -s 72 --keyslot-cipher $KEYSLOT_CIPHER --keyslot-key-size 128 $OPAL2_DEV || fail +[ "$($CRYPTSETUP luksDump $OPAL2_DEV | grep -A8 -m1 "21: luks2" | grep "Cipher:" | sed -e 's/[[:space:]]\+Cipher:\ \+//g')" = $KEYSLOT_CIPHER ] || fail +[ "$($CRYPTSETUP luksDump $OPAL2_DEV | grep -A8 -m1 "21: luks2" | grep "Cipher key:"| sed -e 's/[[:space:]]\+Cipher\ key:\ \+//g')" = "128 bits" ] || fail +echo $PWD3 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT --key-slot 22 --unbound -s 72 $OPAL2_DEV || fail +echo $PWD3 | $CRYPTSETUP luksConvertKey --key-slot 22 $OPAL2_DEV --keyslot-cipher $KEYSLOT_CIPHER --keyslot-key-size 128 $OPAL2_DEV || fail +[ "$($CRYPTSETUP luksDump $OPAL2_DEV | grep -A8 -m1 "22: luks2" | grep "Cipher:" | sed -e 's/[[:space:]]\+Cipher:\ \+//g')" = $KEYSLOT_CIPHER ] || fail +[ "$($CRYPTSETUP luksDump $OPAL2_DEV | grep -A8 -m1 "22: luks2" | grep "Cipher key:"| sed -e 's/[[:space:]]\+Cipher\ key:\ \+//g')" = "128 bits" ] || fail + +prepare "[36] 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]" + echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat --type luks2 --hw-opal $OPAL2_DEV $FAST_PBKDF_OPT --cipher $cipher --key-size $key_size || fail +done +echo + +prepare "[37] New luksAddKey options." wipe +rm -f $VK_FILE +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP luksFormat -q --type luks2 --hw-opal-only $FAST_PBKDF_OPT $OPAL2_DEV || fail +echo $PWD1 | $CRYPTSETUP luksDump -q $OPAL2_DEV --dump-volume-key --volume-key-file $VK_FILE >/dev/null || fail + +# pass pass +echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey -q -S1 $FAST_PBKDF_OPT $OPAL2_DEV || fail +echo $PWD2 | $CRYPTSETUP open -q --test-passphrase -S1 $OPAL2_DEV || fail + +# pass file +echo "$PWD2" | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S1 --new-key-slot 2 $OPAL2_DEV $KEY1 || fail +$CRYPTSETUP open --test-passphrase -q -S2 -d $KEY1 $OPAL2_DEV || fail + +# file pass +echo "$PWD3" | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S2 -d $KEY1 --new-key-slot 3 $OPAL2_DEV || fail +echo $PWD3 | $CRYPTSETUP open -q --test-passphrase -S3 $OPAL2_DEV || fail + +# file file +$CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S2 --new-key-slot 4 -d $KEY1 --new-keyfile $KEY2 $OPAL2_DEV || fail +$CRYPTSETUP open --test-passphrase -q -S4 -d $KEY2 $OPAL2_DEV || fail + +# vk pass +echo $PWD4 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S5 --volume-key-file $VK_FILE $OPAL2_DEV || fail +echo $PWD4 | $CRYPTSETUP open -q --test-passphrase -S5 $OPAL2_DEV || fail + +# vk file +$CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S6 --volume-key-file $VK_FILE --new-keyfile $KEY5 $OPAL2_DEV || fail +$CRYPTSETUP open --test-passphrase -q -S6 -d $KEY5 $OPAL2_DEV || fail + +if [ $HAVE_KEYRING -gt 0 -a -d /proc/sys/kernel/keys ]; then + test_and_prepare_keyring + load_key user $TEST_TOKEN0 $PWD1 "$TEST_KEYRING" || fail "Cannot load 32 byte user key type" + load_key user $TEST_TOKEN1 $PWDW "$TEST_KEYRING" || fail "Cannot load 32 byte user key type" + $CRYPTSETUP token add $OPAL2_DEV --key-description $TEST_TOKEN0 --token-id 0 -S0 || fail + $CRYPTSETUP token add $OPAL2_DEV --key-description $TEST_TOKEN1 --token-id 1 --unbound || fail + + # pass token + echo -e "$PWD1" | $CRYPTSETUP luksAddKey -q -S7 --new-token-id 1 $FAST_PBKDF_OPT $OPAL2_DEV || fail + $CRYPTSETUP open -q --test-passphrase --token-only --token-id 1 -q $OPAL2_DEV || fail + echo $PWD1 | $CRYPTSETUP luksKillSlot $OPAL2_DEV 7 || fail + $CRYPTSETUP open -q --test-passphrase --token-only --token-id 1 -q $OPAL2_DEV && fail + + # file token + $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S2 --new-key-slot 7 --new-token-id 1 -d $KEY1 $OPAL2_DEV || fail + $CRYPTSETUP open -q --test-passphrase --token-only --token-id 1 -q $OPAL2_DEV || fail + echo $PWD1 | $CRYPTSETUP luksKillSlot $OPAL2_DEV 7 || fail + $CRYPTSETUP open -q --test-passphrase --token-only --token-id 1 -q $OPAL2_DEV && fail + + # vk token + $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S7 --volume-key-file $VK_FILE --new-token-id 1 $OPAL2_DEV || fail + $CRYPTSETUP open -q --test-passphrase --token-only --token-id 1 -q $OPAL2_DEV || fail + echo $PWD1 | $CRYPTSETUP luksKillSlot $OPAL2_DEV 7 || fail + $CRYPTSETUP open -q --test-passphrase --token-only --token-id 1 -q $OPAL2_DEV && fail + + # token pass + echo $PWD4 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S7 --token-id 0 $OPAL2_DEV || fail + echo $PWD4 | $CRYPTSETUP open -q --test-passphrase -S7 $OPAL2_DEV || fail + + # token file + echo $PWD4 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S8 --token-id 0 $OPAL2_DEV $KEY2 || fail + $CRYPTSETUP open -q --test-passphrase -S8 --key-file $KEY2 $OPAL2_DEV || fail + + # token token + $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S9 --token-id 0 --new-token-id 1 $OPAL2_DEV || fail + $CRYPTSETUP open -q --test-passphrase --token-only --token-id 1 -q $OPAL2_DEV || fail + echo $PWD1 | $CRYPTSETUP luksKillSlot $OPAL2_DEV 9 || fail + $CRYPTSETUP open -q --test-passphrase --token-only --token-id 1 -q $OPAL2_DEV && fail + + # reuse same token + $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S0 --new-key-slot 9 --token-id 0 --new-token-id 0 $OPAL2_DEV || fail + $CRYPTSETUP open -q --test-passphrase --token-only --token-id 0 -q $OPAL2_DEV || fail + echo $PWD1 | $CRYPTSETUP luksKillSlot $OPAL2_DEV 9 || fail + + # reuse same token + $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT --token-id 0 --new-token-id 0 $OPAL2_DEV || fail + echo $PWD1 | $CRYPTSETUP luksKillSlot $OPAL2_DEV 9 || fail + $CRYPTSETUP open -q --test-passphrase --token-only --token-id 0 -q $OPAL2_DEV || fail +fi + +if [ $HAVE_KEYRING -gt 0 -a -d /proc/sys/kernel/keys ]; then + prepare "[38] Link VK to a keyring and use custom VK type." wipe + + echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $OPAL2_DEV 2> /dev/null || fail + KEY_NAME="cryptsetup:test_volume_key_id" + test_and_prepare_keyring + KID=$(echo -n test | keyctl padd user my_token @s) + keyctl unlink $KID >/dev/null 2>&1 @s && SESSION_KEYRING_WORKS=1 + KID=$(echo -n test | keyctl padd user my_token @us) + keyctl unlink $KID >/dev/null 2>&1 @us && USER_SESSION_KEYRING_WORKS=1 + + test_vk_link $KEY_NAME "@u" + test_vk_link $KEY_NAME "@u" "user" + [[ ! -z "$SESSION_KEYRING_WORKS" ]] && test_vk_link $KEY_NAME "@s" + [[ ! -z "$SESSION_KEYRING_WORKS" ]] && test_vk_link $KEY_NAME "@s" "logon" + [[ ! -z "$SESSION_KEYRING_WORKS" ]] && test_vk_link $KEY_NAME "@s" "user" + test_vk_link $KEY_NAME "%:$TEST_KEYRING_NAME" + test_vk_link $KEY_NAME "%:$TEST_KEYRING_NAME" "user" + test_vk_link $KEY_NAME "%:$TEST_KEYRING_NAME" "logon" + # explicitly specify keyring key type + test_vk_link $KEY_NAME "%keyring:$TEST_KEYRING_NAME" + + test_vk_link_and_reactivate $KEY_NAME "@u" "user" + test_vk_link_and_reactivate $KEY_NAME "@u" + [[ ! -z "$SESSION_KEYRING_WORKS" ]] && test_vk_link_and_reactivate $KEY_NAME "@s" "user" + test_vk_link_and_reactivate $KEY_NAME "%:$TEST_KEYRING_NAME" "user" + # explicitly specify keyring key type + test_vk_link_and_reactivate $KEY_NAME "%keyring:$TEST_KEYRING_NAME" "user" + test_vk_link_and_reactivate $KEY_NAME "%keyring:$TEST_KEYRING_NAME" + + # test numeric keyring name -5 is user session (@us) keyring + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV $DEV_NAME --link-vk-to-keyring -5::%logon:$KEY_NAME || fail + keyctl search @us logon $KEY_NAME > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after activation." + $CRYPTSETUP close $DEV_NAME + keyctl search @us logon $KEY_NAME > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after deactivation." + keyctl unlink "%logon:$KEY_NAME" @us || fail + + # test malformed keyring descriptions and key types + # missing key description + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV $DEV_NAME --link-vk-to-keyring "%$TEST_KEYRING_NAME::" > /dev/null 2>&1 && fail + # malformed keyring description + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV $DEV_NAME --link-vk-to-keyring ":$TEST_KEYRING_NAME::$KEY_NAME" > /dev/null 2>&1 && fail + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV $DEV_NAME --link-vk-to-keyring "@uuu::$KEY_NAME" > /dev/null 2>&1 && fail + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV $DEV_NAME --link-vk-to-keyring "@usu::$KEY_NAME" > /dev/null 2>&1 && fail + + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV $DEV_NAME --link-vk-to-keyring "$TEST_KEYRING_NAME::%user" > /dev/null 2>&1 && fail + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV $DEV_NAME --link-vk-to-keyring "$TEST_KEYRING_NAME::%user:" > /dev/null 2>&1 && fail + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV $DEV_NAME --link-vk-to-keyring "%user:$KEY_NAME" > /dev/null 2>&1 && fail + + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV $DEV_NAME --link-vk-to-keyring "@t::%0:$KEY_NAME" > /dev/null 2>&1 && fail + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV $DEV_NAME --link-vk-to-keyring "@t::%blah:$KEY_NAME" > /dev/null 2>&1 && fail + echo $PWD1 | $CRYPTSETUP open $OPAL2_DEV $DEV_NAME --link-vk-to-keyring "@t::%userlogon:$KEY_NAME" > /dev/null 2>&1 && fail + +fi + +if ! fips_mode; then +prepare "[39] LUKS2 reencryption/decryption blocked" wipe + +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 -s256 --hw-opal $OPAL2_DEV || fail +test_reencryption_does_not_init + +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 -s256 --hw-opal-only $OPAL2_DEV || fail +test_reencryption_does_not_init + +prepare "[40] LUKS2 reencryption/decryption blocked (detached header)" wipe + +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --header $HEADER_IMG --type luks2 -s256 --hw-opal $OPAL2_DEV || fail +test_reencryption_does_not_init $HEADER_IMG + +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --header $HEADER_IMG --type luks2 -s256 --hw-opal-only $OPAL2_DEV || fail +test_reencryption_does_not_init $HEADER_IMG + +prepare "[41] LUKS2 encryption blocked" wipe + +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP reencrypt --encrypt --init-only --reduce-device-size 32m $FAST_PBKDF_OPT --type luks2 -s256 --hw-opal $OPAL2_DEV 2>/dev/null && fail +$CRYPTSETUP isLuks $OPAL2_DEV && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP reencrypt --encrypt --init-only --reduce-device-size 32m $FAST_PBKDF_OPT --type luks2 -s256 --hw-opal $OPAL2_DEV $DEV_NAME 2>/dev/null && fail +$CRYPTSETUP isLuks $OPAL2_DEV && fail +test -b $DEV_NAME && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP reencrypt --encrypt --reduce-device-size 32m $FAST_PBKDF_OPT --type luks2 -s256 --hw-opal $OPAL2_DEV 2>/dev/null && fail +$CRYPTSETUP isLuks $OPAL2_DEV && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP reencrypt --encrypt --init-only --reduce-device-size 32m $FAST_PBKDF_OPT --type luks2 -s256 --hw-opal-only $OPAL2_DEV 2>/dev/null && fail +$CRYPTSETUP isLuks $OPAL2_DEV && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP reencrypt --encrypt --init-only --reduce-device-size 32m $FAST_PBKDF_OPT --type luks2 -s256 --hw-opal-only $OPAL2_DEV $DEV_NAME 2>/dev/null && fail +$CRYPTSETUP isLuks $OPAL2_DEV && fail +test -b $DEV_NAME && fail +echo -e "$PWD1\n$OPAL2_ADMIN_PIN" | $CRYPTSETUP reencrypt --encrypt --reduce-device-size 32m $FAST_PBKDF_OPT --type luks2 -s256 --hw-opal-only $OPAL2_DEV 2>/dev/null && fail +$CRYPTSETUP isLuks $OPAL2_DEV && fail +fi + +prepare "[42] OPAL2 HW only test." wipe +test_device --hw-opal-only + +prepare "[43] OPAL2 + dmcrypt test." wipe +test_device --hw-opal + +prepare "[44] OPAL2 + auth encryption" wipe +test_device --hw-opal "-c aes-gcm-random --integrity aead" --integrity-no-wipe +test_device --hw-opal "-s 280 -c aes-ccm-random --integrity aead" --integrity-no-wipe + +prepare "[45] OPAL2 HW only test (detached header)" wipe +test_device_detached_header $HEADER_IMG --hw-opal-only + +prepare "[46] OPAL2 + dmcrypt test (detached header)" wipe +test_device_detached_header $HEADER_IMG --hw-opal + +prepare "[47] OPAL2 + auth encryption test (detached header)" wipe +test_device_detached_header $HEADER_IMG --hw-opal "-c aes-gcm-random --integrity aead" --integrity-no-wipe +test_device_detached_header $HEADER_IMG --hw-opal "-s 280 -c aes-ccm-random --integrity aead" --integrity-no-wipe + +# FIXME: Add partition based tests + +remove_mapping +reset_device_psid_nofail +exit 0 diff --git a/tests/compat-test2 b/tests/compat-test2 index c54dc7e..bc86563 100755 --- a/tests/compat-test2 +++ b/tests/compat-test2 @@ -3,9 +3,14 @@ PS4='$LINENO:' [ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".." CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup +CRYPTSETUP_RAW=$CRYPTSETUP -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi DEV_NAME=dummy DEV_NAME2=dummy2 @@ -16,6 +21,7 @@ IMG10=luks-test-v10 HEADER_IMG=luks-header HEADER_KEYU=luks2_keyslot_unassigned.img HEADER_LUKS2_PV=blkid-luks2-pv.img +HEADER_LUKS2_INV=luks2_invalid_cipher.img KEY1=key1 KEY2=key2 KEY5=key5 @@ -50,7 +56,9 @@ function remove_mapping() [ -b /dev/mapper/$DEV_NAME2 ] && dmsetup remove --retry $DEV_NAME2 [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME losetup -d $LOOPDEV >/dev/null 2>&1 - rm -f $ORIG_IMG $IMG $IMG10 $KEY1 $KEY2 $KEY5 $KEYE $HEADER_IMG $HEADER_KEYU $VK_FILE $HEADER_LUKS2_PV missing-file $TOKEN_FILE0 $TOKEN_FILE1 test_image_* $KEY_FILE0 $KEY_FILE1 >/dev/null 2>&1 + rm -f $ORIG_IMG $IMG $IMG10 $KEY1 $KEY2 $KEY5 $KEYE $HEADER_IMG $HEADER_KEYU $VK_FILE \ + $HEADER_LUKS2_PV $HEADER_LUKS2_INV missing-file $TOKEN_FILE0 $TOKEN_FILE1 test_image_* \ + $KEY_FILE0 $KEY_FILE1 >/dev/null 2>&1 # unlink whole test keyring [ -n "$TEST_KEYRING" ] && keyctl unlink $TEST_KEYRING "@u" >/dev/null @@ -154,7 +162,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() @@ -164,6 +175,8 @@ function valgrind_run() function dm_crypt_keyring_support() { + $CRYPTSETUP --version | grep -q KEYRING || return 1 + VER_STR=$(dmsetup targets | grep crypt | cut -f2 -dv) [ -z "$VER_STR" ] && fail "Failed to parse dm-crypt version." @@ -284,6 +297,171 @@ function add_scsi_device() { [ -b $DEV ] || fail "Cannot find $DEV." } +# $1 key name +# $2 keyring to link VK to +# $3 key type (optional) +test_vk_link() { + KEY_TYPE=${3:-user} + if [ -z "$3" ]; then + KEY_DESC=$1 + else + KEY_DESC="%$3:$1" + fi + + KEYCTL_KEY_NAME="%$KEY_TYPE:$1" + + echo $PWD1 | $CRYPTSETUP open $LOOPDEV $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 + keyctl search "$2" $KEY_TYPE $1 > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after deactivation." + keyctl unlink "$KEYCTL_KEY_NAME" "$2" || fail + + 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 + 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 + keyctl search "$2" $KEY_TYPE $1 > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after deactivation." + keyctl unlink "$KEYCTL_KEY_NAME" "$2" || fail +} + +# $1 key name +# $2 keyring to link VK to +# $3 key type (optional) +test_vk_link_and_reactivate() { + KEY_TYPE=${3:-user} + if [ -z "$3" ]; then + KEY_DESC=$1 + else + KEY_DESC="%$3:$1" + fi + + KEYCTL_KEY_NAME="%$KEY_TYPE:$1" + + echo $PWD1 | $CRYPTSETUP open $LOOPDEV $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 || fail + keyctl search "$2" $KEY_TYPE $1 > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after deactivation." + $CRYPTSETUP open $LOOPDEV $DEV_NAME --volume-key-keyring $KEY_DESC <&-|| fail "Failed to unlock volume via a VK in keyring." + $CRYPTSETUP luksSuspend $DEV_NAME || fail "Failed to suspend device." + $CRYPTSETUP luksResume $DEV_NAME --volume-key-keyring $KEY_DESC <&- || fail "Failed to resume via a VK in keyring." + + echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase 2>/dev/null || fail + echo $PWD2 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase 2>/dev/null && fail + echo $PWD2 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT --volume-key-keyring $KEY_DESC $LOOPDEV --new-key-slot 1 || fail "Failed to add passphrase by VK in keyring." + echo $PWD2 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase 2>/dev/null || fail + $CRYPTSETUP luksKillSlot -q $LOOPDEV 1 2>/dev/null || fail + + $CRYPTSETUP close $DEV_NAME || fail + # zero-out the key in keyring + keyctl pipe $KEYCTL_KEY_NAME | tr -c '\0' '\0' | keyctl pupdate $KEYCTL_KEY_NAME + $CRYPTSETUP open $LOOPDEV $DEV_NAME --volume-key-keyring $KEY_DESC <&- > /dev/null 2>&1 && fail "Unlocked volume via a bad VK in keyring." + keyctl search "$2" $KEY_TYPE $1 > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after bad activation." + keyctl unlink $KEYCTL_KEY_NAME "$2" || fail +} + +# $1 first key name +# $2 second key name +# $3 keyring to link VK to +# $4 key type (optional) +test_reencrypt_vk_link() { + 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." + + keyctl unlink $KEYCTL_KEY_NAME "$3" || fail + 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]}" + expect "$@" +} + +# expected unlocked keyslot id +# command arguments +function expect_unlocked_keyslot() +{ + command -v expect >/dev/null || { + echo "WARNING: expect tool missing, interactive test will be skipped." + return 0 + } + + EXPECT_TIMEOUT=60 + EXPECT_KEY=$1 + + expect_run - >/dev/null <<EOF +proc abort {} { send_error "Timeout. "; exit 2 } +set timeout $EXPECT_TIMEOUT +eval spawn $CRYPTSETUP_RAW $2 +expect timeout abort "Key slot $EXPECT_KEY unlocked." +expect timeout abort "Command successful." +expect timeout abort eof +exit +EOF + [ $? -eq 0 ] || return 1 +} + export LANG=C [ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped." @@ -569,7 +747,7 @@ test $OLD_SIZE -eq $NEW_SIZE || fail $CRYPTSETUP close $DEV_NAME || fail prepare "[20] Disallow open/create if already mapped." wipe -$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 || fail +$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 --cipher aes-cbc-essiv:sha256 --key-size 256 || fail echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV 2>/dev/null && fail $CRYPTSETUP remove $DEV_NAME || fail echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV || fail @@ -626,6 +804,24 @@ $CRYPTSETUP luksDump $LOOPDEV | grep -q "2: luks2" && fail $CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 $KEY2 || fail $CRYPTSETUP luksDump $LOOPDEV | grep -q "0: luks2" || fail $CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 $KEY2 2>/dev/null && fail +# make a free space in keyslot area +echo $PWD1 | $CRYPTSETUP luksKillSlot -q $LOOPDEV 0 || fail + +# assert LUKS2 does not overwrite existing area with specific keyslot id +AREA_OFFSET_OLD=$($CRYPTSETUP luksDump $LOOPDEV | grep -e "1: luks2" -A12 | grep -e "Area offset:" | cut -d: -f 2 | sed -e 's/[[:space:]]*\[bytes\]//g') +[ 0$AREA_OFFSET_OLD -gt 0 ] || fail +echo -e "$PWD1\n$PWD2\n" | $CRYPTSETUP luksChangeKey --key-slot 1 $LOOPDEV $FAST_PBKDF_OPT +AREA_OFFSET_NEW=$($CRYPTSETUP luksDump $LOOPDEV | grep -e "1: luks2" -A12 | grep -e "Area offset:" | cut -d: -f 2 | sed -e 's/[[:space:]]*\[bytes\]//g') +[ 0$AREA_OFFSET_NEW -gt 0 ] || fail +[ $AREA_OFFSET_OLD -ne $AREA_OFFSET_NEW ] || fail "Area offsets remained same: old area $AREA_OFFSET_OLD, new area $AREA_OFFSET_NEW" + +# assert LUKS2 does not overwrite existing area with any sklot +AREA_OFFSET_OLD=$($CRYPTSETUP luksDump $LOOPDEV | grep -e "1: luks2" -A12 | grep -e "Area offset:" | cut -d: -f 2 | sed -e 's/[[:space:]]*\[bytes\]//g') +[ 0$AREA_OFFSET_OLD -gt 0 ] || fail +echo -e "$PWD2\n$PWD1\n" | $CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT +AREA_OFFSET_NEW=$($CRYPTSETUP luksDump $LOOPDEV | grep -e "1: luks2" -A12 | grep -e "Area offset:" | cut -d: -f 2 | sed -e 's/[[:space:]]*\[bytes\]//g') +[ 0$AREA_OFFSET_NEW -gt 0 ] || fail +[ $AREA_OFFSET_OLD -ne $AREA_OFFSET_NEW ] || fail "Area offsets remained same: old area $AREA_OFFSET_OLD, new area $AREA_OFFSET_NEW" prepare "[24] Keyfile limit" wipe $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV $KEY1 --key-slot 0 -l 13 || fail @@ -924,6 +1120,40 @@ if [ $HAVE_KEYRING -gt 0 -a -d /proc/sys/kernel/keys ]; then $CRYPTSETUP token unassign --token-id 0 -S0 $LOOPDEV 2>/dev/null && fail $CRYPTSETUP token unassign --token-id 0 -S44 $LOOPDEV 2>/dev/null && fail $CRYPTSETUP token unassign --token-id 44 -S0 $LOOPDEV 2>/dev/null && fail + + $CRYPTSETUP token remove $LOOPDEV --token-id 0 || fail + $CRYPTSETUP token add $LOOPDEV --key-description $TEST_TOKEN0 -S0 --token-id 0 || fail + + # token 8 assigned to keyslot 0 and 5. Unlocks only 5 + echo "$PWD2" | $CRYPTSETUP luksAddKey -q -S5 $FAST_PBKDF_OPT --token-id 0 $LOOPDEV || fail + echo -n "{\"type\":\"luks2-keyring\",\"keyslots\":[\"0\",\"5\"],\"key_description\":\"$TEST_TOKEN1\"}" | $CRYPTSETUP token import $LOOPDEV --token-id 8 || fail + load_key user $TEST_TOKEN1 "$PWD2" "$TEST_KEYRING" || fail "Cannot load 32 byte user key type" + + # token 3 assigned to keyslot 1 (wrong passphrase) + echo "$PWD3" | $CRYPTSETUP luksAddKey -q -S1 $FAST_PBKDF_OPT --token-id 0 $LOOPDEV || fail + $CRYPTSETUP token add $LOOPDEV --key-description $TEST_TOKEN2 -S1 --token-id 3 || fail + load_key user $TEST_TOKEN2 "$PWDW" "$TEST_KEYRING" || fail "Cannot load 32 byte user key type" + + # specific token, specific keyslot + $CRYPTSETUP open --test-passphrase --token-id 0 -S0 $LOOPDEV --token-only <&- || fail + # specific keyslot unlocked by any token + $CRYPTSETUP open --test-passphrase -S0 $LOOPDEV --token-only <&- || fail + + # token 0 unusable for keyslot 5 + $CRYPTSETUP open --test-passphrase --token-id 0 -S5 $LOOPDEV --token-only <&- >/dev/null && fail + # backup interactive prompt should work + echo $PWD2 | $CRYPTSETUP open --test-passphrase --token-id 0 -S5 $LOOPDEV || fail + + $CRYPTSETUP open --test-passphrase -S5 --token-id 8 $LOOPDEV <&- || fail + $CRYPTSETUP open --test-passphrase -S5 $LOOPDEV <&- || fail + + expect_unlocked_keyslot 5 "open -v --test-passphrase --token-id 8 -S5 $LOOPDEV" || fail + expect_unlocked_keyslot 5 "open -v --test-passphrase --token-id 8 $LOOPDEV" || fail + + $CRYPTSETUP open --test-passphrase -S0 --token-id 8 $LOOPDEV --token-only >/dev/null && fail + [ $? -ne 2 ] && fail "open should return EPERM exit code." + $CRYPTSETUP open --test-passphrase -S1 $LOOPDEV --token-only && fail + [ $? -ne 2 ] && fail "open should return EPERM exit code." fi echo -n "$IMPORT_TOKEN" | $CRYPTSETUP token import $LOOPDEV --token-id 10 || fail echo -n "$IMPORT_TOKEN" | $CRYPTSETUP token import $LOOPDEV --token-id 11 --json-file - || fail @@ -1200,5 +1430,135 @@ if [ $HAVE_KEYRING -gt 0 -a -d /proc/sys/kernel/keys ]; then $CRYPTSETUP open -q --test-passphrase --token-only --token-id 0 -q $IMG || fail fi +prepare "[44] LUKS2 invalid cipher (kernel cipher driver name)" wipe +xz -dk $HEADER_LUKS2_INV.xz +dd if=$HEADER_LUKS2_INV of=$IMG conv=notrunc >/dev/null 2>&1 +$CRYPTSETUP -q luksDump $LOOPDEV | grep -q "capi:xts(ecb(aes-generic))-plain64" || fail +echo $PWD1 | $CRYPTSETUP open $LOOPDEV --test-passphrase || fail +echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME 2>&1 | grep -q "No known cipher specification pattern" || fail +echo $PWD1 | $CRYPTSETUP reencrypt $LOOPDEV >/dev/null 2>&1 && fail +dmsetup create $DEV_NAME --uuid CRYPT-LUKS2-3d20686f551748cb89911ad32379821b-test --table \ + "0 8 crypt capi:xts(ecb(aes-generic))-plain64 edaa40709797973715e572bf7d86fcbb9cfe2051083c33c28d58fe4e1e7ff642 0 $LOOPDEV 32768" +$CRYPTSETUP status $DEV_NAME | grep -q "n/a" || fail +$CRYPTSETUP close $DEV_NAME ||fail + +if [ $HAVE_KEYRING -gt 0 -a -d /proc/sys/kernel/keys ]; then + prepare "[45] Link VK to a keyring and use custom VK type." wipe + + echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV 2> /dev/null || fail + KEY_NAME="cryptsetup:test_volume_key_id" + KEY_NAME2="cryptsetup:test_volume_key_id2" + KEY_NAME3="cryptsetup:test_volume_key_id3" + test_and_prepare_keyring + KID=$(echo -n test | keyctl padd user my_token @s) + keyctl unlink $KID >/dev/null 2>&1 @s && SESSION_KEYRING_WORKS=1 + KID=$(echo -n test | keyctl padd user my_token @us) + keyctl unlink $KID >/dev/null 2>&1 @us && USER_SESSION_KEYRING_WORKS=1 + + test_vk_link $KEY_NAME "@u" + test_vk_link $KEY_NAME "@u" "user" + [[ ! -z "$SESSION_KEYRING_WORKS" ]] && test_vk_link $KEY_NAME "@s" + [[ ! -z "$SESSION_KEYRING_WORKS" ]] && test_vk_link $KEY_NAME "@s" "logon" + [[ ! -z "$SESSION_KEYRING_WORKS" ]] && test_vk_link $KEY_NAME "@s" "user" + test_vk_link $KEY_NAME "%:$TEST_KEYRING_NAME" + test_vk_link $KEY_NAME "%:$TEST_KEYRING_NAME" "user" + test_vk_link $KEY_NAME "%:$TEST_KEYRING_NAME" "logon" + # explicitly specify keyring key type + test_vk_link $KEY_NAME "%keyring:$TEST_KEYRING_NAME" + + test_vk_link_and_reactivate $KEY_NAME "@u" "user" + test_vk_link_and_reactivate $KEY_NAME "@u" + [[ ! -z "$SESSION_KEYRING_WORKS" ]] && test_vk_link_and_reactivate $KEY_NAME "@s" "user" + test_vk_link_and_reactivate $KEY_NAME "%:$TEST_KEYRING_NAME" "user" + # explicitly specify keyring key type + test_vk_link_and_reactivate $KEY_NAME "%keyring:$TEST_KEYRING_NAME" "user" + test_vk_link_and_reactivate $KEY_NAME "%keyring:$TEST_KEYRING_NAME" + + # test numeric keyring name -5 is user session (@us) keyring + echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring -5::%logon:$KEY_NAME || fail + keyctl search @us logon $KEY_NAME > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after activation." + $CRYPTSETUP close $DEV_NAME + keyctl search @us logon $KEY_NAME > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after deactivation." + keyctl unlink "%logon:$KEY_NAME" @us || fail + + # test malformed keyring descriptions and key types + # missing key description + echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring "%$TEST_KEYRING_NAME::" > /dev/null 2>&1 && fail + # malformed keyring description + echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring ":$TEST_KEYRING_NAME::$KEY_NAME" > /dev/null 2>&1 && fail + echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring "@uuu::$KEY_NAME" > /dev/null 2>&1 && fail + echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring "@usu::$KEY_NAME" > /dev/null 2>&1 && fail + + echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring "$TEST_KEYRING_NAME::%user" > /dev/null 2>&1 && fail + echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring "$TEST_KEYRING_NAME::%user:" > /dev/null 2>&1 && fail + echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring "%user:$KEY_NAME" > /dev/null 2>&1 && fail + + echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring "@t::%0:$KEY_NAME" > /dev/null 2>&1 && fail + 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 + 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 + echo $PWD1 | $CRYPTSETUP -q reencrypt $LOOPDEV --init-only + + test_reencrypt_vk_link $KEY_NAME $KEY_NAME2 "@u" + test_reencrypt_vk_link $KEY_NAME $KEY_NAME2 "@u" "user" + [[ ! -z "$SESSION_KEYRING_WORKS" ]] && test_reencrypt_vk_link $KEY_NAME $KEY_NAME2 "@s" + [[ ! -z "$SESSION_KEYRING_WORKS" ]] && test_reencrypt_vk_link $KEY_NAME $KEY_NAME2 "@s" "logon" + [[ ! -z "$SESSION_KEYRING_WORKS" ]] && test_reencrypt_vk_link $KEY_NAME $KEY_NAME2 "@s" "user" + test_reencrypt_vk_link $KEY_NAME $KEY_NAME2 "%:$TEST_KEYRING_NAME" + test_reencrypt_vk_link $KEY_NAME $KEY_NAME2 "%:$TEST_KEYRING_NAME" "user" + test_reencrypt_vk_link $KEY_NAME $KEY_NAME2 "%:$TEST_KEYRING_NAME" "logon" + # explicitly specify keyring key type + test_reencrypt_vk_link $KEY_NAME $KEY_NAME2 "%keyring:$TEST_KEYRING_NAME" + + 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 + 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 + +prepare "[45] Blkid disable check" wipe +if [ "$HAVE_BLKID" -gt 0 ]; then + xz -dkf $HEADER_LUKS2_PV.xz + # batch mode disables blkid print, use --debug to check it + echo $PWD1 | $CRYPTSETUP -q --debug luksFormat $FAST_PBKDF_OPT --type luks2 $HEADER_LUKS2_PV 2>&1 | grep -q "LVM2_member" || fail + xz -dkf $HEADER_LUKS2_PV.xz + echo $PWD1 | $CRYPTSETUP -q --debug --disable-blkid luksFormat $FAST_PBKDF_OPT --type luks2 $HEADER_LUKS2_PV 2>&1 | grep -q "LVM2_member" && fail +fi + +prepare "[46] Init from suspended device" wipe +dmsetup create $DEV_NAME --table "0 39998 linear $LOOPDEV 2" || fail +echo $PWD1 | $CRYPTSETUP -q $FAST_PBKDF_OPT luksFormat --type luks2 --header $HEADER_IMG /dev/mapper/$DEV_NAME || fail +echo $PWD1 | $CRYPTSETUP -q luksOpen --header $HEADER_IMG /dev/mapper/$DEV_NAME $DEV_NAME2 || fail +# underlying device now returns error but node is still present +dmsetup load $DEV_NAME --table "0 40000 error" || fail +dmsetup resume $DEV_NAME || fail +dmsetup suspend $DEV_NAME || fail +# status must print data even if data device is suspended +$CRYPTSETUP -q status --debug --header $HEADER_IMG $DEV_NAME2 | grep "type:" | grep -q "LUKS2" || fail +dmsetup resume $DEV_NAME || fail +$CRYPTSETUP -q luksClose $DEV_NAME2 || fail +dmsetup remove --retry $DEV_NAME || fail + remove_mapping exit 0 diff --git a/tests/crypto-vectors.c b/tests/crypto-vectors.c index ae8dd68..02e6be3 100644 --- a/tests/crypto-vectors.c +++ b/tests/crypto-vectors.c @@ -1,7 +1,7 @@ /* * cryptsetup crypto backend test vectors * - * Copyright (C) 2018-2023 Milan Broz + * Copyright (C) 2018-2024 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -74,12 +74,9 @@ struct kdf_test_vector { unsigned int password_length; const char *salt; unsigned int salt_length; -// const char *key; -// unsigned int key_length; -// const char *ad; -// unsigned int ad_length; const char *output; unsigned int output_length; + bool can_fail_fips; /* violates minimal length check */ }; static struct kdf_test_vector kdf_test_vectors[] = { @@ -92,17 +89,11 @@ static struct kdf_test_vector kdf_test_vectors[] = { "\x01\x01\x01\x01\x01\x01\x01\x01", 32, "\x02\x02\x02\x02\x02\x02\x02\x02" "\x02\x02\x02\x02\x02\x02\x02\x02", 16, -// "\x03\x03\x03\x03\x03\x03\x03\x03", 8, -// "\x04\x04\x04\x04\x04\x04\x04\x04" -// "\x04\x04\x04\x04", 12, "\xa9\xa7\x51\x0e\x6d\xb4\xd5\x88" "\xba\x34\x14\xcd\x0e\x09\x4d\x48" "\x0d\x68\x3f\x97\xb9\xcc\xb6\x12" - "\xa5\x44\xfe\x8e\xf6\x5b\xa8\xe0", 32 -// "\xc8\x14\xd9\xd1\xdc\x7f\x37\xaa" -// "\x13\xf0\xd7\x7f\x24\x94\xbd\xa1" -// "\xc8\xde\x6b\x01\x6d\xd3\x88\xd2" -// "\x99\x52\xa4\xc4\x67\x2b\x6c\xe8", 32 + "\xa5\x44\xfe\x8e\xf6\x5b\xa8\xe0", 32, + true }, { "argon2id", NULL, 0, 3, 32, 4, @@ -112,17 +103,11 @@ static struct kdf_test_vector kdf_test_vectors[] = { "\x01\x01\x01\x01\x01\x01\x01\x01", 32, "\x02\x02\x02\x02\x02\x02\x02\x02" "\x02\x02\x02\x02\x02\x02\x02\x02", 16, -// "\x03\x03\x03\x03\x03\x03\x03\x03", 8, -// "\x04\x04\x04\x04\x04\x04\x04\x04" -// "\x04\x04\x04\x04", 12, "\x03\xaa\xb9\x65\xc1\x20\x01\xc9" "\xd7\xd0\xd2\xde\x33\x19\x2c\x04" "\x94\xb6\x84\xbb\x14\x81\x96\xd7" - "\x3c\x1d\xf1\xac\xaf\x6d\x0c\x2e", 32 -// "\x0d\x64\x0d\xf5\x8d\x78\x76\x6c" -// "\x08\xc0\x37\xa3\x4a\x8b\x53\xc9" -// "\xd0\x1e\xf0\x45\x2d\x75\xb6\x5e" -// "\xb5\x25\x20\xe9\x6b\x01\xe6\x59", 32 + "\x3c\x1d\xf1\xac\xaf\x6d\x0c\x2e", 32, + true }, /* empty password */ { @@ -133,7 +118,8 @@ static struct kdf_test_vector kdf_test_vectors[] = { "\xbb\x1f\xf2\xb9\x9f\xd4\x4a\xd9" "\xdf\x7f\xb9\x54\x55\x9e\xb8\xeb" "\xb5\x9d\xab\xce\x2e\x62\x9f\x9b" - "\x89\x09\xfe\xde\x57\xcc\x63\x86", 32 + "\x89\x09\xfe\xde\x57\xcc\x63\x86", 32, + true }, { "argon2id", NULL, 0, 3, 128, 1, @@ -143,7 +129,8 @@ static struct kdf_test_vector kdf_test_vectors[] = { "\x09\x2f\x38\x35\xac\xb2\x43\x92" "\x93\xeb\xcd\xe8\x04\x16\x6a\x31" "\xce\x14\xd4\x55\xdb\xd8\xf7\xe6" - "\xb4\xf5\x9d\x64\x8e\xd0\x3a\xdb", 32 + "\xb4\xf5\x9d\x64\x8e\xd0\x3a\xdb", 32, + true }, /* RFC 3962 */ { @@ -153,7 +140,8 @@ static struct kdf_test_vector kdf_test_vectors[] = { "\xcd\xed\xb5\x28\x1b\xb2\xf8\x01" "\x56\x5a\x11\x22\xb2\x56\x35\x15" "\x0a\xd1\xf7\xa0\x4b\xb9\xf3\xa3" - "\x33\xec\xc0\xe2\xe1\xf7\x08\x37", 32 + "\x33\xec\xc0\xe2\xe1\xf7\x08\x37", 32, + true }, { "pbkdf2", "sha1", 64, 2, 0, 0, "password", 8, @@ -161,7 +149,8 @@ static struct kdf_test_vector kdf_test_vectors[] = { "\x01\xdb\xee\x7f\x4a\x9e\x24\x3e" "\x98\x8b\x62\xc7\x3c\xda\x93\x5d" "\xa0\x53\x78\xb9\x32\x44\xec\x8f" - "\x48\xa9\x9e\x61\xad\x79\x9d\x86", 32 + "\x48\xa9\x9e\x61\xad\x79\x9d\x86", 32, + true }, { "pbkdf2", "sha1", 64, 1200, 0, 0, "password", 8, @@ -169,7 +158,8 @@ static struct kdf_test_vector kdf_test_vectors[] = { "\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e" "\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b" "\xa7\xe5\x2d\xdb\xc5\xe5\x14\x2f" - "\x70\x8a\x31\xe2\xe6\x2b\x1e\x13", 32 + "\x70\x8a\x31\xe2\xe6\x2b\x1e\x13", 32, + false }, { "pbkdf2", "sha1", 64, 5, 0, 0, "password", 8, @@ -177,7 +167,8 @@ static struct kdf_test_vector kdf_test_vectors[] = { "\xd1\xda\xa7\x86\x15\xf2\x87\xe6" "\xa1\xc8\xb1\x20\xd7\x06\x2a\x49" "\x3f\x98\xd2\x03\xe6\xbe\x49\xa6" - "\xad\xf4\xfa\x57\x4b\x6e\x64\xee", 32 + "\xad\xf4\xfa\x57\x4b\x6e\x64\xee", 32, + true }, { "pbkdf2", "sha1", 64, 1200, 0, 0, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" @@ -186,7 +177,8 @@ static struct kdf_test_vector kdf_test_vectors[] = { "\x13\x9c\x30\xc0\x96\x6b\xc3\x2b" "\xa5\x5f\xdb\xf2\x12\x53\x0a\xc9" "\xc5\xec\x59\xf1\xa4\x52\xf5\xcc" - "\x9a\xd9\x40\xfe\xa0\x59\x8e\xd1", 32 + "\x9a\xd9\x40\xfe\xa0\x59\x8e\xd1", 32, + false }, { "pbkdf2", "sha1", 64, 1200, 0, 0, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" @@ -195,7 +187,8 @@ static struct kdf_test_vector kdf_test_vectors[] = { "\x9c\xca\xd6\xd4\x68\x77\x0c\xd5" "\x1b\x10\xe6\xa6\x87\x21\xbe\x61" "\x1a\x8b\x4d\x28\x26\x01\xdb\x3b" - "\x36\xbe\x92\x46\x91\x5e\xc8\x2a", 32 + "\x36\xbe\x92\x46\x91\x5e\xc8\x2a", 32, + false }, { "pbkdf2", "sha1", 64, 50, 0, 0, "\360\235\204\236", 4, // g-clef ("\xf09d849e) @@ -203,52 +196,60 @@ static struct kdf_test_vector kdf_test_vectors[] = { "\x6b\x9c\xf2\x6d\x45\x45\x5a\x43" "\xa5\xb8\xbb\x27\x6a\x40\x3b\x39" "\xe7\xfe\x37\xa0\xc4\x1e\x02\xc2" - "\x81\xff\x30\x69\xe1\xe9\x4f\x52", 32 + "\x81\xff\x30\x69\xe1\xe9\x4f\x52", 32, + true }, { /* RFC-6070 */ "pbkdf2", "sha1", 64, 1, 0, 0, "password", 8, "salt", 4, "\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9" - "\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6", 20 + "\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6", 20, + true }, { "pbkdf2", "sha1", 64, 2, 0, 0, "password", 8, "salt", 4, "\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e" - "\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57", 20 + "\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57", 20, + true }, { "pbkdf2", "sha1", 64, 4096, 0, 0, "password", 8, "salt", 4, "\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad" - "\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1", 20 + "\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1", 20, + true }, { "pbkdf2", "sha1", 64, 16777216, 0, 0, "password", 8, "salt", 4, "\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94" - "\x5b\x3d\x6b\xa2\x15\x8c\x26\x34\xe9\x84", 20 + "\x5b\x3d\x6b\xa2\x15\x8c\x26\x34\xe9\x84", 20, + true }, { "pbkdf2", "sha1", 64, 4096, 0, 0, "passwordPASSWORDpassword", 24, "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, "\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8" "\xd8\x36\x62\xc0\xe4\x4a\x8b\x29\x1a\x96" - "\x4c\xf2\xf0\x70\x38", 25 + "\x4c\xf2\xf0\x70\x38", 25, + false }, { "pbkdf2", "sha1", 64, 4096, 0, 0, "pass\0word", 9, "sa\0lt", 5, "\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37" - "\xd7\xf0\x34\x25\xe0\xc3", 16 + "\xd7\xf0\x34\x25\xe0\xc3", 16, + true }, { /* empty password test */ "pbkdf2", "sha1", 64, 2, 0, 0, "", 0, "salt", 4, "\x13\x3a\x4c\xe8\x37\xb4\xd2\x52\x1e\xe2" - "\xbf\x03\xe1\x1c\x71\xca\x79\x4e\x07\x97", 20 + "\xbf\x03\xe1\x1c\x71\xca\x79\x4e\x07\x97", 20, + true }, { /* Password exceeds block size test */ "pbkdf2", "sha256", 64, 1200, 0, 0, @@ -258,7 +259,8 @@ static struct kdf_test_vector kdf_test_vectors[] = { "\x22\x34\x4b\xc4\xb6\xe3\x26\x75" "\xa8\x09\x0f\x3e\xa8\x0b\xe0\x1d" "\x5f\x95\x12\x6a\x2c\xdd\xc3\xfa" - "\xcc\x4a\x5e\x6d\xca\x04\xec\x58", 32 + "\xcc\x4a\x5e\x6d\xca\x04\xec\x58", 32, + false }, { "pbkdf2", "sha512", 128, 1200, 0, 0, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" @@ -269,7 +271,8 @@ static struct kdf_test_vector kdf_test_vectors[] = { "\x0f\xb2\xed\x2c\x0e\x6e\xfb\x7d" "\x7d\x8e\xdd\x58\x01\xb4\x59\x72" "\x99\x92\x16\x30\x5e\xa4\x36\x8d" - "\x76\x14\x80\xf3\xe3\x7a\x22\xb9", 32 + "\x76\x14\x80\xf3\xe3\x7a\x22\xb9", 32, + false }, { "pbkdf2", "whirlpool", 64, 1200, 0, 0, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" @@ -278,7 +281,8 @@ static struct kdf_test_vector kdf_test_vectors[] = { "\x9c\x1c\x74\xf5\x88\x26\xe7\x6a" "\x53\x58\xf4\x0c\x39\xe7\x80\x89" "\x07\xc0\x31\x19\x9a\x50\xa2\x48" - "\xf1\xd9\xfe\x78\x64\xe5\x84\x50", 32 + "\xf1\xd9\xfe\x78\x64\xe5\x84\x50", 32, + true } }; @@ -1024,23 +1028,38 @@ static int pbkdf_test_vectors(void) { char result[256]; unsigned int i; + struct crypt_hash *h; const struct kdf_test_vector *vec; for (i = 0; i < ARRAY_SIZE(kdf_test_vectors); i++) { crypt_backend_memzero(result, sizeof(result)); vec = &kdf_test_vectors[i]; - printf("PBKDF vector %02d %s ", i, vec->type); + if (vec->hash) + printf("PBKDF vector %02d %s-%s ", i, vec->type, vec->hash); + else + printf("PBKDF vector %02d %s ", i, vec->type); if (vec->hash && crypt_hmac_size(vec->hash) < 0) { printf("[%s N/A]\n", vec->hash); continue; } + if (vec->hash) { + if (crypt_hash_init(&h, vec->hash) < 0) { + printf("[%s N/A (init)]\n", vec->hash); + continue; + } + crypt_hash_destroy(h); + } if (crypt_pbkdf(vec->type, vec->hash, vec->password, vec->password_length, vec->salt, vec->salt_length, result, vec->output_length, vec->iterations, vec->memory, vec->parallelism) < 0) { - printf("[%s-%s N/A]\n", vec->type, vec->hash); - continue; + if (vec->can_fail_fips && fips_mode()) { + printf("[API FAILED, IGNORED (FIPS mode)]\n"); + continue; + } + printf("[API FAILED]\n"); + return EXIT_FAILURE; } if (memcmp(result, vec->output, vec->output_length)) { printf("[FAILED]\n"); diff --git a/tests/device-test b/tests/device-test index c8b53bb..9aaf03c 100755 --- a/tests/device-test +++ b/tests/device-test @@ -8,10 +8,15 @@ DEV_NAME2="ymmud" PWD1="93R4P4pIqAH8" PWD2="mymJeD8ivEhE" FAST_PBKDF_OPT="--pbkdf pbkdf2 --pbkdf-force-iterations 1000" +PLAIN_OPT="--type plain --cipher aes-cbc-essiv:sha256 --key-size 256 --hash sha256" SKIP_COUNT=0 -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi cleanup() { [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME @@ -43,7 +48,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() @@ -100,21 +108,6 @@ function dm_crypt_features() DM_PERF_NO_WORKQUEUE=1 } -function dm_crypt_keyring_support() -{ - VER_STR=$(dmsetup targets | grep crypt | cut -f2 -dv) - [ -z "$VER_STR" ] && fail "Failed to parse dm-crypt version." - - VER_MAJ=$(echo $VER_STR | cut -f 1 -d.) - VER_MIN=$(echo $VER_STR | cut -f 2 -d.) - - # run the test with dm-crypt v1.15.0+ on purpose - # the fix is in dm-crypt v1.18.1+ - [ $VER_MAJ -gt 1 ] && return 0 - [ $VER_MAJ -lt 1 ] && return 1 - [ $VER_MIN -ge 15 ] -} - format() # format { add_image @@ -165,33 +158,33 @@ if [ -z "$DM_PERF_CPU" ]; then SKIP_COUNT=$((SKIP_COUNT+1)) else echo -n "PLAIN: same_cpu_crypt submit_from_cpus " - echo -e "$PWD1" | $CRYPTSETUP open -q --type plain --hash sha256 $DEV $DEV_NAME --perf-same_cpu_crypt --perf-submit_from_crypt_cpus || fail + echo -e "$PWD1" | $CRYPTSETUP open -q $PLAIN_OPT $DEV $DEV_NAME --perf-same_cpu_crypt --perf-submit_from_crypt_cpus || fail $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail $CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail check_io $CRYPTSETUP close $DEV_NAME || fail echo -n "allow_discards " - echo -e "$PWD1" | $CRYPTSETUP open -q --type plain --hash sha256 $DEV $DEV_NAME --perf-same_cpu_crypt --allow-discards || fail + echo -e "$PWD1" | $CRYPTSETUP open -q $PLAIN_OPT $DEV $DEV_NAME --perf-same_cpu_crypt --allow-discards || fail $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail $CRYPTSETUP status $DEV_NAME | grep -q discards || fail check_io $CRYPTSETUP close $DEV_NAME || fail - echo -e "$PWD1" | $CRYPTSETUP open -q --type plain --hash sha256 $DEV $DEV_NAME || fail - echo -e "$PWD1" | $CRYPTSETUP refresh --hash sha256 -q $DEV_NAME --perf-same_cpu_crypt --allow-discards || fail + echo -e "$PWD1" | $CRYPTSETUP open -q $PLAIN_OPT $DEV $DEV_NAME || fail + echo -e "$PWD1" | $CRYPTSETUP refresh $PLAIN_OPT -q $DEV_NAME --perf-same_cpu_crypt --allow-discards || fail # Hash affects volume key for plain device. Check we can detect it - echo -e "$PWD1" | $CRYPTSETUP refresh -q $DEV_NAME --hash sha512 --perf-same_cpu_crypt --allow-discards 2>/dev/null && fail + echo -e "$PWD1" | $CRYPTSETUP refresh -q $DEV_NAME --cipher aes-cbc-essiv:sha256 --key-size 256 --hash sha512 --perf-same_cpu_crypt --allow-discards 2>/dev/null && fail $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail $CRYPTSETUP status $DEV_NAME | grep -q discards || fail - echo -e "$PWD1" | $CRYPTSETUP refresh --hash sha256 -q $DEV_NAME --allow-discards || fail + echo -e "$PWD1" | $CRYPTSETUP refresh $PLAIN_OPT -q $DEV_NAME --allow-discards || fail $CRYPTSETUP status $DEV_NAME | grep -q discards || fail $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt && fail - echo -e "$PWD1" | $CRYPTSETUP refresh --hash sha256 -q $DEV_NAME || fail + echo -e "$PWD1" | $CRYPTSETUP refresh $PLAIN_OPT -q $DEV_NAME || fail $CRYPTSETUP status $DEV_NAME | grep -q discards && fail $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt && fail - echo -e "$PWD1" | $CRYPTSETUP refresh --hash sha256 $DEV $DEV_NAME2 2>/dev/null && fail + echo -e "$PWD1" | $CRYPTSETUP refresh $PLAIN_OPT $DEV $DEV_NAME2 2>/dev/null && fail if [ -n "$DM_PERF_NO_WORKQUEUE" ]; then echo -n "no_read_workqueue no_write_workqueue" - echo -e "$PWD1" | $CRYPTSETUP refresh --hash sha256 -q $DEV_NAME --perf-no_read_workqueue --perf-no_write_workqueue || fail + echo -e "$PWD1" | $CRYPTSETUP refresh $PLAIN_OPT -q $DEV_NAME --perf-no_read_workqueue --perf-no_write_workqueue || fail $CRYPTSETUP status $DEV_NAME | grep -q no_read_workqueue || fail $CRYPTSETUP status $DEV_NAME | grep -q no_write_workqueue || fail check_io @@ -279,9 +272,12 @@ else echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME --disable-keyring || fail $CRYPTSETUP status $DEV_NAME | grep -q keyring && fail if [ -n "$DM_KEYRING" ]; then - echo -n "keyring " - echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME || fail - $CRYPTSETUP status $DEV_NAME | grep -q keyring || fail + $CRYPTSETUP --version | grep -q KEYRING + if [ $? -eq 0 ]; then + echo -n "keyring " + echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME || fail + $CRYPTSETUP status $DEV_NAME | grep -q keyring || fail + fi fi if [ -n "$DM_PERF_NO_WORKQUEUE" ]; then echo -n "no_read_workqueue no_write_workqueue" @@ -299,7 +295,7 @@ else fi echo "[3] Kernel dmcrypt sector size options" -echo -e "$PWD1" | $CRYPTSETUP open --type plain --hash sha256 $DEV $DEV_NAME --sector-size 4096 >/dev/null 2>&1 +echo -e "$PWD1" | $CRYPTSETUP open $PLAIN_OPT $DEV $DEV_NAME --sector-size 4096 >/dev/null 2>&1 ret=$? [ -z "$DM_SECTOR_SIZE" -a $ret -eq 0 ] && fail "cryptsetup activated device with --sector-size option on incompatible kernel!" if [ $ret -ne 0 ] ; then @@ -312,18 +308,18 @@ else $CRYPTSETUP close $DEV_NAME || fail echo -n "PLAIN sector size:" - echo -e "$PWD1" | $CRYPTSETUP open --type plain --hash sha256 $DEV $DEV_NAME --sector-size 1234 >/dev/null 2>&1 && fail + echo -e "$PWD1" | $CRYPTSETUP open $PLAIN_OPT $DEV $DEV_NAME --sector-size 1234 >/dev/null 2>&1 && fail for S in 512 1024 2048 4096; do echo -n "[$S]" - echo -e "$PWD1" | $CRYPTSETUP open -q --type plain --hash sha256 $DEV $DEV_NAME --sector-size $S || fail + echo -e "$PWD1" | $CRYPTSETUP open -q $PLAIN_OPT $DEV $DEV_NAME --sector-size $S || fail check_sector_size $S $CRYPTSETUP close $DEV_NAME || fail done - echo -e "$PWD1" | $CRYPTSETUP open --type plain --hash sha256 $DEV $DEV_NAME --iv-large-sectors >/dev/null 2>&1 && fail + echo -e "$PWD1" | $CRYPTSETUP open $PLAIN_OPT $DEV $DEV_NAME --iv-large-sectors >/dev/null 2>&1 && fail for S in 1024 2048 4096; do echo -n "[$S/IV]" - echo -e "$PWD1" | $CRYPTSETUP open -q --type plain --hash sha256 $DEV $DEV_NAME --sector-size $S --iv-large-sectors || fail + echo -e "$PWD1" | $CRYPTSETUP open -q $PLAIN_OPT $DEV $DEV_NAME --sector-size $S --iv-large-sectors || fail check_sector_size $S dmsetup table $DEV_NAME | grep -q "iv_large_sectors" || fail $CRYPTSETUP close $DEV_NAME || fail diff --git a/tests/differ.c b/tests/differ.c index 95da8e5..0045b04 100644 --- a/tests/differ.c +++ b/tests/differ.c @@ -1,7 +1,7 @@ /* * cryptsetup file differ check (rewritten Clemens' fileDiffer in Python) * - * Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved. + * Copyright (C) 2010-2024 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/tests/discards-test b/tests/discards-test index 870f74d..27e5a5b 100755 --- a/tests/discards-test +++ b/tests/discards-test @@ -6,14 +6,18 @@ DEV_NAME="discard-t3st" DEV="" PWD1="93R4P4pIqAH8" -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi cleanup() { [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME udevadm settle >/dev/null 2>&1 rmmod scsi_debug >/dev/null 2>&1 - sleep 2 + sleep 1 } fail() @@ -34,7 +38,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() @@ -54,7 +61,7 @@ add_device() { exit 77 fi - sleep 2 + sleep 1 DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /) DEV="/dev/$DEV" @@ -103,7 +110,7 @@ dmsetup table $DEV_NAME | grep allow_discards >/dev/null || fail $CRYPTSETUP luksClose $DEV_NAME || fail echo "[2] Allowing discards for plain device" -echo $PWD1 | $CRYPTSETUP create -q $DEV_NAME $DEV --hash sha256 --allow-discards || fail +echo $PWD1 | $CRYPTSETUP create -q $DEV_NAME $DEV --cipher aes-cbc-essiv:sha256 --key-size 256 --hash sha256 --allow-discards || fail $CRYPTSETUP status $DEV_NAME | grep flags | grep discards >/dev/null || fail $CRYPTSETUP resize $DEV_NAME --size 100 || fail $CRYPTSETUP status $DEV_NAME | grep flags | grep discards >/dev/null || fail diff --git a/tests/fake_systemd_tpm_path.c b/tests/fake_systemd_tpm_path.c index 6d82989..3dff718 100644 --- a/tests/fake_systemd_tpm_path.c +++ b/tests/fake_systemd_tpm_path.c @@ -2,9 +2,9 @@ #include <stdlib.h> /* systemd tpm2-util.h */ -int tpm2_find_device_auto(int log_level, char **ret); +int tpm2_find_device_auto(char **ret); -extern int tpm2_find_device_auto(int log_level __attribute__((unused)), char **ret) +extern int tpm2_find_device_auto(char **ret) { const char *path = getenv("TPM_PATH"); diff --git a/tests/fake_token_path.c b/tests/fake_token_path.c deleted file mode 100644 index 7b2bad3..0000000 --- a/tests/fake_token_path.c +++ /dev/null @@ -1,6 +0,0 @@ -#include <libcryptsetup.h> - -const char *crypt_token_external_path(void) -{ - return BUILD_DIR; -} diff --git a/tests/fuzz/LUKS2.proto b/tests/fuzz/LUKS2.proto index 3a0f287..f54ed6b 100644 --- a/tests/fuzz/LUKS2.proto +++ b/tests/fuzz/LUKS2.proto @@ -1,8 +1,8 @@ /* * cryptsetup LUKS2 custom mutator * - * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com> - * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved. + * Copyright (C) 2022-2024 Daniel Zatovic <daniel.zatovic@gmail.com> + * Copyright (C) 2022-2024 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -229,7 +229,7 @@ enum keyslot_af_type { KEYSLOT_AF_TYPE_LUKS1 = 1; } -// The af (anti-forensic splitter) object contains this madatory field: +// The af (anti-forensic splitter) object contains this mandatory field: // - type [string] the anti-forensic function type. // AF type luks1 (compatible with LUKS1 [1]) contains these additional fields: // - stripes [integer] the number of stripes, for historical reasons only the 4000 value is supported. diff --git a/tests/fuzz/LUKS2_plain_JSON.proto b/tests/fuzz/LUKS2_plain_JSON.proto index 59096b7..da8ea00 100644 --- a/tests/fuzz/LUKS2_plain_JSON.proto +++ b/tests/fuzz/LUKS2_plain_JSON.proto @@ -1,8 +1,8 @@ /* * cryptsetup LUKS2 custom mutator * - * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com> - * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved. + * Copyright (C) 2022-2024 Daniel Zatovic <daniel.zatovic@gmail.com> + * Copyright (C) 2022-2024 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/tests/fuzz/crypt2_load_fuzz.cc b/tests/fuzz/crypt2_load_fuzz.cc index 1251d72..2195b40 100644 --- a/tests/fuzz/crypt2_load_fuzz.cc +++ b/tests/fuzz/crypt2_load_fuzz.cc @@ -1,8 +1,8 @@ /* * cryptsetup LUKS2 fuzz target * - * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com> - * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved. + * Copyright (C) 2022-2024 Daniel Zatovic <daniel.zatovic@gmail.com> + * Copyright (C) 2022-2024 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -22,91 +22,88 @@ extern "C" { #define FILESIZE (16777216) #include "src/cryptsetup.h" -#include <err.h> #include "luks2/luks2.h" #include "crypto_backend/crypto_backend.h" #include "FuzzerInterface.h" -static int calculate_checksum(const uint8_t* data, size_t size) { - struct crypt_hash *hd = NULL; - struct luks2_hdr_disk *hdr = NULL; - int hash_size; - uint64_t hdr_size1, hdr_size2; - int r = 0; - - /* primary header */ - if (sizeof(struct luks2_hdr_disk) > size) - return 0; - hdr = CONST_CAST(struct luks2_hdr_disk *) data; - - hdr_size1 = be64_to_cpu(hdr->hdr_size); - if (hdr_size1 > size) - return 0; - memset(&hdr->csum, 0, LUKS2_CHECKSUM_L); - if ((r = crypt_hash_init(&hd, "sha256"))) - goto out; - if ((r = crypt_hash_write(hd, CONST_CAST(char*) data, hdr_size1))) - goto out; - hash_size = crypt_hash_size("sha256"); - if (hash_size <= 0) { - r = 1; - goto out; - } - if ((r = crypt_hash_final(hd, (char*)&hdr->csum, (size_t)hash_size))) - goto out; - crypt_hash_destroy(hd); +#define CHKSUM_ALG "sha256" +#define CHKSUM_SIZE 32 - /* secondary header */ - if (hdr_size1 < sizeof(struct luks2_hdr_disk)) - hdr_size1 = sizeof(struct luks2_hdr_disk); +static bool fix_checksum_hdr(struct luks2_hdr_disk *hdr, const char *data, size_t len) +{ + char *csum = (char *)&hdr->csum; + struct crypt_hash *hd = NULL; + bool r = false; - if (hdr_size1 + sizeof(struct luks2_hdr_disk) > size) - return 0; - hdr = CONST_CAST(struct luks2_hdr_disk *) (data + hdr_size1); + if (crypt_hash_init(&hd, CHKSUM_ALG)) + return false; - hdr_size2 = be64_to_cpu(hdr->hdr_size); - if (hdr_size2 > size || (hdr_size1 + hdr_size2) > size) - return 0; + memset(csum, 0, LUKS2_CHECKSUM_L); - memset(&hdr->csum, 0, LUKS2_CHECKSUM_L); - if ((r = crypt_hash_init(&hd, "sha256"))) - goto out; - if ((r = crypt_hash_write(hd, (char*) hdr, hdr_size2))) - goto out; - if ((r = crypt_hash_final(hd, (char*)&hdr->csum, (size_t)hash_size))) - goto out; + if (!crypt_hash_write(hd, data, len) && + !crypt_hash_final(hd, csum, CHKSUM_SIZE)) + r = true; -out: - if (hd) - crypt_hash_destroy(hd); + crypt_hash_destroy(hd); return r; } -int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - int fd; +static bool calculate_checksum(const char *data, size_t size, struct luks2_hdr_disk *hdr_rw) +{ + uint64_t hdr_size; + + /* Primary header cannot fit in data */ + if (sizeof(*hdr_rw) > size) + return false; + + hdr_size = be64_to_cpu(((struct luks2_hdr_disk *)data)->hdr_size); + if (hdr_size > size || hdr_size <= sizeof(*hdr_rw)) + return false; + + /* Calculate checksum for primary header */ + memcpy(hdr_rw, data, sizeof(*hdr_rw)); + return fix_checksum_hdr(hdr_rw, data, (size_t)hdr_size); +} + +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + int fd, r = EXIT_FAILURE; struct crypt_device *cd = NULL; char name[] = "/tmp/test-script-fuzz.XXXXXX"; + struct luks2_hdr_disk hdr_rw; + size_t modified_data_size; - if (calculate_checksum(data, size)) - return 0; + /* if csum calculation fails, keep fuzzer running on original input */ + if (size >= sizeof(hdr_rw) && calculate_checksum((const char *)data, size, &hdr_rw)) + modified_data_size = sizeof(hdr_rw); + else + modified_data_size = 0; + /* create file with LUKS header for libcryptsetup */ fd = mkostemp(name, O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC); if (fd == -1) - err(EXIT_FAILURE, "mkostemp() failed"); + return r; /* enlarge header */ if (ftruncate(fd, FILESIZE) == -1) goto out; - if (write_buffer(fd, data, size) != (ssize_t)size) + if (modified_data_size && + write_buffer(fd, &hdr_rw, modified_data_size) != (ssize_t)modified_data_size) + goto out; + + if (write_buffer(fd, data + modified_data_size, size - modified_data_size) != (ssize_t)size) goto out; + /* Actual fuzzing */ if (crypt_init(&cd, name) == 0) (void)crypt_load(cd, CRYPT_LUKS2, NULL); crypt_free(cd); + r = 0; out: close(fd); unlink(name); - return 0; + + return r; } } diff --git a/tests/fuzz/crypt2_load_proto_fuzz.cc b/tests/fuzz/crypt2_load_proto_fuzz.cc index 498c006..aaabfe8 100644 --- a/tests/fuzz/crypt2_load_proto_fuzz.cc +++ b/tests/fuzz/crypt2_load_proto_fuzz.cc @@ -1,8 +1,8 @@ /* * cryptsetup LUKS2 custom mutator fuzz target * - * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com> - * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved. + * Copyright (C) 2022-2024 Daniel Zatovic <daniel.zatovic@gmail.com> + * Copyright (C) 2022-2024 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/tests/fuzz/crypt2_load_proto_plain_json_fuzz.cc b/tests/fuzz/crypt2_load_proto_plain_json_fuzz.cc index f3565ab..227c49a 100644 --- a/tests/fuzz/crypt2_load_proto_plain_json_fuzz.cc +++ b/tests/fuzz/crypt2_load_proto_plain_json_fuzz.cc @@ -1,8 +1,8 @@ /* * cryptsetup LUKS2 custom mutator fuzz target * - * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com> - * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved. + * Copyright (C) 2022-2024 Daniel Zatovic <daniel.zatovic@gmail.com> + * Copyright (C) 2022-2024 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/tests/fuzz/meson.build b/tests/fuzz/meson.build new file mode 100644 index 0000000..95ea382 --- /dev/null +++ b/tests/fuzz/meson.build @@ -0,0 +1,127 @@ +if get_option('fuzz-targets') + crypt2_load_fuzz = executable('crypt2_load_fuzz', + [ + 'crypt2_load_fuzz.cc', + ], + dependencies: [ + devmapper, + fuzzing_engine, + ], + link_with: [ + libcryptsetup, + libcrypto_backend, + libutils_io, + ], + link_args: [ + link_args, + ], + include_directories: includes_tools) + + crypt2_load_ondisk_fuzz = executable('crypt2_load_ondisk_fuzz', + [ + 'crypt2_load_ondisk_fuzz.cc', + ], + dependencies: [ + devmapper, + fuzzing_engine, + ], + link_with: [ + libcryptsetup, + libcrypto_backend, + libutils_io, + ], + link_args: [ + link_args, + ], + include_directories: includes_tools) + + luks2_generated = protoc_generator.process('LUKS2.proto') + crypt2_load_proto_fuzz = executable('crypt2_load_proto_fuzz', + [ + 'crypt2_load_proto_fuzz.cc', + 'proto_to_luks2_converter.cc', + luks2_generated, + ], + dependencies: [ + devmapper, + protobuf, + libprotobuf_mutator, + fuzzing_engine, + ], + link_with: [ + libcryptsetup, + libcrypto_backend, + libutils_io, + ], + link_args: [ + link_args, + ], + include_directories: includes_tools) + + luks2_plain_json_generated = protoc_generator.process('LUKS2_plain_JSON.proto') + crypt2_load_proto_plain_fuzz = executable('crypt2_load_proto_plain_fuzz', + [ + 'crypt2_load_proto_plain_json_fuzz.cc', + 'json_proto_converter.cc', + 'plain_json_proto_to_luks2_converter.cc', + luks2_plain_json_generated, + ], + dependencies: [ + devmapper, + protobuf, + libprotobuf_mutator, + fuzzing_engine, + ], + link_with: [ + libcryptsetup, + libcrypto_backend, + libutils_io, + ], + link_args: [ + link_args, + ], + include_directories: includes_tools) + + proto_to_luks2 = executable('proto_to_luks2', + [ + 'proto_to_luks2.cc', + 'proto_to_luks2_converter.cc', + luks2_generated, + ], + dependencies: [ + devmapper, + protobuf, + libprotobuf_mutator, + ], + link_with: [ + libcryptsetup, + libcrypto_backend, + libutils_io, + ], + link_args: [ + link_args, + ], + include_directories: includes_tools) + + plain_json_proto_to_luks2 = executable('plain_json_proto_to_luks2', + [ + 'plain_json_proto_to_luks2.cc', + 'plain_json_proto_to_luks2_converter.cc', + 'json_proto_converter.cc', + luks2_plain_json_generated, + ], + dependencies: [ + devmapper, + protobuf, + libprotobuf_mutator, + ], + link_with: [ + libcryptsetup, + libcrypto_backend, + libutils_io, + ], + link_args: [ + link_args, + ], + include_directories: includes_tools) +endif diff --git a/tests/fuzz/oss-fuzz-build.sh b/tests/fuzz/oss-fuzz-build.sh index b2f643f..cf0cfde 100755 --- a/tests/fuzz/oss-fuzz-build.sh +++ b/tests/fuzz/oss-fuzz-build.sh @@ -42,14 +42,16 @@ in_oss_fuzz && LIBFUZZER_PATCH="$PWD/cryptsetup/tests/fuzz/unpoison-mutated-buff in_oss_fuzz && apt-get update && apt-get install -y \ make autoconf automake autopoint libtool pkg-config \ sharutils gettext expect keyutils ninja-build \ - bison + bison flex [ ! -d zlib ] && git clone --depth 1 https://github.com/madler/zlib.git [ ! -d xz ] && git clone https://git.tukaani.org/xz.git [ ! -d json-c ] && git clone --depth 1 https://github.com/json-c/json-c.git -[ ! -d lvm2 ] && git clone --depth 1 https://sourceware.org/git/lvm2.git +[ ! -d lvm2 ] && git clone --depth 1 https://gitlab.com/lvmteam/lvm2 [ ! -d popt ] && git clone --depth 1 https://github.com/rpm-software-management/popt.git -[ ! -d libprotobuf-mutator ] && git clone --depth 1 https://github.com/google/libprotobuf-mutator.git \ +# FIXME: temporary fix until libprotobuf stops shuffling C++ requirements +# [ ! -d libprotobuf-mutator ] && git clone --depth 1 https://github.com/google/libprotobuf-mutator.git \ +[ ! -d libprotobuf-mutator ] && git clone --depth 1 --branch v1.1 https://github.com/google/libprotobuf-mutator.git \ && [ "$SANITIZER" == "memory" ] && ( cd libprotobuf-mutator; patch -p1 < $LIBFUZZER_PATCH ) [ ! -d openssl ] && git clone --depth 1 https://github.com/openssl/openssl [ ! -d util-linux ] && git clone --depth 1 https://github.com/util-linux/util-linux @@ -76,8 +78,8 @@ make install cd .. cd xz -./autogen.sh --no-po4a -./configure --prefix="$DEPS_PATH" --enable-static --disable-shared +./autogen.sh --no-po4a --no-doxygen +./configure --prefix="$DEPS_PATH" --enable-static --disable-shared --disable-ifunc --disable-sandbox make -j make install cd .. @@ -94,16 +96,14 @@ cd ../.. cd lvm2 ./configure --prefix="$DEPS_PATH" --enable-static_link --disable-udev_sync --enable-pkgconfig --disable-selinux make -j libdm.device-mapper -# build of dmsetup.static is broken -# make install_device-mapper -cp ./libdm/ioctl/libdevmapper.a "$DEPS_PATH"/lib/ -cp ./libdm/libdevmapper.h "$DEPS_PATH"/include/ -cp ./libdm/libdevmapper.pc "$PKG_CONFIG_PATH" +make -C libdm install_static install_pkgconfig install_include cd .. cd popt # --no-undefined is incompatible with sanitizers sed -i -e 's/-Wl,--no-undefined //' src/CMakeLists.txt +# force static build of popt +sed -i 's/add_library(popt SHARED/add_library(popt STATIC/' src/CMakeLists.txt mkdir -p build rm -fr build/* cd build diff --git a/tests/fuzz/plain_json_proto_to_luks2.cc b/tests/fuzz/plain_json_proto_to_luks2.cc index 8c56c15..a0f02c5 100644 --- a/tests/fuzz/plain_json_proto_to_luks2.cc +++ b/tests/fuzz/plain_json_proto_to_luks2.cc @@ -1,8 +1,8 @@ /* * cryptsetup LUKS2 protobuf to image converter * - * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com> - * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved. + * Copyright (C) 2022-2024 Daniel Zatovic <daniel.zatovic@gmail.com> + * Copyright (C) 2022-2024 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/tests/fuzz/plain_json_proto_to_luks2_converter.cc b/tests/fuzz/plain_json_proto_to_luks2_converter.cc index 823c0c5..6f756a9 100644 --- a/tests/fuzz/plain_json_proto_to_luks2_converter.cc +++ b/tests/fuzz/plain_json_proto_to_luks2_converter.cc @@ -1,8 +1,8 @@ /* * cryptsetup LUKS2 custom mutator fuzz target * - * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com> - * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved. + * Copyright (C) 2022-2024 Daniel Zatovic <daniel.zatovic@gmail.com> + * Copyright (C) 2022-2024 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -32,6 +32,8 @@ namespace json_proto { void LUKS2ProtoConverter::emit_luks2_binary_header(const LUKS2_header &header_proto, int fd, uint64_t offset, uint64_t seqid, const std::string &json_text) { struct luks2_hdr_disk hdr = {}; + size_t hdr_json_area_len, write_size; + uint8_t csum[LUKS2_CHECKSUM_L]; int r; if (hd) @@ -63,7 +65,6 @@ void LUKS2ProtoConverter::emit_luks2_binary_header(const LUKS2_header &header_pr strncpy(hdr.uuid, "af7f64ea-3233-4581-946b-6187d812841e", LUKS2_UUID_L); memset(hdr.salt, 1, LUKS2_SALT_L); - if (header_proto.has_selected_offset()) hdr.hdr_offset = cpu_to_be64(header_proto.selected_offset()); else @@ -74,10 +75,13 @@ void LUKS2ProtoConverter::emit_luks2_binary_header(const LUKS2_header &header_pr if (crypt_hash_write(hd, (char*)&hdr, LUKS2_HDR_BIN_LEN)) err(EXIT_FAILURE, "crypt_hash_write failed"); - size_t hdr_json_area_len = header_proto.hdr_size() - LUKS2_HDR_BIN_LEN; - uint8_t csum[LUKS2_CHECKSUM_L]; + if (header_proto.hdr_size() <= LUKS2_HDR_BIN_LEN || + header_proto.hdr_size() > LUKS2_DEFAULT_HDR_SIZE) + hdr_json_area_len = LUKS2_DEFAULT_HDR_SIZE - LUKS2_HDR_BIN_LEN; + else + hdr_json_area_len = header_proto.hdr_size() - LUKS2_HDR_BIN_LEN; - size_t write_size = json_text.length() > hdr_json_area_len - 1 ? hdr_json_area_len - 1 : json_text.length(); + write_size = json_text.length() > hdr_json_area_len - 1 ? hdr_json_area_len - 1 : json_text.length(); if (write_buffer(fd, json_text.c_str(), write_size) != (ssize_t)write_size) err(EXIT_FAILURE, "write_buffer failed"); if (crypt_hash_write(hd, json_text.c_str(), write_size)) @@ -113,6 +117,9 @@ void LUKS2ProtoConverter::convert(const LUKS2_both_headers &headers, int fd) { size_t out_size = headers.primary_header().hdr_size() + headers.secondary_header().hdr_size(); + if (out_size < 4096 || out_size > 2 * LUKS2_DEFAULT_HDR_SIZE) + out_size = LUKS2_DEFAULT_HDR_SIZE; + if (!write_headers_only) out_size += KEYSLOTS_SIZE + DATA_SIZE; diff --git a/tests/fuzz/plain_json_proto_to_luks2_converter.h b/tests/fuzz/plain_json_proto_to_luks2_converter.h index 7decf9f..aa1b594 100644 --- a/tests/fuzz/plain_json_proto_to_luks2_converter.h +++ b/tests/fuzz/plain_json_proto_to_luks2_converter.h @@ -1,8 +1,8 @@ /* * cryptsetup LUKS2 custom mutator fuzz target * - * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com> - * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved. + * Copyright (C) 2022-2024 Daniel Zatovic <daniel.zatovic@gmail.com> + * Copyright (C) 2022-2024 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/tests/fuzz/proto_to_luks2.cc b/tests/fuzz/proto_to_luks2.cc index 4a27cad..720d25b 100644 --- a/tests/fuzz/proto_to_luks2.cc +++ b/tests/fuzz/proto_to_luks2.cc @@ -1,8 +1,8 @@ /* * cryptsetup LUKS2 protobuf to image converter * - * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com> - * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved. + * Copyright (C) 2022-2024 Daniel Zatovic <daniel.zatovic@gmail.com> + * Copyright (C) 2022-2024 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/tests/fuzz/proto_to_luks2_converter.cc b/tests/fuzz/proto_to_luks2_converter.cc index 96a70b7..10f2b83 100644 --- a/tests/fuzz/proto_to_luks2_converter.cc +++ b/tests/fuzz/proto_to_luks2_converter.cc @@ -1,8 +1,8 @@ /* * cryptsetup LUKS2 custom mutator fuzz target * - * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com> - * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved. + * Copyright (C) 2022-2024 Daniel Zatovic <daniel.zatovic@gmail.com> + * Copyright (C) 2022-2024 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/tests/fuzz/proto_to_luks2_converter.h b/tests/fuzz/proto_to_luks2_converter.h index 9f926d0..5547ca7 100644 --- a/tests/fuzz/proto_to_luks2_converter.h +++ b/tests/fuzz/proto_to_luks2_converter.h @@ -1,8 +1,8 @@ /* * cryptsetup LUKS2 custom mutator fuzz target * - * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com> - * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved. + * Copyright (C) 2022-2024 Daniel Zatovic <daniel.zatovic@gmail.com> + * Copyright (C) 2022-2024 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/tests/fvault2-compat-test b/tests/fvault2-compat-test index 45022d2..047798a 100755 --- a/tests/fvault2-compat-test +++ b/tests/fvault2-compat-test @@ -5,8 +5,12 @@ CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup MAP=fvault2test TST_DIR=fvault2-images -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi [ -z "$srcdir" ] && srcdir="." @@ -83,7 +87,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() diff --git a/tests/integrity-compat-test b/tests/integrity-compat-test index 208eafb..a2aae8d 100755 --- a/tests/integrity-compat-test +++ b/tests/integrity-compat-test @@ -5,8 +5,12 @@ [ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".." INTSETUP=$CRYPTSETUP_PATH/integritysetup -INTSETUP_VALGRIND=../.libs/integritysetup -INTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + INTSETUP_VALGRIND=$INTSETUP +else + INTSETUP_VALGRIND=../.libs/integritysetup + INTSETUP_LIB_VALGRIND=../.libs +fi DEV_NAME=dmc_test DEV_NAME2=dmc_fake @@ -115,7 +119,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $INTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$INTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$INTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() diff --git a/tests/keyring-compat-test b/tests/keyring-compat-test index ea88c21..dc4787d 100755 --- a/tests/keyring-compat-test +++ b/tests/keyring-compat-test @@ -26,8 +26,12 @@ PWD="aaablabl" [ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".." CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null) @@ -54,7 +58,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() @@ -123,7 +130,7 @@ add_device() { exit 77 fi - sleep 2 + sleep 1 DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /) DEV="/dev/$DEV" diff --git a/tests/loopaes-test b/tests/loopaes-test index fdb4cd3..62fe772 100755 --- a/tests/loopaes-test +++ b/tests/loopaes-test @@ -3,8 +3,12 @@ [ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".." CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi # try to validate using loop-AES losetup/kernel if available LOSETUP_AES=/losetup-aes.old @@ -49,7 +53,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() diff --git a/tests/luks1-compat-test b/tests/luks1-compat-test index 18afcd5..c0de983 100755 --- a/tests/luks1-compat-test +++ b/tests/luks1-compat-test @@ -6,8 +6,12 @@ TST_DIR=luks1-images MAP=luks1tst KEYFILE=keyfile1 -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi [ -z "$srcdir" ] && srcdir="." @@ -38,7 +42,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() diff --git a/tests/luks2-integrity-test b/tests/luks2-integrity-test index a8082f8..ff41ebf 100755 --- a/tests/luks2-integrity-test +++ b/tests/luks2-integrity-test @@ -11,8 +11,12 @@ PWD1=nHjJHjI23JK KEY_FILE=key.img FAST_PBKDF_OPT="--pbkdf pbkdf2 --pbkdf-force-iterations 1000" -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi dmremove() { # device udevadm settle >/dev/null 2>&1 @@ -45,7 +49,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() @@ -60,6 +67,11 @@ add_device() { sync } +set_LO_DEV() { # file + # support both /dev/loopX and /dev/loop/X + LO_DEV=$(losetup -l -O NAME -n -j $1 2>/dev/null | sed -e 's/loop\//loop/') +} + status_check() # name value [detached] { if [ -n "$3" ]; then @@ -122,10 +134,12 @@ intformat() # alg integrity integrity_out key_size int_key_size sector_size csum dump_check "Key:" $(($4 + $5)) echo -n "[ACTIVATE]" $CRYPTSETUP open -d $KEY_FILE $DEV $DEV_NAME || fail "Cannot activate device." + set_LO_DEV $DEV status_check "cipher" $1 status_check "sector size" $6 status_check "integrity:" $3 status_check "keysize:" $(($4 + $5)) + [ -n "$LO_DEV" ] && status_check "device:" $LO_DEV [ $5 -gt 0 ] && status_check "integrity keysize:" $5 int_check_sum $1 $7 echo -n "[REMOVE]" @@ -137,12 +151,21 @@ intformat() # alg integrity integrity_out key_size int_key_size sector_size csum $CRYPTSETUP luksHeaderBackup -q --header-backup-file $HEADER_IMG $DEV || fail wipefs -a $DEV >/dev/null 2>&1 || fail $CRYPTSETUP open --header $HEADER_IMG -d $KEY_FILE $DEV $DEV_NAME || fail "Cannot activate device." + set_LO_DEV $DEV status_check "cipher" $1 1 status_check "sector size" $6 1 status_check "integrity:" $3 1 status_check "keysize:" $(($4 + $5)) 1 + [ -n "$LO_DEV" ] && status_check "device:" $LO_DEV 1 [ $5 -gt 0 ] && status_check "integrity keysize:" $5 1 int_check_sum $1 $7 + # check status returns values even if no --header is set + status_check "cipher" $1 + status_check "sector size" $6 + status_check "integrity:" $3 + status_check "keysize:" $(($4 + $5)) + [ -n "$LO_DEV" ] && status_check "device:" $LO_DEV + [ $5 -gt 0 ] && status_check "integrity keysize:" $5 $CRYPTSETUP close $DEV_NAME || fail "Cannot deactivate device." $CRYPTSETUP luksHeaderRestore -q --header-backup-file $HEADER_IMG $DEV || fail rm -f $HEADER_IMG @@ -169,6 +192,7 @@ intformat aes-xts-plain64 hmac-sha256 hmac\(sha256\) 512 256 512 ee501705a intformat aes-xts-random hmac-sha256 hmac\(sha256\) 512 256 512 492c2d1cc9e222a850c399bfef4ed5a86bf5afc59e54f0f0c7ba8e2a64548323 intformat aes-cbc-essiv:sha256 hmac-sha256 hmac\(sha256\) 128 256 4096 358d6beceddf593aff6b22c31684e0df9c226330aff5812e060950215217d21b intformat aes-xts-plain64 hmac-sha256 hmac\(sha256\) 256 256 4096 358d6beceddf593aff6b22c31684e0df9c226330aff5812e060950215217d21b +intformat aes-xts-plain64 hmac-sha256 hmac\(sha256\) 256 256 4096 358d6beceddf593aff6b22c31684e0df9c226330aff5812e060950215217d21b 1 intformat aes-xts-random hmac-sha256 hmac\(sha256\) 256 256 4096 8c0463f5ac09613674bdf40b0ff6f985edbc3de04e51fdc688873cb333ef3cda intformat aes-cbc-essiv:sha256 hmac-sha256 hmac\(sha256\) 256 256 4096 358d6beceddf593aff6b22c31684e0df9c226330aff5812e060950215217d21b intformat aes-xts-plain64 hmac-sha256 hmac\(sha256\) 512 256 4096 358d6beceddf593aff6b22c31684e0df9c226330aff5812e060950215217d21b diff --git a/tests/luks2-reencryption-mangle-test b/tests/luks2-reencryption-mangle-test index 5aa62e4..79b813d 100755 --- a/tests/luks2-reencryption-mangle-test +++ b/tests/luks2-reencryption-mangle-test @@ -5,8 +5,12 @@ PS4='$LINENO:' CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup CRYPTSETUP_RAW=$CRYPTSETUP -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi IMG=reenc-mangle-data IMG_HDR=$IMG.hdr IMG_HDR_BCP=$IMG_HDR.bcp @@ -210,7 +214,10 @@ 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" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi CRYPTSETUP=valgrind_run CRYPTSETUP_RAW="./valg.sh ${CRYPTSETUP_VALGRIND}" } diff --git a/tests/luks2-reencryption-test b/tests/luks2-reencryption-test index a647a8c..57acae0 100755 --- a/tests/luks2-reencryption-test +++ b/tests/luks2-reencryption-test @@ -4,8 +4,12 @@ [ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".." CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi FAST_PBKDF2="--pbkdf pbkdf2 --pbkdf-force-iterations 1000" FAST_PBKDF_ARGON="--pbkdf-force-iterations 4 --pbkdf-memory 32 --pbkdf-parallel 1" @@ -26,6 +30,13 @@ PWD1="93R4P4pIqAH8" PWD2="1cND4319812f" PWD3="1-9Qu5Ejfnqv" DEV_LINK="reenc-test-link" +KEYRING="luks2_reencryption_test_kr" +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}" +HAVE_KEYRING=0 FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null) @@ -105,6 +116,13 @@ function remove_mapping() scsi_debug_teardown $DEV } +function cleanup_keyring() +{ + if [ $HAVE_KEYRING -eq 1 ]; then + keyctl unlink %:$KEYRING "@s" >/dev/null 2>&1 || echo "Failed to unlink test keyring." + fi +} + function fail() { local frame=0 @@ -112,6 +130,7 @@ function fail() echo "FAILED backtrace:" while caller $frame; do ((frame++)); done remove_mapping + cleanup_keyring exit 2 } @@ -119,6 +138,7 @@ function skip() { [ -n "$1" ] && echo "$1" remove_mapping + cleanup_keyring exit 77 } @@ -362,6 +382,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 @@ -787,14 +839,27 @@ function reencrypt_online_fixed_size() { [ -n "$7" -a -f "$7" ] && rm -f $7 } +function prepare_vk_keyring() +{ + local s_desc=$(keyctl rdescribe @s | cut -d';' -f5) + local us_desc=$(keyctl rdescribe @us | cut -d';' -f5) + + if [ "$s_desc" = "$us_desc" -a -n "$s_desc" ]; then + echo "Session keyring is missing. Giving new one to parent process..." + keyctl new_session > /dev/null || fail + fi + + keyctl newring $KEYRING "@s" >/dev/null || fail "Failed to setup test keyring environment" + keyctl search "@s" keyring $KEYRING >/dev/null 2>&1 || fail "Could not find test keyring in a session keyring." +} + function setup_luks2_env() { 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 + local check_keyring=$($CRYPTSETUP status $DEV_NAME | grep "key location: keyring") + if [ -n "$check_keyring" ]; then HAVE_KEYRING=1 - else - HAVE_KEYRING=0 + prepare_vk_keyring 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." @@ -819,7 +884,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() @@ -1254,6 +1322,42 @@ if [ -n "$DM_SECTOR_SIZE" ]; then reencrypt_recover_online 4096 journal $HASH1 fi +if [ $HAVE_KEYRING -eq 1 ]; then + 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 +fi + echo "[8] Reencryption with detached header recovery" prepare_linear_dev 31 opt_blks=64 $OPT_XFERLEN_EXP @@ -2204,4 +2308,5 @@ echo $PWD1 | $CRYPTSETUP reencrypt --decrypt --header $IMG_HDR $DEV -q || fail check_hash_dev_head $DEV 2048 $HASH2 remove_mapping +cleanup_keyring exit 0 diff --git a/tests/luks2-validation-test b/tests/luks2-validation-test index cd9f0a6..545c38e 100755 --- a/tests/luks2-validation-test +++ b/tests/luks2-validation-test @@ -6,8 +6,12 @@ PS4='$LINENO:' [ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".." CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi START_DIR=$(pwd) @@ -106,7 +110,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() diff --git a/tests/luks2_invalid_cipher.img.xz b/tests/luks2_invalid_cipher.img.xz Binary files differnew file mode 100644 index 0000000..52ce436 --- /dev/null +++ b/tests/luks2_invalid_cipher.img.xz diff --git a/tests/meson.build b/tests/meson.build new file mode 100644 index 0000000..43fff9a --- /dev/null +++ b/tests/meson.build @@ -0,0 +1,482 @@ +fs = import('fs') + +# copy images and generators to build directory from where tests run +test_files_to_copy = [ + 'bitlk-images.tar.xz', + 'blkid-luks2-pv.img.xz', + 'compatimage.img.xz', + 'compatimage2.img.xz', + 'compatv10image.img.xz', + 'conversion_imgs.tar.xz', + 'evil_hdr-keyslot_overlap.xz', + 'evil_hdr-luks_hdr_damage.xz', + 'evil_hdr-payload_overwrite.xz', + 'evil_hdr-small_luks_device.xz', + 'evil_hdr-stripes_payload_dmg.xz', + 'fvault2-images.tar.xz', + 'generators/generate-luks2-area-in-json-hdr-space-json0.img.sh', + 'img_fs_ext4.img.xz', + 'luks1-images.tar.xz', + 'luks2_header_requirements.tar.xz', + 'luks2_keyslot_unassigned.img.xz', + 'luks2_mda_images.tar.xz', + 'luks2_valid_hdr.img.xz', + 'luks2_invalid_cipher.img.xz', + 'tcrypt-images.tar.xz', + 'valid_header_file.xz', + 'xfs_512_block_size.img.xz', + 'valg.sh', + 'cryptsetup-valg-supps', +] + +foreach file : test_files_to_copy + fs.copyfile(file) +endforeach + +api_test = executable('api-test', + [ + 'api-test.c', + 'test_utils.c', + ], + dependencies: devmapper, + link_with: libcryptsetup, + c_args: ['-DNO_CRYPTSETUP_PATH'], + include_directories: includes_lib) + +api_test_2 = executable('api-test-2', + [ + 'api-test-2.c', + 'test_utils.c', + ], + dependencies: devmapper, + link_with: libcryptsetup, + c_args: [ + '-DNO_CRYPTSETUP_PATH', + ], + include_directories: includes_lib) + +vectors_test = executable('vectors-test', + [ + 'crypto-vectors.c', + ], + link_with: libcrypto_backend, + c_args: [ + '-DNO_CRYPTSETUP_PATH', + ], + include_directories: includes_lib) + +differ = executable('differ', + [ + 'differ.c', + ], + c_args: [ + '-Wall', + '-O2', + ]) + +unit_utils_io = executable('unit-utils-io', + [ + 'unit-utils-io.c', + ], + link_with: libutils_io, + c_args: [ + '-DNO_CRYPTSETUP_PATH', + ], + include_directories: includes_lib) + +unit_utils_crypt_test = files('unit-utils-crypt.c',) + lib_utils_crypt_files +unit_utils_crypt_test = executable('unit-utils-crypt-test-test', + unit_utils_crypt_test, + link_with: libcryptsetup, + c_args: [ + '-DNO_CRYPTSETUP_PATH', + ], + include_directories: includes_lib) + +unit_wipe = executable('unit-wipe', + [ + 'unit-wipe.c', + ], + link_with: libcryptsetup, + c_args: [ + '-DNO_CRYPTSETUP_PATH', + ], + include_directories: includes_lib) + +generate_symbols_list = find_program('generate-symbols-list') +test_symbols_list_h = custom_target('test-symbols-list.h', + output: 'test-symbols-list.h', + input: [ + libcryptsetup_sym_path, + ], + # the scripts writes the output to stdout, capture and write to output file + capture: true, + command: [ + generate_symbols_list, + '@INPUT@', + ]) +all_symbols_test = executable('all-symbols-test', + [ + 'all-symbols-test.c', + test_symbols_list_h, + ], + dependencies: dl, + link_with: libcryptsetup, + c_args: [ + '-DNO_CRYPTSETUP_PATH', + ], + include_directories: includes_lib) + +fake_systemd_tpm_path = shared_library('fake_systemd_tpm_path', + [ + 'fake_systemd_tpm_path.c', + ], + name_prefix: '', + build_by_default: not enable_static) + +tests_env = environment() +tests_env.set('CRYPTSETUP_PATH', src_build_dir) +tests_env.set('LIBCRYPTSETUP_DIR', lib_build_dir) +tests_env.set('srcdir', meson.current_source_dir()) +tests_env.set('SSH_BUILD_DIR', tokens_ssh_build_dir) +tests_env.set('CRYPTSETUP_TESTS_RUN_IN_MESON', '1') + +valgrind_tests_env = tests_env +valgrind_tests_env.set('VALG', '1') + +add_test_setup('default', + is_default: true, + env: tests_env, + exclude_suites: [ 'valgrind-only' ] +) + +add_test_setup('valgrind', + env: valgrind_tests_env, + exclude_suites: [ 'not-in-valgrind' ] +) + +test('00modules-test', + find_program('./00modules-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + suite: 'not-in-valgrind', + priority: 9999) +test('api-test', + api_test, + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + suite: 'not-in-valgrind') +test('valg-api-test', + find_program('./valg-api.sh'), + args: [ './api-test'], + depends: [ api_test ], + workdir: meson.current_build_dir(), + env: 'INFOSTRING=api-test-000', + timeout: 14400, + is_parallel: false, + suite: 'valgrind-only') +test('api-test-2', + api_test_2, + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + suite: 'not-in-valgrind') +test('valg-api-test-2', + find_program('./valg-api.sh'), + args: [ './api-test-2'], + depends: [ api_test_2 ], + workdir: meson.current_build_dir(), + env: 'INFOSTRING=api-test-002', + timeout: 14400, + is_parallel: false, + suite: 'valgrind-only') +test('blockwise-compat-test', + find_program('./blockwise-compat-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + suite: 'not-in-valgrind', + depends: [ + unit_utils_io, + ]) +test('keyring-test', + find_program('./keyring-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + suite: 'not-in-valgrind') +test('vectors-test', + vectors_test, + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + suite: 'not-in-valgrind') +test('valg-vectors-test', + find_program('./valg-api.sh'), + args: [ './vectors-test' ], + depends: [ vectors_test ], + workdir: meson.current_build_dir(), + env: 'INFOSTRING=vectors-test', + timeout: 14400, + is_parallel: false, + suite: 'valgrind-only') +test('unit-wipe-test', + find_program('./unit-wipe-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + suite: 'not-in-valgrind', + depends: [ + unit_wipe, + ]) +test('unit-utils-crypt-test', + unit_utils_crypt_test, + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + suite: 'not-in-valgrind') +test('valg-unit-utils-crypt-test', + find_program('./valg-api.sh'), + args: [ './unit-utils-crypt-test' ], + depends: [ unit_utils_crypt_test ], + workdir: meson.current_build_dir(), + env: 'INFOSTRING=unit-utils-crypt-test', + timeout: 14400, + is_parallel: false, + suite: 'valgrind-only') + +if not enable_static + test('run-all-symbols', + find_program('./run-all-symbols'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + suite: 'not-in-valgrind', + depends: [ + all_symbols_test, + libcryptsetup, + ]) +endif + +if get_option('cryptsetup') + test('compat-args-test', + find_program('./compat-args-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + test_symbols_list_h, + ]) + test('compat-test', + find_program('./compat-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + differ, + ]) + test('compat-test2', + find_program('./compat-test2'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) + test('compat-test-opal', + find_program('./compat-test-opal'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) + test('loopaes-test', + find_program('./loopaes-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) + test('align-test', + find_program('./align-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) + test('align-test2', + find_program('./align-test2'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) + test('discards-test', + find_program('./discards-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) + test('mode-test', + find_program('./mode-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) + test('password-hash-test', + find_program('./password-hash-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) + test('tcrypt-compat-test', + find_program('./tcrypt-compat-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) + test('luks1-compat-test', + find_program('./luks1-compat-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) + test('device-test', + find_program('./device-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) + test('keyring-compat-test', + find_program('./keyring-compat-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) + test('luks2-validation-test', + find_program('./luks2-validation-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) + test('luks2-integrity-test', + find_program('./luks2-integrity-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) + test('bitlk-compat-test', + find_program('./bitlk-compat-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) + test('fvault2-compat-test', + find_program('./fvault2-compat-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) + test('reencryption-compat-test', + find_program('./reencryption-compat-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) + test('luks2-reencryption-test', + find_program('./luks2-reencryption-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) + test('luks2-reencryption-mangle-test', + find_program('./luks2-reencryption-mangle-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup, + ]) +endif + +if get_option('veritysetup') + test('verity-compat-test', + find_program('verity-compat-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + veritysetup, + ]) +endif + +if get_option('integritysetup') + test('integrity-compat-test', + find_program('integrity-compat-test'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + integritysetup, + ]) +endif + +if get_option('ssh-token') and not enable_static + test('ssh-test-plugin', + find_program('ssh-test-plugin'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + depends: [ + cryptsetup_ssh, + libcryptsetup_token_ssh, + ]) +endif + +if get_option('external-tokens') and not enable_static + test('systemd-test-plugin', + find_program('systemd-test-plugin'), + workdir: meson.current_build_dir(), + timeout: 14400, + is_parallel: false, + suite: 'not-in-valgrind', + depends: [ + fake_systemd_tpm_path, + ]) +endif + +subdir('fuzz') diff --git a/tests/mode-test b/tests/mode-test index 82171fb..81780cd 100755 --- a/tests/mode-test +++ b/tests/mode-test @@ -8,6 +8,7 @@ DEV_NAME=dmc_test HEADER_IMG=mode-test.img PASSWORD=3xrododenron PASSWORD1=$PASSWORD +KEY="7c0dc5dfd0c9191381d92e6ebb3b29e7f0dba53b0de132ae23f5726727173540" FAST_PBKDF2="--pbkdf pbkdf2 --pbkdf-force-iterations 1000" # cipher-chainmode-ivopts:ivmode @@ -17,8 +18,12 @@ IVMODES="null benbi plain plain64 essiv:sha256" LOOPDEV=$(losetup -f 2>/dev/null) -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi dmremove() { # device udevadm settle >/dev/null 2>&1 @@ -51,7 +56,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() @@ -184,4 +192,13 @@ done dmcrypt xchacha12,aes-adiantum-plain64 dmcrypt xchacha20,aes-adiantum-plain64 +echo -n "CAPI format:" +echo $PASSWORD | $CRYPTSETUP create -h sha256 -c 'capi:xts(aes)-plain64' -s 256 "$DEV_NAME"_tstdev /dev/mapper/$DEV_NAME || fail +$CRYPTSETUP close "$DEV_NAME"_tstdev || fail +echo $PASSWORD | $CRYPTSETUP create -h sha256 -c 'capi:xts(ecb(aes-generic))-plain64' -s 256 "$DEV_NAME"_tstdev /dev/mapper/$DEV_NAME 2>/dev/null && fail +dmsetup create "$DEV_NAME"_tstdev --table "0 8 crypt capi:xts(ecb(aes-generic))-plain64 $KEY 0 /dev/mapper/$DEV_NAME 0" || fail +$CRYPTSETUP status "$DEV_NAME"_tstdev 2>/dev/null | grep "type:" | grep -q "n/a" || fail +$CRYPTSETUP close "$DEV_NAME"_tstdev 2>/dev/null || fail +echo [OK] + cleanup diff --git a/tests/password-hash-test b/tests/password-hash-test index 6e3c78c..e777390 100755 --- a/tests/password-hash-test +++ b/tests/password-hash-test @@ -9,8 +9,12 @@ KEY_FILE=keyfile DEV2=$DEV_NAME"_x" -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi dmremove() { # device udevadm settle >/dev/null 2>&1 @@ -42,7 +46,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() diff --git a/tests/reencryption-compat-test b/tests/reencryption-compat-test index 453831d..68a8c1f 100755 --- a/tests/reencryption-compat-test +++ b/tests/reencryption-compat-test @@ -6,8 +6,12 @@ REENC_BIN=$CRYPTSETUP REENC="$REENC_BIN reencrypt" FAST_PBKDF="--pbkdf-force-iterations 1000 --pbkdf pbkdf2" -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi DEV_NAME=reenc9768 DEV_NAME2=reenc1273 @@ -33,7 +37,7 @@ function fips_mode() function del_scsi_device() { rmmod scsi_debug >/dev/null 2>&1 - sleep 2 + sleep 1 } function remove_mapping() @@ -68,7 +72,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() @@ -88,7 +95,7 @@ function add_scsi_device() { exit 77 fi - sleep 2 + sleep 1 SCSI_DEV="/dev/"$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /) [ -b $SCSI_DEV ] || fail "Cannot find $SCSI_DEV." } diff --git a/tests/run-all-symbols b/tests/run-all-symbols index 775d5bb..58a1ba6 100755 --- a/tests/run-all-symbols +++ b/tests/run-all-symbols @@ -1,7 +1,7 @@ #!/bin/bash -DIR=../.libs -FILE=$DIR/libcryptsetup.so +[ -z "$LIBCRYPTSETUP_DIR" ] && LIBCRYPTSETUP_DIR=../.libs +FILE=$LIBCRYPTSETUP_DIR/libcryptsetup.so function fail() { @@ -15,7 +15,7 @@ function skip() exit 77 } -test -d $DIR || fail "Directory $DIR is missing." +test -d $LIBCRYPTSETUP_DIR || fail "Directory $LIBCRYPTSETUP_DIR is missing." test -f $FILE || skip "WARNING: Shared $FILE is missing, test skipped." ./all-symbols-test $FILE $@ diff --git a/tests/ssh-test-plugin b/tests/ssh-test-plugin index 5b3966e..2475034 100755 --- a/tests/ssh-test-plugin +++ b/tests/ssh-test-plugin @@ -1,10 +1,10 @@ #!/bin/bash [ -z "$CRYPTSETUP_PATH" ] && { - TOKEN_PATH="./fake_token_path.so" - [ ! -f $TOKEN_PATH ] && { echo "Please compile $TOKEN_PATH."; exit 77; } - export LD_PRELOAD=$TOKEN_PATH CRYPTSETUP_PATH=".." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + SSH_BUILD_DIR="$PWD/../.libs" + fi } CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup CRYPTSETUP_SSH=$CRYPTSETUP_PATH/cryptsetup-ssh @@ -21,12 +21,24 @@ SSH_KEY_PATH="$HOME/sshtest-key" FAST_PBKDF_OPT="--pbkdf pbkdf2 --pbkdf-force-iterations 1000" -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_SSH_VALGRIND=../.libs/cryptsetup-ssh -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup + CRYPTSETUP_VALGRIND=$CRYPTSETUP + CRYPTSETUP_SSH=$CRYPTSETUP_PATH/../tokens/ssh/cryptsetup-ssh + CRYPTSETUP_SSH_VALGRIND=$CRYPTSETUP_SSH +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_SSH_VALGRIND=../.libs/cryptsetup-ssh + CRYPTSETUP_LIB_VALGRIND=../.libs +fi [ -z "$srcdir" ] && srcdir="." +[ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ] || { + # test runs on meson build + CRYPTSETUP_SSH="$CRYPTSETUP_PATH/../tokens/ssh/cryptsetup-ssh" +} + function remove_mapping() { [ -b /dev/mapper/$MAP ] && dmsetup remove --retry $MAP @@ -104,7 +116,9 @@ function valgrind_setup() command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." [ ! -f $CRYPTSETUP_SSH_VALGRIND ] && fail "Unable to get location of cryptsetup-ssh executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() @@ -152,6 +166,9 @@ check_dump() [ "$keyslot_dump" = "$keyslot" ] || fail " keyslot check from dump failed." } +if [ -n "$SSH_BUILD_DIR" ]; then + CUSTOM_TOKENS_PATH="--external-tokens-path $SSH_BUILD_DIR" +fi [ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped." [ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run && CRYPTSETUP_SSH=valgrind_run_ssh [ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped." @@ -174,17 +191,17 @@ ssh_check create_user ssh_setup -$CRYPTSETUP_SSH add $IMG --ssh-server $SSH_SERVER --ssh-user $USER --ssh-path $SSH_PATH --ssh-keypath $SSH_KEY_PATH +$CRYPTSETUP_SSH add $IMG --ssh-server $SSH_SERVER --ssh-user $USER --ssh-path $SSH_PATH --ssh-keypath $SSH_KEY_PATH $CUSTOM_TOKENS_PATH [ $? -ne 0 ] && fail "Failed to add SSH token to $IMG" -out=$($CRYPTSETUP luksDump $IMG) +out=$($CRYPTSETUP luksDump $CUSTOM_TOKENS_PATH $IMG) check_dump "$out" 0 echo "[OK]" echo -n "Activating using SSH token: " $CRYPTSETUP luksOpen --token-only --disable-external-tokens -r $IMG $MAP && fail "Tokens should be disabled" -$CRYPTSETUP luksOpen -r $IMG $MAP -q >/dev/null 2>&1 <&- +$CRYPTSETUP luksOpen $CUSTOM_TOKENS_PATH -r $IMG $MAP -q >/dev/null 2>&1 <&- [ $? -ne 0 ] && fail "Failed to open $IMG using SSH token" echo "[OK]" @@ -193,10 +210,10 @@ $CRYPTSETUP token remove --token-id 0 $IMG || fail "Failed to remove token" echo -n "Adding SSH token with --key-slot: " -$CRYPTSETUP_SSH add $IMG --ssh-server $SSH_SERVER --ssh-user $USER --ssh-path $SSH_PATH --ssh-keypath $SSH_KEY_PATH --key-slot 1 +$CRYPTSETUP_SSH add $IMG --ssh-server $SSH_SERVER --ssh-user $USER --ssh-path $SSH_PATH --ssh-keypath $SSH_KEY_PATH --key-slot 1 $CUSTOM_TOKENS_PATH [ $? -ne 0 ] && fail "Failed to add SSH token to $IMG" -out=$($CRYPTSETUP luksDump $IMG) +out=$($CRYPTSETUP luksDump $CUSTOM_TOKENS_PATH $IMG) check_dump "$out" 1 echo "[OK]" diff --git a/tests/systemd-test-plugin b/tests/systemd-test-plugin index 5f37324..7515f76 100755 --- a/tests/systemd-test-plugin +++ b/tests/systemd-test-plugin @@ -61,14 +61,51 @@ CRYPTENROLL_LD_PRELOAD="" # if CRYPTSETUP_PATH is defined, we run against installed binaries, # otherwise we compile systemd tokens from source +[ ! -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ] && { + bin_check git + bin_check meson + bin_check ninja + bin_check pkgconf + + INSTALL_PATH=$CRYPTSETUP_PATH/../external-tokens/install + mkdir -p $INSTALL_PATH + DESTDIR=$INSTALL_PATH meson install -C .. + PC_FILE="$(find $INSTALL_PATH -name 'libcryptsetup.pc')" + echo "INSTALL_PATH $INSTALL_PATH" + echo "PC_FILE $PC_FILE" + sed -i "s/^prefix=/prefix=${INSTALL_PATH//\//\\\/}/g" "$PC_FILE" + export PKG_CONFIG_PATH=$(dirname $PC_FILE) + + # systemd build system misses libcryptsetup.h if it is installed in non-default path + export CFLAGS="${CFLAGS:-} $(pkgconf --cflags libcryptsetup)" + + SYSTEMD_PATH=$CRYPTSETUP_PATH/../external-tokens/systemd + SYSTEMD_CRYPTENROLL=$SYSTEMD_PATH/build/systemd-cryptenroll + + mkdir -p $SYSTEMD_PATH + [ -d $SYSTEMD_PATH/.git ] || git clone --depth=1 https://github.com/systemd/systemd.git $SYSTEMD_PATH + cd $SYSTEMD_PATH + meson setup build/ -D tpm2=true -D libcryptsetup=true -D libcryptsetup-plugins=true || skip "Failed to configure systemd via meson, some dependencies are probably missing." + ninja -C build/ systemd-cryptenroll libcryptsetup-token-systemd-tpm2.so || skip "Failed to build systemd." + + CRYPTSETUP_TOKENS_PATH=$CRYPTSETUP_PATH/../tokens/ssh + + cd $CRYPTSETUP_PATH/../tests + cp $SYSTEMD_PATH/build/libcryptsetup-token-*.so $CRYPTSETUP_TOKENS_PATH + cp $SYSTEMD_PATH/build/src/shared/*.so $CRYPTSETUP_TOKENS_PATH + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$CRYPTSETUP_PATH/../tests" + + CRYPTENROLL_LD_PRELOAD="$CRYPTSETUP_PATH/../lib/libcryptsetup.so" + + echo "CRYPTENROLL_LD_PRELOAD $CRYPTENROLL_LD_PRELOAD" +} + [ -z "$CRYPTSETUP_PATH" ] && { bin_check git bin_check meson bin_check ninja bin_check pkgconf - TOKEN_PATH=fake_token_path.so - [ -f $TOKEN_PATH ] || skip "Please compile $TOKEN_PATH." INSTALL_PATH=$(pwd)/external-tokens/install make -C .. install DESTDIR=$INSTALL_PATH PC_FILE="$(find $INSTALL_PATH -name 'libcryptsetup.pc')" @@ -83,16 +120,17 @@ CRYPTENROLL_LD_PRELOAD="" SYSTEMD_CRYPTENROLL=$SYSTEMD_PATH/build/systemd-cryptenroll mkdir -p $SYSTEMD_PATH - [ "$(ls -A $SYSTEMD_PATH)" ] || git clone --depth=1 https://github.com/systemd/systemd.git $SYSTEMD_PATH + [ -d $SYSTEMD_PATH/.git ] || git clone --depth=1 https://github.com/systemd/systemd.git $SYSTEMD_PATH cd $SYSTEMD_PATH - meson -D tpm2=true -D libcryptsetup=true -D libcryptsetup-plugins=true build/ || skip "Failed to configure systemd via meson, some dependencies are probably missing." + meson setup build/ -D tpm2=true -D libcryptsetup=true -D libcryptsetup-plugins=true || skip "Failed to configure systemd via meson, some dependencies are probably missing." ninja -C build/ systemd-cryptenroll libcryptsetup-token-systemd-tpm2.so || skip "Failed to build systemd." + CRYPTSETUP_TOKENS_PATH=$CRYPTSETUP_PATH/.libs + cd $CRYPTSETUP_PATH/tests - cp $SYSTEMD_PATH/build/libcryptsetup-token-*.so ../.libs/ - cp $SYSTEMD_PATH/build/src/shared/*.so ../.libs/ + cp $SYSTEMD_PATH/build/libcryptsetup-token-*.so $CRYPTSETUP_TOKENS_PATH + cp $SYSTEMD_PATH/build/src/shared/*.so $CRYPTSETUP_TOKENS_PATH - export LD_PRELOAD="${LD_PRELOAD-}:$CRYPTSETUP_PATH/tests/$TOKEN_PATH" CRYPTENROLL_LD_PRELOAD="$CRYPTSETUP_PATH/.libs/libcryptsetup.so" } CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup @@ -115,7 +153,11 @@ CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup echo "Virtual TPM set up at $TPM_PATH" } +if [ -n "$SSH_BUILD_DIR" ]; then + CUSTOM_TOKENS_PATH="--external-tokens-path $SSH_BUILD_DIR" +fi FAKE_TPM_PATH="$(pwd)/fake_systemd_tpm_path.so" +[ ! -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ] && FAKE_TPM_PATH="$CRYPTSETUP_PATH/../tests/fake_systemd_tpm_path.so" [ -f $FAKE_TPM_PATH ] || skip "Please compile $FAKE_TPM_PATH." export LD_PRELOAD="$LD_PRELOAD:$FAKE_TPM_PATH" @@ -128,23 +170,23 @@ echo $PASSWD | $CRYPTSETUP luksFormat --type luks2 $FAST_PBKDF_OPT $IMG --force- echo "Enrolling the device to TPM 2 using systemd-cryptenroll.." LD_PRELOAD="$LD_PRELOAD:$CRYPTENROLL_LD_PRELOAD" PASSWORD="$PASSWD" $SYSTEMD_CRYPTENROLL $IMG --tpm2-device=$TPM_PATH >/dev/null 2>&1 -$CRYPTSETUP luksDump $IMG | grep -q "tpm2-blob" || fail "Failed to dump $IMG using systemd_tpm2 token (no tpm2-blob in output)." +$CRYPTSETUP luksDump --external-tokens-path $CRYPTSETUP_TOKENS_PATH $IMG | grep -q "tpm2-blob" || fail "Failed to dump $IMG using systemd_tpm2 token (no tpm2-blob in output)." echo "Activating the device via TPM2 external token.." -$CRYPTSETUP open --token-only $IMG $MAP >/dev/null 2>&1 || fail "Failed to open $IMG using systemd_tpm2 token." +$CRYPTSETUP open --external-tokens-path $CRYPTSETUP_TOKENS_PATH --token-only $IMG $MAP >/dev/null 2>&1 || fail "Failed to open $IMG using systemd_tpm2 token." $CRYPTSETUP close $MAP >/dev/null 2>&1 || fail "Failed to close $MAP." echo "Adding passphrase via TPM2 token.." -echo $PASSWD2 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT $IMG --force-password -q --token-only >/dev/null 2>&1 || fail "Failed to add passphrase by tpm2 token." +echo $PASSWD2 | $CRYPTSETUP luksAddKey --external-tokens-path $CRYPTSETUP_TOKENS_PATH $FAST_PBKDF_OPT $IMG --force-password -q --token-only >/dev/null 2>&1 || fail "Failed to add passphrase by tpm2 token." echo $PASSWD2 | $CRYPTSETUP open $IMG --test-passphrase --disable-external-tokens >/dev/null 2>&1 || fail "Failed to test passphrase added by tpm2 token." echo "Exporting and removing TPM2 token.." EXPORTED_TOKEN=$($CRYPTSETUP token export $IMG --token-id 0) $CRYPTSETUP token remove $IMG --token-id 0 -$CRYPTSETUP open $IMG --test-passphrase --token-only >/dev/null 2>&1 && fail "Activating without passphrase should fail after TPM2 token removal." +$CRYPTSETUP open --external-tokens-path $CRYPTSETUP_TOKENS_PATH $IMG --test-passphrase --token-only >/dev/null 2>&1 && fail "Activating without passphrase should fail after TPM2 token removal." echo "Re-importing TPM2 token.." echo $EXPORTED_TOKEN | $CRYPTSETUP token import $IMG --token-id 0 || fail "Failed to re-import deleted token." -$CRYPTSETUP open $IMG --test-passphrase --token-only >/dev/null 2>&1 || fail "Failed to activate after re-importing deleted token." +$CRYPTSETUP open --external-tokens-path $CRYPTSETUP_TOKENS_PATH $IMG --test-passphrase --token-only >/dev/null 2>&1 || fail "Failed to activate after re-importing deleted token." cleanup exit 0 diff --git a/tests/tcrypt-compat-test b/tests/tcrypt-compat-test index c0fc50a..0708b32 100755 --- a/tests/tcrypt-compat-test +++ b/tests/tcrypt-compat-test @@ -11,8 +11,12 @@ PASSWORD_HIDDEN="bbbbbbbbbbbb" PASSWORD_72C="aaaaaaaaaaaabbbbbbbbbbbbccccccccccccddddddddddddeeeeeeeeeeeeffffffffffff" PIM=1234 -CRYPTSETUP_VALGRIND=../.libs/cryptsetup -CRYPTSETUP_LIB_VALGRIND=../.libs +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + CRYPTSETUP_VALGRIND=$CRYPTSETUP +else + CRYPTSETUP_VALGRIND=../.libs/cryptsetup + CRYPTSETUP_LIB_VALGRIND=../.libs +fi [ -z "$srcdir" ] && srcdir="." @@ -54,12 +58,12 @@ function test_one() # cipher mode keysize rm_pattern fi } -function test_kdf() # hash +function test_kdf() # hash img_hash { $CRYPTSETUP benchmark -h "$1" >/dev/null 2>&1 if [ $? -ne 0 ] ; then echo "pbkdf2-$1 [N/A]" - IMGS=$(ls $TST_DIR/[tv]c* | grep "$1") + IMGS=$(ls $TST_DIR/[tv]c* | grep "$2") [ -n "$IMGS" ] && rm $IMGS else echo "pbkdf2-$1 [OK]" @@ -78,11 +82,12 @@ function test_required() command -v blkid >/dev/null || skip "blkid tool required, test skipped." echo "REQUIRED KDF TEST" - test_kdf sha256 - test_kdf sha512 - test_kdf ripemd160 - test_kdf whirlpool - test_kdf stribog512 + test_kdf sha256 sha256 + test_kdf sha512 sha512 + test_kdf blake2s-256 blake2 + test_kdf ripemd160 ripemd160 + test_kdf whirlpool whirlpool + test_kdf stribog512 stribog echo "REQUIRED CIPHERS TEST" test_one aes cbc 256 cbc-aes @@ -114,7 +119,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable." - export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() diff --git a/tests/tcrypt-images.tar.xz b/tests/tcrypt-images.tar.xz Binary files differindex 1841870..5ccef08 100644 --- a/tests/tcrypt-images.tar.xz +++ b/tests/tcrypt-images.tar.xz diff --git a/tests/test_utils.c b/tests/test_utils.c index 97c62a0..d06e738 100644 --- a/tests/test_utils.c +++ b/tests/test_utils.c @@ -1,8 +1,8 @@ /* * cryptsetup library API test utilities * - * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2023 Milan Broz + * Copyright (C) 2009-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2024 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -201,25 +201,39 @@ int fips_mode(void) */ int create_dmdevice_over_loop(const char *dm_name, const uint64_t size) { + int r; + + r = create_dmdevice_over_device(dm_name, THE_LOOP_DEV, size, t_dev_offset); + if (r != 0) + return r; + + t_dev_offset += size; + + return r; +} + +/* + * Creates dm-linear target over the desired block device. + */ +int create_dmdevice_over_device(const char *dm_name, const char *device, uint64_t size, uint64_t offset) +{ char cmd[128]; int r; uint64_t r_size; - if (t_device_size(THE_LOOP_DEV, &r_size) < 0 || r_size <= t_dev_offset || !size) + if (!device || t_device_size(device, &r_size) < 0 || r_size <= offset || !size) return -1; - if ((r_size - t_dev_offset) < size) { - printf("No enough space on backing loop device\n."); + if ((r_size - offset) < size) { + printf("No enough space on device %s\n.", device); return -2; } r = snprintf(cmd, sizeof(cmd), "dmsetup create %s --table \"0 %" PRIu64 " linear %s %" PRIu64 "\"", - dm_name, size, THE_LOOP_DEV, t_dev_offset); + dm_name, size, device, offset); if (r < 0 || (size_t)r >= sizeof(cmd)) return -3; - if (!(r = _system(cmd, 1))) - t_dev_offset += size; - return r; + return _system(cmd, 1); } __attribute__((format(printf, 3, 4))) @@ -450,12 +464,12 @@ void global_log_callback(int level, const char *msg, void *usrptr __attribute__( len = strlen(global_log); - if (len + strlen(msg) > sizeof(global_log)) { + if (len + strlen(msg) >= sizeof(global_log)) { printf("Log buffer is too small, fix the test.\n"); return; } - strncat(global_log, msg, sizeof(global_log) - len); + strncat(global_log, msg, sizeof(global_log) - len - 1); global_lines++; if (level == CRYPT_LOG_ERROR) { len = strlen(msg); diff --git a/tests/unit-utils-crypt.c b/tests/unit-utils-crypt.c index 4ab3c96..22b8788 100644 --- a/tests/unit-utils-crypt.c +++ b/tests/unit-utils-crypt.c @@ -1,7 +1,7 @@ /* * cryptsetup crypto name and hex conversion helper test vectors * - * Copyright (C) 2022-2023 Milan Broz + * Copyright (C) 2022-2024 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/tests/unit-utils-io.c b/tests/unit-utils-io.c index 3bfc762..642f778 100644 --- a/tests/unit-utils-io.c +++ b/tests/unit-utils-io.c @@ -1,7 +1,7 @@ /* * simple unit test for utils_io.c (blockwise low level functions) * - * Copyright (C) 2018-2023 Red Hat, Inc. All rights reserved. + * Copyright (C) 2018-2024 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/tests/unit-wipe-test b/tests/unit-wipe-test index 4d0a078..a898354 100755 --- a/tests/unit-wipe-test +++ b/tests/unit-wipe-test @@ -41,7 +41,7 @@ function add_device() if [ $? -ne 0 ] ; then skip "This kernel seems to not support proper scsi_debug module." fi - grep -q scsi_debug /sys/block/*/device/model || sleep 2 + sleep 1 DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /) DEV="/dev/$DEV" [ -b $DEV ] || fail "Cannot find $DEV." diff --git a/tests/unit-wipe.c b/tests/unit-wipe.c index c3019c7..d381a83 100644 --- a/tests/unit-wipe.c +++ b/tests/unit-wipe.c @@ -1,7 +1,7 @@ /* * unit test helper for crypt_wipe API call * - * Copyright (C) 2022-2023 Milan Broz + * Copyright (C) 2022-2024 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/tests/verity-compat-test b/tests/verity-compat-test index 8a28a12..82c49d3 100755 --- a/tests/verity-compat-test +++ b/tests/verity-compat-test @@ -2,8 +2,13 @@ [ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".." VERITYSETUP=$CRYPTSETUP_PATH/veritysetup -VERITYSETUP_VALGRIND=../.libs/veritysetup -VERITYSETUP_LIB_VALGRIND=../.libs + +if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + VERITYSETUP_VALGRIND=$VERITYSETUP +else + VERITYSETUP_VALGRIND=../.libs/veritysetup + VERITYSETUP_LIB_VALGRIND=../.libs +fi DEV_NAME=verity3273 DEV_NAME2=verity3273x @@ -304,7 +309,10 @@ function valgrind_setup() { command -v valgrind >/dev/null || fail "Cannot find valgrind." [ ! -f $VERITYSETUP_VALGRIND ] && fail "Unable to get location of veritysetup executable." - export LD_LIBRARY_PATH="$VERITYSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + [ ! -f valg.sh ] && fail "Unable to get location of valg runner script." + if [ -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then + export LD_LIBRARY_PATH="$VERITYSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH" + fi } function valgrind_run() |