X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=tests%2Fapi-test.c;h=15f95ed7b002708dd217bbf49bf73eb7827da40a;hb=2780ccdd62f9986bf1aaf015e577e0b4168d436e;hp=9f8aa114f94c2ca0789dce3f1dd344c8bbaae7dd;hpb=38c694a14318ffeedaa7f86e58bf865b90bae9cc;p=platform%2Fupstream%2Fcryptsetup.git diff --git a/tests/api-test.c b/tests/api-test.c index 9f8aa11..15f95ed 100644 --- a/tests/api-test.c +++ b/tests/api-test.c @@ -1,11 +1,13 @@ /* * cryptsetup library API check functions * - * Copyright (C) 2009-2010 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2012 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2012, Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,7 +16,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include @@ -25,16 +27,18 @@ #include #include #include +#include #include #include +#include +#include "luks.h" #include "libcryptsetup.h" +#include "utils_loop.h" #define DMDIR "/dev/mapper/" -#define DEVICE_1 "/dev/loop5" #define DEVICE_1_UUID "28632274-8c8a-493f-835b-da802e1c576b" -#define DEVICE_2 "/dev/loop6" #define DEVICE_EMPTY_name "crypt_zero" #define DEVICE_EMPTY DMDIR DEVICE_EMPTY_name #define DEVICE_ERROR_name "crypt_error" @@ -43,7 +47,18 @@ #define CDEVICE_1 "ctest1" #define CDEVICE_2 "ctest2" #define CDEVICE_WRONG "O_o" - +#define H_DEVICE "head_ok" +#define H_DEVICE_WRONG "head_wr" +#define L_DEVICE_1S "luks_onesec" +#define L_DEVICE_0S "luks_zerosec" +#define L_DEVICE_WRONG "luks_wr" +#define L_DEVICE_OK "luks_ok" +#define EVL_HEADER_1 "evil_hdr-luks_hdr_damage" +#define EVL_HEADER_2 "evil_hdr-payload_overwrite" +#define EVL_HEADER_3 "evil_hdr-stripes_payload_dmg" +#define EVL_HEADER_4 "evil_hdr-small_luks_device" +#define VALID_HEADER "valid_header_file" +#define BACKUP_FILE "csetup_backup_file" #define IMAGE1 "compatimage.img" #define IMAGE_EMPTY "empty.img" @@ -57,27 +72,188 @@ #define DEVICE_TEST_UUID "12345678-1234-1234-1234-123456789abc" +#define DEVICE_WRONG "/dev/Ooo_" +#define DEVICE_CHAR "/dev/zero" +#define THE_LFILE_TEMPLATE "cryptsetup-tstlp.XXXXXX" + +#define SECTOR_SHIFT 9L +#define SECTOR_SIZE 512 +#define TST_LOOP_FILE_SIZE (((1<<20)*50)>>SECTOR_SHIFT) +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) +#define DIV_ROUND_UP_MODULO(n,d) (DIV_ROUND_UP(n,d)*(d)) +#define LUKS_PHDR_SIZE_B 1024 + static int _debug = 0; static int _verbose = 1; +static int _fips_mode = 0; + +static int _quit = 0; static char global_log[4096]; static int global_lines = 0; -static int gcrypt_compatible = 0; +static char *DEVICE_1 = NULL; +static char *DEVICE_2 = NULL; +static char *THE_LOOP_DEV = NULL; + +static char *tmp_file_1 = NULL; +static char *test_loop_file = NULL; +static uint64_t t_dev_offset = 0; + +static int _system(const char*, int); // Helpers -static int _prepare_keyfile(const char *name, const char *passphrase) + +static int device_size(const char *device, uint64_t *size) +{ + int devfd, r = 0; + + devfd = open(device, O_RDONLY); + if(devfd == -1) + return -EINVAL; + + if (ioctl(devfd, BLKGETSIZE64, size) < 0) + r = -EINVAL; + close(devfd); + return r; +} + +static int fips_mode(void) +{ + int fd; + char buf = 0; + + fd = open("/proc/sys/crypto/fips_enabled", O_RDONLY); + + if (fd < 0) + return 0; + + if (read(fd, &buf, 1) != 1) + buf = '0'; + + close(fd); + + return (buf == '1'); +} + +static int get_luks_offsets(int metadata_device, + size_t keylength, + unsigned int alignpayload_sec, + unsigned int alignoffset_sec, + uint64_t *r_header_size, + uint64_t *r_payload_offset) +{ + int i; + uint64_t current_sector; + uint32_t sectors_per_stripes_set; + + if (!keylength) + return -1; + + sectors_per_stripes_set = DIV_ROUND_UP(keylength*LUKS_STRIPES, SECTOR_SIZE); + printf("sectors_per_stripes %" PRIu32 "\n", sectors_per_stripes_set); + current_sector = DIV_ROUND_UP_MODULO(DIV_ROUND_UP(LUKS_PHDR_SIZE_B, SECTOR_SIZE), + LUKS_ALIGN_KEYSLOTS / 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); + 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); + + if (r_payload_offset) { + if (metadata_device) + *r_payload_offset = alignpayload_sec; + else + *r_payload_offset = DIV_ROUND_UP_MODULO(current_sector, alignpayload_sec) + + alignoffset_sec; + } + + return 0; +} + +/* + * Creates dm-linear target over the test loop device. Offset is held in + * global variables so that size can be tested whether it fits into remaining + * size of the loop device or not + */ +static int create_dmdevice_over_loop(const char *dm_name, const uint64_t size) +{ + char cmd[128]; + int r; + uint64_t r_size; + + if(device_size(THE_LOOP_DEV, &r_size) < 0 || r_size <= t_dev_offset || !size) + return -1; + if ((r_size - t_dev_offset) < size) { + printf("No enough space on backing loop device\n."); + return -2; + } + snprintf(cmd, sizeof(cmd), + "dmsetup create %s --table \"0 %" PRIu64 " linear %s %" PRIu64 "\"", + dm_name, size, THE_LOOP_DEV, t_dev_offset); + if (!(r = _system(cmd, 1))) { + t_dev_offset += size; + } + return r; +} + +// TODO some utility to remove dmdevice over the loop file + +// Get key from kernel dm mapping table using dm-ioctl +static int _get_key_dm(const char *name, char *buffer, unsigned int buffer_size) +{ + struct dm_task *dmt; + struct dm_info dmi; + uint64_t start, length; + char *target_type, *key, *params; + void *next = NULL; + int r = -EINVAL; + + if (!(dmt = dm_task_create(DM_DEVICE_TABLE))) + goto out; + if (!dm_task_set_name(dmt, name)) + goto out; + if (!dm_task_run(dmt)) + goto out; + if (!dm_task_get_info(dmt, &dmi)) + goto out; + if (!dmi.exists) + goto out; + + next = dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms); + if (!target_type || strcmp(target_type, "crypt") != 0) + goto out; + + (void)strsep(¶ms, " "); /* rcipher */ + key = strsep(¶ms, " "); + + if (buffer_size <= strlen(key)) + goto out; + + strncpy(buffer, key, buffer_size); + r = 0; +out: + if (dmt) + dm_task_destroy(dmt); + + return r; +} + +static int _prepare_keyfile(const char *name, const char *passphrase, int size) { int fd, r; fd = open(name, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR); if (fd != -1) { - r = write(fd, passphrase, strlen(passphrase)); + r = write(fd, passphrase, size); close(fd); } else r = 0; - return r == strlen(passphrase) ? 0 : 1; + return r == size ? 0 : 1; } static void _remove_keyfiles(void) @@ -87,7 +263,7 @@ static void _remove_keyfiles(void) } // Decode key from its hex representation -static int crypt_decode_key(char *key, char *hex, unsigned int size) +static int crypt_decode_key(char *key, const char *hex, unsigned int size) { char buffer[3]; char *endp; @@ -111,12 +287,7 @@ static int crypt_decode_key(char *key, char *hex, unsigned int size) return 0; } -static int yesDialog(char *msg) -{ - return 1; -} - -static void cmdLineLog(int level, char *msg) +static void cmdLineLog(int level, const char *msg) { strncat(global_log, msg, sizeof(global_log) - strlen(global_log)); global_lines++; @@ -124,26 +295,52 @@ static void cmdLineLog(int level, char *msg) static void new_log(int level, const char *msg, void *usrptr) { - cmdLineLog(level, (char*)msg); + if (_debug) + printf("LOG: %s", msg); + cmdLineLog(level, msg); } - -static void reset_log() +static void reset_log(void) { memset(global_log, 0, sizeof(global_log)); global_lines = 0; } -static void _system(const char *command, int warn) +static int _system(const char *command, int warn) { - if (system(command) < 0 && warn) + int r; + if (_debug) + printf("Running system: %s\n", command); + if ((r=system(command)) < 0 && warn) printf("System command failed: %s", command); + return r; } -static struct interface_callbacks cmd_icb = { - .yesDialog = yesDialog, - .log = cmdLineLog, -}; +static void _cleanup_dmdevices(void) +{ + struct stat st; + + if (!stat(DMDIR H_DEVICE, &st)) { + _system("dmsetup remove " H_DEVICE, 0); + } + if (!stat(DMDIR H_DEVICE_WRONG, &st)) { + _system("dmsetup remove " H_DEVICE_WRONG, 0); + } + if (!stat(DMDIR L_DEVICE_0S, &st)) { + _system("dmsetup remove " L_DEVICE_0S, 0); + } + if (!stat(DMDIR L_DEVICE_1S, &st)) { + _system("dmsetup remove " L_DEVICE_1S, 0); + } + if (!stat(DMDIR L_DEVICE_WRONG, &st)) { + _system("dmsetup remove " L_DEVICE_WRONG, 0); + } + if (!stat(DMDIR L_DEVICE_OK, &st)) { + _system("dmsetup remove " L_DEVICE_OK, 0); + } + + t_dev_offset = 0; +} static void _cleanup(void) { @@ -163,32 +360,128 @@ static void _cleanup(void) if (!stat(DEVICE_ERROR, &st)) _system("dmsetup remove " DEVICE_ERROR_name, 0); - if (!strncmp("/dev/loop", DEVICE_1, 9)) - _system("losetup -d " DEVICE_1, 0); + _cleanup_dmdevices(); + + if (crypt_loop_device(THE_LOOP_DEV)) + crypt_loop_detach(THE_LOOP_DEV); - if (!strncmp("/dev/loop", DEVICE_2, 9)) - _system("losetup -d " DEVICE_2, 0); + if (crypt_loop_device(DEVICE_1)) + crypt_loop_detach(DEVICE_1); + + if (crypt_loop_device(DEVICE_2)) + crypt_loop_detach(DEVICE_2); _system("rm -f " IMAGE_EMPTY, 0); + _system("rm -f " IMAGE1, 0); + + remove(test_loop_file); + remove(tmp_file_1); + + remove(EVL_HEADER_1); + remove(EVL_HEADER_2); + remove(EVL_HEADER_3); + remove(EVL_HEADER_4); + remove(VALID_HEADER); + remove(BACKUP_FILE); + _remove_keyfiles(); + + free(tmp_file_1); + free(test_loop_file); + free(THE_LOOP_DEV); + free(DEVICE_1); + free(DEVICE_2); } -static void _setup(void) +static int _setup(void) { + int fd, ro = 0; + char cmd[128]; + + test_loop_file = strdup(THE_LFILE_TEMPLATE); + 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 (_system(cmd, 1)) + return 1; + + if (!THE_LOOP_DEV) + THE_LOOP_DEV = crypt_loop_get_device(); + if (!THE_LOOP_DEV) { + printf("Cannot find free loop device.\n"); + return 1; + } + if (crypt_loop_device(THE_LOOP_DEV)) { + fd = crypt_loop_attach(THE_LOOP_DEV, test_loop_file, 0, 0, &ro); + close(fd); + } + + tmp_file_1 = strdup(THE_LFILE_TEMPLATE); + 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 (_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 (!strncmp("/dev/loop", DEVICE_1, 9)) { + if (!DEVICE_1) + DEVICE_1 = crypt_loop_get_device(); + if (!DEVICE_1) { + printf("Cannot find free loop device.\n"); + return 1; + } + if (crypt_loop_device(DEVICE_1)) { _system(" [ ! -e " IMAGE1 " ] && bzip2 -dk " IMAGE1 ".bz2", 1); - _system("losetup " DEVICE_1 " " IMAGE1, 1); + fd = crypt_loop_attach(DEVICE_1, IMAGE1, 0, 0, &ro); + close(fd); + } + if (!DEVICE_2) + DEVICE_2 = crypt_loop_get_device(); + if (!DEVICE_2) { + printf("Cannot find free loop device.\n"); + return 1; } - if (!strncmp("/dev/loop", DEVICE_2, 9)) { - _system("dd if=/dev/zero of=" IMAGE_EMPTY " bs=1M count=4", 1); - _system("losetup " DEVICE_2 " " IMAGE_EMPTY, 1); + if (crypt_loop_device(DEVICE_2)) { + _system("dd if=/dev/zero of=" IMAGE_EMPTY " bs=1M count=4 2>/dev/null", 1); + fd = crypt_loop_attach(DEVICE_2, IMAGE_EMPTY, 0, 0, &ro); + close(fd); } + /* Keymaterial offset is less than 8 sectors */ + _system(" [ ! -e " EVL_HEADER_1 " ] && bzip2 -dk " EVL_HEADER_1 ".bz2", 1); + /* keymaterial offset aims into payload area */ + _system(" [ ! -e " EVL_HEADER_2 " ] && bzip2 -dk " EVL_HEADER_2 ".bz2", 1); + /* keymaterial offset is valid, number of stripes causes payload area to be overwriten */ + _system(" [ ! -e " EVL_HEADER_3 " ] && bzip2 -dk " EVL_HEADER_3 ".bz2", 1); + /* luks device header for data and header on same device. payloadOffset is greater than + * device size (crypt_load() test) */ + _system(" [ ! -e " EVL_HEADER_4 " ] && bzip2 -dk " EVL_HEADER_4 ".bz2", 1); + /* valid header: payloadOffset=4096, key_size=32, + * volume_key = bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a */ + _system(" [ ! -e " VALID_HEADER " ] && bzip2 -dk " VALID_HEADER ".bz2", 1); + + /* Prepare tcrypt images */ + _system(" [ ! -d tcrypt-images ] && tar xjf tcrypt-images.tar.bz2 2>/dev/null", 1); + + _system("modprobe dm-crypt", 0); + _system("modprobe dm-verity", 0); + + _fips_mode = fips_mode(); + if (_debug) + printf("FIPS MODE: %d\n", _fips_mode); + return 0; } -void check_ok(int status, int line, const char *func) +static void check_ok(int status, int line, const char *func) { char buf[256]; @@ -200,7 +493,7 @@ void check_ok(int status, int line, const char *func) } } -void check_ko(int status, int line, const char *func) +static void check_ko(int status, int line, const char *func) { char buf[256]; @@ -214,14 +507,15 @@ void check_ko(int status, int line, const char *func) printf(" => errno %d, errmsg: %s\n", status, buf); } -void check_equal(int line, const char *func) +static void check_equal(int line, const char *func, int64_t x, int64_t y) { - printf("FAIL line %d [%s]: expected equal values differs.\n", line, func); + printf("FAIL line %d [%s]: expected equal values differs: %" + PRIi64 " != %" PRIi64 "\n", line, func, x, y); _cleanup(); exit(-1); } -void xlog(const char *msg, const char *tst, const char *func, int line, const char *txt) +static void xlog(const char *msg, const char *tst, const char *func, int line, const char *txt) { if (_verbose) { if (txt) @@ -229,7 +523,15 @@ void xlog(const char *msg, const char *tst, const char *func, int line, const ch else printf(" [%s,%s:%d] %s\n", msg, func, line, tst); } + if (_quit) { + if (_verbose) + printf("Interrupted by a signal.\n"); + _cleanup(); + exit(-1); + } } + +/* crypt_device context must be "cd" to parse error properly here */ #define OK_(x) do { xlog("(success)", #x, __FUNCTION__, __LINE__, NULL); \ check_ok((x), __LINE__, __FUNCTION__); \ } while(0) @@ -237,303 +539,11 @@ void xlog(const char *msg, const char *tst, const char *func, int line, const ch check_ko((x), __LINE__, __FUNCTION__); \ } while(0) #define EQ_(x, y) do { xlog("(equal) ", #x " == " #y, __FUNCTION__, __LINE__, NULL); \ - if ((x) != (y)) check_equal(__LINE__, __FUNCTION__); \ + int64_t _x = (x), _y = (y); \ + if (_x != _y) check_equal(__LINE__, __FUNCTION__, _x, _y); \ } while(0) - #define RUN_(x, y) do { printf("%s: %s\n", #x, (y)); x(); } while (0) -// OLD API TESTS -static void LuksUUID(void) -{ - struct crypt_options co = { .icb = &cmd_icb }; - - co.device = DEVICE_EMPTY; - EQ_(crypt_luksUUID(&co), -EINVAL); - - co.device = DEVICE_ERROR; - EQ_(crypt_luksUUID(&co), -EINVAL); - - reset_log(); - co.device = DEVICE_1; - OK_(crypt_luksUUID(&co)); - EQ_(strlen(global_log), 37); /* UUID + "\n" */ - EQ_(strncmp(global_log, DEVICE_1_UUID, strlen(DEVICE_1_UUID)), 0); - -} - -static void IsLuks(void) -{ - struct crypt_options co = { .icb = &cmd_icb }; - - co.device = DEVICE_EMPTY; - EQ_(crypt_isLuks(&co), -EINVAL); - - co.device = DEVICE_ERROR; - EQ_(crypt_isLuks(&co), -EINVAL); - - co.device = DEVICE_1; - OK_(crypt_isLuks(&co)); -} - -static void LuksOpen(void) -{ - struct crypt_options co = { - .name = CDEVICE_1, - //.passphrase = "blabla", - .icb = &cmd_icb, - }; - - OK_(_prepare_keyfile(KEYFILE1, KEY1)); - co.key_file = KEYFILE1; - - co.device = DEVICE_EMPTY; - EQ_(crypt_luksOpen(&co), -EINVAL); - - co.device = DEVICE_ERROR; - EQ_(crypt_luksOpen(&co), -EINVAL); - - co.device = DEVICE_1; - OK_(crypt_luksOpen(&co)); - FAIL_(crypt_luksOpen(&co), "already open"); - - _remove_keyfiles(); -} - -static void query_device(void) -{ - struct crypt_options co = {.icb = &cmd_icb }; - - co.name = CDEVICE_WRONG; - EQ_(crypt_query_device(&co), 0); - - co.name = CDEVICE_1; - EQ_(crypt_query_device(&co), 1); - - OK_(strncmp(crypt_get_dir(), DMDIR, 11)); - OK_(strcmp(co.cipher, "aes-cbc-essiv:sha256")); - EQ_(co.key_size, 16); - EQ_(co.offset, 1032); - EQ_(co.flags & CRYPT_FLAG_READONLY, 0); - EQ_(co.skip, 0); - crypt_put_options(&co); -} - -static void remove_device(void) -{ - int fd; - struct crypt_options co = {.icb = &cmd_icb }; - - co.name = CDEVICE_WRONG; - EQ_(crypt_remove_device(&co), -ENODEV); - - fd = open(DMDIR CDEVICE_1, O_RDONLY); - co.name = CDEVICE_1; - FAIL_(crypt_remove_device(&co), "device busy"); - close(fd); - - OK_(crypt_remove_device(&co)); -} - -static void LuksFormat(void) -{ - struct crypt_options co = { - .device = DEVICE_2, - .key_size = 256 / 8, - .key_slot = -1, - .cipher = "aes-cbc-essiv:sha256", - .hash = "sha1", - .flags = 0, - .iteration_time = 10, - .align_payload = 0, - .icb = &cmd_icb, - }; - - OK_(_prepare_keyfile(KEYFILE1, KEY1)); - - co.new_key_file = KEYFILE1; - co.device = DEVICE_ERROR; - FAIL_(crypt_luksFormat(&co), "error device"); - - co.device = DEVICE_2; - OK_(crypt_luksFormat(&co)); - - co.new_key_file = NULL; - co.key_file = KEYFILE1; - co.name = CDEVICE_2; - OK_(crypt_luksOpen(&co)); - OK_(crypt_remove_device(&co)); - _remove_keyfiles(); -} - -static void LuksKeyGame(void) -{ - int i; - struct crypt_options co = { - .device = DEVICE_2, - .key_size = 256 / 8, - .key_slot = -1, - .cipher = "aes-cbc-essiv:sha256", - .hash = "sha1", - .flags = 0, - .iteration_time = 10, - .align_payload = 0, - .icb = &cmd_icb, - }; - - OK_(_prepare_keyfile(KEYFILE1, KEY1)); - OK_(_prepare_keyfile(KEYFILE2, KEY2)); - - co.new_key_file = KEYFILE1; - co.device = DEVICE_2; - co.key_slot = 8; - FAIL_(crypt_luksFormat(&co), "wrong slot #"); - - co.key_slot = 7; // last slot - OK_(crypt_luksFormat(&co)); - - co.new_key_file = KEYFILE1; - co.key_file = KEYFILE1; - co.key_slot = 8; - FAIL_(crypt_luksAddKey(&co), "wrong slot #"); - co.key_slot = 7; - FAIL_(crypt_luksAddKey(&co), "slot already used"); - - co.key_slot = 6; - OK_(crypt_luksAddKey(&co)); - - co.key_file = KEYFILE2 "blah"; - co.key_slot = 5; - FAIL_(crypt_luksAddKey(&co), "keyfile not found"); - - co.new_key_file = KEYFILE2; // key to add - co.key_file = KEYFILE1; - co.key_slot = -1; - for (i = 0; i < 6; i++) - OK_(crypt_luksAddKey(&co)); //FIXME: EQ_(i)? - - FAIL_(crypt_luksAddKey(&co), "all slots full"); - - // REMOVE KEY - co.new_key_file = KEYFILE1; // key to remove - co.key_file = NULL; - co.key_slot = 8; // should be ignored - // only 2 slots should use KEYFILE1 - OK_(crypt_luksRemoveKey(&co)); - OK_(crypt_luksRemoveKey(&co)); - FAIL_(crypt_luksRemoveKey(&co), "no slot with this passphrase"); - - co.new_key_file = KEYFILE2 "blah"; - co.key_file = NULL; - FAIL_(crypt_luksRemoveKey(&co), "keyfile not found"); - - // KILL SLOT - co.new_key_file = NULL; - co.key_file = NULL; - co.key_slot = 8; - FAIL_(crypt_luksKillSlot(&co), "wrong slot #"); - co.key_slot = 7; - FAIL_(crypt_luksKillSlot(&co), "slot already wiped"); - - co.key_slot = 5; - OK_(crypt_luksKillSlot(&co)); - - _remove_keyfiles(); -} - -size_t _get_device_size(const char *device) -{ - unsigned long size = 0; - int fd; - - fd = open(device, O_RDONLY); - if (fd == -1) - return 0; - (void)ioctl(fd, BLKGETSIZE, &size); - close(fd); - - return size; -} - -void DeviceResizeGame(void) -{ - size_t orig_size; - struct crypt_options co = { - .name = CDEVICE_2, - .device = DEVICE_2, - .key_size = 128 / 8, - .cipher = "aes-cbc-plain", - .hash = "sha1", - .offset = 333, - .skip = 0, - .icb = &cmd_icb, - }; - - orig_size = _get_device_size(DEVICE_2); - - OK_(_prepare_keyfile(KEYFILE2, KEY2)); - - co.key_file = KEYFILE2; - co.size = 1000; - OK_(crypt_create_device(&co)); - EQ_(_get_device_size(DMDIR CDEVICE_2), 1000); - - co.size = 2000; - OK_(crypt_resize_device(&co)); - EQ_(_get_device_size(DMDIR CDEVICE_2), 2000); - - co.size = 0; - OK_(crypt_resize_device(&co)); - EQ_(_get_device_size(DMDIR CDEVICE_2), (orig_size - 333)); - co.size = 0; - co.offset = 444; - co.skip = 555; - co.cipher = "aes-cbc-essiv:sha256"; - OK_(crypt_update_device(&co)); - EQ_(_get_device_size(DMDIR CDEVICE_2), (orig_size - 444)); - - memset(&co, 0, sizeof(co)); - co.icb = &cmd_icb, - co.name = CDEVICE_2; - EQ_(crypt_query_device(&co), 1); - EQ_(strcmp(co.cipher, "aes-cbc-essiv:sha256"), 0); - EQ_(co.key_size, 128 / 8); - EQ_(co.offset, 444); - EQ_(co.skip, 555); - crypt_put_options(&co); - - // dangerous switch device still works - memset(&co, 0, sizeof(co)); - co.name = CDEVICE_2, - co.device = DEVICE_1; - co.key_file = KEYFILE2; - co.key_size = 128 / 8; - co.cipher = "aes-cbc-plain"; - co.hash = "sha1"; - co.icb = &cmd_icb; - OK_(crypt_update_device(&co)); - - memset(&co, 0, sizeof(co)); - co.icb = &cmd_icb, - co.name = CDEVICE_2; - EQ_(crypt_query_device(&co), 1); - EQ_(strcmp(co.cipher, "aes-cbc-plain"), 0); - EQ_(co.key_size, 128 / 8); - EQ_(co.offset, 0); - EQ_(co.skip, 0); - // This expect lookup returns prefered /dev/loopX - EQ_(strcmp(co.device, DEVICE_1), 0); - crypt_put_options(&co); - - memset(&co, 0, sizeof(co)); - co.icb = &cmd_icb, - co.name = CDEVICE_2; - OK_(crypt_remove_device(&co)); - - _remove_keyfiles(); -} - -// NEW API tests - static void AddDevicePlain(void) { struct crypt_device *cd; @@ -541,19 +551,46 @@ static void AddDevicePlain(void) .hash = "sha1", .skip = 0, .offset = 0, + .size = 0 }; int fd; char key[128], key2[128], path[128]; - char *passphrase = PASSPHRASE; - char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a"; + const char *passphrase = PASSPHRASE; + // hashed hex version of PASSPHRASE + const char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a"; size_t key_size = strlen(mk_hex) / 2; - char *cipher = "aes"; - char *cipher_mode = "cbc-essiv:sha256"; + const char *cipher = "aes"; + const char *cipher_mode = "cbc-essiv:sha256"; - crypt_decode_key(key, mk_hex, key_size); + uint64_t size, r_size; + crypt_decode_key(key, mk_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"); + OK_(crypt_init(&cd, tmp_file_1)); + crypt_free(cd); + + // test crypt_format, crypt_get_cipher, crypt_get_cipher_mode, crypt_get_volume_key_size + OK_(crypt_init(&cd,DEVICE_1)); + params.skip = 3; + params.offset = 42; + FAIL_(crypt_format(cd,CRYPT_PLAIN,NULL,cipher_mode,NULL,NULL,key_size,¶ms),"cipher param is null"); + FAIL_(crypt_format(cd,CRYPT_PLAIN,cipher,NULL,NULL,NULL,key_size,¶ms),"cipher_mode param is null"); + OK_(crypt_format(cd,CRYPT_PLAIN,cipher,cipher_mode,NULL,NULL,key_size,¶ms)); + OK_(strcmp(cipher_mode,crypt_get_cipher_mode(cd))); + OK_(strcmp(cipher,crypt_get_cipher(cd))); + EQ_((int)key_size, crypt_get_volume_key_size(cd)); + EQ_(params.skip, crypt_get_iv_offset(cd)); + EQ_(params.offset, crypt_get_data_offset(cd)); + params.skip = 0; + params.offset = 0; + + // crypt_set_uuid() + FAIL_(crypt_set_uuid(cd,DEVICE_1_UUID),"can't set uuid to plain device"); + + crypt_free(cd); // default is "plain" hash - no password hash OK_(crypt_init(&cd, DEVICE_1)); @@ -561,12 +598,87 @@ static void AddDevicePlain(void) FAIL_(crypt_activate_by_volume_key(cd, NULL, key, key_size, 0), "cannot verify key with plain"); OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0)); EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); - // FIXME: this should get key from active device? - //OK_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key2, &key_size, passphrase, strlen(passphrase))); - //OK_(memcmp(key, key2, key_size)); OK_(crypt_deactivate(cd, CDEVICE_1)); crypt_free(cd); + // test boundaries in offset parameter + device_size(DEVICE_1,&size); + params.hash = NULL; + // zero sectors length + params.offset = size >> SECTOR_SHIFT; + OK_(crypt_init(&cd, DEVICE_1)); + OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, ¶ms)); + EQ_(crypt_get_data_offset(cd),params.offset); + // device size is 0 sectors + 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; + crypt_free(cd); + + OK_(crypt_init(&cd, DEVICE_1)); + OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, ¶ms)); + OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0)); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + snprintf(path, sizeof(path), "%s/%s", crypt_get_dir(), CDEVICE_1); + if (device_size(path, &r_size) >= 0) + EQ_(r_size>>SECTOR_SHIFT, 1); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + + // size > device_size + params.offset = 0; + params.size = (size >> SECTOR_SHIFT) + 1; + crypt_init(&cd, DEVICE_1); + OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, ¶ms)); + FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0),"Device too small"); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE); + crypt_free(cd); + + // offset == device_size (autodetect size) + params.offset = (size >> SECTOR_SHIFT); + params.size = 0; + crypt_init(&cd, DEVICE_1); + OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, ¶ms)); + FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0),"Device too small"); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE); + crypt_free(cd); + + // offset == device_size (user defined size) + params.offset = (size >> SECTOR_SHIFT); + params.size = 123; + crypt_init(&cd, DEVICE_1); + OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, ¶ms)); + FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0),"Device too small"); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE); + crypt_free(cd); + + // offset+size > device_size + params.offset = 42; + params.size = (size >> SECTOR_SHIFT) - params.offset + 1; + crypt_init(&cd, DEVICE_1); + OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, ¶ms)); + FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0),"Offset and size are beyond device real size"); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE); + crypt_free(cd); + + // offset+size == device_size + params.offset = 42; + params.size = (size >> SECTOR_SHIFT) - params.offset; + crypt_init(&cd, DEVICE_1); + OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, ¶ms)); + OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0)); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + if (!device_size(path, &r_size)) + EQ_((r_size >> SECTOR_SHIFT),params.size); + OK_(crypt_deactivate(cd,CDEVICE_1)); + + crypt_free(cd); + params.hash = "sha1"; + params.offset = 0; + params.size = 0; + params.skip = 0; + // Now use hashed password OK_(crypt_init(&cd, DEVICE_1)); OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, ¶ms)); @@ -583,31 +695,142 @@ static void AddDevicePlain(void) close(fd); OK_(crypt_deactivate(cd, CDEVICE_1)); EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE); + crypt_free(cd); + + // crypt_init_by_name_and_header + OK_(crypt_init(&cd,DEVICE_1)); + OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, ¶ms)); + OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0)); + crypt_free(cd); + + FAIL_(crypt_init_by_name_and_header(&cd, CDEVICE_1, H_DEVICE),"can't init plain device by header device"); + OK_(crypt_init_by_name(&cd, CDEVICE_1)); + OK_(strcmp(cipher_mode,crypt_get_cipher_mode(cd))); + OK_(strcmp(cipher,crypt_get_cipher(cd))); + EQ_((int)key_size, crypt_get_volume_key_size(cd)); + EQ_(params.skip, crypt_get_iv_offset(cd)); + EQ_(params.offset, crypt_get_data_offset(cd)); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + + OK_(crypt_init(&cd,DEVICE_1)); + OK_(crypt_format(cd,CRYPT_PLAIN,cipher,cipher_mode,NULL,NULL,key_size,¶ms)); + params.size = 0; + params.offset = 0; + + // crypt_set_data_device + FAIL_(crypt_set_data_device(cd,H_DEVICE),"can't set data device for plain device"); + + // crypt_get_type + OK_(strcmp(crypt_get_type(cd),CRYPT_PLAIN)); OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0)); EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + // crypt_resize() + OK_(crypt_resize(cd,CDEVICE_1,size>>SECTOR_SHIFT)); // same size + if (!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"); + + // resize ok + OK_(crypt_resize(cd,CDEVICE_1, 123)); + if (!device_size(path,&r_size)) + EQ_(r_size>>SECTOR_SHIFT, 123); + OK_(crypt_resize(cd,CDEVICE_1,0)); // full size (autodetect) + if (!device_size(path,&r_size)) + EQ_(r_size, size); + OK_(crypt_deactivate(cd,CDEVICE_1)); + EQ_(crypt_status(cd,CDEVICE_1),CRYPT_INACTIVE); + crypt_free(cd); + + // offset tests + OK_(crypt_init(&cd,DEVICE_1)); + params.offset = 42; + params.size = (size>>SECTOR_SHIFT) - params.offset - 10; + OK_(crypt_format(cd,CRYPT_PLAIN,cipher,cipher_mode,NULL,NULL,key_size,¶ms)); + OK_(crypt_activate_by_volume_key(cd,CDEVICE_1,key,key_size,0)); + if (!device_size(path,&r_size)) + EQ_(r_size>>SECTOR_SHIFT, params.size); + // resize to fill remaining capacity + OK_(crypt_resize(cd,CDEVICE_1,params.size + 10)); + if (!device_size(path,&r_size)) + EQ_(r_size>>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 (!device_size(path,&r_size)) + EQ_(r_size>>SECTOR_SHIFT, params.size + 10); + EQ_(crypt_status(cd,CDEVICE_1),CRYPT_ACTIVE); + fd = open(path, O_RDONLY); + close(fd); + OK_(fd < 0); + + // resize to minimal size + OK_(crypt_resize(cd,CDEVICE_1, 1)); // minimal device size + if (!device_size(path,&r_size)) + EQ_(r_size>>SECTOR_SHIFT, 1); + // use size of backing device (autodetect with respect to offset) + OK_(crypt_resize(cd,CDEVICE_1,0)); + if (!device_size(path,&r_size)) + EQ_(r_size>>SECTOR_SHIFT, (size >> SECTOR_SHIFT)- 42); + OK_(crypt_deactivate(cd,CDEVICE_1)); + crypt_free(cd); + + params.size = 0; + params.offset = 0; + OK_(crypt_init(&cd,DEVICE_1)); + OK_(crypt_format(cd,CRYPT_PLAIN,cipher,cipher_mode,NULL,NULL,key_size,¶ms)); + OK_(crypt_activate_by_volume_key(cd,CDEVICE_1,key,key_size,0)); + + // suspend/resume tests + FAIL_(crypt_suspend(cd,CDEVICE_1),"cannot suspend plain device"); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + FAIL_(crypt_resume_by_passphrase(cd,CDEVICE_1,CRYPT_ANY_SLOT,passphrase, strlen(passphrase)),"cannot resume plain device"); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + // retrieve volume key check - memset(key2, 0, key_size); - key_size--; - // small buffer - FAIL_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key2, &key_size, passphrase, strlen(passphrase)), "small buffer"); - key_size++; - OK_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key2, &key_size, passphrase, strlen(passphrase))); - - OK_(memcmp(key, key2, key_size)); + if (!_fips_mode) { + memset(key2, 0, key_size); + key_size--; + // small buffer + FAIL_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key2, &key_size, passphrase, strlen(passphrase)), "small buffer"); + key_size++; + OK_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key2, &key_size, passphrase, strlen(passphrase))); + + OK_(memcmp(key, key2, key_size)); + } OK_(strcmp(cipher, crypt_get_cipher(cd))); OK_(strcmp(cipher_mode, crypt_get_cipher_mode(cd))); - EQ_(key_size, crypt_get_volume_key_size(cd)); + EQ_((int)key_size, crypt_get_volume_key_size(cd)); EQ_(0, crypt_get_data_offset(cd)); OK_(crypt_deactivate(cd, CDEVICE_1)); // now with keyfile - OK_(_prepare_keyfile(KEYFILE1, KEY1)); + OK_(_prepare_keyfile(KEYFILE1, KEY1, strlen(KEY1))); + OK_(_prepare_keyfile(KEYFILE2, KEY2, strlen(KEY2))); FAIL_(crypt_activate_by_keyfile(cd, NULL, CRYPT_ANY_SLOT, KEYFILE1, 0, 0), "cannot verify key with plain"); EQ_(0, crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0, 0)); EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); OK_(crypt_deactivate(cd, CDEVICE_1)); + FAIL_(crypt_activate_by_keyfile_offset(cd, NULL, CRYPT_ANY_SLOT, KEYFILE1, 0, strlen(KEY1) + 1, 0), "cannot seek"); + EQ_(0, crypt_activate_by_keyfile_offset(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0, 0, 0)); + OK_(crypt_deactivate(cd, CDEVICE_1)); + _remove_keyfiles(); + crypt_free(cd); + + OK_(crypt_init(&cd,DEVICE_1)); + OK_(crypt_format(cd,CRYPT_PLAIN,cipher,cipher_mode,NULL,NULL,key_size,¶ms)); + + // crypt_keyslot_*() + FAIL_(crypt_keyslot_add_by_passphrase(cd,CRYPT_ANY_SLOT,passphrase,strlen(passphrase),passphrase,strlen(passphrase)), "can't add keyslot to plain device"); + FAIL_(crypt_keyslot_add_by_volume_key(cd,CRYPT_ANY_SLOT ,key,key_size,passphrase,strlen(passphrase)),"can't add keyslot to plain device"); + 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); _remove_keyfiles(); crypt_free(cd); @@ -644,9 +867,10 @@ static void CallbacksTest(void) }; size_t key_size = 256 / 8; - char *cipher = "aes"; - char *cipher_mode = "cbc-essiv:sha256"; - char *passphrase = PASSPHRASE; + const char *cipher = "aes"; + const char *cipher_mode = "cbc-essiv:sha256"; + const char *passphrase = PASSPHRASE; + char buf1[256] = {0}, buf2[256] = {0}; OK_(crypt_init(&cd, DEVICE_1)); crypt_set_log_callback(cd, &new_log, NULL); @@ -668,6 +892,22 @@ static void CallbacksTest(void) EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); OK_(crypt_deactivate(cd, CDEVICE_1)); + // Check error reporting. + // This must fail and create error message + crypt_deactivate(cd, CDEVICE_1); + + // Here context must be the same + crypt_get_error(buf1, sizeof(buf1)); + crypt_last_error(cd, buf2, sizeof(buf2)); + OK_(!*buf1); + OK_(!*buf2); + OK_(strcmp(buf1, buf2)); + + crypt_get_error(buf1, sizeof(buf1)); + crypt_last_error(cd, buf2, sizeof(buf2)); + OK_(*buf1); + OK_(*buf2); + crypt_free(cd); } @@ -691,19 +931,21 @@ static void UseLuksDevice(void) OK_(strcmp("aes", crypt_get_cipher(cd))); OK_(strcmp("cbc-essiv:sha256", crypt_get_cipher_mode(cd))); OK_(strcmp(DEVICE_1_UUID, crypt_get_uuid(cd))); - EQ_(key_size, crypt_get_volume_key_size(cd)); + EQ_((int)key_size, crypt_get_volume_key_size(cd)); EQ_(1032, crypt_get_data_offset(cd)); - EQ_(0, crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, KEY1, strlen(KEY1))); - OK_(crypt_volume_key_verify(cd, key, key_size)); - OK_(crypt_activate_by_volume_key(cd, NULL, key, key_size, 0)); - OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0)); - EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); - OK_(crypt_deactivate(cd, CDEVICE_1)); - - key[1] = ~key[1]; - FAIL_(crypt_volume_key_verify(cd, key, key_size), "key mismatch"); - FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "key mismatch"); + if (!_fips_mode) { + EQ_(0, crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, KEY1, strlen(KEY1))); + OK_(crypt_volume_key_verify(cd, key, key_size)); + OK_(crypt_activate_by_volume_key(cd, NULL, key, key_size, 0)); + OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0)); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + OK_(crypt_deactivate(cd, CDEVICE_1)); + + key[1] = ~key[1]; + FAIL_(crypt_volume_key_verify(cd, key, key_size), "key mismatch"); + FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "key mismatch"); + } crypt_free(cd); } @@ -728,10 +970,11 @@ static void SuspendDevice(void) OK_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1))); FAIL_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)), "not suspended"); - OK_(_prepare_keyfile(KEYFILE1, KEY1)); + OK_(_prepare_keyfile(KEYFILE1, KEY1, strlen(KEY1))); OK_(crypt_suspend(cd, CDEVICE_1)); FAIL_(crypt_resume_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1 "blah", 0), "wrong keyfile"); - OK_(crypt_resume_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0)); + FAIL_(crypt_resume_by_keyfile_offset(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 1, 0), "wrong key"); + OK_(crypt_resume_by_keyfile_offset(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0, 0)); FAIL_(crypt_resume_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0), "not suspended"); _remove_keyfiles(); out: @@ -745,17 +988,127 @@ static void AddDeviceLuks(void) struct crypt_params_luks1 params = { .hash = "sha512", .data_alignment = 2048, // 4M, data offset will be 4096 + .data_device = DEVICE_2 }; char key[128], key2[128]; - char *passphrase = "blabla"; - char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a"; + const char *passphrase = "blabla", *passphrase2 = "nsdkFI&Y#.sd"; + const char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a"; size_t key_size = strlen(mk_hex) / 2; - char *cipher = "aes"; - char *cipher_mode = "cbc-essiv:sha256"; + const char *cipher = "aes"; + const char *cipher_mode = "cbc-essiv:sha256"; + uint64_t r_payload_offset, r_header_size, r_size_1; crypt_decode_key(key, mk_hex, key_size); + // init test devices + OK_(get_luks_offsets(1, key_size, 0, 0, &r_header_size, &r_payload_offset)); + OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size)); + OK_(create_dmdevice_over_loop(H_DEVICE_WRONG, r_header_size - 1)); + + // format + OK_(crypt_init(&cd, DMDIR H_DEVICE_WRONG)); + params.data_alignment = 0; + FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms), "Not enough space for keyslots material"); + crypt_free(cd); + + // test payload_offset = 0 for encrypted device with external header device + OK_(crypt_init(&cd, DMDIR H_DEVICE)); + OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); + EQ_(crypt_get_data_offset(cd), 0); + crypt_free(cd); + + params.data_alignment = 0; + params.data_device = NULL; + + // test payload_offset = 0. format() should look up alignment offset from device topology + OK_(crypt_init(&cd, DEVICE_2)); + OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); + OK_(!(crypt_get_data_offset(cd) > 0)); + crypt_free(cd); + + /* + * test limit values for backing device size + */ + params.data_alignment = 4096; + OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, NULL, &r_payload_offset)); + OK_(create_dmdevice_over_loop(L_DEVICE_0S, r_payload_offset)); + OK_(create_dmdevice_over_loop(L_DEVICE_1S, r_payload_offset + 1)); + //OK_(create_dmdevice_over_loop(L_DEVICE_WRONG, r_payload_offset - 1)); + OK_(create_dmdevice_over_loop(L_DEVICE_WRONG, 2050 - 1)); //FIXME last keyslot - 1 sector + + // 1 sector less than required + OK_(crypt_init(&cd, DMDIR L_DEVICE_WRONG)); + FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms), "Device too small"); + crypt_free(cd); + + // 0 sectors for encrypted area + OK_(crypt_init(&cd, DMDIR L_DEVICE_0S)); + OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); + 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_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); + EQ_(crypt_get_data_offset(cd), params.data_alignment); + OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0)); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + OK_(device_size(DMDIR CDEVICE_1, &r_size_1)); + EQ_(r_size_1, SECTOR_SIZE); + OK_(crypt_deactivate(cd, CDEVICE_1)); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE); + // restrict format only to empty context + FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms), "Context is already formated"); + FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, NULL), "Context is already formated"); + // change data device to wrong one + OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_0S)); + FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "Device too small"); + OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_1S)); + OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0)); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + + params.data_alignment = 0; + params.data_device = DEVICE_2; + + // generate keyslot material at the end of luks header + OK_(crypt_init(&cd, DMDIR H_DEVICE)); + OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); + EQ_(crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, passphrase, strlen(passphrase)), 7); + EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 7, passphrase, strlen(passphrase) ,0), 7); + crypt_free(cd); + OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, DMDIR H_DEVICE)); + FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms), "Context is already formated"); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + + params.data_alignment = 2048; + params.data_device = NULL; + + // test uuid mismatch and _init_by_name_and_header + OK_(crypt_init(&cd, DMDIR L_DEVICE_1S)); + OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); + OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0)); + crypt_free(cd); + params.data_alignment = 0; + params.data_device = DEVICE_2; + OK_(crypt_init(&cd, DMDIR H_DEVICE)); + OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); + crypt_free(cd); + // there we've got uuid mismatch + OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, DMDIR H_DEVICE)); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + OK_(!!crypt_get_type(cd)); + FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "Device is active"); + 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)); + crypt_free(cd); + + params.data_device = NULL; + OK_(crypt_init(&cd, DEVICE_2)); OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); @@ -772,15 +1125,26 @@ static void AddDeviceLuks(void) EQ_(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)); - OK_(_prepare_keyfile(KEYFILE2, KEY2)); + OK_(_prepare_keyfile(KEYFILE1, KEY1, strlen(KEY1))); + OK_(_prepare_keyfile(KEYFILE2, KEY2, strlen(KEY2))); EQ_(2, crypt_keyslot_add_by_keyfile(cd, 2, KEYFILE1, 0, KEYFILE2, 0)); + FAIL_(crypt_keyslot_add_by_keyfile_offset(cd, 3, KEYFILE1, 0, 1, KEYFILE2, 0, 1), "wrong key"); + EQ_(3, crypt_keyslot_add_by_keyfile_offset(cd, 3, KEYFILE1, 0, 0, KEYFILE2, 0, 1)); + EQ_(4, crypt_keyslot_add_by_keyfile_offset(cd, 4, KEYFILE2, 0, 1, KEYFILE1, 0, 1)); FAIL_(crypt_activate_by_keyfile(cd, CDEVICE_2, CRYPT_ANY_SLOT, KEYFILE2, strlen(KEY2)-1, 0), "key mismatch"); EQ_(2, crypt_activate_by_keyfile(cd, NULL, CRYPT_ANY_SLOT, KEYFILE2, 0, 0)); + EQ_(3, crypt_activate_by_keyfile_offset(cd, NULL, CRYPT_ANY_SLOT, KEYFILE2, 0, 1, 0)); + EQ_(4, crypt_activate_by_keyfile_offset(cd, NULL, CRYPT_ANY_SLOT, KEYFILE1, 0, 1, 0)); + FAIL_(crypt_activate_by_keyfile_offset(cd, CDEVICE_2, CRYPT_ANY_SLOT, KEYFILE2, strlen(KEY2), 2, 0), "not enough data"); + FAIL_(crypt_activate_by_keyfile_offset(cd, CDEVICE_2, CRYPT_ANY_SLOT, KEYFILE2, 0, strlen(KEY2) + 1, 0), "cannot seek"); + FAIL_(crypt_activate_by_keyfile_offset(cd, CDEVICE_2, CRYPT_ANY_SLOT, KEYFILE2, 0, 2, 0), "wrong key"); EQ_(2, crypt_activate_by_keyfile(cd, CDEVICE_2, CRYPT_ANY_SLOT, KEYFILE2, 0, 0)); OK_(crypt_keyslot_destroy(cd, 1)); OK_(crypt_keyslot_destroy(cd, 2)); + OK_(crypt_keyslot_destroy(cd, 3)); + OK_(crypt_keyslot_destroy(cd, 4)); OK_(crypt_deactivate(cd, CDEVICE_2)); _remove_keyfiles(); @@ -798,13 +1162,20 @@ static void AddDeviceLuks(void) EQ_(CRYPT_SLOT_INACTIVE, crypt_keyslot_status(cd, 7)); EQ_(CRYPT_SLOT_ACTIVE_LAST, crypt_keyslot_status(cd, 6)); - EQ_(6, crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key2, &key_size, passphrase, strlen(passphrase))); - OK_(crypt_volume_key_verify(cd, key2, key_size)); + 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)); + EQ_(6, crypt_keyslot_change_by_passphrase(cd, CRYPT_ANY_SLOT, 6, passphrase2, strlen(passphrase2), passphrase, strlen(passphrase))); + + if (!_fips_mode) { + EQ_(6, crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key2, &key_size, passphrase, strlen(passphrase))); + OK_(crypt_volume_key_verify(cd, key2, key_size)); - OK_(memcmp(key, key2, key_size)); + OK_(memcmp(key, key2, key_size)); + } OK_(strcmp(cipher, crypt_get_cipher(cd))); OK_(strcmp(cipher_mode, crypt_get_cipher_mode(cd))); - EQ_(key_size, crypt_get_volume_key_size(cd)); + EQ_((int)key_size, crypt_get_volume_key_size(cd)); EQ_(4096, crypt_get_data_offset(cd)); OK_(strcmp(DEVICE_2, crypt_get_device_name(cd))); @@ -821,11 +1192,13 @@ static void AddDeviceLuks(void) FAIL_(crypt_deactivate(cd, CDEVICE_2), "not active"); crypt_free(cd); + _cleanup_dmdevices(); } static void UseTempVolumes(void) { struct crypt_device *cd; + char tmp[256]; // Tepmporary device without keyslot but with on-disk LUKS header OK_(crypt_init(&cd, DEVICE_2)); @@ -835,28 +1208,27 @@ static void UseTempVolumes(void) EQ_(crypt_status(cd, CDEVICE_2), CRYPT_ACTIVE); crypt_free(cd); - // Volume key is properly initialised from active device OK_(crypt_init_by_name(&cd, CDEVICE_2)); OK_(crypt_deactivate(cd, CDEVICE_2)); - OK_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0)); - OK_(crypt_deactivate(cd, CDEVICE_2)); crypt_free(cd); // Dirty checks: device without UUID // we should be able to remove it but not manuipulate with it - _system("dmsetup create " CDEVICE_2 " --table \"" + snprintf(tmp, sizeof(tmp), "dmsetup create %s --table \"" "0 100 crypt aes-cbc-essiv:sha256 deadbabedeadbabedeadbabedeadbabe 0 " - DEVICE_2 " 2048\"", 1); + "%s 2048\"", CDEVICE_2, DEVICE_2); + _system(tmp, 1); OK_(crypt_init_by_name(&cd, CDEVICE_2)); OK_(crypt_deactivate(cd, CDEVICE_2)); FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0), "No known device type"); crypt_free(cd); // Dirty checks: device with UUID but LUKS header key fingerprint must fail) - _system("dmsetup create " CDEVICE_2 " --table \"" + snprintf(tmp, sizeof(tmp), "dmsetup create %s --table \"" "0 100 crypt aes-cbc-essiv:sha256 deadbabedeadbabedeadbabedeadbabe 0 " - DEVICE_2 " 2048\" " - "-u CRYPT-LUKS1-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-ctest1", 1); + "%s 2048\" -u CRYPT-LUKS1-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-ctest1", + CDEVICE_2, DEVICE_2); + _system(tmp, 1); OK_(crypt_init_by_name(&cd, CDEVICE_2)); OK_(crypt_deactivate(cd, CDEVICE_2)); FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0), "wrong volume key"); @@ -880,52 +1252,620 @@ static void UseTempVolumes(void) crypt_free(cd); } -// Check that gcrypt is properly initialised in format -static void NonFIPSAlg(void) +static void LuksHeaderRestore(void) { struct crypt_device *cd; struct crypt_params_luks1 params = { - .hash = "whirlpool", + .hash = "sha512", + .data_alignment = 2048, // 4M, data offset will be 4096 }; - char key[128] = ""; - size_t key_size = 128; - char *cipher = "aes"; - char *cipher_mode = "cbc-essiv:sha256"; + struct crypt_params_plain pl_params = { + .hash = "sha1", + .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 *cipher = "aes"; + const char *cipher_mode = "cbc-essiv:sha256"; + uint64_t r_payload_offset; + + crypt_decode_key(key, mk_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)); + + // do not restore header over plain device + OK_(crypt_init(&cd, DMDIR L_DEVICE_OK)); + OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &pl_params)); + OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0)); + FAIL_(crypt_header_restore(cd, CRYPT_PLAIN, VALID_HEADER), "Cannot restore header to PLAIN type device"); + FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, VALID_HEADER), "Cannot restore header over PLAIN type device"); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + + // invalid headers + OK_(crypt_init(&cd, DMDIR L_DEVICE_OK)); + OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); + FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_1), "Header corrupted"); + FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_2), "Header corrupted"); + FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_3), "Header corrupted"); + FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_4), "Header too small"); + 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); + 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"); + FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_3), "Header corrupted"); + FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_4), "Header too small"); + OK_(crypt_header_restore(cd, CRYPT_LUKS1, VALID_HEADER)); + OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0)); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + + // volume key_size mismatch + OK_(crypt_init(&cd, DMDIR L_DEVICE_OK)); + memcpy(key2, key, key_size - 1); + OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key2, key_size - 1, ¶ms)); + FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, VALID_HEADER), "Volume keysize mismatch"); + crypt_free(cd); + + // payload offset mismatch + params.data_alignment = 8192; + OK_(crypt_init(&cd, DMDIR L_DEVICE_OK)); + OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); + FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, VALID_HEADER), "Payload offset mismatch"); + //_system("dmsetup table;sleep 1",1); + crypt_free(cd); + + _cleanup_dmdevices(); +} + +static void LuksHeaderLoad(void) +{ + struct crypt_device *cd; + struct crypt_params_luks1 params = { + .hash = "sha512", + .data_alignment = 2048, + }; + struct crypt_params_plain pl_params = { + .hash = "sha1", + .skip = 0, + .offset = 0, + .size = 0 + }; + char key[128], cmd[256]; - if (!gcrypt_compatible) { - printf("WARNING: old libgcrypt, skipping test.\n"); + const char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a"; + size_t key_size = strlen(mk_hex) / 2; + const char *cipher = "aes"; + const char *cipher_mode = "cbc-essiv:sha256"; + uint64_t r_payload_offset, r_header_size; + + crypt_decode_key(key, mk_hex, key_size); + + // prepare test env + OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, &r_header_size, &r_payload_offset)); + // external header device + OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size)); + // 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); + OK_(_system(cmd, 1)); + // some device + OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1000)); + // 1 sector device + OK_(create_dmdevice_over_loop(L_DEVICE_1S, r_payload_offset + 1)); + // 0 sectors device for payload + OK_(create_dmdevice_over_loop(L_DEVICE_0S, r_payload_offset)); + + // valid metadata and device size + params.data_alignment = 0; + params.data_device = DMDIR L_DEVICE_OK; + OK_(crypt_init(&cd, DMDIR H_DEVICE)); + OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); + crypt_free(cd); + OK_(crypt_init(&cd, DMDIR H_DEVICE)); + OK_(crypt_load(cd, CRYPT_LUKS1, NULL)); + OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK)); + OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0)); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + + // bad header: device too small (payloadOffset > device_size) + OK_(crypt_init(&cd, DMDIR H_DEVICE_WRONG)); + FAIL_(crypt_load(cd, CRYPT_LUKS1, NULL), "Device too small"); + OK_(!!crypt_get_type(cd)); + crypt_free(cd); + + // 0 secs for encrypted data area + params.data_alignment = 2048; + params.data_device = NULL; + OK_(crypt_init(&cd, DMDIR L_DEVICE_0S)); + OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); + crypt_free(cd); + // load should be ok + OK_(crypt_init(&cd, DMDIR L_DEVICE_0S)); + OK_(crypt_load(cd, CRYPT_LUKS1, NULL)); + FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "Device too small"); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE); + crypt_free(cd); + + // damaged header + OK_(_system("dd if=/dev/zero of=" DMDIR L_DEVICE_OK " bs=512 count=8 2>/dev/null", 1)); + OK_(crypt_init(&cd, DMDIR L_DEVICE_OK)); + FAIL_(crypt_load(cd, CRYPT_LUKS1, NULL), "Header not found"); + crypt_free(cd); + + // plain device + OK_(crypt_init(&cd, DMDIR H_DEVICE)); + FAIL_(crypt_load(cd, CRYPT_PLAIN, NULL), "Can't load nonLUKS device type"); + crypt_free(cd); + OK_(crypt_init(&cd, DMDIR H_DEVICE)); + OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, key, key_size, &pl_params)); + FAIL_(crypt_load(cd, CRYPT_LUKS1, NULL), "Can't load over nonLUKS device type"); + crypt_free(cd); + + _cleanup_dmdevices(); +} + +static void LuksHeaderBackup(void) +{ + struct crypt_device *cd; + struct crypt_params_luks1 params = { + .hash = "sha512", + .data_alignment = 2048, + }; + 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"; + uint64_t r_payload_offset; + + crypt_decode_key(key, mk_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)); + + // create LUKS device and backup the header + OK_(crypt_init(&cd, DMDIR L_DEVICE_OK)); + OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); + OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0)); + OK_(crypt_header_backup(cd, CRYPT_LUKS1, BACKUP_FILE)); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + + // restore header from backup + OK_(crypt_init(&cd, DMDIR L_DEVICE_OK)); + OK_(crypt_header_restore(cd, CRYPT_LUKS1, BACKUP_FILE)); + OK_(crypt_load(cd, CRYPT_LUKS1, NULL)); + OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0)); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + + _cleanup_dmdevices(); +} + +static void ResizeDeviceLuks(void) +{ + struct crypt_device *cd; + struct crypt_params_luks1 params = { + .hash = "sha512", + .data_alignment = 2048, + }; + 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"; + uint64_t r_payload_offset, r_header_size, r_size; + + crypt_decode_key(key, mk_hex, key_size); + + // prepare env + OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, NULL, &r_payload_offset)); + OK_(get_luks_offsets(1, key_size, 0, 0, &r_header_size, NULL)); + OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size)); + OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1000)); + OK_(create_dmdevice_over_loop(L_DEVICE_0S, 1000)); + + // test header and encrypted payload all in one device + OK_(crypt_init(&cd, DMDIR L_DEVICE_OK)); + OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); + OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0)); + OK_(crypt_resize(cd, CDEVICE_1, 42)); + if (!device_size(DMDIR CDEVICE_1, &r_size)) + EQ_(42, r_size >> SECTOR_SHIFT); + // autodetect encrypted device area size + OK_(crypt_resize(cd, CDEVICE_1, 0)); + if (!device_size(DMDIR CDEVICE_1, &r_size)) + EQ_(1000, r_size >> SECTOR_SHIFT); + FAIL_(crypt_resize(cd, CDEVICE_1, 1001), "Device too small"); + if (!device_size(DMDIR CDEVICE_1, &r_size)) + EQ_(1000, r_size >> SECTOR_SHIFT); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + + params.data_alignment = 0; + params.data_device = DMDIR L_DEVICE_0S; + // test case for external header + OK_(crypt_init(&cd, DMDIR H_DEVICE)); + OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); + OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0)); + OK_(crypt_resize(cd, CDEVICE_1, 666)); + if (!device_size(DMDIR CDEVICE_1, &r_size)) + EQ_(666, r_size >> SECTOR_SHIFT); + // autodetect encrypted device size + OK_(crypt_resize(cd, CDEVICE_1, 0)); + if (!device_size(DMDIR CDEVICE_1, &r_size)) + EQ_(1000, r_size >> SECTOR_SHIFT); + FAIL_(crypt_resize(cd, CDEVICE_1, 1001), "Device too small"); + if (!device_size(DMDIR CDEVICE_1, &r_size)) + EQ_(1000, r_size >> SECTOR_SHIFT); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + + _cleanup_dmdevices(); +} + +static void HashDevicePlain(void) +{ + struct crypt_device *cd; + struct crypt_params_plain params = { + .hash = NULL, + .skip = 0, + .offset = 0, + }; + + size_t key_size; + const char *mk_hex, *keystr; + char key[256]; + + OK_(crypt_init(&cd, DEVICE_1)); + OK_(crypt_format(cd, CRYPT_PLAIN, "aes", "cbc-essiv:sha256", NULL, NULL, 16, ¶ms)); + + // hash PLAIN, short key + OK_(_prepare_keyfile(KEYFILE1, "tooshort", 8)); + FAIL_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 16, 0), "not enough data in keyfile"); + _remove_keyfiles(); + + // hash PLAIN, exact key + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + mk_hex = "caffeecaffeecaffeecaffeecaffee88"; + key_size = 16; + crypt_decode_key(key, mk_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_(crypt_deactivate(cd, CDEVICE_1)); + + // Limit plain key + mk_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_(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"; + key_size = 16; + crypt_decode_key(key, mk_hex, key_size); + OK_(_prepare_keyfile(KEYFILE1, key, strlen(mk_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)); + 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)); + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + + _remove_keyfiles(); + + // hash sha256 + params.hash = "sha256"; + OK_(crypt_init(&cd, DEVICE_1)); + OK_(crypt_format(cd, CRYPT_PLAIN, "aes", "cbc-essiv:sha256", NULL, NULL, 16, ¶ms)); + + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + mk_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_(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_(crypt_deactivate(cd, CDEVICE_1)); + + _remove_keyfiles(); + + // Limit keyfile read + keystr = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxAAAAAAAA"; + 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_(crypt_deactivate(cd, CDEVICE_1)); + + // 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, "0e49cb34a1dee1df33f6505e4de44a66")); + OK_(crypt_deactivate(cd, CDEVICE_1)); + + _remove_keyfiles(); + + // FIXME: add keyfile="-" tests somehow + + crypt_free(cd); +} + +static void VerityTest(void) +{ + struct crypt_device *cd; + const char *salt_hex = "20c28ffc129c12360ba6ceea2b6cf04e89c2b41cfe6b8439eb53c1897f50df7b"; + const char *root_hex = "ab018b003a967fc782effb293b6dccb60b4f40c06bf80d16391acf686d28b5d6"; + char salt[256], root_hash[256]; + struct crypt_active_device cad; + struct crypt_params_verity params = { + .data_device = DEVICE_EMPTY, + .salt = salt, + .data_size = 0, /* whole device */ + .hash_area_offset = 0, + .flags = CRYPT_VERITY_CREATE_HASH, + }; + + crypt_decode_key(salt, salt_hex, strlen(salt_hex) / 2); + crypt_decode_key(root_hash, root_hex, strlen(root_hex) / 2); + + /* Format */ + OK_(crypt_init(&cd, DEVICE_2)); + + /* block size */ + params.data_block_size = 333; + FAIL_(crypt_format(cd, CRYPT_VERITY, NULL, NULL, NULL, NULL, 0, ¶ms), + "Unsupppored block size."); + params.data_block_size = 4096; + params.hash_block_size = 333; + FAIL_(crypt_format(cd, CRYPT_VERITY, NULL, NULL, NULL, NULL, 0, ¶ms), + "Unsupppored block size."); + params.hash_block_size = 4096; + + /* salt size */ + params.salt_size = 257; + FAIL_(crypt_format(cd, CRYPT_VERITY, NULL, NULL, NULL, NULL, 0, ¶ms), + "Too large salt."); + params.salt_size = 32; + + /* hash_type */ + params.hash_type = 3; + FAIL_(crypt_format(cd, CRYPT_VERITY, NULL, NULL, NULL, NULL, 0, ¶ms), + "Unsupported hash type."); + params.hash_type = 1; + params.hash_name = "blah"; + FAIL_(crypt_format(cd, CRYPT_VERITY, NULL, NULL, NULL, NULL, 0, ¶ms), + "Unsupported hash name."); + params.hash_name = "sha256"; + + OK_(crypt_format(cd, CRYPT_VERITY, NULL, NULL, NULL, NULL, 0, ¶ms)); + crypt_free(cd); + + /* Verify */ + OK_(crypt_init(&cd, DEVICE_2)); + memset(¶ms, 0, sizeof(params)); + params.data_device = DEVICE_EMPTY; + params.flags = CRYPT_VERITY_CHECK_HASH; + OK_(crypt_load(cd, CRYPT_VERITY, ¶ms)); + + /* check verity params */ + EQ_(crypt_get_volume_key_size(cd), 32); + OK_(strcmp(CRYPT_VERITY, crypt_get_type(cd))); + memset(¶ms, 0, sizeof(params)); + OK_(crypt_get_verity_info(cd, ¶ms)); + OK_(strcmp("sha256", params.hash_name)); + EQ_(strlen(salt_hex) / 2, params.salt_size); + OK_(memcmp(salt, params.salt, params.salt_size)); + EQ_(4096, params.data_block_size); + EQ_(4096, params.hash_block_size); + EQ_(1, params.hash_type); + EQ_(crypt_get_volume_key_size(cd), 32); + + OK_(crypt_activate_by_volume_key(cd, NULL, root_hash, 32, 0)); + OK_(crypt_set_data_device(cd, DEVICE_1)); + FAIL_(crypt_activate_by_volume_key(cd, NULL, root_hash, 32, 0), "Data corrupted");; + + OK_(crypt_set_data_device(cd, DEVICE_EMPTY)); + if (crypt_activate_by_volume_key(cd, CDEVICE_1, root_hash, 32, + CRYPT_ACTIVATE_READONLY) == -ENOTSUP) { + printf("WARNING: kernel dm-verity not supported, skipping test.\n"); + crypt_free(cd); return; } - OK_(crypt_init(&cd, DEVICE_2)); - OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); + OK_(crypt_get_active_device(cd, CDEVICE_1, &cad)); + EQ_(CRYPT_ACTIVATE_READONLY, cad.flags); + crypt_free(cd); + + OK_(crypt_init_by_name(&cd, CDEVICE_1)); + OK_(crypt_deactivate(cd, CDEVICE_1)); + + /* hash fail */ + root_hash[1] = ~root_hash[1]; + OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, root_hash, 32, CRYPT_ACTIVATE_READONLY)); + OK_(crypt_get_active_device(cd, CDEVICE_1, &cad)); + EQ_(CRYPT_ACTIVATE_READONLY|CRYPT_ACTIVATE_CORRUPTED, cad.flags); + OK_(crypt_deactivate(cd, CDEVICE_1)); + root_hash[1] = ~root_hash[1]; + + /* data fail */ + OK_(crypt_set_data_device(cd, DEVICE_1)); + OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, root_hash, 32, CRYPT_ACTIVATE_READONLY)); + OK_(crypt_get_active_device(cd, CDEVICE_1, &cad)); + EQ_(CRYPT_ACTIVATE_READONLY|CRYPT_ACTIVATE_CORRUPTED, cad.flags); + OK_(crypt_deactivate(cd, CDEVICE_1)); - params.hash = "md5"; - FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms), - "MD5 unsupported, too short"); crypt_free(cd); } +static void TcryptTest(void) +{ + struct crypt_device *cd = NULL; + struct crypt_active_device cad; + const char *passphrase = "aaaaaaaaaaaa"; + const char *kf1 = "tcrypt-images/keyfile1"; + const char *kf2 = "tcrypt-images/keyfile2"; + const char *keyfiles[] = { kf1, kf2 }; + struct crypt_params_tcrypt params = { + .passphrase = passphrase, + .passphrase_size = strlen(passphrase), + .keyfiles = keyfiles, + .keyfiles_count = 2, + }; + double enc_mbr = 0, dec_mbr = 0; + const char *tcrypt_dev = "tcrypt-images/tck_5-sha512-xts-aes"; + size_t key_size = 64; + char key[key_size], key_def[key_size]; + const char *key_hex = + "98dee64abe44bbf41d171c1f7b3e8eacda6d6b01f459097459a167f8c2872a96" + "3979531d1cdc18af62757cf22286f16f8583d848524f128d7594ac2082668c73"; + int r; + + crypt_decode_key(key_def, key_hex, strlen(key_hex) / 2); + + // First ensure we can use af_alg skcipher interface + r = crypt_benchmark(NULL, "aes", "xts", 512, 16, 1024, &enc_mbr, &dec_mbr); + if (r == -ENOTSUP || r == -ENOENT) { + printf("WARNING: algif_skcipher interface not present, skipping test.\n"); + return; + } + + OK_(crypt_init(&cd, tcrypt_dev)); + params.passphrase_size--; + FAIL_(crypt_load(cd, CRYPT_TCRYPT, ¶ms), "Wrong passphrase"); + params.passphrase_size++; + OK_(crypt_load(cd, CRYPT_TCRYPT, ¶ms)); + + // check params after load + OK_(strcmp("xts-plain64", crypt_get_cipher_mode(cd))); + OK_(strcmp("aes", crypt_get_cipher(cd))); + EQ_(key_size, crypt_get_volume_key_size(cd)); + EQ_(256, crypt_get_iv_offset(cd)); + EQ_(256, crypt_get_data_offset(cd)); + + memset(key, 0, key_size); + if (!_fips_mode) { + key_size--; + // small buffer + FAIL_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, NULL, 0), "small buffer"); + key_size++; + OK_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, NULL, 0)); + OK_(memcmp(key, key_def, key_size)); + } + + reset_log(); + crypt_set_log_callback(cd, &new_log, NULL); + OK_(crypt_dump(cd)); + OK_(!(global_lines != 0)); + crypt_set_log_callback(cd, NULL, NULL); + reset_log(); + + OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, NULL, 0, CRYPT_ACTIVATE_READONLY)); + crypt_free(cd); + + OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, NULL)); + EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE); + + FAIL_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, NULL, 0), "Need crypt_load"); + + // check params after init_by_name + OK_(strcmp("xts-plain64", crypt_get_cipher_mode(cd))); + OK_(strcmp("aes", crypt_get_cipher(cd))); + EQ_(key_size, crypt_get_volume_key_size(cd)); + EQ_(256, crypt_get_iv_offset(cd)); + EQ_(256, crypt_get_data_offset(cd)); + + OK_(crypt_get_active_device(cd, CDEVICE_1, &cad)); + EQ_(CRYPT_ACTIVATE_READONLY, cad.flags); + EQ_(256, cad.offset); + EQ_(256, cad.iv_offset); + EQ_(72, cad.size); -static void _gcrypt_compatible() + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); +} + +// Check that gcrypt is properly initialised in format +static void NonFIPSAlg(void) { - int maj, min, patch; - FILE *f; + struct crypt_device *cd; + struct crypt_params_luks1 params = {0}; + char key[128] = ""; + size_t key_size = 128; + const char *cipher = "aes"; + const char *cipher_mode = "cbc-essiv:sha256"; + int ret; + + OK_(crypt_init(&cd, DEVICE_2)); + params.hash = "sha256"; + OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); + FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms), + "Already formatted."); + crypt_free(cd); - if (!(f = popen("libgcrypt-config --version", "r"))) + params.hash = "whirlpool"; + OK_(crypt_init(&cd, DEVICE_2)); + ret = crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms); + if (ret < 0) { + printf("WARNING: whirlpool not supported, skipping test.\n"); + crypt_free(cd); return; + } + crypt_free(cd); - if (fscanf(f, "%d.%d.%d", &maj, &min, &patch) == 3 && - maj >= 1 && min >= 4) - gcrypt_compatible = 1; - if (_debug) - printf("libgcrypt version %d.%d.%d detected.\n", maj, min, patch); + params.hash = "md5"; + OK_(crypt_init(&cd, DEVICE_2)); + FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms), + "MD5 unsupported, too short"); + crypt_free(cd); +} - (void)fclose(f); - return; +static void int_handler(int sig __attribute__((__unused__))) +{ + _quit++; } -int main (int argc, char *argv[]) +int main(int argc, char *argv[]) { + struct sigaction sa = { .sa_handler = int_handler }; int i; if (getuid() != 0) { @@ -940,31 +1880,31 @@ int main (int argc, char *argv[]) _debug = _verbose = 1; } + /* Handle interrupt properly */ + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + _cleanup(); - _setup(); - _gcrypt_compatible(); + if (_setup()) + goto out; crypt_set_debug_level(_debug ? CRYPT_DEBUG_ALL : CRYPT_DEBUG_NONE); RUN_(NonFIPSAlg, "Crypto is properly initialised in format"); //must be the first! - - RUN_(LuksUUID, "luksUUID API call"); - RUN_(IsLuks, "isLuks API call"); - RUN_(LuksOpen, "luksOpen API call"); - RUN_(query_device, "crypt_query_device API call"); - RUN_(remove_device, "crypt_remove_device API call"); - RUN_(LuksFormat, "luksFormat API call"); - RUN_(LuksKeyGame, "luksAddKey, RemoveKey, KillSlot API calls"); - RUN_(DeviceResizeGame, "regular crypto, resize calls"); - RUN_(AddDevicePlain, "plain device API creation exercise"); + RUN_(HashDevicePlain, "plain device API hash test"); RUN_(AddDeviceLuks, "Format and use LUKS device"); + RUN_(LuksHeaderLoad, "test header load"); + RUN_(LuksHeaderRestore, "test LUKS header restore"); + RUN_(LuksHeaderBackup, "test LUKS header backup"); + RUN_(ResizeDeviceLuks, "Luks device resize tests"); RUN_(UseLuksDevice, "Use pre-formated LUKS device"); RUN_(SuspendDevice, "Suspend/Resume test"); RUN_(UseTempVolumes, "Format and use temporary encrypted device"); - RUN_(CallbacksTest, "API callbacks test"); - + RUN_(VerityTest, "DM verity test"); + RUN_(TcryptTest, "Tcrypt API test"); +out: _cleanup(); return 0; }