Imported Upstream version 2.6.1
[platform/upstream/cryptsetup.git] / tests / api-test.c
index 85f7a93..aa430dd 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * cryptsetup library 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
 #include <sys/types.h>
 
 #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
@@ -67,8 +65,8 @@
 #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"
 
@@ -110,17 +108,17 @@ static int get_luks_offsets(int metadata_device,
                return -1;
        }
 
-       sectors_per_stripes_set = DIV_ROUND_UP(keylength*LUKS_STRIPES, SECTOR_SIZE);
-       current_sector = DIV_ROUND_UP_MODULO(DIV_ROUND_UP(LUKS_PHDR_SIZE_B, SECTOR_SIZE),
-                       LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE);
+       sectors_per_stripes_set = DIV_ROUND_UP(keylength*LUKS_STRIPES, TST_SECTOR_SIZE);
+       current_sector = DIV_ROUND_UP_MODULO(DIV_ROUND_UP(LUKS_PHDR_SIZE_B, TST_SECTOR_SIZE),
+                       LUKS_ALIGN_KEYSLOTS / TST_SECTOR_SIZE);
        for (i=0; i < (LUKS_NUMKEYS - 1); i++)
                current_sector = DIV_ROUND_UP_MODULO(current_sector + sectors_per_stripes_set,
-                               LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE);
+                               LUKS_ALIGN_KEYSLOTS / TST_SECTOR_SIZE);
        if (r_header_size)
                *r_header_size = current_sector + sectors_per_stripes_set;
 
        current_sector = DIV_ROUND_UP_MODULO(current_sector + sectors_per_stripes_set,
-                               LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE);
+                               LUKS_ALIGN_KEYSLOTS / TST_SECTOR_SIZE);
 
        if (r_payload_offset) {
                if (metadata_device)
@@ -239,13 +237,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;
 
@@ -253,13 +255,17 @@ 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;
 
@@ -292,8 +298,12 @@ static int _setup(void)
        /* Prepare tcrypt images */
        _system("tar xJf tcrypt-images.tar.xz 2>/dev/null", 1);
 
-       _system("modprobe dm-crypt", 0);
-       _system("modprobe dm-verity", 0);
+       _system("modprobe dm-crypt >/dev/null 2>&1", 0);
+       _system("modprobe dm-verity >/dev/null 2>&1", 0);
+       _system("modprobe dm-integrity >/dev/null 2>&1", 0);
+
+       if (t_dm_check_versions())
+               return 1;
 
        _fips_mode = fips_mode();
        if (_debug)
@@ -308,24 +318,25 @@ static int _setup(void)
 static void AddDevicePlain(void)
 {
        struct crypt_params_plain params = {
-               .hash = "sha1",
+               .hash = "sha256",
                .skip = 0,
                .offset = 0,
                .size = 0
        };
        int fd;
        char key[128], key2[128], path[128];
+       struct crypt_keyslot_context *kc = NULL;
 
-       const char *passphrase = PASSPHRASE;
+       const char *passphrase = "blabla";
        // hashed hex version of PASSPHRASE
-       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 size, r_size;
 
-       crypt_decode_key(key, mk_hex, key_size);
+       crypt_decode_key(key, vk_hex, key_size);
        FAIL_(crypt_init(&cd, ""), "empty device string");
        FAIL_(crypt_init(&cd, DEVICE_WRONG), "nonexistent device name ");
        FAIL_(crypt_init(&cd, DEVICE_CHAR), "character device as backing device");
@@ -365,7 +376,7 @@ static void AddDevicePlain(void)
        t_device_size(DEVICE_1,&size);
        params.hash = NULL;
        // zero sectors length
-       params.offset = size >> SECTOR_SHIFT;
+       params.offset = size >> TST_SECTOR_SHIFT;
        OK_(crypt_init(&cd, DEVICE_1));
        OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
        EQ_(crypt_get_data_offset(cd),params.offset);
@@ -373,22 +384,22 @@ static void AddDevicePlain(void)
        FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0), "invalid device size (0 blocks)");
        EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
        // data part of crypt device is of 1 sector size
-       params.offset = (size >> SECTOR_SHIFT) - 1;
+       params.offset = (size >> TST_SECTOR_SHIFT) - 1;
        CRYPT_FREE(cd);
 
        OK_(crypt_init(&cd, DEVICE_1));
        OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
        OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0));
        GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
-       snprintf(path, sizeof(path), "%s/%s", crypt_get_dir(), CDEVICE_1);
+       GE_(snprintf(path, sizeof(path), "%s/%s", crypt_get_dir(), CDEVICE_1), 0);
        if (t_device_size(path, &r_size) >= 0)
-               EQ_(r_size>>SECTOR_SHIFT, 1);
+               EQ_(r_size >> TST_SECTOR_SHIFT, 1);
        OK_(crypt_deactivate(cd, CDEVICE_1));
        CRYPT_FREE(cd);
 
        // size > device_size
        params.offset = 0;
-       params.size = (size >> SECTOR_SHIFT) + 1;
+       params.size = (size >> TST_SECTOR_SHIFT) + 1;
        crypt_init(&cd, DEVICE_1);
        OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
        FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0),"Device too small");
@@ -396,7 +407,7 @@ static void AddDevicePlain(void)
        CRYPT_FREE(cd);
 
        // offset == device_size (autodetect size)
-       params.offset = (size >> SECTOR_SHIFT);
+       params.offset = (size >> TST_SECTOR_SHIFT);
        params.size = 0;
        crypt_init(&cd, DEVICE_1);
        OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
