Imported Upstream version 2.6.1
[platform/upstream/cryptsetup.git] / tests / api-test-2.c
index c0bfc9a..824ae65 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * cryptsetup library LUKS2 API check functions
  *
- * Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2009-2021 Milan Broz
- * Copyright (C) 2016-2021 Ondrej Kozina
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ * Copyright (C) 2016-2023 Ondrej Kozina
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -41,11 +41,9 @@ typedef int32_t key_serial_t;
 #endif
 
 #include "api_test.h"
-#include "luks.h"
+#include "luks1/luks.h"
 #include "libcryptsetup.h"
 
-#define DMDIR "/dev/mapper/"
-
 #define DEVICE_1_UUID "28632274-8c8a-493f-835b-da802e1c576b"
 #define DEVICE_EMPTY_name "crypt_zero"
 #define DEVICE_EMPTY DMDIR DEVICE_EMPTY_name
@@ -76,8 +74,8 @@ typedef int32_t key_serial_t;
 #define KEYFILE2 "key2.file"
 #define KEY2 "0123456789abcdef"
 
-#define PASSPHRASE "blabla"
-#define PASSPHRASE1 "albalb"
+#define PASSPHRASE "blablabl"
+#define PASSPHRASE1 "albalbal"
 
 #define DEVICE_TEST_UUID "12345678-1234-1234-1234-123456789abc"
 
@@ -109,25 +107,15 @@ typedef int32_t key_serial_t;
 #define CONV_L2_512_DET_FULL "l2_512b_det_full"
 #define CONV_L1_256_LEGACY "l1_256b_legacy_offset"
 #define CONV_L1_256_UNMOVABLE "l1_256b_unmovable"
-#define PASS0 "aaa"
-#define PASS1 "hhh"
-#define PASS2 "ccc"
-#define PASS3 "ddd"
-#define PASS4 "eee"
-#define PASS5 "fff"
-#define PASS6 "ggg"
-#define PASS7 "bbb"
-#define PASS8 "iii"
-
-/* Allow to run without config.h */
-#ifndef DEFAULT_LUKS1_HASH
-  #define DEFAULT_LUKS1_HASH "sha256"
-  #define DEFAULT_LUKS1_ITER_TIME 2000
-  #define DEFAULT_LUKS2_ITER_TIME 2000
-  #define DEFAULT_LUKS2_MEMORY_KB 1048576
-  #define DEFAULT_LUKS2_PARALLEL_THREADS 4
-  #define DEFAULT_LUKS2_PBKDF "argon2i"
-#endif
+#define PASS0 "aaablabl"
+#define PASS1 "hhhblabl"
+#define PASS2 "cccblabl"
+#define PASS3 "dddblabl"
+#define PASS4 "eeeblabl"
+#define PASS5 "fffblabl"
+#define PASS6 "gggblabl"
+#define PASS7 "bbbblabl"
+#define PASS8 "iiiblabl"
 
 static int _fips_mode = 0;
 
@@ -145,6 +133,26 @@ unsigned int test_progress_steps;
 
 struct crypt_device *cd = NULL, *cd2 = NULL;
 
+static const char *default_luks1_hash = NULL;
+static uint32_t default_luks1_iter_time = 0;
+
+static const char *default_luks2_pbkdf = NULL;
+static uint32_t default_luks2_iter_time = 0;
+static uint32_t default_luks2_memory_kb = 0;
+static uint32_t default_luks2_parallel_threads = 0;
+
+static struct crypt_pbkdf_type min_pbkdf2 = {
+       .type = "pbkdf2",
+       .iterations = 1000,
+       .flags = CRYPT_PBKDF_NO_BENCHMARK
+}, min_argon2 = {
+       .type = "argon2id",
+       .iterations = 4,
+       .max_memory_kb = 32,
+       .parallel_threads = 1,
+       .flags = CRYPT_PBKDF_NO_BENCHMARK
+};
+
 // Helpers
 
 static unsigned cpus_online(void)
@@ -167,14 +175,14 @@ static uint32_t adjusted_pbkdf_memory(void)
        uint64_t memory_kb;
 
        if (pagesize <= 0 || pages <= 0)
-               return DEFAULT_LUKS2_MEMORY_KB;
+               return default_luks2_memory_kb;
 
        memory_kb = pagesize / 1024 * pages / 2;
 
-       if (memory_kb < DEFAULT_LUKS2_MEMORY_KB)
+       if (memory_kb < default_luks2_memory_kb)
                return (uint32_t)memory_kb;
 
-       return DEFAULT_LUKS2_MEMORY_KB;
+       return default_luks2_memory_kb;
 }
 
 static unsigned _min(unsigned a, unsigned b)
@@ -191,6 +199,11 @@ static int get_luks2_offsets(int metadata_device,
        struct crypt_device *cd = NULL;
        static uint64_t default_header_size = 0;
 
+       if (r_header_size)
+               *r_header_size = 0;
+       if (r_payload_offset)
+               *r_payload_offset = 0;
+
        if (!default_header_size) {
                if (crypt_init(&cd, THE_LOOP_DEV))
                        return -EINVAL;
@@ -225,6 +238,28 @@ static int get_luks2_offsets(int metadata_device,
        return 0;
 }
 
+static bool get_luks_pbkdf_defaults(void)
+{
+       const struct crypt_pbkdf_type *pbkdf_defaults = crypt_get_pbkdf_default(CRYPT_LUKS1);
+
+       if (!pbkdf_defaults)
+               return false;
+
+       default_luks1_hash = pbkdf_defaults->hash;
+       default_luks1_iter_time = pbkdf_defaults->time_ms;
+
+       pbkdf_defaults = crypt_get_pbkdf_default(CRYPT_LUKS2);
+       if (!pbkdf_defaults)
+               return false;
+
+       default_luks2_pbkdf = pbkdf_defaults->type;
+       default_luks2_iter_time = pbkdf_defaults->time_ms;
+       default_luks2_memory_kb = pbkdf_defaults->max_memory_kb;
+       default_luks2_parallel_threads = pbkdf_defaults->parallel_threads;
+
+       return true;
+}
+
 static void _remove_keyfiles(void)
 {
        remove(KEYFILE1);
@@ -344,13 +379,17 @@ static int _setup(void)
        char cmd[128];
 
        test_loop_file = strdup(THE_LFILE_TEMPLATE);
+       if (!test_loop_file)
+               return 1;
+
        if ((fd=mkstemp(test_loop_file)) == -1) {
                printf("cannot create temporary file with template %s\n", test_loop_file);
                return 1;
        }
        close(fd);
-       snprintf(cmd, sizeof(cmd), "dd if=/dev/zero of=%s bs=%d count=%d 2>/dev/null",
-                test_loop_file, SECTOR_SIZE, TST_LOOP_FILE_SIZE);
+       if (snprintf(cmd, sizeof(cmd), "dd if=/dev/zero of=%s bs=%d count=%d 2>/dev/null",
+           test_loop_file, TST_SECTOR_SIZE, TST_LOOP_FILE_SIZE) < 0)
+               return 1;
        if (_system(cmd, 1))
                return 1;
 
@@ -358,19 +397,26 @@ static int _setup(void)
        close(fd);
 
        tmp_file_1 = strdup(THE_LFILE_TEMPLATE);
+       if (!tmp_file_1)
+               return 1;
+
        if ((fd=mkstemp(tmp_file_1)) == -1) {
                printf("cannot create temporary file with template %s\n", tmp_file_1);
                return 1;
        }
        close(fd);
-       snprintf(cmd, sizeof(cmd), "dd if=/dev/zero of=%s bs=%d count=%d 2>/dev/null",
-                tmp_file_1, SECTOR_SIZE, 10);
+       if (snprintf(cmd, sizeof(cmd), "dd if=/dev/zero of=%s bs=%d count=%d 2>/dev/null",
+           tmp_file_1, TST_SECTOR_SIZE, 10) < 0)
+               return 1;
        if (_system(cmd, 1))
                return 1;
 
        _system("dmsetup create " DEVICE_EMPTY_name " --table \"0 10000 zero\"", 1);
        _system("dmsetup create " DEVICE_ERROR_name " --table \"0 10000 error\"", 1);
 
+       if (t_set_readahead(DEVICE_ERROR, 0))
+               printf("cannot set read ahead on device %s\n", DEVICE_ERROR);
+
        _system(" [ ! -e " IMAGE1 " ] && xz -dk " IMAGE1 ".xz", 1);
        fd = loop_attach(&DEVICE_1, IMAGE1, 0, 0, &ro);
        close(fd);
@@ -383,11 +429,11 @@ static int _setup(void)
 
        _system("dd if=/dev/zero of=" IMAGE_EMPTY_SMALL_2 " bs=512 count=2050 2>/dev/null", 1);
 
-       _system(" [ ! -e " NO_REQS_LUKS2_HEADER " ] && xz -dk " NO_REQS_LUKS2_HEADER ".xz", 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);
 
-       _system(" [ ! -e " REQS_LUKS2_HEADER " ] && xz -dk " REQS_LUKS2_HEADER ".xz", 1);
+       _system(" [ ! -e " REQS_LUKS2_HEADER " ] && tar xJf " REQS_LUKS2_HEADER ".tar.xz", 1);
        fd = loop_attach(&DEVICE_5, REQS_LUKS2_HEADER, 0, 0, &ro);
        close(fd);
 
@@ -398,13 +444,13 @@ static int _setup(void)
 
        _system(" [ ! -d " CONV_DIR " ] && tar xJf " CONV_DIR ".tar.xz 2>/dev/null", 1);
 
-       if (_system("modprobe dm-crypt", 1))
+       if (_system("modprobe dm-crypt >/dev/null 2>&1", 1))
                return 1;
 
        if (t_dm_check_versions())
                return 1;
 
-       _system("rmmod dm-crypt", 0);
+       _system("rmmod dm-crypt >/dev/null 2>&1", 0);
 
        _fips_mode = fips_mode();
        if (_debug)
@@ -413,9 +459,25 @@ static int _setup(void)
        /* Use default log callback */
        crypt_set_log_callback(NULL, &global_log_callback, NULL);
 
+       if (!get_luks_pbkdf_defaults())
+               return 1;
+
+       min_pbkdf2.hash = min_argon2.hash = default_luks1_hash;
+
        return 0;
 }
 
+static int set_fast_pbkdf(struct crypt_device *cd)
+{
+       const struct crypt_pbkdf_type *pbkdf = &min_argon2;
+
+       /* Cannot use Argon2 in FIPS */
+       if (_fips_mode)
+               pbkdf = &min_pbkdf2;
+
+       return crypt_set_pbkdf_type(cd, pbkdf);
+}
+
 #ifdef KERNEL_KEYRING
 static key_serial_t add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t keyring)
 {
@@ -461,11 +523,11 @@ static int _drop_keyring_key(struct crypt_device *cd, int segment)
 }
 #endif
 
-static int test_open(struct crypt_device *cd,
-                    int token,
-                    char **buffer,
-                    size_t *buffer_len,
-                    void *usrptr)
+static int test_open(struct crypt_device *cd __attribute__((unused)),
+       int token __attribute__((unused)),
+       char **buffer,
+       size_t *buffer_len,
+       void *usrptr)
 {
        const char *str = (const char *)usrptr;
 
@@ -477,7 +539,7 @@ static int test_open(struct crypt_device *cd,
        return 0;
 }
 
-static int test_validate(struct crypt_device *cd, const char *json)
+static int test_validate(struct crypt_device *cd __attribute__((unused)), const char *json)
 {
        return (strstr(json, "magic_string") == NULL);
 }
@@ -542,12 +604,6 @@ static void SuspendDevice(void)
        size_t key_size;
        int suspend_status;
        uint64_t r_payload_offset;
-       const struct crypt_pbkdf_type fast_pbkdf = {
-               .type = "pbkdf2",
-               .hash = "sha256",
-               .iterations = 1000,
-               .flags = CRYPT_PBKDF_NO_BENCHMARK
-       };
 
        OK_(crypt_init(&cd, DEVICE_1));
        OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
@@ -617,7 +673,7 @@ static void SuspendDevice(void)
 
        /* Resume device with cipher_null */
        OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
-       OK_(crypt_set_pbkdf_type(cd, &fast_pbkdf));
+       OK_(set_fast_pbkdf(cd));
        OK_(crypt_format(cd, CRYPT_LUKS2, "cipher_null", "ecb", NULL, key, key_size, NULL));
        EQ_(0, crypt_keyslot_add_by_volume_key(cd, 0, key, key_size, PASSPHRASE, strlen(PASSPHRASE)));
        OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
@@ -653,10 +709,10 @@ static void AddDeviceLuks2(void)
        };
        char key[128], key2[128], key3[128];
 
-       const char *passphrase = "blabla", *passphrase2 = "nsdkFI&Y#.sd";
-       const char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
-       const char *mk_hex2 = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1e";
-       size_t key_size = strlen(mk_hex) / 2;
+       const char *tmp_buf, *passphrase = PASSPHRASE, *passphrase2 = "nsdkFI&Y#.sd";
+       const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+       const char *vk_hex2 = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1e";
+       size_t key_size = strlen(vk_hex) / 2;
        const char *cipher = "aes";
        const char *cipher_mode = "cbc-essiv:sha256";
        uint64_t r_payload_offset, r_header_size, r_size_1;
@@ -668,8 +724,8 @@ static void AddDeviceLuks2(void)
                pbkdf.max_memory_kb = 0;
        }
 
-       crypt_decode_key(key, mk_hex, key_size);
-       crypt_decode_key(key3, mk_hex2, key_size);
+       crypt_decode_key(key, vk_hex, key_size);
+       crypt_decode_key(key3, vk_hex2, key_size);
 
        // init test devices
        OK_(get_luks2_offsets(0, 0, 0, &r_header_size, &r_payload_offset));
@@ -685,6 +741,7 @@ static void AddDeviceLuks2(void)
 
        // test payload_offset = 0 for encrypted device with external header device
        OK_(crypt_init(&cd, DMDIR H_DEVICE));
+       OK_(set_fast_pbkdf(cd));
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
        EQ_(crypt_get_data_offset(cd), 0);
        CRYPT_FREE(cd);
@@ -694,6 +751,7 @@ static void AddDeviceLuks2(void)
 
        // test payload_offset = 0. format() should look up alignment offset from device topology
        OK_(crypt_init(&cd, DEVICE_2));
+       OK_(set_fast_pbkdf(cd));
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
        OK_(!(crypt_get_data_offset(cd) > 0));
        CRYPT_FREE(cd);
@@ -701,6 +759,7 @@ static void AddDeviceLuks2(void)
        // set_data_offset has priority, alignment must be 0 or must be compatible
        params.data_alignment = 0;
        OK_(crypt_init(&cd, DEVICE_2));
+       OK_(set_fast_pbkdf(cd));
        OK_(crypt_set_data_offset(cd, OFFSET_8M));
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
        EQ_(crypt_get_data_offset(cd), OFFSET_8M);
@@ -715,6 +774,7 @@ static void AddDeviceLuks2(void)
 
        params.data_alignment = OFFSET_4M;
        OK_(crypt_init(&cd, DEVICE_2));
+       OK_(set_fast_pbkdf(cd));
        FAIL_(crypt_set_data_offset(cd, OFFSET_2M + 1), "Not aligned to 4096"); // must be aligned to 4k
        OK_(crypt_set_data_offset(cd, OFFSET_2M));
        FAIL_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params), "Alignment not compatible");
@@ -734,23 +794,26 @@ static void AddDeviceLuks2(void)
 
        // 1 sector less than required
        OK_(crypt_init(&cd, DMDIR L_DEVICE_WRONG));
