X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=tests%2Fapi-test.c;h=b359ca16d7d215914ef9711c6da0db2b7faa6c2b;hb=1349efa34db577947083daee2e521770614fcfe0;hp=b9a3bd444b032c6ce3e42a613d9870352428acf7;hpb=d6016b1c2d85be308dd471d9d4431fe08f15b678;p=platform%2Fupstream%2Fcryptsetup.git diff --git a/tests/api-test.c b/tests/api-test.c index b9a3bd4..b359ca1 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-2013, 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,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -82,6 +85,9 @@ 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; @@ -112,6 +118,24 @@ static int device_size(const char *device, uint64_t *size) 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, @@ -121,10 +145,12 @@ static int get_luks_offsets(int metadata_device, { int i; uint64_t current_sector; + uint32_t sectors_per_stripes_set; + if (!keylength) return -1; - uint32_t sectors_per_stripes_set = DIV_ROUND_UP(keylength*LUKS_STRIPES, SECTOR_SIZE); + 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); @@ -182,7 +208,7 @@ 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, *rcipher, *key, *params; + char *target_type, *key, *params; void *next = NULL; int r = -EINVAL; @@ -201,7 +227,7 @@ static int _get_key_dm(const char *name, char *buffer, unsigned int buffer_size) if (!target_type || strcmp(target_type, "crypt") != 0) goto out; - rcipher = strsep(¶ms, " "); + (void)strsep(¶ms, " "); /* rcipher */ key = strsep(¶ms, " "); if (buffer_size <= strlen(key)) @@ -237,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; @@ -261,7 +287,7 @@ static int crypt_decode_key(char *key, char *hex, unsigned int size) return 0; } -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++; @@ -269,10 +295,12 @@ 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; @@ -281,6 +309,8 @@ static void reset_log() static int _system(const char *command, int 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; @@ -374,7 +404,7 @@ static int _setup(void) return 1; } close(fd); - snprintf(cmd, sizeof(cmd), "dd if=/dev/zero of=%s bs=%d count=%d", + 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; @@ -396,7 +426,7 @@ static int _setup(void) return 1; } close(fd); - snprintf(cmd, sizeof(cmd), "dd if=/dev/zero of=%s bs=%d count=%d", + 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; @@ -421,7 +451,7 @@ static int _setup(void) return 1; } if (crypt_loop_device(DEVICE_2)) { - _system("dd if=/dev/zero of=" IMAGE_EMPTY " bs=1M count=4", 1); + _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); } @@ -438,10 +468,20 @@ static int _setup(void) * 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]; @@ -453,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]; @@ -467,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) @@ -482,6 +523,12 @@ 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 */ @@ -492,9 +539,9 @@ 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) static void AddDevicePlain(void) @@ -509,12 +556,12 @@ static void AddDevicePlain(void) int fd; char key[128], key2[128], path[128]; - char *passphrase = PASSPHRASE; + const char *passphrase = PASSPHRASE; // hashed hex version of PASSPHRASE - char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a"; + 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 size, r_size; @@ -534,7 +581,7 @@ static void AddDevicePlain(void) 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_(key_size, crypt_get_volume_key_size(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; @@ -658,6 +705,11 @@ static void AddDevicePlain(void) 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); @@ -681,7 +733,7 @@ static void AddDevicePlain(void) EQ_(r_size, size); // size overlaps - FAIL_(crypt_resize(cd, CDEVICE_1, ULLONG_MAX),"Backing device is too small"); + 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 @@ -741,17 +793,19 @@ static void AddDevicePlain(void) 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)); @@ -762,6 +816,9 @@ static void AddDevicePlain(void) 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); @@ -810,9 +867,9 @@ 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)); @@ -874,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); } @@ -914,7 +973,8 @@ static void SuspendDevice(void) 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: @@ -932,11 +992,11 @@ static void AddDeviceLuks(void) }; 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); @@ -974,7 +1034,8 @@ static void AddDeviceLuks(void) 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, 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)); @@ -1039,7 +1100,7 @@ static void AddDeviceLuks(void) // 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); - EQ_(crypt_get_type(cd), NULL); + 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); @@ -1064,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, 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(); @@ -1090,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))); @@ -1188,10 +1267,10 @@ static void LuksHeaderRestore(void) }; char key[128], key2[128], cmd[256]; - char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a"; + 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; crypt_decode_key(key, mk_hex, key_size); @@ -1218,7 +1297,7 @@ static void LuksHeaderRestore(void) 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, r_payload_offset); + 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"); @@ -1262,10 +1341,10 @@ static void LuksHeaderLoad(void) }; char key[128], cmd[256]; - char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a"; + 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; crypt_decode_key(key, mk_hex, key_size); @@ -1275,8 +1354,10 @@ static void LuksHeaderLoad(void) // 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)); - snprintf(cmd, sizeof(cmd), "dd if=" EVL_HEADER_4 " of=" DMDIR H_DEVICE_WRONG " bs=512 count=%" PRIu64, r_payload_offset - 1); + //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)); @@ -1302,7 +1383,7 @@ static void LuksHeaderLoad(void) // 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"); - EQ_(crypt_get_type(cd), NULL); + OK_(!!crypt_get_type(cd)); crypt_free(cd); // 0 secs for encrypted data area @@ -1319,7 +1400,7 @@ static void LuksHeaderLoad(void) crypt_free(cd); // damaged header - OK_(_system("dd if=/dev/zero of=" DMDIR L_DEVICE_0S "bs=512 count=8", 1)); + 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); @@ -1345,10 +1426,10 @@ static void LuksHeaderBackup(void) }; char key[128]; - char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a"; + 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; crypt_decode_key(key, mk_hex, key_size); @@ -1385,10 +1466,10 @@ static void ResizeDeviceLuks(void) }; char key[128]; - char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a"; + 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; crypt_decode_key(key, mk_hex, key_size); @@ -1451,7 +1532,8 @@ static void HashDevicePlain(void) }; size_t key_size; - char *mk_hex, *keystr, key[256]; + 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)); @@ -1548,6 +1630,212 @@ static void HashDevicePlain(void) 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_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)); + + 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"; + 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]; + 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); + + OK_(crypt_deactivate(cd, CDEVICE_1)); + crypt_free(cd); + + OK_(crypt_init(&cd, tcrypt_dev2)); + params.keyfiles = NULL; + params.keyfiles_count = 0; + OK_(crypt_load(cd, CRYPT_TCRYPT, ¶ms)); + OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, NULL, 0, CRYPT_ACTIVATE_READONLY)); + crypt_free(cd); + + // Deactivate the whole chain + EQ_(crypt_status(NULL, CDEVICE_1 "_1"), CRYPT_BUSY); + OK_(crypt_deactivate(NULL, CDEVICE_1)); + EQ_(crypt_status(NULL, CDEVICE_1 "_1"), CRYPT_INACTIVE); +} + // Check that gcrypt is properly initialised in format static void NonFIPSAlg(void) { @@ -1555,30 +1843,42 @@ static void NonFIPSAlg(void) struct crypt_params_luks1 params = {0}; char key[128] = ""; size_t key_size = 128; - char *cipher = "aes"; - char *cipher_mode = "cbc-essiv:sha256"; + 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); 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); 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); } -int main (int argc, char *argv[]) +static void int_handler(int sig __attribute__((__unused__))) +{ + _quit++; +} + +int main(int argc, char *argv[]) { + struct sigaction sa = { .sa_handler = int_handler }; int i; if (getuid() != 0) { @@ -1593,6 +1893,10 @@ int main (int argc, char *argv[]) _debug = _verbose = 1; } + /* Handle interrupt properly */ + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + _cleanup(); if (_setup()) goto out; @@ -1610,8 +1914,9 @@ int main (int argc, char *argv[]) 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;