@@ -405,7 +416,7 @@ static void AddDevicePlain(void)
        CRYPT_FREE(cd);
 
        // offset == device_size (user defined size)
-       params.offset = (size >> SECTOR_SHIFT);
+       params.offset = (size >> TST_SECTOR_SHIFT);
        params.size = 123;
        crypt_init(&cd, DEVICE_1);
        OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
@@ -415,7 +426,7 @@ static void AddDevicePlain(void)
 
        // offset+size > device_size
        params.offset = 42;
-       params.size = (size >> SECTOR_SHIFT) - params.offset + 1;
+       params.size = (size >> TST_SECTOR_SHIFT) - params.offset + 1;
        crypt_init(&cd, DEVICE_1);
        OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
        FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0),"Offset and size are beyond device real size");
@@ -424,17 +435,17 @@ static void AddDevicePlain(void)
 
        // offset+size == device_size
        params.offset = 42;
-       params.size = (size >> SECTOR_SHIFT) - params.offset;
+       params.size = (size >> TST_SECTOR_SHIFT) - params.offset;
        crypt_init(&cd, DEVICE_1);
        OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
        OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0));
        GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
        if (!t_device_size(path, &r_size))
-               EQ_((r_size >> SECTOR_SHIFT),params.size);
+               EQ_((r_size >> TST_SECTOR_SHIFT),params.size);
        OK_(crypt_deactivate(cd,CDEVICE_1));
 
        CRYPT_FREE(cd);
-       params.hash = "sha1";
+       params.hash = "sha256";
        params.offset = 0;
        params.size = 0;
        params.skip = 0;
@@ -448,7 +459,7 @@ static void AddDevicePlain(void)
 
        // device status check
        GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
-       snprintf(path, sizeof(path), "%s/%s", crypt_get_dir(), CDEVICE_1);
+       GE_(snprintf(path, sizeof(path), "%s/%s", crypt_get_dir(), CDEVICE_1), 0);
        fd = open(path, O_RDONLY);
        EQ_(crypt_status(cd, CDEVICE_1), CRYPT_BUSY);
        FAIL_(crypt_deactivate(cd, CDEVICE_1), "Device is busy");
@@ -487,6 +498,7 @@ static void AddDevicePlain(void)
        // crypt_set_data_device
        FAIL_(crypt_set_data_device(cd,H_DEVICE),"can't set data device for plain device");
        NULL_(crypt_get_metadata_device_name(cd));
+       FAIL_(crypt_header_is_detached(cd), "plain has no header");
 
        // crypt_get_type
        OK_(strcmp(crypt_get_type(cd),CRYPT_PLAIN));
@@ -495,18 +507,18 @@ static void AddDevicePlain(void)
        GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
 
        // crypt_resize()
-       OK_(crypt_resize(cd,CDEVICE_1,size>>SECTOR_SHIFT)); // same size
+       OK_(crypt_resize(cd, CDEVICE_1, size >> TST_SECTOR_SHIFT)); // same size
        if (!t_device_size(path,&r_size))
                EQ_(r_size, size);
 
        // size overlaps
        FAIL_(crypt_resize(cd, CDEVICE_1, (uint64_t)-1),"Backing device is too small");
-       FAIL_(crypt_resize(cd, CDEVICE_1, (size>>SECTOR_SHIFT)+1),"crypt device overlaps backing device");
+       FAIL_(crypt_resize(cd, CDEVICE_1, (size >> TST_SECTOR_SHIFT) + 1),"crypt device overlaps backing device");
 
        // resize ok
        OK_(crypt_resize(cd,CDEVICE_1, 123));
        if (!t_device_size(path,&r_size))
-               EQ_(r_size>>SECTOR_SHIFT, 123);
+               EQ_(r_size >> TST_SECTOR_SHIFT, 123);
        OK_(crypt_resize(cd,CDEVICE_1,0)); // full size (autodetect)
        if (!t_device_size(path,&r_size))
                EQ_(r_size, size);
@@ -517,20 +529,20 @@ static void AddDevicePlain(void)
        // offset tests
        OK_(crypt_init(&cd,DEVICE_1));
        params.offset = 42;
-       params.size = (size>>SECTOR_SHIFT) - params.offset - 10;
+       params.size = (size >> TST_SECTOR_SHIFT) - params.offset - 10;
        OK_(crypt_format(cd,CRYPT_PLAIN,cipher,cipher_mode,NULL,NULL,key_size,&params));
        OK_(crypt_activate_by_volume_key(cd,CDEVICE_1,key,key_size,0));
        if (!t_device_size(path,&r_size))
-               EQ_(r_size>>SECTOR_SHIFT, params.size);
+               EQ_(r_size >> TST_SECTOR_SHIFT, params.size);
        // resize to fill remaining capacity
        OK_(crypt_resize(cd,CDEVICE_1,params.size + 10));
        if (!t_device_size(path,&r_size))
-               EQ_(r_size>>SECTOR_SHIFT, params.size + 10);
+               EQ_(r_size >> TST_SECTOR_SHIFT, params.size + 10);
 
        // 1 sector beyond real size
        FAIL_(crypt_resize(cd,CDEVICE_1,params.size + 11), "new device size overlaps backing device"); // with respect to offset
        if (!t_device_size(path,&r_size))
-               EQ_(r_size>>SECTOR_SHIFT, params.size + 10);
+               EQ_(r_size >> TST_SECTOR_SHIFT, params.size + 10);
        GE_(crypt_status(cd,CDEVICE_1),CRYPT_ACTIVE);
        fd = open(path, O_RDONLY);
        NOTFAIL_(fd, "Bad loop device.");