+       OK_(set_fast_pbkdf(cd));
        FAIL_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params), "Device too small");
        CRYPT_FREE(cd);
 
        // 0 sectors for encrypted area
        OK_(crypt_init(&cd, DMDIR L_DEVICE_0S));
+       OK_(set_fast_pbkdf(cd));
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
        FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "Encrypted area too small");
        CRYPT_FREE(cd);
 
        // 1 sector for encrypted area
        OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+       OK_(set_fast_pbkdf(cd));
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
        EQ_(crypt_get_data_offset(cd), r_payload_offset);
        OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
        GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
        OK_(t_device_size(DMDIR CDEVICE_1, &r_size_1));
-       EQ_(r_size_1, SECTOR_SIZE);
+       EQ_(r_size_1, TST_SECTOR_SIZE);
        OK_(crypt_deactivate(cd, CDEVICE_1));
        EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
        // restrict format only to empty context
@@ -769,6 +832,7 @@ static void AddDeviceLuks2(void)
 
        // generate keyslot material at the end of luks header
        OK_(crypt_init(&cd, DMDIR H_DEVICE));
+       OK_(set_fast_pbkdf(cd));
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
        EQ_((int)key_size, crypt_get_volume_key_size(cd));
        EQ_(crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, passphrase, strlen(passphrase)), 7);
@@ -787,6 +851,7 @@ static void AddDeviceLuks2(void)
 
        CRYPT_FREE(cd);
        OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, DMDIR H_DEVICE));
+       OK_(set_fast_pbkdf(cd));
        FAIL_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params), "Context is already formatted");
        GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
        CRYPT_FREE(cd);
@@ -805,12 +870,15 @@ static void AddDeviceLuks2(void)
 
        // test uuid mismatch and _init_by_name_and_header
        OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+       OK_(set_fast_pbkdf(cd));
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
        OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+       EQ_(0, crypt_header_is_detached(cd));
        CRYPT_FREE(cd);
        params.data_alignment = 0;
        params.data_device = DEVICE_2;
        OK_(crypt_init(&cd, DMDIR H_DEVICE));
+       OK_(set_fast_pbkdf(cd));
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
        CRYPT_FREE(cd);
        // there we've got uuid mismatch
@@ -821,11 +889,13 @@ static void AddDeviceLuks2(void)
        FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, key, key_size, 0), "Device is active");
        EQ_(crypt_status(cd, CDEVICE_2), CRYPT_INACTIVE);
        OK_(crypt_deactivate(cd, CDEVICE_1));
+       EQ_(crypt_header_is_detached(cd), 1);
        CRYPT_FREE(cd);
 
        params.data_device = NULL;
 
        OK_(crypt_init(&cd, DEVICE_2));
+       OK_(set_fast_pbkdf(cd));
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
 
        // even with no keyslots defined it can be activated by volume key
@@ -841,7 +911,6 @@ static void AddDeviceLuks2(void)
        GE_(crypt_status(cd, CDEVICE_2), CRYPT_ACTIVE);
        OK_(crypt_deactivate(cd, CDEVICE_2));
 
-       crypt_set_iteration_time(cd, 1);
        EQ_(1, crypt_keyslot_add_by_volume_key(cd, 1, key, key_size, KEY1, strlen(KEY1)));
        OK_(prepare_keyfile(KEYFILE1, KEY1, strlen(KEY1)));
        OK_(prepare_keyfile(KEYFILE2, KEY2, strlen(KEY2)));
@@ -868,7 +937,7 @@ static void AddDeviceLuks2(void)
        key[1] = ~key[1];
        FAIL_(crypt_keyslot_add_by_volume_key(cd, 6, key, key_size, passphrase, strlen(passphrase)), "key mismatch");
        key[1] = ~key[1];
-       EQ_(6, crypt_keyslot_add_by_volume_key(cd, 6, key, key_size, passphrase, strlen(passphrase)));
+       EQ_(6, crypt_keyslot_add_by_volume_key(cd, 6, key, key_size, passphrase2, strlen(passphrase2)));
        EQ_(CRYPT_SLOT_ACTIVE, crypt_keyslot_status(cd, 6));
 
        FAIL_(crypt_keyslot_destroy(cd, 8), "invalid keyslot");
@@ -878,6 +947,8 @@ static void AddDeviceLuks2(void)
        EQ_(CRYPT_SLOT_INACTIVE, crypt_keyslot_status(cd, 7));
        EQ_(CRYPT_SLOT_ACTIVE_LAST, crypt_keyslot_status(cd, 6));
 
+       EQ_(6, crypt_keyslot_change_by_passphrase(cd, 6, CRYPT_ANY_SLOT, passphrase2, strlen(passphrase2), passphrase, strlen(passphrase)));
+       EQ_(CRYPT_SLOT_ACTIVE_LAST, crypt_keyslot_status(cd, 6));
        EQ_(7, crypt_keyslot_change_by_passphrase(cd, 6, 7, passphrase, strlen(passphrase), passphrase2, strlen(passphrase2)));
        EQ_(CRYPT_SLOT_ACTIVE_LAST, crypt_keyslot_status(cd, 7));
        EQ_(7, crypt_activate_by_passphrase(cd, NULL, 7, passphrase2, strlen(passphrase2), 0));
@@ -898,6 +969,13 @@ static void AddDeviceLuks2(void)
        OK_(!(global_lines != 0));
        reset_log();
 
+       FAIL_(crypt_dump_json(cd, NULL, 42), "flags be used later");
+       OK_(crypt_dump_json(cd, NULL, 0));
+       OK_(!(global_lines != 0));
+       reset_log();
+       OK_(crypt_dump_json(cd, &tmp_buf, 0));
+       OK_(!(tmp_buf && strlen(tmp_buf) != 0));
+
        FAIL_(crypt_set_uuid(cd, "blah"), "wrong UUID format");
        OK_(crypt_set_uuid(cd, DEVICE_TEST_UUID));
        OK_(strcmp(DEVICE_TEST_UUID, crypt_get_uuid(cd)));
@@ -920,13 +998,13 @@ static void AddDeviceLuks2(void)
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, NULL));
        CRYPT_FREE(cd);
        OK_(crypt_init(&cd, DEVICE_2));
-       crypt_set_iteration_time(cd, 1);
+       OK_(set_fast_pbkdf(cd));
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, NULL));
        EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, key_size, PASSPHRASE, strlen(PASSPHRASE)), 0);
        CRYPT_FREE(cd);
 
        OK_(crypt_init(&cd, DEVICE_2));
-       crypt_set_iteration_time(cd, 1);
+       OK_(set_fast_pbkdf(cd));
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, key_size, NULL));
        FAIL_(crypt_keyslot_add_by_volume_key(cd, CRYPT_ANY_SLOT, key, key_size, PASSPHRASE, strlen(PASSPHRASE)), "VK doesn't match any digest");
        FAIL_(crypt_keyslot_add_by_volume_key(cd, 1, key, key_size, PASSPHRASE, strlen(PASSPHRASE)), "VK doesn't match any digest");
@@ -934,7 +1012,7 @@ static void AddDeviceLuks2(void)
 
        OK_(create_dmdevice_over_loop(L_DEVICE_1S, r_payload_offset + 1));
        OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
-       crypt_set_iteration_time(cd, 1);
+       OK_(set_fast_pbkdf(cd));
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, NULL));
        EQ_(crypt_keyslot_add_by_volume_key(cd, 3, NULL, key_size, PASSPHRASE, strlen(PASSPHRASE)), 3);
        FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key3, key_size, 0), "VK doesn't match any digest assigned to segment 0");
@@ -945,7 +1023,7 @@ static void AddDeviceLuks2(void)
         * volume key size is unknown (no active keyslots).
         */
        OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
-       crypt_set_iteration_time(cd, 1);
+       OK_(set_fast_pbkdf(cd));
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, NULL));
        EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, key_size, PASSPHRASE, strlen(PASSPHRASE)), 0);
        /* drop context copy of volume key */
@@ -954,6 +1032,7 @@ static void AddDeviceLuks2(void)
        OK_(crypt_load(cd, CRYPT_LUKS, NULL));
        EQ_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, PASSPHRASE, strlen(PASSPHRASE)), 0);
        OK_(crypt_keyslot_destroy(cd, 0));
+       OK_(set_fast_pbkdf(cd));
        EQ_(crypt_keyslot_add_by_volume_key(cd, 0, key, key_size, PASSPHRASE, strlen(PASSPHRASE)), 0);
        CRYPT_FREE(cd);
 
@@ -977,9 +1056,8 @@ static void Luks2MetadataSize(void)
        };
        char key[128], tmp[128];
 
-       const char *passphrase = "blabla";
-       const char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
-       size_t key_size = strlen(mk_hex) / 2;
+       const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+       size_t key_size = strlen(vk_hex) / 2;
        const char *cipher = "aes";
        const char *cipher_mode = "cbc-essiv:sha256";
        uint64_t r_header_size, default_mdata_size, default_keyslots_size, mdata_size,
@@ -993,7 +1071,7 @@ static void Luks2MetadataSize(void)
                pbkdf.iterations = 1000;
        }
 
-       crypt_decode_key(key, mk_hex, key_size);
+       crypt_decode_key(key, vk_hex, key_size);
 
        // init test devices
        OK_(get_luks2_offsets(0, 0, 0, &r_header_size, NULL));
@@ -1024,7 +1102,7 @@ static void Luks2MetadataSize(void)
        OK_(crypt_init(&cd, DMDIR H_DEVICE));
        OK_(crypt_set_metadata_size(cd, 0x080000, 0x080000));
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
-       EQ_(crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, passphrase, strlen(passphrase)), 7);
+       EQ_(crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, PASSPHRASE, strlen(PASSPHRASE)), 7);
        CRYPT_FREE(cd);
        OK_(crypt_init(&cd, DMDIR H_DEVICE));
        OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
@@ -1119,9 +1197,9 @@ static void UseTempVolumes(void)
 
        // Dirty checks: device without UUID
        // we should be able to remove it but not manipulate with it
-       snprintf(tmp, sizeof(tmp), "dmsetup create %s --table \""
+       GE_(snprintf(tmp, sizeof(tmp), "dmsetup create %s --table \""
                "0 100 crypt aes-cbc-essiv:sha256 deadbabedeadbabedeadbabedeadbabe 0 "
-               "%s 2048\"", CDEVICE_2, DEVICE_2);
+               "%s 2048\"", CDEVICE_2, DEVICE_2), 0);
        _system(tmp, 1);
        OK_(crypt_init_by_name(&cd, CDEVICE_2));
        OK_(crypt_deactivate(cd, CDEVICE_2));
@@ -1129,10 +1207,10 @@ static void UseTempVolumes(void)
        CRYPT_FREE(cd);
 
        // Dirty checks: device with UUID but LUKS header key fingerprint must fail)
-       snprintf(tmp, sizeof(tmp), "dmsetup create %s --table \""
+       GE_(snprintf(tmp, sizeof(tmp), "dmsetup create %s --table \""
                "0 100 crypt aes-cbc-essiv:sha256 deadbabedeadbabedeadbabedeadbabe 0 "
                "%s 2048\" -u CRYPT-LUKS2-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-ctest1",
-                CDEVICE_2, DEVICE_2);
+                CDEVICE_2, DEVICE_2), 0);
        _system(tmp, 1);
        OK_(crypt_init_by_name(&cd, CDEVICE_2));
        OK_(crypt_deactivate(cd, CDEVICE_2));
@@ -1162,7 +1240,7 @@ static void Luks2HeaderRestore(void)
                .sector_size = 512
        };
        struct crypt_params_plain pl_params = {
-               .hash = "sha1",
+               .hash = "sha256",
                .skip = 0,
                .offset = 0,
                .size = 0
@@ -1172,8 +1250,8 @@ static void Luks2HeaderRestore(void)
        };
        uint32_t flags = 0;
 
-       const char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
-       size_t key_size = strlen(mk_hex) / 2;
+       const char *vk_hex = "ccadd99b16cd3d200c22d6db45d8b6630ef3d936767127347ec8a76ab992c2ea";
+       size_t key_size = strlen(vk_hex) / 2;
        const char *cipher = "aes";
        const char *cipher_mode = "cbc-essiv:sha256";
        uint64_t r_payload_offset;
@@ -1185,7 +1263,7 @@ static void Luks2HeaderRestore(void)
                pbkdf.max_memory_kb = 0;
        }
 
-       crypt_decode_key(key, mk_hex, key_size);
+       crypt_decode_key(key, vk_hex, key_size);
 
        OK_(get_luks2_offsets(0, params.data_alignment, 0, NULL, &r_payload_offset));
        OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 5000));
@@ -1224,7 +1302,7 @@ static void Luks2HeaderRestore(void)
 
        // do not allow restore over LUKS1 header on device
        OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
-       crypt_set_iteration_time(cd, 1);
+       OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
        OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, NULL, 32, &luks1));
        CRYPT_FREE(cd);
        OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
@@ -1267,15 +1345,15 @@ static void Luks2HeaderLoad(void)
                .sector_size = 512
        };
        struct crypt_params_plain pl_params = {
-               .hash = "sha1",
+               .hash = "sha256",
                .skip = 0,
                .offset = 0,
                .size = 0
        };
        char key[128], cmd[256];
 
-       const char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
-       size_t key_size = strlen(mk_hex) / 2;
+       const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+       size_t key_size = strlen(vk_hex) / 2;
        const char *cipher = "aes";
        const char *cipher_mode = "cbc-essiv:sha256";
        uint64_t r_payload_offset, r_header_size, img_size;
@@ -1287,7 +1365,7 @@ static void Luks2HeaderLoad(void)
                pbkdf.max_memory_kb = 0;
        }
 
-       crypt_decode_key(key, mk_hex, key_size);
+       crypt_decode_key(key, vk_hex, key_size);
 
        // hardcoded values for existing image IMAGE1
        img_size = 8192;
@@ -1298,7 +1376,8 @@ static void Luks2HeaderLoad(void)
        // prepared header on a device too small to contain header and payload
        //OK_(create_dmdevice_over_loop(H_DEVICE_WRONG, r_payload_offset - 1));
        OK_(create_dmdevice_over_loop(H_DEVICE_WRONG, img_size - 1));
-       snprintf(cmd, sizeof(cmd), "dd if=" IMAGE1 " of=" DMDIR H_DEVICE_WRONG " bs=%" PRIu32 " count=%" PRIu64 " 2>/dev/null", params.sector_size, img_size - 1);
+       GE_(snprintf(cmd, sizeof(cmd), "dd if=" IMAGE1 " of=" DMDIR H_DEVICE_WRONG " bs=%" PRIu32
+           " count=%" PRIu64 " 2>/dev/null", params.sector_size, img_size - 1), 0);
        OK_(_system(cmd, 1));
        // some device
        OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1000));
@@ -1321,6 +1400,7 @@ static void Luks2HeaderLoad(void)
        OK_(!crypt_get_metadata_device_name(cd));
        EQ_(strcmp(DMDIR H_DEVICE, crypt_get_metadata_device_name(cd)), 0);
        OK_(crypt_deactivate(cd, CDEVICE_1));
+       EQ_(1, crypt_header_is_detached(cd));
        CRYPT_FREE(cd);
 
        // repeat with init with two devices
@@ -1331,6 +1411,7 @@ static void Luks2HeaderLoad(void)
        OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
        OK_(!crypt_get_metadata_device_name(cd));
        EQ_(strcmp(DMDIR H_DEVICE, crypt_get_metadata_device_name(cd)), 0);
+       EQ_(1, crypt_header_is_detached(cd));
        CRYPT_FREE(cd);
 
        // bad header: device too small (payloadOffset > device_size)
@@ -1404,8 +1485,8 @@ static void Luks2HeaderBackup(void)
        char key[128];
        int fd, ro = O_RDONLY;
 
