diff --git a/lib/setup.c b/lib/setup.c index 408e47fa..dcb1224b 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -1265,13 +1265,17 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot) } ki = crypt_keyslot_status(cd, keyslot); - if (ki == SLOT_INVALID) + if (ki == SLOT_INVALID) { + log_err(cd, _("Key slot %d is invalid.\n"), keyslot); return -EINVAL; + } - if (ki == SLOT_INACTIVE) - return 0; + if (ki == SLOT_INACTIVE) { + log_err(cd, _("Key slot %d is not used.\n"), keyslot); + return -EINVAL; + } - return LUKS_del_key(cd->device, keyslot, cd); + return LUKS_del_key(cd->device, keyslot, &cd->hdr, cd); } // activation/deactivation of device mapping @@ -1464,7 +1468,8 @@ int crypt_deactivate(struct crypt_device *cd, const char *name) case ACTIVE: return dm_remove_device(name, 0, 0); case BUSY: log_err(cd, _("Device %s is busy."), name); return -EBUSY; - case INACTIVE: return -ENODEV; + case INACTIVE: log_err(cd, _("Device %s is not active."), name); + return -ENODEV; default: log_err(cd, _("Invalid device %s."), name); return -EINVAL; } diff --git a/luks/keymanage.c b/luks/keymanage.c index 298e09f8..d9e386cc 100644 --- a/luks/keymanage.c +++ b/luks/keymanage.c @@ -512,17 +512,19 @@ static int wipe(const char *device, unsigned int from, unsigned int to) return r; } -int LUKS_del_key(const char *device, unsigned int keyIndex, struct crypt_device *ctx) +int LUKS_del_key(const char *device, + unsigned int keyIndex, + struct luks_phdr *hdr, + struct crypt_device *ctx) { - struct luks_phdr hdr; unsigned int startOffset, endOffset, stripesLen; int r; - r = LUKS_read_phdr(device, &hdr, 1, ctx); + r = LUKS_read_phdr(device, hdr, 1, ctx); if (r) return r; - r = LUKS_keyslot_set(&hdr, keyIndex, 0); + r = LUKS_keyslot_set(hdr, keyIndex, 0); if (r) { log_err(ctx, _("Key slot %d is invalid, please select keyslot between 0 and %d.\n"), keyIndex, LUKS_NUMKEYS - 1); @@ -530,8 +532,8 @@ int LUKS_del_key(const char *device, unsigned int keyIndex, struct crypt_device } /* secure deletion of key material */ - startOffset = hdr.keyblock[keyIndex].keyMaterialOffset; - stripesLen = hdr.keyBytes * hdr.keyblock[keyIndex].stripes; + startOffset = hdr->keyblock[keyIndex].keyMaterialOffset; + stripesLen = hdr->keyBytes * hdr->keyblock[keyIndex].stripes; endOffset = startOffset + div_round_up(stripesLen, SECTOR_SIZE); r = wipe(device, startOffset, endOffset); @@ -540,7 +542,7 @@ int LUKS_del_key(const char *device, unsigned int keyIndex, struct crypt_device return r; } - r = LUKS_write_phdr(device, &hdr, ctx); + r = LUKS_write_phdr(device, hdr, ctx); return r; } diff --git a/luks/luks.h b/luks/luks.h index c433bc5c..046c365a 100644 --- a/luks/luks.h +++ b/luks/luks.h @@ -135,6 +135,7 @@ int LUKS_open_key_with_hdr( int LUKS_del_key( const char *device, unsigned int keyIndex, + struct luks_phdr *hdr, struct crypt_device *ctx); crypt_keyslot_info LUKS_keyslot_info(struct luks_phdr *hdr, int keyslot); diff --git a/tests/apitest.c b/tests/apitest.c index c6d6fedd..9764c5e1 100644 --- a/tests/apitest.c +++ b/tests/apitest.c @@ -54,6 +54,7 @@ static int _debug = 0; static int _verbose = 1; static char global_log[4096]; +static int global_lines = 0; // Helpers static int _prepare_keyfile(const char *name, const char *passphrase) @@ -109,11 +110,19 @@ static int yesDialog(char *msg) static void cmdLineLog(int class, char *msg) { strncat(global_log, msg, sizeof(global_log)); + global_lines++; } +static void new_log(int class, const char *msg, void *usrptr) +{ + cmdLineLog(class, (char*)msg); +} + + static void reset_log() { memset(global_log, 0, sizeof(global_log)); + global_lines = 0; } static struct interface_callbacks cmd_icb = { @@ -538,6 +547,109 @@ static void AddDevicePlain(void) crypt_free(cd); } +static void UseLuksDevice(void) +{ + struct crypt_device *cd; + char key[128]; + size_t key_size; + int fd; + + OK_(crypt_init(&cd, DEVICE_1)); + OK_(crypt_load(cd, CRYPT_LUKS1, NULL)); + EQ_(crypt_status(cd, CDEVICE_1), INACTIVE); + OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0)); + FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0), "already open"); + EQ_(crypt_status(cd, CDEVICE_1), ACTIVE); + OK_(crypt_deactivate(cd, CDEVICE_1)); + FAIL_(crypt_deactivate(cd, CDEVICE_1), "no such device"); + + key_size = 16; + 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_(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, CDEVICE_1, key, key_size, 0)); + EQ_(crypt_status(cd, CDEVICE_1), 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); +} + +static void AddDeviceLuks(void) +{ + struct crypt_device *cd; + struct crypt_params_luks1 params = { + .hash = "sha512", + .data_alignment = 2048, // 4M, data offset will be 4096 + }; + int fd; + unsigned char key[128], key2[128], path[128]; + + char *passphrase = "blabla"; + char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a"; + size_t key_size = strlen(mk_hex) / 2; + char *cipher = "aes"; + char *cipher_mode = "cbc-essiv:sha256"; + + crypt_decode_key(key, mk_hex, key_size); + + OK_(crypt_init(&cd, DEVICE_2)); + OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms)); + + // even with no keyslots defined it can be activated by volume key + OK_(crypt_volume_key_verify(cd, key, key_size)); + OK_(crypt_activate_by_volume_key(cd, CDEVICE_2, key, key_size, 0)); + EQ_(crypt_status(cd, CDEVICE_2), ACTIVE); + OK_(crypt_deactivate(cd, CDEVICE_2)); + + // now with keyslot + EQ_(7, crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, passphrase, strlen(passphrase))); + EQ_(SLOT_ACTIVE_LAST, crypt_keyslot_status(cd, 7)); + EQ_(7, crypt_activate_by_passphrase(cd, CDEVICE_2, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0)); + EQ_(crypt_status(cd, CDEVICE_2), ACTIVE); + OK_(crypt_deactivate(cd, CDEVICE_2)); + + FAIL_(crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, passphrase, strlen(passphrase)), "slot used"); + key[1] = ~key[1]; + FAIL_(crypt_keyslot_add_by_volume_key(cd, 6, key, key_size, passphrase, strlen(passphrase)), "key mismatch"); + key[1] = ~key[1]; + EQ_(6, crypt_keyslot_add_by_volume_key(cd, 6, key, key_size, passphrase, strlen(passphrase))); + EQ_(SLOT_ACTIVE, crypt_keyslot_status(cd, 6)); + + FAIL_(crypt_keyslot_destroy(cd, 8), "invalid keyslot"); + FAIL_(crypt_keyslot_destroy(cd, CRYPT_ANY_SLOT), "invalid keyslot"); + FAIL_(crypt_keyslot_destroy(cd, 0), "keyslot not used"); + OK_(crypt_keyslot_destroy(cd, 7)); + EQ_(SLOT_INACTIVE, crypt_keyslot_status(cd, 7)); + EQ_(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)); + + 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_(4096, crypt_get_data_offset(cd)); + + 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(); + + FAIL_(crypt_deactivate(cd, CDEVICE_2), "not active"); + crypt_free(cd); +} + int main (int argc, char *argv[]) { int i; @@ -564,6 +676,9 @@ int main (int argc, char *argv[]) RUN_(DeviceResizeGame, "regular crypto, resize calls"); RUN_(AddDevicePlain, "plain device API creation exercise"); + RUN_(AddDeviceLuks, "Format and use LUKS device"); + RUN_(UseLuksDevice, "Use pre-formated LUKS device"); + _cleanup(); return 0;