@@ -539,11 +551,11 @@ static void AddDevicePlain(void)
        // resize to minimal size
        OK_(crypt_resize(cd,CDEVICE_1, 1)); // minimal device size
        if (!t_device_size(path,&r_size))
-               EQ_(r_size>>SECTOR_SHIFT, 1);
+               EQ_(r_size >> TST_SECTOR_SHIFT, 1);
        // use size of backing device (autodetect with respect to offset)
        OK_(crypt_resize(cd,CDEVICE_1,0));
        if (!t_device_size(path,&r_size))
-               EQ_(r_size>>SECTOR_SHIFT, (size >> SECTOR_SHIFT)- 42);
+               EQ_(r_size >> TST_SECTOR_SHIFT, (size >> TST_SECTOR_SHIFT)- 42);
        OK_(crypt_deactivate(cd,CDEVICE_1));
        CRYPT_FREE(cd);
 
@@ -567,6 +579,11 @@ static void AddDevicePlain(void)
        key_size++;
        OK_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key2, &key_size, passphrase, strlen(passphrase)));
        OK_(memcmp(key, key2, key_size));
+       memset(key2, 0, key_size);
+       OK_(crypt_keyslot_context_init_by_passphrase(cd, passphrase, strlen(passphrase), &kc));
+       OK_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, kc));
+       OK_(memcmp(key, key2, key_size));
+       crypt_keyslot_context_free(kc);
 
        OK_(strcmp(cipher, crypt_get_cipher(cd)));
        OK_(strcmp(cipher_mode, crypt_get_cipher_mode(cd)));
@@ -599,6 +616,9 @@ static void AddDevicePlain(void)
        FAIL_(crypt_keyslot_add_by_keyfile(cd,CRYPT_ANY_SLOT,KEYFILE1,strlen(KEY1),KEYFILE2,strlen(KEY2)),"can't add keyslot to plain device");
        FAIL_(crypt_keyslot_destroy(cd,1),"can't manipulate keyslots on plain device");
        EQ_(crypt_keyslot_status(cd, 0), CRYPT_SLOT_INVALID);
+       FAIL_(crypt_set_label(cd, "label", "subsystem"), "can't set labels for plain device");
+       NULL_(crypt_get_label(cd));
+       NULL_(crypt_get_subsystem(cd));
        _remove_keyfiles();
 
        CRYPT_FREE(cd);
@@ -615,7 +635,7 @@ static void new_log(int level, const char *msg, void *usrptr)
 static void CallbacksTest(void)
 {
        struct crypt_params_plain params = {
-               .hash = "sha1",
+               .hash = "sha256",
                .skip = 0,
                .offset = 0,
        };
@@ -752,6 +772,10 @@ static void SuspendDevice(void)
        OK_(crypt_deactivate(cd, CDEVICE_1));
        CRYPT_FREE(cd);
 
+       /* skip tests using empty passphrase */
+       if(_fips_mode)
+               return;
+
        OK_(get_luks_offsets(0, key_size, 1024*2, 0, NULL, &r_payload_offset));
        OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1));
 
@@ -786,17 +810,17 @@ static void AddDeviceLuks(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 *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;
        struct crypt_pbkdf_type pbkdf;
 
-       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_luks_offsets(1, key_size, 0, 0, &r_header_size, &r_payload_offset));
@@ -877,7 +901,7 @@ static void AddDeviceLuks(void)
        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
@@ -921,6 +945,7 @@ static void AddDeviceLuks(void)
        OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
        OK_(crypt_format(cd, CRYPT_LUKS1, 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;
@@ -935,6 +960,7 @@ static void AddDeviceLuks(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;
@@ -1023,11 +1049,16 @@ static void AddDeviceLuks(void)
        OK_(crypt_dump(cd));
        OK_(!(global_lines != 0));
        reset_log();
+       FAIL_(crypt_dump_json(cd, NULL, 0), "LUKS1 not supported");
 
        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)));
 
+       FAIL_(crypt_set_label(cd, "label", "subsystem"), "can't set labels for LUKS1 device");
+       NULL_(crypt_get_label(cd));
+       NULL_(crypt_get_subsystem(cd));
+
        FAIL_(crypt_deactivate(cd, CDEVICE_2), "not active");
        CRYPT_FREE(cd);
 
@@ -1063,9 +1094,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));
@@ -1073,10 +1104,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-LUKS1-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));
@@ -1108,20 +1139,20 @@ static void LuksHeaderRestore(void)
                .data_alignment = 2048, // 4M, data offset will be 4096
        };
        struct crypt_params_plain pl_params = {
-               .hash = "sha1",
+               .hash = "sha256",
                .skip = 0,
                .offset = 0,
                .size = 0
        };
        char key[128], key2[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;
 
-       crypt_decode_key(key, mk_hex, key_size);
+       crypt_decode_key(key, vk_hex, key_size);
 
        OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, NULL, &r_payload_offset));
        OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 5000));
@@ -1146,7 +1177,7 @@ static void LuksHeaderRestore(void)
        FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_5), "Header corrupted");
        OK_(crypt_header_restore(cd, CRYPT_LUKS1, VALID_HEADER));
        // wipe valid luks header
-       snprintf(cmd, sizeof(cmd), "dd if=/dev/zero of=" DMDIR L_DEVICE_OK " bs=512 count=%" PRIu64 " 2>/dev/null", r_payload_offset);
+       GE_(snprintf(cmd, sizeof(cmd), "dd if=/dev/zero of=" DMDIR L_DEVICE_OK " bs=512 count=%" PRIu64 " 2>/dev/null", r_payload_offset), 0);
        OK_(_system(cmd, 1));
        FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_1), "Header corrupted");
        FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_2), "Header corrupted");