-       const char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
-       size_t key_size = strlen(mk_hex) / 2;
+       const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+       size_t key_size = strlen(vk_hex) / 2;
        const char *cipher = "aes";
        const char *cipher_mode = "cbc-essiv:sha256";
        uint64_t r_payload_offset;
@@ -1419,7 +1500,7 @@ static void Luks2HeaderBackup(void)
                pbkdf.max_memory_kb = 0;
        }
 
-       crypt_decode_key(key, mk_hex, key_size);
+       crypt_decode_key(key, vk_hex, key_size);
 
        OK_(get_luks2_offsets(1, params.data_alignment, 0, NULL, &r_payload_offset));
        OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1));
@@ -1441,6 +1522,7 @@ static void Luks2HeaderBackup(void)
        OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
        GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
        OK_(crypt_deactivate(cd, CDEVICE_1));
+       EQ_(0, crypt_header_is_detached(cd));
        CRYPT_FREE(cd);
 
        // exercise luksOpen using backup header in file
@@ -1450,6 +1532,7 @@ static void Luks2HeaderBackup(void)
        EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, passphrase, strlen(passphrase), 0), 0);
        GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
        OK_(crypt_deactivate(cd, CDEVICE_1));
+       EQ_(1, crypt_header_is_detached(cd));
        CRYPT_FREE(cd);
 
        OK_(crypt_init(&cd, BACKUP_FILE));
@@ -1499,10 +1582,10 @@ static void ResizeDeviceLuks2(void)
        };
        char key[128];
 
-       const char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
-       size_t key_size = strlen(mk_hex) / 2;
-       const char *cipher = "aes";
-       const char *cipher_mode = "cbc-essiv:sha256";
+       const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+       size_t key_size = strlen(vk_hex) / 2;
+       const char *cipher = "aes", *capi_cipher = "capi:cbc(aes)";
+       const char *cipher_mode = "cbc-essiv:sha256", *capi_cipher_mode = "essiv:sha256";
        uint64_t r_payload_offset, r_header_size, r_size;
 
        /* Cannot use Argon2 in FIPS */
@@ -1512,7 +1595,7 @@ static void ResizeDeviceLuks2(void)
                pbkdf.max_memory_kb = 0;
        }
 
-       crypt_decode_key(key, mk_hex, key_size);
+       crypt_decode_key(key, vk_hex, key_size);
 
        // prepare env
        OK_(get_luks2_offsets(0, params.data_alignment, 0, NULL, &r_payload_offset));
@@ -1531,15 +1614,15 @@ static void ResizeDeviceLuks2(void)
        OK_(crypt_resize(cd, CDEVICE_1, 0));
        OK_(crypt_resize(cd, CDEVICE_1, 42));
        if (!t_device_size(DMDIR CDEVICE_1, &r_size))
-               EQ_(42, r_size >> SECTOR_SHIFT);
+               EQ_(42, r_size >> TST_SECTOR_SHIFT);
        OK_(crypt_resize(cd, CDEVICE_1, 0));
        // autodetect encrypted device area size
        OK_(crypt_resize(cd, CDEVICE_1, 0));
        if (!t_device_size(DMDIR CDEVICE_1, &r_size))
-               EQ_(1000, r_size >> SECTOR_SHIFT);
+               EQ_(1000, r_size >> TST_SECTOR_SHIFT);
        FAIL_(crypt_resize(cd, CDEVICE_1, 1001), "Device too small");
        if (!t_device_size(DMDIR CDEVICE_1, &r_size))
-               EQ_(1000, r_size >> SECTOR_SHIFT);
+               EQ_(1000, r_size >> TST_SECTOR_SHIFT);
        GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
        OK_(crypt_deactivate(cd, CDEVICE_1));
        CRYPT_FREE(cd);
@@ -1552,14 +1635,14 @@ static void ResizeDeviceLuks2(void)
        OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
        OK_(crypt_resize(cd, CDEVICE_1, 666));
        if (!t_device_size(DMDIR CDEVICE_1, &r_size))
-               EQ_(666, r_size >> SECTOR_SHIFT);
+               EQ_(666, r_size >> TST_SECTOR_SHIFT);
        // autodetect encrypted device size
        OK_(crypt_resize(cd, CDEVICE_1, 0));
        if (!t_device_size(DMDIR CDEVICE_1, &r_size))
-               EQ_(1000, r_size >> SECTOR_SHIFT);
+               EQ_(1000, r_size >> TST_SECTOR_SHIFT);
        FAIL_(crypt_resize(cd, CDEVICE_1, 1001), "Device too small");
        if (!t_device_size(DMDIR CDEVICE_1, &r_size))
-               EQ_(1000, r_size >> SECTOR_SHIFT);
+               EQ_(1000, r_size >> TST_SECTOR_SHIFT);
        GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
        OK_(crypt_deactivate(cd, CDEVICE_1));
        CRYPT_FREE(cd);
@@ -1592,7 +1675,7 @@ static void ResizeDeviceLuks2(void)
        OK_(crypt_activate_by_volume_key(cd, NULL, key, key_size, t_dm_crypt_keyring_support() ? CRYPT_ACTIVATE_KEYRING_KEY : 0));
        OK_(crypt_resize(cd, CDEVICE_1, 43));
        if (!t_device_size(DMDIR CDEVICE_1, &r_size))
-               EQ_(43, r_size >> SECTOR_SHIFT);
+               EQ_(43, r_size >> TST_SECTOR_SHIFT);
        CRYPT_FREE(cd);
 
        OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
@@ -1627,7 +1710,7 @@ static void ResizeDeviceLuks2(void)
        CRYPT_FREE(cd2);
 
        OK_(crypt_init(&cd2, DMDIR L_DEVICE_WRONG));
-       crypt_set_iteration_time(cd2, 1);
+       OK_(crypt_set_pbkdf_type(cd2, &min_pbkdf2));
        OK_(crypt_format(cd2, CRYPT_LUKS1, cipher, cipher_mode, crypt_get_uuid(cd), key, key_size, NULL));
        OK_(crypt_activate_by_volume_key(cd2, CDEVICE_2, key, key_size, 0));
        FAIL_(crypt_resize(cd2, CDEVICE_1, 1), "Device got resized by wrong device context.");
@@ -1644,6 +1727,18 @@ static void ResizeDeviceLuks2(void)
        OK_(crypt_deactivate(cd, CDEVICE_1));
        CRYPT_FREE(cd);
 
+       if (t_dm_capi_string_supported()) {
+               OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+               OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+               OK_(crypt_format(cd, CRYPT_LUKS2, capi_cipher, capi_cipher_mode, NULL, key, key_size, NULL));
+               OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+               OK_(crypt_resize(cd, CDEVICE_1, 8));
+               if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+                       EQ_(8, r_size >> TST_SECTOR_SHIFT);
+               OK_(crypt_deactivate(cd, CDEVICE_1));
+               CRYPT_FREE(cd);
+       }
+
        _cleanup_dmdevices();
 }
 
@@ -1660,7 +1755,7 @@ static void TokenActivationByKeyring(void)
                .key_description = KEY_DESC_TEST0
        }, params2 = {
                .key_description = KEY_DESC_TEST1
-       };
+       }, params_invalid = {};
        uint64_t r_payload_offset;
 
        if (!t_dm_crypt_keyring_support()) {
@@ -1676,9 +1771,10 @@ static void TokenActivationByKeyring(void)
 
        // prepare the device
        OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
-       crypt_set_iteration_time(cd, 1);
+       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);
+       FAIL_(crypt_token_luks2_keyring_set(cd, CRYPT_ANY_TOKEN, &params_invalid), "Invalid key description property.");
        EQ_(crypt_token_luks2_keyring_set(cd, 3, &params), 3);
        EQ_(crypt_token_assign_keyslot(cd, 3, 0), 3);
        CRYPT_FREE(cd);
@@ -1727,7 +1823,7 @@ static void TokenActivationByKeyring(void)
        EQ_(crypt_token_assign_keyslot(cd, 0, 0), 0);
        EQ_(crypt_token_luks2_keyring_set(cd, 1, &params2), 1);
        FAIL_(crypt_token_assign_keyslot(cd, 1, 1), "Keyslot 1 doesn't exist");
-       crypt_set_iteration_time(cd, 1);
+       OK_(set_fast_pbkdf(cd));
        EQ_(crypt_keyslot_add_by_passphrase(cd, 1, PASSPHRASE, strlen(PASSPHRASE), PASSPHRASE1, strlen(PASSPHRASE1)), 1);
        EQ_(crypt_token_assign_keyslot(cd, 1, 1), 1);
        CRYPT_FREE(cd);
@@ -1765,7 +1861,7 @@ static void TokenActivationByKeyring(void)
        OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
        OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
        OK_(crypt_keyslot_destroy(cd, 0));
-       crypt_set_iteration_time(cd, 1);
+       OK_(set_fast_pbkdf(cd));
        EQ_(crypt_keyslot_add_by_passphrase(cd, 0, PASSPHRASE1, strlen(PASSPHRASE1), PASSPHRASE1, strlen(PASSPHRASE1)), 0);
        CRYPT_FREE(cd);
 
@@ -1780,7 +1876,7 @@ static void TokenActivationByKeyring(void)
         // 1st token being invalid (missing key in keyring)
         // 2nd token can activate keyslot 1 after failing to do so w/ keyslot 0 (wrong pass)
        OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
-       crypt_set_iteration_time(cd, 1);
+       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, PASSPHRASE1, strlen(PASSPHRASE1)), 1);
@@ -1830,12 +1926,13 @@ static void Tokens(void)
                        "\"key_description\":" y ", \"some_field\":\"some_value\"}"
 
 
-       int ks;
+       int ks, token_max;
        const char *dummy;
        const char *cipher = "aes";
        const char *cipher_mode = "xts-plain64";
        char passptr[] = PASSPHRASE;
        char passptr1[] = PASSPHRASE1;
+       struct crypt_active_device cad;
 
        static const crypt_token_handler th = {
                .name = "test_token",
@@ -1868,7 +1965,7 @@ static void Tokens(void)
 
        // basic token API tests
        OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
-       crypt_set_iteration_time(cd, 1);
+       OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, 32, NULL));
        EQ_(crypt_token_status(cd, -1, NULL), CRYPT_TOKEN_INVALID);
        EQ_(crypt_token_status(cd, 32, NULL), CRYPT_TOKEN_INVALID);
@@ -1981,9 +2078,84 @@ static void Tokens(void)
        ks = crypt_keyslot_change_by_passphrase(cd, 5, CRYPT_ANY_SLOT, PASSPHRASE1, strlen(PASSPHRASE1), PASSPHRASE1, strlen(PASSPHRASE1));
        NOTFAIL_(ks, "Failed to change keyslot passphrase.");
        OK_(crypt_token_is_assigned(cd, 10, ks));
+       CRYPT_FREE(cd);
+
+       // test token activation respects keyslot priorities
+       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_key(cd,        3,  NULL, 32, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 3);
+       EQ_(crypt_keyslot_add_by_volume_key(cd, 5,  NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 5);
+       EQ_(crypt_keyslot_add_by_volume_key(cd, 8,  NULL, 32, PASSPHRASE1, strlen(PASSPHRASE1)), 8);
+       EQ_(crypt_keyslot_add_by_volume_key(cd, 12, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 12);
+       EQ_(crypt_keyslot_add_by_volume_key(cd, 21, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 21);
+       EQ_(crypt_keyslot_add_by_volume_key(cd, 31, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 31);
+
+       OK_(crypt_keyslot_set_priority(cd, 0, CRYPT_SLOT_PRIORITY_IGNORE));
+       OK_(crypt_keyslot_set_priority(cd, 3, CRYPT_SLOT_PRIORITY_PREFER));
+       OK_(crypt_keyslot_set_priority(cd, 8, CRYPT_SLOT_PRIORITY_PREFER));
+       OK_(crypt_keyslot_set_priority(cd, 12,CRYPT_SLOT_PRIORITY_PREFER));
+
+       // expected unusable with CRYPT_ANY_TOKEN
+       EQ_(crypt_token_json_set(cd, 1, TEST_TOKEN_JSON("\"0\", \"3\"")), 1);
+
+       // expected unusable (-EPERM)
+       EQ_(crypt_token_json_set(cd, 5, TEST_TOKEN_JSON("\"8\"")), 5);
+
+       // expected unusable (-EPERM)
+       EQ_(crypt_token_json_set(cd, 4, TEST_TOKEN_JSON("\"8\", \"3\"")), 4);
 
+       // expected unusable (-ENOENT)
+       EQ_(crypt_token_json_set(cd, 6, TEST_TOKEN_JSON("\"3\"")), 6);
+
+       // expected unusable (-ENOENT)
+       EQ_(crypt_token_json_set(cd, 11, TEST_TOKEN_JSON("")), 11);
+
+       token_max = crypt_token_max(CRYPT_LUKS2) - 1;
+       GE_(token_max, 0);
+
+       // expected to be used first with CRYPT_ANY_TOKEN (unlocks with high priority ks 12)
+       EQ_(crypt_token_json_set(cd, token_max, TEST_TOKEN_JSON("\"12\", \"0\", \"3\"")), token_max);
+
+       // expected usable with CRYPT_ANY_TOKEN
+       EQ_(crypt_token_json_set(cd, 8, TEST_TOKEN_JSON("\"5\", \"0\", \"3\"")), 8);
+
+       // of all tokens keyslot 12 has highest priority now
+       EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", CRYPT_ANY_TOKEN, NULL, 0, passptr, 0), 12);
+       EQ_(crypt_activate_by_token_pin(cd, CDEVICE_1, "test_token", CRYPT_ANY_TOKEN, NULL, 0, passptr, 0), 12);
+       OK_(crypt_deactivate(cd, CDEVICE_1));
+
+       // with explicit token priority ignore may be used
+       EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", 1, NULL, 0, passptr, 0), 0);
+       EQ_(crypt_activate_by_token_pin(cd, CDEVICE_1, "test_token", 1, NULL, 0, passptr, 0), 0);
+       OK_(crypt_deactivate(cd, CDEVICE_1));
+
+       EQ_(crypt_token_json_set(cd, token_max, NULL), token_max);
+
+       EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", CRYPT_ANY_TOKEN, NULL, 0, passptr, 0), 5);
+
+       EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", 5, NULL, 0, passptr, 0), -EPERM);
+       EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", 4, NULL, 0, passptr, 0), -EPERM);
+
+       EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", 6, NULL, 0, passptr, 0), -ENOENT);
+       EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", 6, NULL, 0, passptr, CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY), 3);
+
+       EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", 11, NULL, 0, passptr, 0), -ENOENT);
+       EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", 11, NULL, 0, passptr, CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY), -ENOENT);
+
+       // test crypt_resume_by_token_pin
+       EQ_(crypt_activate_by_token_pin(cd, CDEVICE_1, "test_token", CRYPT_ANY_TOKEN, NULL, 0, passptr, 0), 5);
+       OK_(crypt_suspend(cd, CDEVICE_1));
+       EQ_(crypt_resume_by_token_pin(cd, CDEVICE_1, "test_token", CRYPT_ANY_TOKEN, NULL, 0, passptr), 5);
+       OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+       EQ_(0, cad.flags & CRYPT_ACTIVATE_SUSPENDED);
+       OK_(crypt_deactivate(cd, CDEVICE_1));
        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");
        _cleanup_dmdevices();
 }
 
@@ -2000,7 +2172,7 @@ static void LuksConvert(void)
                .parallel_threads = 1
        }, pbkdf2 = {
                .type = CRYPT_KDF_PBKDF2,
-               .hash = "sha1",
+               .hash = "sha256",
                .time_ms = 1
        };
 
@@ -2019,7 +2191,7 @@ static void LuksConvert(void)
 
        // prepare the device
        OK_(crypt_init(&cd, DEVICE_1));
-       crypt_set_iteration_time(cd, 1);
+       OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
        OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, NULL, 32, NULL));
        offset = crypt_get_data_offset(cd);
        EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0);