@@ -1195,21 +1226,21 @@ static void LuksHeaderLoad(void)
                .data_alignment = 2048,
        };
        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;
        uint64_t mdata_size, keyslots_size;
 
-       crypt_decode_key(key, mk_hex, key_size);
+       crypt_decode_key(key, vk_hex, key_size);
 
        // prepare test env
        OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, &r_header_size, &r_payload_offset));
@@ -1218,8 +1249,8 @@ static void LuksHeaderLoad(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, 2050 - 1)); //FIXME
-       //snprintf(cmd, sizeof(cmd), "dd if=" EVL_HEADER_4 " of=" DMDIR H_DEVICE_WRONG " bs=512 count=%" PRIu64, r_payload_offset - 1);
-       snprintf(cmd, sizeof(cmd), "dd if=" EVL_HEADER_4 " of=" DMDIR H_DEVICE_WRONG " bs=512 count=%d 2>/dev/null", 2050 - 1);
+       //GE_(snprintf(cmd, sizeof(cmd), "dd if=" EVL_HEADER_4 " of=" DMDIR H_DEVICE_WRONG " bs=512 count=%" PRIu64, r_payload_offset - 1), 0);
+       GE_(snprintf(cmd, sizeof(cmd), "dd if=" EVL_HEADER_4 " of=" DMDIR H_DEVICE_WRONG " bs=512 count=%d 2>/dev/null", 2050 - 1), 0);
        OK_(_system(cmd, 1));
        // some device
        OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1000));
@@ -1242,6 +1273,7 @@ static void LuksHeaderLoad(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
@@ -1252,6 +1284,7 @@ static void LuksHeaderLoad(void)
        OK_(crypt_load(cd, CRYPT_LUKS1, 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)
@@ -1268,7 +1301,7 @@ static void LuksHeaderLoad(void)
        FAIL_(crypt_set_metadata_size(cd, 0x004000, 0x004000), "Wrong context type");
        OK_(crypt_get_metadata_size(cd, &mdata_size, &keyslots_size));
        EQ_(mdata_size, LUKS_ALIGN_KEYSLOTS);
-       EQ_(keyslots_size, r_header_size * SECTOR_SIZE - mdata_size);
+       EQ_(keyslots_size, r_header_size * TST_SECTOR_SIZE - mdata_size);
        CRYPT_FREE(cd);
        // load should be ok
        OK_(crypt_init(&cd, DMDIR L_DEVICE_0S));
@@ -1312,15 +1345,15 @@ static void LuksHeaderBackup(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;
 
        const char *passphrase = PASSPHRASE;
 
-       crypt_decode_key(key, mk_hex, key_size);
+       crypt_decode_key(key, vk_hex, key_size);
 
        OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, NULL, &r_payload_offset));
        OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1));
@@ -1342,6 +1375,7 @@ static void LuksHeaderBackup(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
@@ -1351,6 +1385,7 @@ static void LuksHeaderBackup(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));
@@ -1392,13 +1427,13 @@ static void ResizeDeviceLuks(void)
        };
        char key[128];
 
-       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, r_size;
 
-       crypt_decode_key(key, mk_hex, key_size);
+       crypt_decode_key(key, vk_hex, key_size);
 
        // prepare env
        OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, NULL, &r_payload_offset));
@@ -1414,14 +1449,14 @@ static void ResizeDeviceLuks(void)
        OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 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);
        // 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);
@@ -1434,14 +1469,14 @@ static void ResizeDeviceLuks(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);
@@ -1480,7 +1515,7 @@ static void HashDevicePlain(void)
        };
 
        size_t key_size;
-       const char *mk_hex, *keystr;
+       const char *vk_hex, *keystr;
        char key[256];
 
        OK_(crypt_init(&cd, DEVICE_1));
@@ -1493,41 +1528,41 @@ static void HashDevicePlain(void)
 
        // hash PLAIN, exact key
        //         0 1 2 3 4 5 6 7 8 9 a b c d e f
-       mk_hex = "caffeecaffeecaffeecaffeecaffee88";
+       vk_hex = "caffeecaffeecaffeecaffeecaffee88";
        key_size = 16;
-       crypt_decode_key(key, mk_hex, key_size);
+       crypt_decode_key(key, vk_hex, key_size);
        OK_(prepare_keyfile(KEYFILE1, key, key_size));
        OK_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, key_size, 0));
        OK_(get_key_dm(CDEVICE_1, key, sizeof(key)));
-       OK_(strcmp(key, mk_hex));
+       OK_(strcmp(key, vk_hex));
        OK_(crypt_deactivate(cd, CDEVICE_1));
 
        // Limit plain key
-       mk_hex = "caffeecaffeecaffeecaffeeca000000";
+       vk_hex = "caffeecaffeecaffeecaffeeca000000";
        OK_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, key_size - 3, 0));
        OK_(get_key_dm(CDEVICE_1, key, sizeof(key)));
-       OK_(strcmp(key, mk_hex));
+       OK_(strcmp(key, vk_hex));
        OK_(crypt_deactivate(cd, CDEVICE_1));
 
        _remove_keyfiles();
 
        // hash PLAIN, long key
        //         0 1 2 3 4 5 6 7 8 9 a b c d e f
-       mk_hex = "caffeecaffeecaffeecaffeecaffee88babebabe";
+       vk_hex = "caffeecaffeecaffeecaffeecaffee88babebabe";
        key_size = 16;
-       crypt_decode_key(key, mk_hex, key_size);
-       OK_(prepare_keyfile(KEYFILE1, key, strlen(mk_hex) / 2));
+       crypt_decode_key(key, vk_hex, key_size);
+       OK_(prepare_keyfile(KEYFILE1, key, strlen(vk_hex) / 2));
        OK_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, key_size, 0));
        OK_(get_key_dm(CDEVICE_1, key, sizeof(key)));
-       FAIL_(strcmp(key, mk_hex), "only key length used");
-       OK_(strncmp(key, mk_hex, key_size));
+       FAIL_(strcmp(key, vk_hex), "only key length used");
+       OK_(strncmp(key, vk_hex, key_size));
        OK_(crypt_deactivate(cd, CDEVICE_1));
 
        // Now without explicit limit
        OK_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0, 0));
        OK_(get_key_dm(CDEVICE_1, key, sizeof(key)));
-       FAIL_(strcmp(key, mk_hex), "only key length used");
-       OK_(strncmp(key, mk_hex, key_size));
+       FAIL_(strcmp(key, vk_hex), "only key length used");
+       OK_(strncmp(key, vk_hex, key_size));
        OK_(crypt_deactivate(cd, CDEVICE_1));
        CRYPT_FREE(cd);
 
@@ -1536,15 +1571,15 @@ static void HashDevicePlain(void)
        // Handling of legacy "plain" hash (no hash)
        params.hash = "plain";
        //         0 1 2 3 4 5 6 7 8 9 a b c d e f
-       mk_hex = "aabbcaffeecaffeecaffeecaffeecaff";
+       vk_hex = "aabbcaffeecaffeecaffeecaffeecaff";
        key_size = 16;
-       crypt_decode_key(key, mk_hex, key_size);
-       OK_(prepare_keyfile(KEYFILE1, key, strlen(mk_hex) / 2));
+       crypt_decode_key(key, vk_hex, key_size);
+       OK_(prepare_keyfile(KEYFILE1, key, strlen(vk_hex) / 2));
        OK_(crypt_init(&cd, DEVICE_1));
        OK_(crypt_format(cd, CRYPT_PLAIN, "aes", "cbc-essiv:sha256", NULL, NULL, 16, &params));
        OK_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, key_size, 0));
        OK_(get_key_dm(CDEVICE_1, key, sizeof(key)));
-       OK_(strcmp(key, mk_hex));
+       OK_(strcmp(key, vk_hex));
        OK_(crypt_deactivate(cd, CDEVICE_1));
        CRYPT_FREE(cd);
 
@@ -1556,19 +1591,19 @@ static void HashDevicePlain(void)
        OK_(crypt_format(cd, CRYPT_PLAIN, "aes", "cbc-essiv:sha256", NULL, NULL, 16, &params));
 
        //         0 1 2 3 4 5 6 7 8 9 a b c d e f
-       mk_hex = "c62e4615bd39e222572f3a1bf7c2132e";
+       vk_hex = "c62e4615bd39e222572f3a1bf7c2132e";
        keystr = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
        key_size = strlen(keystr); // 32
        OK_(prepare_keyfile(KEYFILE1, keystr, strlen(keystr)));
        OK_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, key_size, 0));
        OK_(get_key_dm(CDEVICE_1, key, sizeof(key)));
-       OK_(strcmp(key, mk_hex));
+       OK_(strcmp(key, vk_hex));
        OK_(crypt_deactivate(cd, CDEVICE_1));
 
        // Read full keyfile
        OK_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0, 0));
        OK_(get_key_dm(CDEVICE_1, key, sizeof(key)));
-       OK_(strcmp(key, mk_hex));
+       OK_(strcmp(key, vk_hex));
        OK_(crypt_deactivate(cd, CDEVICE_1));
 
        _remove_keyfiles();
@@ -1578,7 +1613,7 @@ static void HashDevicePlain(void)
        OK_(prepare_keyfile(KEYFILE1, keystr, strlen(keystr)));
        OK_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, key_size, 0));
        OK_(get_key_dm(CDEVICE_1, key, sizeof(key)));
-       OK_(strcmp(key, mk_hex));
+       OK_(strcmp(key, vk_hex));
        OK_(crypt_deactivate(cd, CDEVICE_1));
 
        // Full keyfile
@@ -1690,6 +1725,10 @@ static void VerityTest(void)
        OK_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, root_hash_out, &root_hash_out_size, NULL, 0));
        EQ_(32, root_hash_out_size);
        OK_(memcmp(root_hash, root_hash_out, root_hash_out_size));
+       memset(root_hash_out, 0, root_hash_out_size);
+       OK_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, root_hash_out, &root_hash_out_size, NULL));
+       EQ_(32, root_hash_out_size);
+       OK_(memcmp(root_hash, root_hash_out, root_hash_out_size));
        OK_(crypt_deactivate(cd, CDEVICE_1));
 
        /* hash fail */
@@ -1730,7 +1769,7 @@ static void TcryptTest(void)
        const char *tcrypt_dev = "tcrypt-images/tck_5-sha512-xts-aes";
        const char *tcrypt_dev2 = "tcrypt-images/tc_5-sha512-xts-serpent-twofish-aes";
        size_t key_size = 64;
-       char key[key_size], key_def[key_size];
+       char key[64], key_def[64];
        const char *key_hex =
                "98dee64abe44bbf41d171c1f7b3e8eacda6d6b01f459097459a167f8c2872a96"
                "3979531d1cdc18af62757cf22286f16f8583d848524f128d7594ac2082668c73";
@@ -1766,6 +1805,9 @@ static void TcryptTest(void)
        key_size++;
        OK_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, NULL, 0));
        OK_(memcmp(key, key_def, key_size));