@@ -2495,8 +2667,7 @@ static void LuksConvert(void)
        // detached LUKS1 header upconversion
        OK_(create_dmdevice_over_loop(H_DEVICE, 2050)); // default LUKS1 header should fit there
        OK_(crypt_init(&cd, DMDIR H_DEVICE));
-       crypt_set_iteration_time(cd, 1);
-       //OK_(crypt_set_pbkdf_type(cd, &pbkdf2));
+       OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
        OK_(crypt_format(cd, CRYPT_LUKS1, "aes", "xts-plain64", NULL, NULL, 32, &luks1));
        EQ_(crypt_keyslot_add_by_volume_key(cd, 7, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 7);
        FAIL_(crypt_convert(cd, CRYPT_LUKS2, NULL), "Unable to move keyslots. Not enough space.");
@@ -2504,8 +2675,7 @@ static void LuksConvert(void)
 
        // 2050 sectors, empty file
        OK_(crypt_init(&cd, IMAGE_EMPTY_SMALL_2));
-       //OK_(crypt_set_pbkdf_type(cd, &pbkdf2));
-       crypt_set_iteration_time(cd, 1);
+       OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
        OK_(crypt_format(cd, CRYPT_LUKS1, "aes", "xts-plain64", NULL, NULL, 32, &luks1));
        EQ_(crypt_get_data_offset(cd), 0);
        EQ_(crypt_keyslot_add_by_volume_key(cd, 7, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 7);
@@ -2522,20 +2692,20 @@ static void Pbkdf(void)
        const char *cipher = "aes", *mode="xts-plain64";
        struct crypt_pbkdf_type argon2 = {
                .type = CRYPT_KDF_ARGON2I,
-               .hash = DEFAULT_LUKS1_HASH,
+               .hash = default_luks1_hash,
                .time_ms = 6,
                .max_memory_kb = 1024,
                .parallel_threads = 1
        }, pbkdf2 = {
                .type = CRYPT_KDF_PBKDF2,
-               .hash = DEFAULT_LUKS1_HASH,
+               .hash = default_luks1_hash,
                .time_ms = 9
        }, bad = {
                .type = "hamster_pbkdf",
-               .hash = DEFAULT_LUKS1_HASH
+               .hash = default_luks1_hash
        };
        struct crypt_params_plain params = {
-               .hash = "sha1",
+               .hash = "sha256",
                .skip = 0,
                .offset = 0,
                .size = 0
@@ -2588,7 +2758,7 @@ static void Pbkdf(void)
        OK_(crypt_set_pbkdf_type(cd, &pbkdf2));
        OK_(crypt_set_pbkdf_type(cd, NULL));
        NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd));
-       EQ_(pbkdf->time_ms, DEFAULT_LUKS1_ITER_TIME);
+       EQ_(pbkdf->time_ms, default_luks1_iter_time);
        CRYPT_FREE(cd);
        // test value set in crypt_set_iteration_time() can be obtained via following crypt_get_pbkdf_type()
        OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
@@ -2598,7 +2768,7 @@ static void Pbkdf(void)
        EQ_(pbkdf->time_ms, 42);
        // test crypt_get_pbkdf_type() returns expected values for LUKSv1
        OK_(strcmp(pbkdf->type, CRYPT_KDF_PBKDF2));
-       OK_(strcmp(pbkdf->hash, DEFAULT_LUKS1_HASH));
+       OK_(strcmp(pbkdf->hash, default_luks1_hash));
        EQ_(pbkdf->max_memory_kb, 0);
        EQ_(pbkdf->parallel_threads, 0);
        crypt_set_iteration_time(cd, 43);
@@ -2629,11 +2799,11 @@ static void Pbkdf(void)
        OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, mode, NULL, NULL, 32, NULL));
        NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd));
-       OK_(strcmp(pbkdf->type, DEFAULT_LUKS2_PBKDF));
-       OK_(strcmp(pbkdf->hash, DEFAULT_LUKS1_HASH));
-       EQ_(pbkdf->time_ms, DEFAULT_LUKS2_ITER_TIME);
+       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());
-       EQ_(pbkdf->parallel_threads, _min(cpus_online(), DEFAULT_LUKS2_PARALLEL_THREADS));
+       EQ_(pbkdf->parallel_threads, _min(cpus_online(), default_luks2_parallel_threads));
        // set and verify argon2 type
        OK_(crypt_set_pbkdf_type(cd, &argon2));
        NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd));
@@ -2654,11 +2824,11 @@ static void Pbkdf(void)
        crypt_set_iteration_time(cd, 1); // it's supposed to override this call
        OK_(crypt_set_pbkdf_type(cd, NULL));
        NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd));
-       OK_(strcmp(pbkdf->type, DEFAULT_LUKS2_PBKDF));
-       OK_(strcmp(pbkdf->hash, DEFAULT_LUKS1_HASH));
-       EQ_(pbkdf->time_ms, DEFAULT_LUKS2_ITER_TIME);
+       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());
-       EQ_(pbkdf->parallel_threads, _min(cpus_online(), DEFAULT_LUKS2_PARALLEL_THREADS));
+       EQ_(pbkdf->parallel_threads, _min(cpus_online(), default_luks2_parallel_threads));
        // try to pass illegal values
        argon2.parallel_threads = 0;
        FAIL_(crypt_set_pbkdf_type(cd, &argon2), "Parallel threads can't be 0");
@@ -2676,7 +2846,7 @@ static void Pbkdf(void)
        bad.hash = NULL;
        FAIL_(crypt_set_pbkdf_type(cd, &bad), "Hash member is empty");
        bad.type = NULL;
-       bad.hash = DEFAULT_LUKS1_HASH;
+       bad.hash = default_luks1_hash;
        FAIL_(crypt_set_pbkdf_type(cd, &bad), "Pbkdf type member is empty");
        bad.hash = "hamster_hash";
        FAIL_(crypt_set_pbkdf_type(cd, &pbkdf2), "Unknown hash member");
@@ -2685,18 +2855,18 @@ static void Pbkdf(void)
        OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
        OK_(crypt_load(cd, CRYPT_LUKS, NULL));
        NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd));
-       OK_(strcmp(pbkdf->type, DEFAULT_LUKS2_PBKDF));
-       OK_(strcmp(pbkdf->hash, DEFAULT_LUKS1_HASH));
-       EQ_(pbkdf->time_ms, DEFAULT_LUKS2_ITER_TIME);
+       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());
-       EQ_(pbkdf->parallel_threads, _min(cpus_online(), DEFAULT_LUKS2_PARALLEL_THREADS));
+       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));
+       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());
-       EQ_(pbkdf->parallel_threads, _min(cpus_online(), DEFAULT_LUKS2_PARALLEL_THREADS));
+       EQ_(pbkdf->parallel_threads, _min(cpus_online(), default_luks2_parallel_threads));
        CRYPT_FREE(cd);
 
        // test crypt_set_pbkdf_type() overwrites invalid value set by crypt_set_iteration_time()
@@ -2734,11 +2904,11 @@ static void Pbkdf(void)
        pbkdf2.time_ms = 9;
        pbkdf2.hash = NULL;
        FAIL_(crypt_set_pbkdf_type(cd, &pbkdf2), "Hash is mandatory for pbkdf2");
-       pbkdf2.hash = "sha1";
+       pbkdf2.hash = "sha256";
        OK_(crypt_set_pbkdf_type(cd, &pbkdf2));
 
        argon2.time_ms = 9;
-       argon2.hash = "sha1"; // will be ignored
+       argon2.hash = "sha256"; // will be ignored
        OK_(crypt_set_pbkdf_type(cd, &argon2));
        argon2.hash = NULL;
        OK_(crypt_set_pbkdf_type(cd, &argon2));
@@ -2747,17 +2917,17 @@ static void Pbkdf(void)
 
        NOTNULL_(pbkdf = crypt_get_pbkdf_default(CRYPT_LUKS1));
        OK_(strcmp(pbkdf->type, CRYPT_KDF_PBKDF2));
-       EQ_(pbkdf->time_ms, DEFAULT_LUKS1_ITER_TIME);
-       OK_(strcmp(pbkdf->hash, DEFAULT_LUKS1_HASH));
+       EQ_(pbkdf->time_ms, default_luks1_iter_time);
+       OK_(strcmp(pbkdf->hash, default_luks1_hash));
        EQ_(pbkdf->max_memory_kb, 0);
        EQ_(pbkdf->parallel_threads, 0);
 
        NOTNULL_(pbkdf = crypt_get_pbkdf_default(CRYPT_LUKS2));
-       OK_(strcmp(pbkdf->type, DEFAULT_LUKS2_PBKDF));
-       EQ_(pbkdf->time_ms, DEFAULT_LUKS2_ITER_TIME);
-       OK_(strcmp(pbkdf->hash, DEFAULT_LUKS1_HASH));
-       EQ_(pbkdf->max_memory_kb, DEFAULT_LUKS2_MEMORY_KB);
-       EQ_(pbkdf->parallel_threads, DEFAULT_LUKS2_PARALLEL_THREADS);
+       OK_(strcmp(pbkdf->type, default_luks2_pbkdf));
+       EQ_(pbkdf->time_ms, default_luks2_iter_time);
+       OK_(strcmp(pbkdf->hash, default_luks1_hash));
+       EQ_(pbkdf->max_memory_kb, default_luks2_memory_kb);
+       EQ_(pbkdf->parallel_threads, default_luks2_parallel_threads);
 
        NULL_(pbkdf = crypt_get_pbkdf_default(CRYPT_PLAIN));
 
@@ -2768,9 +2938,9 @@ static void Luks2KeyslotAdd(void)
 {
        char key[128], key2[128], key_ret[128];
        const char *cipher = "aes", *cipher_mode="xts-plain64";
-       const char *mk_hex =  "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
-       const char *mk_hex2 = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1e";
-       size_t key_ret_len, key_size = strlen(mk_hex) / 2;
+       const char *vk_hex =  "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+       const char *vk_hex2 = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1e";
+       size_t key_ret_len, key_size = strlen(vk_hex) / 2;
        uint64_t r_payload_offset;
        struct crypt_pbkdf_type pbkdf = {
                .type = "argon2i",
@@ -2782,11 +2952,11 @@ static void Luks2KeyslotAdd(void)
        };
        struct crypt_params_luks2 params2 = {
                .pbkdf = &pbkdf,
-               .sector_size = SECTOR_SIZE
+               .sector_size = TST_SECTOR_SIZE
        };
 
-       crypt_decode_key(key, mk_hex, key_size);
-       crypt_decode_key(key2, mk_hex2, key_size);
+       crypt_decode_key(key, vk_hex, key_size);
+       crypt_decode_key(key2, vk_hex2, key_size);
 
        /* Cannot use Argon2 in FIPS */
        if (_fips_mode) {
@@ -2907,19 +3077,13 @@ static void Luks2KeyslotParams(void)
        char key[128], key2[128];
        const char *cipher = "aes", *cipher_mode="xts-plain64";
        const char *cipher_spec = "aes-xts-plain64", *cipher_keyslot = "aes-cbc-essiv:sha256";
-       const char *mk_hex =  "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
-       const char *mk_hex2 = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1e";
-       size_t key_size_ret, key_size = strlen(mk_hex) / 2, keyslot_key_size = 16;
+       const char *vk_hex =  "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+       const char *vk_hex2 = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1e";
+       size_t key_size_ret, key_size = strlen(vk_hex) / 2, keyslot_key_size = 16;
        uint64_t r_payload_offset;
-       const struct crypt_pbkdf_type fast_pbkdf = {
-               .type = "pbkdf2",
-               .hash = "sha256",
-               .iterations = 1000,
-               .flags = CRYPT_PBKDF_NO_BENCHMARK
-       };
 
-       crypt_decode_key(key, mk_hex, key_size);
-       crypt_decode_key(key2, mk_hex2, key_size);
+       crypt_decode_key(key, vk_hex, key_size);
+       crypt_decode_key(key2, vk_hex2, key_size);
 
        OK_(prepare_keyfile(KEYFILE1, PASSPHRASE, strlen(PASSPHRASE)));
        OK_(prepare_keyfile(KEYFILE2, PASSPHRASE1, strlen(PASSPHRASE1)));
@@ -2930,7 +3094,7 @@ static void Luks2KeyslotParams(void)
        EQ_(key_size, 2 * keyslot_key_size);
        /* test crypt_keyslot_add_by_key */
        OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
-       OK_(crypt_set_pbkdf_type(cd, &fast_pbkdf));
+       OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, NULL));
        NULL_(crypt_keyslot_get_encryption(cd, 0, &key_size_ret));
        OK_(strcmp(crypt_keyslot_get_encryption(cd, CRYPT_ANY_SLOT, &key_size_ret), cipher_spec));
@@ -2989,7 +3153,7 @@ static void Luks2KeyslotParams(void)
        OK_(strcmp(crypt_keyslot_get_encryption(cd, 7, &key_size_ret), cipher_keyslot));
        EQ_(key_size_ret, keyslot_key_size);
 
-       OK_(crypt_set_pbkdf_type(cd, &fast_pbkdf));
+       OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
        EQ_(8, crypt_keyslot_change_by_passphrase(cd, 1, 8, PASSPHRASE1, strlen(PASSPHRASE1), PASSPHRASE, strlen(PASSPHRASE)));
        OK_(strcmp(crypt_keyslot_get_encryption(cd, 8, &key_size_ret), cipher_spec));
        EQ_(key_size_ret, key_size);
@@ -3018,7 +3182,7 @@ static void Luks2KeyslotParams(void)
 
        /* LUKS1 compatible calls */
        OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
-       OK_(crypt_set_pbkdf_type(cd, &fast_pbkdf));
+       OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
        OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, NULL));
        NULL_(crypt_keyslot_get_encryption(cd, 0, &key_size_ret));
        OK_(strcmp(crypt_keyslot_get_encryption(cd, CRYPT_ANY_SLOT, &key_size_ret), cipher_spec));
@@ -3030,7 +3194,7 @@ static void Luks2KeyslotParams(void)
 
        /* LUKS2 cipher null checks */
        OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
-       OK_(crypt_set_pbkdf_type(cd, &fast_pbkdf));
+       OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
        OK_(crypt_format(cd, CRYPT_LUKS2, "cipher_null", "ecb", NULL, key, key_size, NULL));
        FAIL_(crypt_keyslot_set_encryption(cd, "null", 32), "cipher null is not allowed");
        FAIL_(crypt_keyslot_set_encryption(cd, "cipher_null", 32), "cipher null is not allowed");
@@ -3069,7 +3233,7 @@ static void Luks2ActivateByKeyring(void)
 
        // prepare the device
        OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
-       crypt_set_iteration_time(cd, 1);
+       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_key(cd, 1, NULL, 32, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT), 1);
@@ -3130,21 +3294,21 @@ static void Luks2Requirements(void)
        const char *token, *json = "{\"type\":\"test_token\",\"keyslots\":[]}";
        struct crypt_pbkdf_type argon2 = {
                .type = CRYPT_KDF_ARGON2I,
-               .hash = DEFAULT_LUKS1_HASH,
+               .hash = default_luks1_hash,
                .time_ms = 6,
                .max_memory_kb = 1024,
                .parallel_threads = 1
        }, pbkdf2 = {
                .type = CRYPT_KDF_PBKDF2,
-               .hash = DEFAULT_LUKS1_HASH,
+               .hash = default_luks1_hash,
                .time_ms = 9
        };
        struct crypt_token_params_luks2_keyring params_get, params = {
                .key_description = KEY_DESC_TEST0
        };
 