+       memset(key, 0, key_size);
+       OK_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key, &key_size, NULL));
+       OK_(memcmp(key, key_def, key_size));
 
        reset_log();
        OK_(crypt_dump(cd));
@@ -1780,6 +1822,7 @@ static void TcryptTest(void)
        GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
 
        FAIL_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, NULL, 0), "Need crypt_load");
+       FAIL_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key, &key_size, NULL), "Need crypt_load");
 
        // check params after init_by_name
        OK_(strcmp("xts-plain64", crypt_get_cipher_mode(cd)));
@@ -1824,6 +1867,150 @@ static void TcryptTest(void)
        EQ_(crypt_status(NULL, CDEVICE_1 "_1"), CRYPT_INACTIVE);
 }
 
+static void ResizeIntegrity(void)
+{
+       struct crypt_params_integrity params = {
+               .tag_size = 4,
+               .integrity = "crc32c",
+               .sector_size = 4096,
+       };
+       int ret;
+       uint64_t r_size, whole_device_size = 0;
+
+       if (!t_dm_integrity_resize_support()) {
+               printf("WARNING: integrity device resize not supported, skipping test.\n");
+               return;
+       }
+
+       OK_(crypt_init(&cd, DEVICE_2));
+       ret = crypt_format(cd,CRYPT_INTEGRITY,NULL,NULL,NULL,NULL,0,&params);
+       if (ret < 0) {
+               printf("WARNING: cannot format integrity device, skipping test.\n");
+               CRYPT_FREE(cd);
+               return;
+       }
+       OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, NULL, 0, 0));
+       t_device_size(DMDIR CDEVICE_1, &whole_device_size);
+       // shrink the device
+       OK_(crypt_resize(cd, CDEVICE_1, 1024 * 1024 / 512));
+       if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+               EQ_(1024 * 1024 / 512, r_size >> TST_SECTOR_SHIFT);
+       FAIL_(crypt_resize(cd, CDEVICE_1, 1001), "Device too small");
+       // fill the whole device again (size = 0)
+       OK_(crypt_resize(cd, CDEVICE_1, 0));
+       if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+               EQ_(whole_device_size, r_size);
+       GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+       OK_(crypt_deactivate(cd, CDEVICE_1));
+       CRYPT_FREE(cd);
+
+       // detached metadata
+       OK_(create_dmdevice_over_loop(H_DEVICE, 1024 * 1024 / 512));
+       OK_(crypt_init_data_device(&cd, DMDIR H_DEVICE, DEVICE_2));
+       OK_(crypt_format(cd,CRYPT_INTEGRITY,NULL,NULL,NULL,NULL,0,&params));
+       OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, NULL, 0, 0));
+       if (!t_device_size(DMDIR CDEVICE_1, &whole_device_size))
+               EQ_(10 * 1024 * 1024 / 512, whole_device_size >> TST_SECTOR_SHIFT);
+       // shrink the device
+       OK_(crypt_resize(cd, CDEVICE_1, 1024 * 1024 / 512));
+       if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+               EQ_(1024 * 1024 / 512, r_size >> TST_SECTOR_SHIFT);
+       FAIL_(crypt_resize(cd, CDEVICE_1, 1001), "Device too small");
+       // fill the whole device again (size = 0)
+       OK_(crypt_resize(cd, CDEVICE_1, 0));
+       if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+               EQ_(whole_device_size, r_size);
+       GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+       OK_(crypt_deactivate(cd, CDEVICE_1));
+       CRYPT_FREE(cd);
+
+       _cleanup_dmdevices();
+}
+
+static void ResizeIntegrityWithKey(void)
+{
+       struct crypt_params_integrity params = {
+               .tag_size = 4,
+               .integrity = "hmac(sha256)",
+               .journal_integrity = "hmac(sha256)",
+               .journal_crypt = "cbc(aes)",
+               .sector_size = 4096,
+       };
+       int ret;
+       uint64_t r_size, whole_device_size = 0;
+
+       const char *key_integrity_hex = "41b06f3968ff10783edf3dd8c31d0d6e";
+       const char *key_journal_integrity_hex = "9a3f924d03ab4a3307b148f844628f59";
+       const char *key_journal_crypt_hex = "087a6943383f6c344cef03695b4f7277";
+
+       char integrity_key[128], journal_integrity_key[128], journal_crypt_key[128];
+
+       size_t integrity_key_size = strlen(key_integrity_hex) / 2;
+       size_t journal_integrity_key_size = strlen(key_journal_integrity_hex) / 2;
+       size_t journal_crypt_key_size = strlen(key_journal_crypt_hex) / 2;
+
+       crypt_decode_key(integrity_key, key_integrity_hex, integrity_key_size);
+       crypt_decode_key(journal_integrity_key, key_journal_integrity_hex, journal_integrity_key_size);
+       crypt_decode_key(journal_crypt_key, key_journal_crypt_hex, journal_crypt_key_size);
+
+       params.integrity_key_size = integrity_key_size;
+
+       params.journal_integrity_key_size = journal_integrity_key_size;
+       params.journal_integrity_key = journal_integrity_key;
+
+       params.journal_crypt_key_size = journal_crypt_key_size;
+       params.journal_crypt_key = journal_crypt_key;
+
+       if (!t_dm_integrity_resize_support()) {
+               printf("WARNING: integrity device resize not supported, skipping test.\n");
+               return;
+       }
+
+       OK_(crypt_init(&cd, DEVICE_2));
+       ret = crypt_format(cd,CRYPT_INTEGRITY,NULL,NULL,NULL,NULL,0,&params);
+       if (ret < 0) {
+               printf("WARNING: cannot format integrity device, skipping test.\n");
+               CRYPT_FREE(cd);
+               return;
+       }
+       OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, integrity_key, integrity_key_size, 0));
+       t_device_size(DMDIR CDEVICE_1, &whole_device_size);
+       // shrink the device
+       OK_(crypt_resize(cd, CDEVICE_1, 1024*1024/512));
+       if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+               EQ_(1024*1024/512, r_size >> TST_SECTOR_SHIFT);
+       FAIL_(crypt_resize(cd, CDEVICE_1, 1001), "Device too small");
+       // fill the whole device again (size = 0)
+       OK_(crypt_resize(cd, CDEVICE_1, 0));
+       if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+               EQ_(whole_device_size, r_size);
+       GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+       OK_(crypt_deactivate(cd, CDEVICE_1));
+       CRYPT_FREE(cd);
+
+       // detached metadata
+       OK_(create_dmdevice_over_loop(H_DEVICE, 1024 * 1024 / 512));
+       OK_(crypt_init_data_device(&cd, DMDIR H_DEVICE, DEVICE_2));
+       OK_(crypt_format(cd,CRYPT_INTEGRITY,NULL,NULL,NULL,NULL,0,&params));
+       OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, integrity_key, integrity_key_size, 0));
+       if (!t_device_size(DMDIR CDEVICE_1, &whole_device_size))
+               EQ_(10*1024*1024/512, whole_device_size >> TST_SECTOR_SHIFT);
+       // shrink the device
+       OK_(crypt_resize(cd, CDEVICE_1, 1024*1024/512));
+       if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+               EQ_(1024*1024/512, r_size >> TST_SECTOR_SHIFT);
+       FAIL_(crypt_resize(cd, CDEVICE_1, 1001), "Device too small");
+       // fill the whole device again (size = 0)
+       OK_(crypt_resize(cd, CDEVICE_1, 0));
+       if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+               EQ_(whole_device_size, r_size);
+       GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+       OK_(crypt_deactivate(cd, CDEVICE_1));
+       CRYPT_FREE(cd);
+
+       _cleanup_dmdevices();
+}
+
 static void IntegrityTest(void)
 {
        struct crypt_params_integrity params = {
@@ -1831,6 +2018,7 @@ static void IntegrityTest(void)
                .integrity = "crc32c",
                .sector_size = 4096,
        }, ip = {};
+       struct crypt_active_device cad;
        int ret;
 
        // FIXME: this should be more detailed
@@ -1850,6 +2038,7 @@ static void IntegrityTest(void)
        EQ_(ip.interleave_sectors, params.interleave_sectors);
        EQ_(ip.journal_size, params.journal_size);
        EQ_(ip.journal_watermark, params.journal_watermark);
+       EQ_(ip.integrity_key_size, 0);
        OK_(strcmp(ip.integrity,params.integrity));
        FAIL_(crypt_set_uuid(cd,DEVICE_1_UUID),"can't set uuid to integrity device");
        CRYPT_FREE(cd);
@@ -1873,10 +2062,253 @@ static void IntegrityTest(void)
        EQ_(ip.tag_size, params.tag_size);
        OK_(strcmp(ip.integrity,params.integrity));
        OK_(strcmp(CRYPT_INTEGRITY,crypt_get_type(cd)));
+
+       if (t_dm_integrity_recalculate_support()) {
+               OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+               EQ_(cad.flags & CRYPT_ACTIVATE_RECALCULATE, 0);
+               OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, NULL, 0, CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_RECALCULATE));
+               OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+               EQ_(cad.flags & CRYPT_ACTIVATE_RECALCULATE, CRYPT_ACTIVATE_RECALCULATE);
+       }
+
        OK_(crypt_deactivate(cd, CDEVICE_1));
        CRYPT_FREE(cd);
 }
 
+static void WipeTest(void)
+{
+       OK_(crypt_init(&cd, NULL));
+       FAIL_(crypt_wipe(cd, NULL, CRYPT_WIPE_ZERO, 0, 4096, 0, 0, NULL, NULL), "No device");
+       FAIL_(crypt_wipe(cd, DEVICE_WRONG, CRYPT_WIPE_ZERO, 0, 4096, 0, 0, NULL, NULL), "Wrong device");
+       OK_(crypt_wipe(cd, DEVICE_1, CRYPT_WIPE_ZERO, 0, 4096, 0, 0, NULL, NULL));
+       OK_(crypt_wipe(cd, DEVICE_1, CRYPT_WIPE_RANDOM, 0, 4096, 0, 0, NULL, NULL));
+       OK_(crypt_wipe(cd, DEVICE_1, CRYPT_WIPE_RANDOM, 0, 4096, 0, CRYPT_WIPE_NO_DIRECT_IO, NULL, NULL));
+       CRYPT_FREE(cd);
+
+       OK_(crypt_init(&cd, DEVICE_1));
+       OK_(crypt_wipe(cd, NULL, CRYPT_WIPE_ZERO, 0, 4096, 0, 0, NULL, NULL));
+       OK_(crypt_wipe(cd, NULL, CRYPT_WIPE_RANDOM, 0, 4096, TST_SECTOR_SIZE, 0, NULL, NULL));
+       FAIL_(crypt_wipe(cd, NULL, CRYPT_WIPE_RANDOM, 0, 4096, TST_SECTOR_SIZE-1, 0, NULL, NULL), "Sector size");
+       FAIL_(crypt_wipe(cd, NULL, CRYPT_WIPE_RANDOM, 0, 4096 - 1, 0, 0, NULL, NULL), "Length size not aligned");
+       FAIL_(crypt_wipe(cd, NULL, CRYPT_WIPE_RANDOM, 1, 4096, 0, 0, NULL, NULL), "Offset not aligned");
+       CRYPT_FREE(cd);
+}
+
+static void LuksKeyslotAdd(void)
+{
+       enum { OFFSET_1M = 2048 , OFFSET_2M = 4096, OFFSET_4M = 8192, OFFSET_8M = 16384 };
+       struct crypt_params_luks1 params = {
+               .hash = "sha512",
+               .data_alignment = OFFSET_1M, // 4M, data offset will be 4096
+       };
+       struct crypt_pbkdf_type min_pbkdf2 = {
+               .type = "pbkdf2",
+               .hash = "sha256",
+               .iterations = 1000,
+               .flags = CRYPT_PBKDF_NO_BENCHMARK
+       };
+       char key[128], key3[128];
+
+       const char *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;
+       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_luks_offsets(0, key_size, params.data_alignment, 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_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+       OK_(crypt_format(cd, CRYPT_LUKS1, 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);
+       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_LUKS1, NULL));
+       OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+       OK_(crypt_keyslot_context_init_by_volume_key(cd, key, key_size, &um1));
+       OK_(crypt_keyslot_context_init_by_passphrase(cd, passphrase2, strlen(passphrase2), &um2));
+       EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, CRYPT_ANY_SLOT, um2, 0), 0);
+       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);
+       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, passphrase2, strlen(passphrase2)));
+       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);
+       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, CRYPT_ANY_SLOT, um1, 4, um1, 0), 4);
+       crypt_keyslot_context_free(um1);
+
+       // keyslot already exists
+       OK_(crypt_keyslot_context_init_by_passphrase(cd, passphrase2, strlen(passphrase2), &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(um2);
+
+       // flags not supported with LUKS1
+       OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &um2));
+       FAIL_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, CRYPT_ANY_SLOT, um2, CRYPT_VOLUME_KEY_NO_SEGMENT), "Not supported with LUKS1.");
+       crypt_keyslot_context_free(um1);
+       crypt_keyslot_context_free(um2);
+
+       // LUKS2 token not supported
+       OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE2, 0, 0, &um1));
+       OK_(crypt_keyslot_context_init_by_token(cd, CRYPT_ANY_TOKEN, NULL, NULL, 0, NULL, &um2));
+       FAIL_(crypt_keyslot_add_by_keyslot_context(cd, 2, um1, CRYPT_ANY_SLOT, um2, 0), "Not supported with LUKS1.");
+       EQ_(crypt_keyslot_context_get_error(um2), -EINVAL);
+       crypt_keyslot_context_free(um1);
+       crypt_keyslot_context_free(um2);
+
+       OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE2, 0, 0, &um1));
+       OK_(crypt_keyslot_context_init_by_token(cd, CRYPT_ANY_TOKEN, NULL, NULL, 0, NULL, &um2));
+       FAIL_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um2, CRYPT_ANY_SLOT, um1, 0), "Not supported with LUKS1.");
+       crypt_keyslot_context_free(um1);
+       crypt_keyslot_context_free(um2);
+
+       CRYPT_FREE(cd);
+
+       _cleanup_dmdevices();
+}
+
+static void VolumeKeyGet(void)
+{
+       struct crypt_params_luks1 params = {
+               .hash = "sha512",
+               .data_alignment = 2048, // 2M, data offset will be 2048
+       };
+       struct crypt_pbkdf_type min_pbkdf2 = {
+               .type = "pbkdf2",
+               .hash = "sha256",
+               .iterations = 1000,
+               .flags = CRYPT_PBKDF_NO_BENCHMARK
+       };
+       char key[128], key2[128];
+
+       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;
+       struct crypt_keyslot_context *um1, *um2;
+
+       crypt_decode_key(key, vk_hex, key_size);
+
+       OK_(prepare_keyfile(KEYFILE1, PASSPHRASE1, strlen(PASSPHRASE1)));
+
+       // init test devices
+       OK_(get_luks_offsets(0, key_size, params.data_alignment, 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_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+       OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, 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_LUKS1, NULL));
+       OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+       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_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+       OK_(crypt_format(cd, CRYPT_LUKS1, 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);
+       crypt_keyslot_context_free(um1);
+       CRYPT_FREE(cd);
+
+       OK_(crypt_init(&cd, DMDIR H_DEVICE));
+       OK_(crypt_load(cd, CRYPT_LUKS1, 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);
+
+       // check token context is not usable
+       OK_(crypt_keyslot_context_init_by_token(cd, CRYPT_ANY_TOKEN, NULL, NULL, 0, NULL, &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);
+       CRYPT_FREE(cd);
+
+       _remove_keyfiles();
+       _cleanup_dmdevices();
+}
+
 // Check that gcrypt is properly initialised in format
 static void NonFIPSAlg(void)
 {
@@ -1968,6 +2400,11 @@ int main(int argc, char *argv[])
        RUN_(VerityTest, "DM verity");
        RUN_(TcryptTest, "Tcrypt API");
        RUN_(IntegrityTest, "Integrity API");
+       RUN_(ResizeIntegrity, "Integrity raw resize");
+       RUN_(ResizeIntegrityWithKey, "Integrity raw resize with key");
+       RUN_(WipeTest, "Wipe device");
+       RUN_(LuksKeyslotAdd, "Adding keyslot via new API");
+       RUN_(VolumeKeyGet, "Getting volume key via keyslot context API");
 
        _cleanup();
        return 0;