-       OK_(prepare_keyfile(KEYFILE1, "aaa", 3));
-       OK_(prepare_keyfile(KEYFILE2, "xxx", 3));
+       OK_(prepare_keyfile(KEYFILE1, PASSPHRASE, strlen(PASSPHRASE)));
+       OK_(prepare_keyfile(KEYFILE2, PASSPHRASE1, strlen(PASSPHRASE1)));
 
        /* crypt_load (unrestricted) */
        OK_(crypt_init(&cd, DEVICE_5));
@@ -3187,15 +3351,22 @@ static void Luks2Requirements(void)
        FAIL_((r = crypt_set_label(cd, "label", "subsystem")), "Unmet requirements detected");
        EQ_(r, -ETXTBSY);
 
+       /* crypt_get_label (unrestricted) */
+       NOTNULL_(crypt_get_label(cd));
+       OK_(strcmp("", crypt_get_label(cd)));
+       /* crypt_get_subsystem (unrestricted) */
+       NOTNULL_(crypt_get_subsystem(cd));
+       OK_(strcmp("", crypt_get_subsystem(cd)));
+
        /* crypt_repair (with current repair capabilities it's unrestricted) */
        OK_(crypt_repair(cd, CRYPT_LUKS2, NULL));
 
        /* crypt_keyslot_add_passphrase (restricted) */
-       FAIL_((r = crypt_keyslot_add_by_passphrase(cd, CRYPT_ANY_SLOT, "aaa", 3, "bbb", 3)), "Unmet requirements detected");
+       FAIL_((r = crypt_keyslot_add_by_passphrase(cd, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), "bbb", 3)), "Unmet requirements detected");
        EQ_(r, -ETXTBSY);
 
        /* crypt_keyslot_change_by_passphrase (restricted) */
-       FAIL_((r = crypt_keyslot_change_by_passphrase(cd, CRYPT_ANY_SLOT, 9, "aaa", 3, "bbb", 3)), "Unmet requirements detected");
+       FAIL_((r = crypt_keyslot_change_by_passphrase(cd, CRYPT_ANY_SLOT, 9, PASSPHRASE, strlen(PASSPHRASE), "bbb", 3)), "Unmet requirements detected");
        EQ_(r, -ETXTBSY);
 
        /* crypt_keyslot_add_by_keyfile (restricted) */
@@ -3207,18 +3378,18 @@ static void Luks2Requirements(void)
        EQ_(r, -ETXTBSY);
 
        /* crypt_volume_key_get (unrestricted, but see below) */
-       OK_(crypt_volume_key_get(cd, 0, key, &key_size, "aaa", 3));
+       OK_(crypt_volume_key_get(cd, 0, key, &key_size, PASSPHRASE, strlen(PASSPHRASE)));
 
        /* crypt_keyslot_add_by_volume_key (restricted) */
-       FAIL_((r = crypt_keyslot_add_by_volume_key(cd, CRYPT_ANY_SLOT, key, key_size, "xxx", 3)), "Unmet requirements detected");
+       FAIL_((r = crypt_keyslot_add_by_volume_key(cd, CRYPT_ANY_SLOT, key, key_size, PASSPHRASE1, strlen(PASSPHRASE1))), "Unmet requirements detected");
        EQ_(r, -ETXTBSY);
 
        /* crypt_keyslot_add_by_key (restricted) */
-       FAIL_((r = crypt_keyslot_add_by_key(cd, CRYPT_ANY_SLOT, NULL, key_size, "xxx", 3, CRYPT_VOLUME_KEY_NO_SEGMENT)), "Unmet requirements detected");
+       FAIL_((r = crypt_keyslot_add_by_key(cd, CRYPT_ANY_SLOT, NULL, key_size, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT)), "Unmet requirements detected");
        EQ_(r, -ETXTBSY);
 
        /* crypt_keyslot_add_by_key (restricted) */
-       FAIL_((r = crypt_keyslot_add_by_key(cd, CRYPT_ANY_SLOT, key, key_size, "xxx", 3, 0)), "Unmet requirements detected");
+       FAIL_((r = crypt_keyslot_add_by_key(cd, CRYPT_ANY_SLOT, key, key_size, PASSPHRASE1, strlen(PASSPHRASE1), 0)), "Unmet requirements detected");
        EQ_(r, -ETXTBSY);
 
        /* crypt_persistent_flasgs_set (restricted) */
@@ -3227,13 +3398,13 @@ static void Luks2Requirements(void)
 
        /* crypt_persistent_flasgs_get (unrestricted) */
        OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_REQUIREMENTS, &flags));
-       EQ_(flags, (uint32_t) CRYPT_REQUIREMENT_UNKNOWN);
+       EQ_(flags, CRYPT_REQUIREMENT_UNKNOWN);
 
        /* crypt_activate_by_passphrase (restricted for activation only) */
-       FAIL_((r = crypt_activate_by_passphrase(cd, CDEVICE_1, 0, "aaa", 3, 0)), "Unmet requirements detected");
+       FAIL_((r = crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), 0)), "Unmet requirements detected");
        EQ_(r, -ETXTBSY);
-       OK_(crypt_activate_by_passphrase(cd, NULL, 0, "aaa", 3, 0));
-       OK_(crypt_activate_by_passphrase(cd, NULL, 0, "aaa", 3, t_dm_crypt_keyring_support() ? CRYPT_ACTIVATE_KEYRING_KEY : 0));
+       OK_(crypt_activate_by_passphrase(cd, NULL, 0, PASSPHRASE, strlen(PASSPHRASE), 0));
+       OK_(crypt_activate_by_passphrase(cd, NULL, 0, PASSPHRASE, strlen(PASSPHRASE), t_dm_crypt_keyring_support() ? CRYPT_ACTIVATE_KEYRING_KEY : 0));
        EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
 
        /* crypt_activate_by_keyfile (restricted for activation only) */
@@ -3250,7 +3421,7 @@ static void Luks2Requirements(void)
 
 #ifdef KERNEL_KEYRING
        if (t_dm_crypt_keyring_support()) {
-               kid = add_key("user", KEY_DESC_TEST0, "aaa", 3, KEY_SPEC_THREAD_KEYRING);
+               kid = add_key("user", KEY_DESC_TEST0, PASSPHRASE, strlen(PASSPHRASE), KEY_SPEC_THREAD_KEYRING);
                NOTFAIL_(kid, "Test or kernel keyring are broken.");
 
                /* crypt_activate_by_keyring (restricted for activation only) */
@@ -3258,6 +3429,8 @@ static void Luks2Requirements(void)
                EQ_(r, t_dm_crypt_keyring_support() ? -ETXTBSY : -EINVAL);
                OK_(crypt_activate_by_keyring(cd, NULL, KEY_DESC_TEST0, 0, 0));
                OK_(crypt_activate_by_keyring(cd, NULL, KEY_DESC_TEST0, 0, CRYPT_ACTIVATE_KEYRING_KEY));
+
+               NOTFAIL_(keyctl_unlink(kid, KEY_SPEC_THREAD_KEYRING), "Test or kernel keyring are broken.");
        }
 #endif
 
@@ -3343,10 +3516,15 @@ static void Luks2Requirements(void)
        /* crypt_activate_by_token (restricted for activation only) */
 #ifdef KERNEL_KEYRING
        if (t_dm_crypt_keyring_support()) {
+               kid = add_key("user", KEY_DESC_TEST0, PASSPHRASE, strlen(PASSPHRASE), KEY_SPEC_THREAD_KEYRING);
+               NOTFAIL_(kid, "Test or kernel keyring are broken.");
+
                FAIL_((r = crypt_activate_by_token(cd, CDEVICE_1, 1, NULL, 0)), ""); // supposed to be silent
                EQ_(r, -ETXTBSY);
                OK_(crypt_activate_by_token(cd, NULL, 1, NULL, 0));
                OK_(crypt_activate_by_token(cd, NULL, 1, NULL, CRYPT_ACTIVATE_KEYRING_KEY));
+
+               NOTFAIL_(keyctl_unlink(kid, KEY_SPEC_THREAD_KEYRING), "Test or kernel keyring are broken.");
        }
 #endif
        OK_(get_luks2_offsets(0, 8192, 0, NULL, &r_payload_offset));
@@ -3358,7 +3536,7 @@ static void Luks2Requirements(void)
        CRYPT_FREE(cd);
        OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
        OK_(crypt_load(cd, CRYPT_LUKS, NULL));
-       OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, "aaa", 3, 0));
+       OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), 0));
        OK_(crypt_header_backup(cd, CRYPT_LUKS2, BACKUP_FILE));
        /* replace header with no requirements */
        OK_(_system("dd if=" REQS_LUKS2_HEADER " of=" DMDIR L_DEVICE_OK " bs=1M count=4 oflag=direct 2>/dev/null", 1));
@@ -3396,7 +3574,7 @@ static void Luks2Requirements(void)
        OK_(crypt_init_by_name(&cd, CDEVICE_1));
 
        /* crypt_resume_by_passphrase (restricted) */
-       FAIL_((r = crypt_resume_by_passphrase(cd, CDEVICE_1, 0, "aaa", 3)), "Unmet requirements detected");
+       FAIL_((r = crypt_resume_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE))), "Unmet requirements detected");
        EQ_(r, -ETXTBSY);
 
        /* crypt_resume_by_keyfile (restricted) */
@@ -3410,13 +3588,13 @@ static void Luks2Requirements(void)
 
        OK_(_system("dd if=" NO_REQS_LUKS2_HEADER " of=" DMDIR L_DEVICE_OK " bs=1M count=4 oflag=direct 2>/dev/null", 1));
        OK_(crypt_init_by_name(&cd, CDEVICE_1));
-       OK_(crypt_resume_by_passphrase(cd, CDEVICE_1, 0, "aaa", 3));
+       OK_(crypt_resume_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE)));
        CRYPT_FREE(cd);
        OK_(_system("dd if=" REQS_LUKS2_HEADER " of=" DMDIR L_DEVICE_OK " bs=1M count=4 oflag=direct 2>/dev/null", 1));
 
        OK_(crypt_init_by_name(&cd, CDEVICE_1));
        /* load VK in keyring */
-       OK_(crypt_activate_by_passphrase(cd, NULL, 0, "aaa", 3, t_dm_crypt_keyring_support() ? CRYPT_ACTIVATE_KEYRING_KEY : 0));
+       OK_(crypt_activate_by_passphrase(cd, NULL, 0, PASSPHRASE, strlen(PASSPHRASE), t_dm_crypt_keyring_support() ? CRYPT_ACTIVATE_KEYRING_KEY : 0));
        /* crypt_resize (restricted) */
        FAIL_((r = crypt_resize(cd, CDEVICE_1, 1)), "Unmet requirements detected");
        EQ_(r, -ETXTBSY);
@@ -3452,7 +3630,6 @@ static void Luks2Integrity(void)
                .integrity = "hmac(sha256)"
        };
        size_t key_size = 32 + 32;
-       const char *passphrase = "blabla";
        const char *cipher = "aes";
        const char *cipher_mode = "xts-random";
        int ret;
@@ -3466,8 +3643,8 @@ static void Luks2Integrity(void)
                return;
        }
 
-       EQ_(crypt_keyslot_add_by_volume_key(cd, 7, NULL, key_size, passphrase, strlen(passphrase)), 7);
-       EQ_(crypt_activate_by_passphrase(cd, CDEVICE_2, 7, passphrase, strlen(passphrase) ,0), 7);
+       EQ_(crypt_keyslot_add_by_volume_key(cd, 7, NULL, key_size, PASSPHRASE, strlen(PASSPHRASE)), 7);
+       EQ_(crypt_activate_by_passphrase(cd, CDEVICE_2, 7, PASSPHRASE, strlen(PASSPHRASE) ,0), 7);
        GE_(crypt_status(cd, CDEVICE_2), CRYPT_ACTIVE);
        CRYPT_FREE(cd);
 
@@ -3487,27 +3664,6 @@ static void Luks2Integrity(void)
        CRYPT_FREE(cd);
 }
 
-static int set_fast_pbkdf(struct crypt_device *cd)
-{
-       struct crypt_pbkdf_type pbkdf = {
-               .type = "argon2id",
-               .hash = "sha256",
-               .iterations = 4,
-               .max_memory_kb = 32,
-               .parallel_threads = 1,
-               .flags = CRYPT_PBKDF_NO_BENCHMARK
-       };
-
-       /* Cannot use Argon2 in FIPS */
-       if (_fips_mode) {
-               pbkdf.type = CRYPT_KDF_PBKDF2;
-               pbkdf.parallel_threads = 0;
-               pbkdf.max_memory_kb = 0;
-               pbkdf.iterations = 1000;
-       }
-       return crypt_set_pbkdf_type(cd, &pbkdf);
-}
-
 static int check_flag(uint32_t flags, uint32_t flag)
 {
        return (flags & flag) ? 0 : -1;
@@ -3518,17 +3674,17 @@ static void Luks2Refresh(void)
        uint64_t r_payload_offset;
        char key[128], key1[128];
        const char *cipher = "aes", *mode = "xts-plain64";
-       const char *mk_hex =  "bb21158c733229347bd4e681891e213d94c645be6a5b84818afe7a78a6de7a1a";
-       const char *mk_hex2 = "bb22158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1e";
-       size_t key_size = strlen(mk_hex) / 2;
+       const char *vk_hex =  "bb21158c733229347bd4e681891e213d94c645be6a5b84818afe7a78a6de7a1a";
+       const char *vk_hex2 = "bb22158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1e";
+       size_t key_size = strlen(vk_hex) / 2;
        struct crypt_params_luks2 params = {
                .sector_size = 512,
                .integrity = "aead"
        };
        struct crypt_active_device cad = {};
 
-       crypt_decode_key(key, mk_hex, key_size);
-       crypt_decode_key(key1, mk_hex2, key_size);
+       crypt_decode_key(key, vk_hex, key_size);
+       crypt_decode_key(key1, vk_hex2, key_size);
 
        OK_(get_luks2_offsets(0, 0, 0, NULL, &r_payload_offset));
        OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1000));
@@ -3540,36 +3696,36 @@ static void Luks2Refresh(void)
        OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
        OK_(set_fast_pbkdf(cd));
        OK_(crypt_format(cd, CRYPT_LUKS2, cipher, mode, NULL, key, 32, NULL));
-       OK_(crypt_keyslot_add_by_volume_key(cd, CRYPT_ANY_SLOT, key, 32, "aaa", 3));
-       OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, "aaa", 3, 0));
+       OK_(crypt_keyslot_add_by_volume_key(cd, CRYPT_ANY_SLOT, key, 32, PASSPHRASE, strlen(PASSPHRASE)));
+       OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), 0));
 
        /* check we can refresh significant flags */
        if (t_dm_crypt_discard_support()) {
-               OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, "aaa", 3, CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_ALLOW_DISCARDS));
+               OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_ALLOW_DISCARDS));
                OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
                OK_(check_flag(cad.flags, CRYPT_ACTIVATE_ALLOW_DISCARDS));
                cad.flags = 0;
        }
 
        if (t_dm_crypt_cpu_switch_support()) {
-               OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, "aaa", 3, CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_SAME_CPU_CRYPT));
+               OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_SAME_CPU_CRYPT));
                OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
                OK_(check_flag(cad.flags, CRYPT_ACTIVATE_SAME_CPU_CRYPT));
                cad.flags = 0;
 
-               OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, "aaa", 3, CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS));
+               OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS));
                OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
                OK_(check_flag(cad.flags, CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS));
                cad.flags = 0;
 
-               OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, "aaa", 3, CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS));
+               OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS));
                OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
                OK_(check_flag(cad.flags, CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS));
                cad.flags = 0;
        }
 
        OK_(crypt_volume_key_keyring(cd, 0));
-       OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, "aaa", 3, CRYPT_ACTIVATE_REFRESH));
+       OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH));
        OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
        FAIL_(check_flag(cad.flags, CRYPT_ACTIVATE_KEYRING_KEY), "Unexpected flag raised.");
        cad.flags = 0;
@@ -3577,7 +3733,7 @@ static void Luks2Refresh(void)
 #ifdef KERNEL_KEYRING
        if (t_dm_crypt_keyring_support()) {
                OK_(crypt_volume_key_keyring(cd, 1));
-               OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, "aaa", 3, CRYPT_ACTIVATE_REFRESH));
+               OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH));
                OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
                OK_(check_flag(cad.flags, CRYPT_ACTIVATE_KEYRING_KEY));
                cad.flags = 0;
@@ -3586,26 +3742,26 @@ static void Luks2Refresh(void)
 
        /* multiple flags at once */
        if (t_dm_crypt_discard_support() && t_dm_crypt_cpu_switch_support()) {
-               OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, "aaa", 3, CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS | CRYPT_ACTIVATE_ALLOW_DISCARDS));
+               OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS | CRYPT_ACTIVATE_ALLOW_DISCARDS));
                OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
                OK_(check_flag(cad.flags, CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS | CRYPT_ACTIVATE_ALLOW_DISCARDS));
                cad.flags = 0;
        }
 
        /* do not allow reactivation with read-only (and drop flag silently because activation behaves exactly same) */
-       OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, "aaa", 3, CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_READONLY));
+       OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_READONLY));
        OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
        FAIL_(check_flag(cad.flags, CRYPT_ACTIVATE_READONLY), "Reactivated with read-only flag.");
        cad.flags = 0;
 
        /* reload flag is dropped silently */
        OK_(crypt_deactivate(cd, CDEVICE_1));
-       OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, "aaa", 3, CRYPT_ACTIVATE_REFRESH));
+       OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH));
 
        /* check read-only flag is not lost after reload */
        OK_(crypt_deactivate(cd, CDEVICE_1));
-       OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, "aaa", 3, CRYPT_ACTIVATE_READONLY));
-       OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, "aaa", 3, CRYPT_ACTIVATE_REFRESH));
+       OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_READONLY));
+       OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH));
        OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
        OK_(check_flag(cad.flags, CRYPT_ACTIVATE_READONLY));
        cad.flags = 0;
@@ -3613,7 +3769,7 @@ static void Luks2Refresh(void)
        /* check LUKS2 with auth. enc. reload */
        OK_(crypt_init(&cd2, DMDIR L_DEVICE_WRONG));
        if (!crypt_format(cd2, CRYPT_LUKS2, "aes", "gcm-random", crypt_get_uuid(cd), key, 32, &params)) {
-               OK_(crypt_keyslot_add_by_volume_key(cd2, 0, key, 32, "aaa", 3));
+               OK_(crypt_keyslot_add_by_volume_key(cd2, 0, key, 32, PASSPHRASE, strlen(PASSPHRASE)));
                OK_(crypt_activate_by_volume_key(cd2, CDEVICE_2, key, 32, 0));
                OK_(crypt_activate_by_volume_key(cd2, CDEVICE_2, key, 32, CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_NO_JOURNAL));
                OK_(crypt_get_active_device(cd2, CDEVICE_2, &cad));
@@ -3623,11 +3779,11 @@ static void Luks2Refresh(void)
                OK_(crypt_get_active_device(cd2, CDEVICE_2, &cad));
                OK_(check_flag(cad.flags, CRYPT_ACTIVATE_NO_JOURNAL | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS));
                cad.flags = 0;
-               OK_(crypt_activate_by_passphrase(cd2, CDEVICE_2, 0, "aaa", 3, CRYPT_ACTIVATE_REFRESH));
+               OK_(crypt_activate_by_passphrase(cd2, CDEVICE_2, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH));
                OK_(crypt_get_active_device(cd2, CDEVICE_2, &cad));
                FAIL_(check_flag(cad.flags, CRYPT_ACTIVATE_NO_JOURNAL), "");
                FAIL_(check_flag(cad.flags, CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS), "");
-               FAIL_(crypt_activate_by_passphrase(cd2, CDEVICE_1, 0, "aaa", 3, CRYPT_ACTIVATE_REFRESH), "Refreshed LUKS2 device with LUKS2/aead context");
+               FAIL_(crypt_activate_by_passphrase(cd2, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH), "Refreshed LUKS2 device with LUKS2/aead context");
                OK_(crypt_deactivate(cd2, CDEVICE_2));
        } else {
                printf("WARNING: cannot format integrity device, skipping few reload tests.\n");
@@ -3637,8 +3793,8 @@ static void Luks2Refresh(void)
        /* Use LUKS1 context on LUKS2 device */
        OK_(crypt_init(&cd2, DMDIR L_DEVICE_1S));
        OK_(crypt_format(cd2, CRYPT_LUKS1, cipher, mode, crypt_get_uuid(cd), key, 32, NULL));
-       OK_(crypt_keyslot_add_by_volume_key(cd2, CRYPT_ANY_SLOT, NULL, 32, "aaa", 3));
-       FAIL_(crypt_activate_by_passphrase(cd2, CDEVICE_1, 0, "aaa", 3, CRYPT_ACTIVATE_REFRESH), "Refreshed LUKS2 device with LUKS1 context");
+       OK_(crypt_keyslot_add_by_volume_key(cd2, CRYPT_ANY_SLOT, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)));
+       FAIL_(crypt_activate_by_passphrase(cd2, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH), "Refreshed LUKS2 device with LUKS1 context");
        CRYPT_FREE(cd2);
 
        /* Use PLAIN context on LUKS2 device */
@@ -3654,8 +3810,8 @@ static void Luks2Refresh(void)
        OK_(crypt_init(&cd2, DMDIR L_DEVICE_WRONG));
        OK_(set_fast_pbkdf(cd2));
        OK_(crypt_format(cd2, CRYPT_LUKS2, cipher, mode, crypt_get_uuid(cd), key, 32, NULL));
-       OK_(crypt_keyslot_add_by_volume_key(cd2, CRYPT_ANY_SLOT, key, 32, "aaa", 3));
-       FAIL_(crypt_activate_by_passphrase(cd2, CDEVICE_1, 0, "aaa", 3, CRYPT_ACTIVATE_REFRESH), "Refreshed dm-crypt mapped over mismatching data device");
+       OK_(crypt_keyslot_add_by_volume_key(cd2, CRYPT_ANY_SLOT, key, 32, PASSPHRASE, strlen(PASSPHRASE)));
+       FAIL_(crypt_activate_by_passphrase(cd2, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH), "Refreshed dm-crypt mapped over mismatching data device");
 
        OK_(crypt_deactivate(cd, CDEVICE_1));
 
@@ -3685,15 +3841,26 @@ static void Luks2Flags(void)
 
        flags = CRYPT_ACTIVATE_ALLOW_DISCARDS | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS;
        OK_(crypt_persistent_flags_set(cd, CRYPT_FLAGS_ACTIVATION, flags));
-       flags = (uint32_t)~0;
+       flags = ~UINT32_C(0);
        OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_ACTIVATION, &flags));
        EQ_(flags,CRYPT_ACTIVATE_ALLOW_DISCARDS | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS);
 
+       /* label and subsystem (second label */
+       OK_(crypt_set_label(cd, "label", "subsystem"));
+       OK_(strcmp("label", crypt_get_label(cd)));
+       OK_(strcmp("subsystem", crypt_get_subsystem(cd)));
+
+       OK_(crypt_set_label(cd, NULL, NULL));
+       OK_(strcmp("", crypt_get_label(cd)));
+       OK_(strcmp("", crypt_get_subsystem(cd)));
+
        CRYPT_FREE(cd);
 }
 
 #if KERNEL_KEYRING && USE_LUKS2_REENCRYPTION
-static int test_progress(uint64_t size, uint64_t offset, void *usrptr)
+static int test_progress(uint64_t size __attribute__((unused)),
+       uint64_t offset __attribute__((unused)),
+       void *usrptr __attribute__((unused)))
 {
        while (--test_progress_steps)
                return 0;
@@ -3724,15 +3891,16 @@ static void Luks2Reencryption(void)
        struct crypt_params_reencrypt retparams = {}, rparams = {
                .direction = CRYPT_REENCRYPT_FORWARD,
                .resilience = "checksum",
-               .hash = "sha1",
+               .hash = "sha256",
                .luks2 = &params2,
        };
+       dev_t devno;
 
-       const char *mk_hex = "bb21babe733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
-       size_t key_size = strlen(mk_hex) / 2;
+       const char *vk_hex = "bb21babe733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+       size_t key_size = strlen(vk_hex) / 2;
        char key[128];
 
-       crypt_decode_key(key, mk_hex, key_size);
+       crypt_decode_key(key, vk_hex, key_size);
 
        /* reencryption currently depends on kernel keyring support in dm-crypt */
        if (!t_dm_crypt_keyring_support())
@@ -3775,7 +3943,7 @@ static void Luks2Reencryption(void)
 
        OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_REQUIREMENTS, &getflags));
        EQ_(getflags & CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 0);
-       FAIL_(crypt_reencrypt(cd, NULL), "Reencryption context not initialized.");
+       FAIL_(crypt_reencrypt_run(cd, NULL, NULL), "Reencryption context not initialized.");
 
        rparams.flags &= ~CRYPT_REENCRYPT_RESUME_ONLY;
        OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams));
@@ -3808,7 +3976,7 @@ static void Luks2Reencryption(void)
 
        rparams.flags = 0;
        OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams));
-       OK_(crypt_reencrypt(cd, NULL));
+       OK_(crypt_reencrypt_run(cd, NULL, NULL));
 
        /* check keyslots are reassigned to segment after reencryption */
        EQ_(crypt_keyslot_status(cd, 0), CRYPT_SLOT_INACTIVE);
@@ -3832,10 +4000,10 @@ static void Luks2Reencryption(void)
        FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 9, 21, "aes", "xts-plain64", &rparams), "Invalid device size alignment.");
        OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_REQUIREMENTS, &getflags));
        EQ_(getflags & CRYPT_REQUIREMENT_ONLINE_REENCRYPT, CRYPT_REQUIREMENT_ONLINE_REENCRYPT);
-       FAIL_(crypt_reencrypt(cd, NULL), "Reencryption context not initialized.");
+       FAIL_(crypt_reencrypt_run(cd, NULL, NULL), "Reencryption context not initialized.");
        rparams.device_size = 16;
        OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 9, 21, "aes", "xts-plain64", &rparams));
-       OK_(crypt_reencrypt(cd, NULL));
+       OK_(crypt_reencrypt_run(cd, NULL, NULL));
        OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_REQUIREMENTS, &getflags));
        EQ_(getflags & CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 0);
 
@@ -3867,9 +4035,9 @@ static void Luks2Reencryption(void)
        rparams.hash = "hamSter";
        FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams), "Invalid resilience hash.");
 
-       rparams.hash = "sha1";
+       rparams.hash = "sha256";
        OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams));
-       OK_(crypt_reencrypt(cd, NULL));
+       OK_(crypt_reencrypt_run(cd, NULL, NULL));
 
        /* FIXME: this is a bug, but not critical (data shift parameter is ignored after initialization) */
        //rparams.data_shift = 8;
@@ -3896,7 +4064,7 @@ static void Luks2Reencryption(void)
        FAIL_(crypt_reencrypt_init_by_passphrase(cd2, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams), "Reencryption already running.");
        rparams.flags = 0;
        FAIL_(crypt_reencrypt_init_by_passphrase(cd2, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams), "Reencryption already running.");
-       FAIL_(crypt_reencrypt(cd2, NULL), "Invalid reencryption context.");
+       FAIL_(crypt_reencrypt_run(cd2, NULL, NULL), "Invalid reencryption context.");
        OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_REQUIREMENTS, &getflags));
        EQ_(getflags & CRYPT_REQUIREMENT_ONLINE_REENCRYPT, CRYPT_REQUIREMENT_ONLINE_REENCRYPT);
        OK_(crypt_persistent_flags_get(cd2, CRYPT_FLAGS_REQUIREMENTS, &getflags));
@@ -3905,7 +4073,7 @@ static void Luks2Reencryption(void)
        EQ_(crypt_reencrypt_status(cd2, NULL), CRYPT_REENCRYPT_CLEAN);
        FAIL_(crypt_activate_by_passphrase(cd2, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), "Reencryption already in progress.");
        FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), "Reencryption already in progress.");
-       OK_(crypt_reencrypt(cd, NULL));
+       OK_(crypt_reencrypt_run(cd, NULL, NULL));
        CRYPT_FREE(cd);
        CRYPT_FREE(cd2);
 
@@ -3923,8 +4091,8 @@ static void Luks2Reencryption(void)
        EQ_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, 1, "aes", "xts-plain64", &rparams), 2);
 
        /* interrupt reencryption after 'test_progress_steps' */
-       test_progress_steps = 1;
-       OK_(crypt_reencrypt(cd, &test_progress));
+       test_progress_steps = 2;
+       OK_(crypt_reencrypt_run(cd, &test_progress, NULL));
        EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_CLEAN);
 
        NOTFAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), "Could not activate device in reencryption.");
@@ -3943,7 +4111,7 @@ static void Luks2Reencryption(void)
        rparams.device_size = 2;
        rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
        NOTFAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, 1, "aes", "xts-plain64", &rparams), "Failed to initialize reencryption.");
-       OK_(crypt_reencrypt(cd, NULL));
+       OK_(crypt_reencrypt_run(cd, NULL, NULL));
        EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
        EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 1, PASSPHRASE, strlen(PASSPHRASE), 0), 1);
        OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
@@ -4016,7 +4184,7 @@ static void Luks2Reencryption(void)
        EQ_(crypt_get_data_offset(cd), 32776);
        rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
        EQ_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, 1, "aes", "xts-plain64", &rparams), 2);
-       OK_(crypt_reencrypt(cd, NULL));
+       OK_(crypt_reencrypt_run(cd, NULL, NULL));
        CRYPT_FREE(cd);
        OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
        OK_(crypt_set_pbkdf_type(cd, &pbkdf));
@@ -4049,7 +4217,7 @@ static void Luks2Reencryption(void)
        EQ_(crypt_get_data_offset(cd), 32760);
        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(cd, NULL));
+       OK_(crypt_reencrypt_run(cd, NULL, NULL));
        CRYPT_FREE(cd);
        OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
        OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
@@ -4078,7 +4246,7 @@ static void Luks2Reencryption(void)
        EQ_(cad.size, 8);
        rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
        EQ_(crypt_reencrypt_init_by_passphrase(cd, CDEVICE_1, PASSPHRASE, strlen(PASSPHRASE), 0, 1, "aes", "xts-plain64", &rparams), 2);
-       OK_(crypt_reencrypt(cd, NULL));
+       OK_(crypt_reencrypt_run(cd, NULL, NULL));
        OK_(crypt_deactivate(cd, CDEVICE_1));
        CRYPT_FREE(cd);
 
@@ -4117,12 +4285,12 @@ static void Luks2Reencryption(void)
        EQ_(crypt_get_data_offset(cd), 8192);
        rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
        EQ_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ANY_SLOT, 30, NULL, NULL, &rparams), 0);
-       OK_(crypt_reencrypt(cd, NULL));
+       OK_(crypt_reencrypt_run(cd, NULL, NULL));
        CRYPT_FREE(cd);
 
        _cleanup_dmdevices();
        OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
-       OK_(create_dmdevice_over_loop(L_DEVICE_OK, 12*1024*2+1));
+       OK_(create_dmdevice_over_loop(L_DEVICE_OK, 8*1024*2+1));
 
        /* encryption with datashift and moved segment (data shift + 1 sector) */
        OK_(crypt_init(&cd, DMDIR H_DEVICE));
@@ -4137,16 +4305,16 @@ static void Luks2Reencryption(void)
        EQ_(crypt_get_data_offset(cd), 8192);
        rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
        EQ_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ANY_SLOT, 30, NULL, NULL, &rparams), 0);
-       OK_(crypt_reencrypt(cd, NULL));
+       OK_(crypt_reencrypt_run(cd, NULL, NULL));
        CRYPT_FREE(cd);
 
        _cleanup_dmdevices();
        OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
-       OK_(create_dmdevice_over_loop(L_DEVICE_OK, 12*1024*2));
+       OK_(create_dmdevice_over_loop(L_DEVICE_OK, 2*8200));
 
        OK_(crypt_init(&cd, DMDIR H_DEVICE));
 
-       /* encryption with datashift and moved segment (data shift + data offset > device size) */
+       /* encryption with datashift and moved segment (data shift + data offset <= device size) */
        memset(&rparams, 0, sizeof(rparams));
        params2.sector_size = 512;
        params2.data_device = DMDIR L_DEVICE_OK;
@@ -4179,7 +4347,7 @@ static void Luks2Reencryption(void)
        rparams.resilience = "none";
        rparams.max_hotzone_size = 2048;
        OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 6, CRYPT_ANY_SLOT, NULL, NULL, &rparams));
-       OK_(crypt_reencrypt(cd, NULL));
+       OK_(crypt_reencrypt_run(cd, NULL, NULL));
        CRYPT_FREE(cd);
        OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
        OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
@@ -4200,7 +4368,23 @@ static void Luks2Reencryption(void)
        rparams.resilience = "none";
        rparams.max_hotzone_size = 2048;
        OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 6, CRYPT_ANY_SLOT, NULL, NULL, &rparams));
-       OK_(crypt_reencrypt(cd, NULL));
+       OK_(crypt_reencrypt_run(cd, NULL, NULL));
+       CRYPT_FREE(cd);
+
+       /* decryption forward (online) */
+       OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+       params2.data_device = NULL;
+       OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+       OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+       EQ_(crypt_keyslot_add_by_volume_key(cd, 6, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 6);
+       EQ_(crypt_activate_by_passphrase(cd, CDEVICE_2, 6, PASSPHRASE, strlen(PASSPHRASE), 0), 6);
+       memset(&rparams, 0, sizeof(rparams));
+       rparams.mode = CRYPT_REENCRYPT_DECRYPT;
+       rparams.direction = CRYPT_REENCRYPT_FORWARD;
+       rparams.resilience = "none";
+       rparams.max_hotzone_size = 2048;
+       OK_(crypt_reencrypt_init_by_passphrase(cd, CDEVICE_2, PASSPHRASE, strlen(PASSPHRASE), 6, CRYPT_ANY_SLOT, NULL, NULL, &rparams));
+       OK_(crypt_reencrypt_run(cd, NULL, NULL));
        CRYPT_FREE(cd);
 
        /* decryption with data shift */
@@ -4224,7 +4408,7 @@ static void Luks2Reencryption(void)
        rparams.data_shift = r_header_size;
        OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 6, CRYPT_ANY_SLOT, NULL, NULL, &rparams));
        EQ_(crypt_get_data_offset(cd), 0);
-       OK_(crypt_reencrypt(cd, NULL));
+       OK_(crypt_reencrypt_run(cd, NULL, NULL));
        remove(BACKUP_FILE);
        CRYPT_FREE(cd);
 
@@ -4237,6 +4421,8 @@ static void Luks2Reencryption(void)
        EQ_(crypt_activate_by_passphrase(cd, CDEVICE_2, 6, PASSPHRASE, strlen(PASSPHRASE), 0), 6);
        OK_(t_device_size(DMDIR CDEVICE_2, &r_size_1));
        EQ_(r_size_1, 512);
+       // store devno for later size check
+       OK_(t_get_devno(CDEVICE_2, &devno));
        // create placeholder device to block automatic deactivation after decryption
        OK_(_system("dmsetup create " CDEVICE_1 " --table \"0 1 linear " DMDIR CDEVICE_2 " 0\"", 1));
        remove(BACKUP_FILE);
@@ -4254,9 +4440,9 @@ static void Luks2Reencryption(void)
        rparams.data_shift = r_header_size;
        OK_(crypt_reencrypt_init_by_passphrase(cd, CDEVICE_2, PASSPHRASE, strlen(PASSPHRASE), 6, CRYPT_ANY_SLOT, NULL, NULL, &rparams));
        EQ_(crypt_get_data_offset(cd), 0);
-       OK_(crypt_reencrypt(cd, NULL));
+       OK_(crypt_reencrypt_run(cd, NULL, NULL));
        remove(BACKUP_FILE);
-       OK_(t_device_size(DMDIR CDEVICE_2, &r_size_1));
+       OK_(t_device_size_by_devno(devno, &r_size_1));
        EQ_(r_size_1, 512);
        OK_(_system("dmsetup remove " DM_RETRY CDEVICE_1 DM_NOSTDERR, 0));
        CRYPT_FREE(cd);
@@ -4287,7 +4473,7 @@ static void Luks2Reencryption(void)
        rparams.luks2 = &params2;
 
        OK_(crypt_reencrypt_init_by_passphrase(cd, CDEVICE_1, PASSPHRASE, strlen(PASSPHRASE), 6, 1, "aes", "cbc-essiv:sha256", &rparams));
-       OK_(crypt_reencrypt(cd, NULL));
+       OK_(crypt_reencrypt_run(cd, NULL, NULL));
 
        OK_(crypt_init_data_device(&cd2, IMAGE_EMPTY_SMALL, DMDIR L_DEVICE_OK));
        OK_(crypt_load(cd2, CRYPT_LUKS2, NULL));
@@ -4313,9 +4499,9 @@ static void Luks2Reencryption(void)
        rparams.flags = 0;
        rparams.max_hotzone_size = 8;
        OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 6, 1, "aes", "cbc-essiv:sha256", &rparams));
-       /* reencrypt 8 srectors of device */
-       test_progress_steps = 1;
-       OK_(crypt_reencrypt(cd, &test_progress));
+       /* reencrypt 8 sectors of device */
+       test_progress_steps = 2;
+       OK_(crypt_reencrypt_run(cd, &test_progress, NULL));
 
        /* activate another data device with same LUKS2 header (this is wrong, but we can't detect such mistake) */
        OK_(crypt_init_data_device(&cd2, IMAGE_EMPTY_SMALL, DMDIR L_DEVICE_OK));
@@ -4326,8 +4512,8 @@ static void Luks2Reencryption(void)
        /* reencrypt yet another 8 sectors of first device */
        rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
        OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 6, 1, "aes", "cbc-essiv:sha256", &rparams));
-       test_progress_steps = 1;
-       OK_(crypt_reencrypt(cd, &test_progress));
+       test_progress_steps = 2;
+       OK_(crypt_reencrypt_run(cd, &test_progress, NULL));
 
        /* Now active mapping for second data device does not match its metadata */
        OK_(crypt_init_data_device(&cd2, IMAGE_EMPTY_SMALL, DMDIR L_DEVICE_OK));
@@ -4359,8 +4545,8 @@ static void Luks2Reencryption(void)
        rparams.flags = 0;
        EQ_(crypt_keyslot_add_by_key(cd, 1, NULL, 64, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 1);
        OK_(crypt_reencrypt_init_by_passphrase(cd, CDEVICE_1, PASSPHRASE, strlen(PASSPHRASE), 6, 1, "aes", "xts-plain64", &rparams));
-       test_progress_steps = 1;
-       OK_(crypt_reencrypt(cd, &test_progress));
+       test_progress_steps = 2;
+       OK_(crypt_reencrypt_run(cd, &test_progress, NULL));
        EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_CLEAN);
        OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
        EQ_(cad.flags & CRYPT_ACTIVATE_ALLOW_DISCARDS, CRYPT_ACTIVATE_ALLOW_DISCARDS);
@@ -4369,7 +4555,7 @@ static void Luks2Reencryption(void)
        OK_(crypt_init_by_name(&cd, CDEVICE_1));
        rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
        OK_(crypt_reencrypt_init_by_passphrase(cd, CDEVICE_1, PASSPHRASE, strlen(PASSPHRASE), 6, 1, "aes", "xts-plain64", &rparams));
-       OK_(crypt_reencrypt(cd, NULL));
+       OK_(crypt_reencrypt_run(cd, NULL, NULL));
        OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
        EQ_(cad.flags & CRYPT_ACTIVATE_ALLOW_DISCARDS, CRYPT_ACTIVATE_ALLOW_DISCARDS);
        EQ_(cad.flags & CRYPT_ACTIVATE_KEYRING_KEY, 0);
@@ -4397,27 +4583,447 @@ static void Luks2Reencryption(void)
        EQ_(crypt_keyslot_add_by_key(cd, 9, key, key_size, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 9);
        EQ_(crypt_keyslot_add_by_key(cd, 10, key, key_size, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT | CRYPT_VOLUME_KEY_DIGEST_REUSE ), 10);
        OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 3, 9, "aes", "xts-plain64", &rparams));
-       OK_(crypt_reencrypt(cd, NULL));
+       OK_(crypt_reencrypt_run(cd, NULL, NULL));
        OK_(crypt_activate_by_volume_key(cd, NULL, key, key_size, 0));
        OK_(crypt_keyslot_destroy(cd, 9));
        OK_(crypt_activate_by_volume_key(cd, NULL, key, key_size, 0));
-       crypt_free(cd);
+       CRYPT_FREE(cd);
+
+       _cleanup_dmdevices();
+       OK_(create_dmdevice_over_loop(L_DEVICE_OK, 2 * r_header_size));
+       OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
+
+       rparams = (struct crypt_params_reencrypt) {
+               .mode = CRYPT_REENCRYPT_DECRYPT,
+               .direction = CRYPT_REENCRYPT_FORWARD,
+               .resilience = "datashift-checksum",
+               .hash = "sha256",
+               .data_shift = r_header_size,
+               .flags = CRYPT_REENCRYPT_INITIALIZE_ONLY | CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT
+       };
+
+       OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+       OK_(set_fast_pbkdf(cd));
+       OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "xts-plain64", NULL, NULL, 64, NULL));
+       EQ_(0, crypt_keyslot_add_by_volume_key(cd, 0, NULL, 64, PASSPHRASE, strlen(PASSPHRASE)));
+       OK_(crypt_header_backup(cd, CRYPT_LUKS2, BACKUP_FILE));
+       CRYPT_FREE(cd);
+
+       params2.data_device = DMDIR L_DEVICE_OK;
+       params2.sector_size = 512;
+
+       /* create detached LUKS2 header (with data_offset == 0) */
+       OK_(crypt_init(&cd, DMDIR H_DEVICE));
+       OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "xts-plain64", NULL, NULL, 64, &params2));
+       EQ_(crypt_get_data_offset(cd), 0);
+       OK_(set_fast_pbkdf(cd));
+       EQ_(0, crypt_keyslot_add_by_volume_key(cd, 0, NULL, 64, PASSPHRASE, strlen(PASSPHRASE)));
+       CRYPT_FREE(cd);
+
+       /* initiate LUKS2 decryption with datashift on bogus LUKS2 header (data_offset == 0) */
+       OK_(crypt_init_data_device(&cd, DMDIR H_DEVICE, DMDIR L_DEVICE_OK));
+       OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+       FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Illegal data offset");
+       /* reencryption must not initialize */
+       EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+       CRYPT_FREE(cd);
+       /* original data device must stay untouched */
+       OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+       OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+       EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+       CRYPT_FREE(cd);
+
+       OK_(chmod(BACKUP_FILE, S_IRUSR|S_IWUSR));
+       OK_(crypt_init_data_device(&cd, BACKUP_FILE, DMDIR L_DEVICE_OK));
+       OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+
+       /* simulate read error at first segment beyond data offset*/
+       OK_(dmdevice_error_io(L_DEVICE_OK, DMDIR L_DEVICE_OK, DEVICE_ERROR, 0, r_header_size, 8, ERR_RD));
+
+       FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Could not read first data segment");
+       CRYPT_FREE(cd);
+
+       /* Device must not be in reencryption */
+       OK_(crypt_init_data_device(&cd, BACKUP_FILE, DMDIR L_DEVICE_OK));
+       OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+       EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+
+       /* simulate write error in original LUKS2 header area */
+       OK_(dmdevice_error_io(L_DEVICE_OK, DMDIR L_DEVICE_OK, DEVICE_ERROR, 0, 0, 8, ERR_WR));
+
+       FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Could not write first data segment");
+       CRYPT_FREE(cd);
+
+       /* Device must not be in reencryption */
+       OK_(crypt_init_data_device(&cd, BACKUP_FILE, DMDIR L_DEVICE_OK));
+       OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+       EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+       CRYPT_FREE(cd);
+       remove(BACKUP_FILE);
+
+       /* remove error mapping */
+       OK_(dmdevice_error_io(L_DEVICE_OK, DMDIR L_DEVICE_OK, DEVICE_ERROR, 0, 0, 8, ERR_REMOVE));
+
+       /* test various bogus reencryption resilience parameters */
+       rparams = (struct crypt_params_reencrypt) {
+               .mode = CRYPT_REENCRYPT_DECRYPT,
+               .direction = CRYPT_REENCRYPT_FORWARD,
+               .resilience = "checksum", /* should have been datashift-checksum */
+               .hash = "sha256",
+               .data_shift = r_header_size,
+               .flags = CRYPT_REENCRYPT_INITIALIZE_ONLY | CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT
+       };
+
+       OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+       OK_(set_fast_pbkdf(cd));
+       OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "xts-plain64", NULL, NULL, 64, NULL));
+       EQ_(0, crypt_keyslot_add_by_volume_key(cd, 0, NULL, 64, PASSPHRASE, strlen(PASSPHRASE)));
+       OK_(crypt_header_backup(cd, CRYPT_LUKS2, BACKUP_FILE));
+       CRYPT_FREE(cd);
+
+       OK_(chmod(BACKUP_FILE, S_IRUSR|S_IWUSR));
+       OK_(crypt_init_data_device(&cd, BACKUP_FILE, DMDIR L_DEVICE_OK));
+       OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
 
+       /* decryption on device with data offset and no datashift subvariant mode */
+       FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
+       EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+
+       rparams.resilience = "journal"; /* should have been datashift-journal */
+       FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
+       EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+
+       rparams = (struct crypt_params_reencrypt) {
+               .mode = CRYPT_REENCRYPT_DECRYPT,
+               .direction = CRYPT_REENCRYPT_FORWARD,
+               .resilience = "datashift-checksum",
+               .hash = "sha256",
+               .data_shift = 0, /* must be non zero */
+               .flags = CRYPT_REENCRYPT_INITIALIZE_ONLY | CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT
+       };
+
+       /* datashift = 0 */
+       FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
+       EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+
+       rparams.resilience = "datashift-journal";
+       FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
+       EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+
+       rparams.resilience = "datashift"; /* datashift only is not supported in decryption mode with moved segment */
+       FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
+       EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+
+       CRYPT_FREE(cd);
+
+       OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+       OK_(set_fast_pbkdf(cd));
+       OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+       EQ_(crypt_keyslot_add_by_volume_key(cd, 21, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 21);
+
+       rparams = (struct crypt_params_reencrypt) {
+               .mode = CRYPT_REENCRYPT_REENCRYPT,
+               .direction = CRYPT_REENCRYPT_FORWARD,
+               .resilience = "datashift-checksum",
+               .hash = "sha256",
+               .data_shift = r_header_size,
+               .flags = CRYPT_REENCRYPT_INITIALIZE_ONLY
+       };
+
+       /* regular reencryption must not accept datashift subvariants */
+       FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
+       EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+
+       rparams.resilience = "datashift-journal";
+       FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
+       EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+
+       CRYPT_FREE(cd);
        _cleanup_dmdevices();
 }
 #endif
 
+static void LuksKeyslotAdd(void)
+{
+       struct crypt_params_luks2 params = {
+               .sector_size = 512
+       };
+       char key[128], key3[128];
+#ifdef KERNEL_KEYRING
+       int ks;
+       key_serial_t kid;
+#endif
+       const struct crypt_token_params_luks2_keyring tparams = {
+               .key_description = KEY_DESC_TEST0
+       };
+
+       const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+       const char *vk_hex2 = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1e";
+       size_t key_size = strlen(vk_hex) / 2;
+       const char *cipher = "aes";
+       const char *cipher_mode = "cbc-essiv:sha256";
+       uint64_t r_payload_offset;
+       struct crypt_keyslot_context *um1, *um2;
+
+       crypt_decode_key(key, vk_hex, key_size);
+       crypt_decode_key(key3, vk_hex2, key_size);
+
+       // init test devices
+       OK_(get_luks2_offsets(0, 0, 0, NULL, &r_payload_offset));
+       OK_(create_dmdevice_over_loop(H_DEVICE, r_payload_offset + 1));
+
+       // test support for embedded key (after crypt_format)
+       OK_(crypt_init(&cd, DMDIR H_DEVICE));
+       OK_(set_fast_pbkdf(cd));
+       OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+       OK_(crypt_keyslot_context_init_by_volume_key(cd, NULL, key_size, &um1));
+       OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um2));
+       EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 3, um2, 0), 3);
+       EQ_(crypt_keyslot_status(cd, 3), CRYPT_SLOT_ACTIVE_LAST);
+       crypt_keyslot_context_free(um1);
+       crypt_keyslot_context_free(um2);
+       CRYPT_FREE(cd);
+
+       // test add by volume key
+       OK_(crypt_init(&cd, DMDIR H_DEVICE));
+       OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+       OK_(set_fast_pbkdf(cd));
+       OK_(crypt_keyslot_context_init_by_volume_key(cd, key, key_size, &um1));
+       OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE1, strlen(PASSPHRASE1), &um2));
+       EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, CRYPT_ANY_SLOT, um2, 0), 0);
+       EQ_(crypt_keyslot_status(cd, 0), CRYPT_SLOT_ACTIVE);
+       crypt_keyslot_context_free(um1);
+       crypt_keyslot_context_free(um2);
+
+       // Add by same passphrase
+       OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um1));
+       EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 1, um1, 0), 1);
+       EQ_(crypt_keyslot_status(cd, 1), CRYPT_SLOT_ACTIVE);
+       crypt_keyslot_context_free(um1);
+
+       // new passphrase can't be provided by key method
+       OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um1));
+       OK_(crypt_keyslot_context_init_by_volume_key(cd, key, key_size, &um2));
+       FAIL_(crypt_keyslot_add_by_keyslot_context(cd, 1, um1, CRYPT_ANY_SLOT, um2, 0), "Can't get passphrase via selected unlock method");
+       crypt_keyslot_context_free(um1);
+       crypt_keyslot_context_free(um2);
+
+       // add by keyfile
+       OK_(prepare_keyfile(KEYFILE1, PASSPHRASE1, strlen(PASSPHRASE1)));
+       OK_(prepare_keyfile(KEYFILE2, KEY1, strlen(KEY1)));
+       OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &um1));
+       OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE2, 0, 0, &um2));
+       EQ_(crypt_keyslot_add_by_keyslot_context(cd, 0, um1, 2, um2, 0), 2);
+       EQ_(crypt_keyslot_status(cd, 2), CRYPT_SLOT_ACTIVE);
+       crypt_keyslot_context_free(um1);
+       crypt_keyslot_context_free(um2);
+
+       // add by same keyfile
+       OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE2, 0, 0, &um1));
+       EQ_(crypt_keyslot_add_by_keyslot_context(cd, 2, um1, 4, um1, 0), 4);
+       EQ_(crypt_keyslot_status(cd, 4), CRYPT_SLOT_ACTIVE);
+       crypt_keyslot_context_free(um1);
+
+       // keyslot already exists
+       OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um1));
+       OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &um2));
+       FAIL_(crypt_keyslot_add_by_keyslot_context(cd, 3, um1, 0, um2, 0), "Keyslot already exists.");
+       crypt_keyslot_context_free(um1);
+       crypt_keyslot_context_free(um2);
+
+       // generate new unbound key
+       OK_(crypt_keyslot_context_init_by_volume_key(cd, NULL, 9, &um1));
+       OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &um2));
+       EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 10, um2, CRYPT_VOLUME_KEY_NO_SEGMENT), 10);
+       EQ_(crypt_keyslot_status(cd, 10), CRYPT_SLOT_UNBOUND);
+       crypt_keyslot_context_free(um1);
+       crypt_keyslot_context_free(um2);
+
+       EQ_(crypt_token_luks2_keyring_set(cd, 3, &tparams), 3);
+       EQ_(crypt_token_assign_keyslot(cd, 3, 1), 3);
+       EQ_(crypt_token_assign_keyslot(cd, 3, 3), 3);
+
+       // test unlocking/adding keyslot by LUKS2 token
+       OK_(crypt_keyslot_context_init_by_token(cd, CRYPT_ANY_TOKEN, NULL, NULL, 0, NULL, &um1));
+       OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &um2));
+       // passphrase not in keyring
+       FAIL_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 13, um2, 0), "No token available.");
+#ifdef KERNEL_KEYRING
+       // wrong passphrase in keyring
+       kid = add_key("user", KEY_DESC_TEST0, PASSPHRASE1, strlen(PASSPHRASE1), KEY_SPEC_THREAD_KEYRING);
+       NOTFAIL_(kid, "Test or kernel keyring are broken.");
+       FAIL_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 13, um2, 0), "No token available.");
+
+       // token unlocks keyslot
+       kid = add_key("user", KEY_DESC_TEST0, PASSPHRASE, strlen(PASSPHRASE), KEY_SPEC_THREAD_KEYRING);
+       NOTFAIL_(kid, "Test or kernel keyring are broken.");
+       EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 13, um2, 0), 13);
+       EQ_(crypt_keyslot_status(cd, 13), CRYPT_SLOT_ACTIVE);
+
+       crypt_keyslot_context_free(um1);
+       crypt_keyslot_context_free(um2);
+
+       // token provides passphrase for new keyslot
+       OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um1));
+       OK_(crypt_keyslot_context_init_by_token(cd, CRYPT_ANY_TOKEN, NULL, NULL, 0, NULL, &um2));
+       EQ_(crypt_keyslot_add_by_keyslot_context(cd, 3, um1, 30, um2, 0), 30);
+       EQ_(crypt_keyslot_status(cd, 30), CRYPT_SLOT_ACTIVE);
+       OK_(crypt_token_is_assigned(cd, 3, 30));
+
+       // unlock and add by same token
+       crypt_keyslot_context_free(um1);
+       OK_(crypt_keyslot_context_init_by_token(cd, CRYPT_ANY_TOKEN, NULL, NULL, 0, NULL, &um1));
+       ks = crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, CRYPT_ANY_SLOT, um1, 0);
+       GE_(ks, 0);
+       EQ_(crypt_keyslot_status(cd, ks), CRYPT_SLOT_ACTIVE);
+       OK_(crypt_token_is_assigned(cd, 3, ks));
+#endif
+       crypt_keyslot_context_free(um1);
+       crypt_keyslot_context_free(um2);
+
+       CRYPT_FREE(cd);
+
+       _cleanup_dmdevices();
+}
+
+static void VolumeKeyGet(void)
+{
+       struct crypt_params_luks2 params = {
+               .sector_size = 512
+       };
+       char key[256], key2[256];
+#ifdef KERNEL_KEYRING
+       key_serial_t kid;
+       const struct crypt_token_params_luks2_keyring tparams = {
+               .key_description = KEY_DESC_TEST0
+       };
+#endif
+
+       const char *vk_hex =  "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a"
+                             "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1b";
+       size_t key_size = strlen(vk_hex) / 2;
+       const char *cipher = "aes";
+       const char *cipher_mode = "xts-plain64";
+       uint64_t r_payload_offset;
+       struct crypt_keyslot_context *um1, *um2;
+
+       crypt_decode_key(key, vk_hex, key_size);
+
+       OK_(prepare_keyfile(KEYFILE1, PASSPHRASE1, strlen(PASSPHRASE1)));
+
+#ifdef KERNEL_KEYRING
+       kid = add_key("user", KEY_DESC_TEST0, PASSPHRASE1, strlen(PASSPHRASE1), KEY_SPEC_THREAD_KEYRING);
+       NOTFAIL_(kid, "Test or kernel keyring are broken.");
+#endif
+
+       // init test devices
+       OK_(get_luks2_offsets(0, 0, 0, NULL, &r_payload_offset));
+       OK_(create_dmdevice_over_loop(H_DEVICE, r_payload_offset + 1));
+
+       // test support for embedded key (after crypt_format)
+       OK_(crypt_init(&cd, DMDIR H_DEVICE));
+       OK_(set_fast_pbkdf(cd));
+       OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, key_size, &params));
+       key_size--;
+       FAIL_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, NULL), "buffer too small");
+
+       // check cached generated volume key can be retrieved
+       key_size++;
+       OK_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, NULL));
+       OK_(crypt_volume_key_verify(cd, key2, key_size));
+       CRYPT_FREE(cd);
+
+       // check we can add keyslot via retrieved key
+       OK_(crypt_init(&cd, DMDIR H_DEVICE));
+       OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+       OK_(set_fast_pbkdf(cd));
+       OK_(crypt_keyslot_context_init_by_volume_key(cd, key2, key_size, &um1));
+       OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um2));
+       EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 3, um2, 0), 3);
+       crypt_keyslot_context_free(um1);
+       crypt_keyslot_context_free(um2);
+       CRYPT_FREE(cd);
+
+       // check selected volume key can be retrieved and added
+       OK_(crypt_init(&cd, DMDIR H_DEVICE));
+       OK_(set_fast_pbkdf(cd));
+       OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+       memset(key2, 0, key_size);
+       OK_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, NULL));
+       OK_(memcmp(key, key2, key_size));
+       OK_(crypt_keyslot_context_init_by_volume_key(cd, key2, key_size, &um1));
+       OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um2));
+       EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 0, um2, 0), 0);
+       crypt_keyslot_context_free(um2);
+       OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &um2));
+       EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 1, um2, 0), 1);
+       crypt_keyslot_context_free(um2);
+#ifdef KERNEL_KEYRING
+       EQ_(crypt_token_luks2_keyring_set(cd, 0, &tparams), 0);
+       EQ_(crypt_token_assign_keyslot(cd, 0, 1), 0);
+#endif
+       crypt_keyslot_context_free(um1);
+       CRYPT_FREE(cd);
+
+       OK_(crypt_init(&cd, DMDIR H_DEVICE));
+       OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+       // check key context is not usable
+       OK_(crypt_keyslot_context_init_by_volume_key(cd, key, key_size, &um1));
+       EQ_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, um1), -EINVAL);
+       crypt_keyslot_context_free(um1);
+
+       // by passphrase
+       memset(key2, 0, key_size);
+       OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um1));
+       EQ_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, um1), 0);
+       OK_(memcmp(key, key2, key_size));
+       memset(key2, 0, key_size);
+       EQ_(crypt_volume_key_get_by_keyslot_context(cd, 0, key2, &key_size, um1), 0);
+       OK_(memcmp(key, key2, key_size));
+       crypt_keyslot_context_free(um1);
+
+       // by keyfile
+       memset(key2, 0, key_size);
+       OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &um1));
+       EQ_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, um1), 1);
+       OK_(memcmp(key, key2, key_size));
+       memset(key2, 0, key_size);
+       EQ_(crypt_volume_key_get_by_keyslot_context(cd, 1, key2, &key_size, um1), 1);
+       crypt_keyslot_context_free(um1);
+
+#ifdef KERNEL_KEYRING
+       // by token
+       OK_(crypt_keyslot_context_init_by_token(cd, CRYPT_ANY_TOKEN, NULL, NULL, 0, NULL, &um1));
+       memset(key2, 0, key_size);
+       EQ_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, um1), 1);
+       OK_(memcmp(key, key2, key_size));
+       crypt_keyslot_context_free(um1);
+#endif
+       CRYPT_FREE(cd);
+
+       _remove_keyfiles();
+       _cleanup_dmdevices();
+}
+
+static int _crypt_load_check(struct crypt_device *cd)
+{
+#ifdef HAVE_BLKID
+       return crypt_load(cd, CRYPT_LUKS, NULL);
+#else
+       return -ENOTSUP;
+#endif
+}
+
 static void Luks2Repair(void)
 {
        char rollback[256];
 
-       snprintf(rollback, sizeof(rollback),
-                "dd if=" IMAGE_PV_LUKS2_SEC ".bcp of=%s bs=1M 2>/dev/null",
-                DEVICE_6);
+       GE_(snprintf(rollback, sizeof(rollback),
+           "dd if=" IMAGE_PV_LUKS2_SEC ".bcp of=%s bs=1M 2>/dev/null", DEVICE_6), 0);
 
        OK_(crypt_init(&cd, DEVICE_6));
 
-       FAIL_(crypt_load(cd, CRYPT_LUKS, NULL), "Ambiguous signature detected");
+       FAIL_(_crypt_load_check(cd), "Ambiguous signature detected");
        FAIL_(crypt_repair(cd, CRYPT_LUKS1, NULL), "Not a LUKS2 device");
 
        /* check explicit LUKS2 repair works */
@@ -4428,7 +5034,7 @@ static void Luks2Repair(void)
 
        /* rollback */
        OK_(_system(rollback, 1));
-       FAIL_(crypt_load(cd, CRYPT_LUKS, NULL), "Ambiguous signature detected");
+       FAIL_(_crypt_load_check(cd), "Ambiguous signature detected");
 
        /* check repair with type detection works */
        OK_(crypt_repair(cd, CRYPT_LUKS, NULL));
@@ -4440,7 +5046,7 @@ static void Luks2Repair(void)
        OK_(crypt_init(&cd, DEVICE_6));
        OK_(crypt_metadata_locking(cd, 0));
 
-       FAIL_(crypt_load(cd, CRYPT_LUKS, NULL), "Ambiguous signature detected");
+       FAIL_(_crypt_load_check(cd), "Ambiguous signature detected");
        FAIL_(crypt_repair(cd, CRYPT_LUKS1, NULL), "Not a LUKS2 device");
 
        /* check explicit LUKS2 repair works */
@@ -4451,7 +5057,7 @@ static void Luks2Repair(void)
 
        /* rollback */
        OK_(_system(rollback, 1));
-       FAIL_(crypt_load(cd, CRYPT_LUKS, NULL), "Ambiguous signature detected");
+       FAIL_(_crypt_load_check(cd), "Ambiguous signature detected");
 
        /* check repair with type detection works */
        OK_(crypt_repair(cd, CRYPT_LUKS, NULL));
@@ -4524,6 +5130,8 @@ int main(int argc, char *argv[])
 #if KERNEL_KEYRING && USE_LUKS2_REENCRYPTION
        RUN_(Luks2Reencryption, "LUKS2 reencryption");
 #endif
+       RUN_(LuksKeyslotAdd, "Adding keyslot via new API");
+       RUN_(VolumeKeyGet, "Getting volume key via keyslot context API");
        RUN_(Luks2Repair, "LUKS2 repair"); // test disables metadata locking. Run always last!
 
        _cleanup();