From aa1551c6e86b96924e3b4fbbf45da6db6fa97a5a Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Thu, 19 Apr 2018 15:22:28 +0200 Subject: [PATCH] Introduce CRYPT_SLOT_UNBOUND keyslot status for LUKS2. A keyslot not bound to any segment can store any key for any purpose. To easily check slot status, new enum value is introduced. This status is valid only for LUKS2, so the functions are backward compatible with LUKS1. --- lib/libcryptsetup.h | 6 ++- lib/luks2/luks2_digest.c | 1 + lib/luks2/luks2_json_metadata.c | 12 ++---- lib/luks2/luks2_keyslot.c | 42 +++++++++++++------- lib/luks2/luks2_token.c | 6 ++- lib/setup.c | 9 ++++- python/pycryptsetup.c | 2 + src/cryptsetup.c | 15 ++++--- src/cryptsetup_reencrypt.c | 70 ++++++++++++++++++++++++++------- tests/api-test-2.c | 10 ++--- tests/compat-test2 | 15 +++++-- tests/reencryption-compat-test2 | 11 ++++++ 12 files changed, 145 insertions(+), 54 deletions(-) diff --git a/lib/libcryptsetup.h b/lib/libcryptsetup.h index 98cdd33c..1bc7a08f 100644 --- a/lib/libcryptsetup.h +++ b/lib/libcryptsetup.h @@ -956,6 +956,8 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot); #define CRYPT_ACTIVATE_IGNORE_PERSISTENT (1 << 14) /** dm-verity: check_at_most_once - check data blocks only the first time */ #define CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE (1 << 15) +/** allow activation check including unbound keyslots (kesylots without segments) */ +#define CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY (1 << 16) /** * Active device runtime attributes @@ -1437,8 +1439,10 @@ typedef enum { CRYPT_SLOT_INVALID, /**< invalid keyslot */ CRYPT_SLOT_INACTIVE, /**< keyslot is inactive (free) */ CRYPT_SLOT_ACTIVE, /**< keyslot is active (used) */ - CRYPT_SLOT_ACTIVE_LAST /**< keylost is active (used) + CRYPT_SLOT_ACTIVE_LAST,/**< keylost is active (used) * and last used at the same time */ + CRYPT_SLOT_UNBOUND /**< keyslot is active and not bound + * to any crypt segment (LUKS2 only) */ } crypt_keyslot_info; /** diff --git a/lib/luks2/luks2_digest.c b/lib/luks2/luks2_digest.c index cfd333a3..fe054b12 100644 --- a/lib/luks2/luks2_digest.c +++ b/lib/luks2/luks2_digest.c @@ -175,6 +175,7 @@ int LUKS2_digest_verify_by_segment(struct crypt_device *cd, return digest; } +/* FIXME: segment can have more digests */ int LUKS2_digest_by_segment(struct crypt_device *cd, struct luks2_hdr *hdr, int segment) diff --git a/lib/luks2/luks2_json_metadata.c b/lib/luks2/luks2_json_metadata.c index c40571b5..640b1bb7 100644 --- a/lib/luks2/luks2_json_metadata.c +++ b/lib/luks2/luks2_json_metadata.c @@ -882,17 +882,11 @@ int LUKS2_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr) return r; } -/* NOTE: is called before LUKS2 validation routines */ -static void LUKS2_hdr_free_unused_objects(struct crypt_device *cd, struct luks2_hdr *hdr) -{ - /* erase unused digests (no assigned keyslot or segment) */ - LUKS2_digests_erase_unused(cd, hdr); -} - int LUKS2_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr) { - /* FIXME: we risk to hide future internal implementation bugs with this */ - LUKS2_hdr_free_unused_objects(cd, hdr); + /* NOTE: is called before LUKS2 validation routines */ + /* erase unused digests (no assigned keyslot or segment) */ + LUKS2_digests_erase_unused(cd, hdr); if (LUKS2_hdr_validate(hdr->jobj)) return -EINVAL; diff --git a/lib/luks2/luks2_keyslot.c b/lib/luks2/luks2_keyslot.c index e2dc9193..feadd36a 100644 --- a/lib/luks2/luks2_keyslot.c +++ b/lib/luks2/luks2_keyslot.c @@ -63,14 +63,6 @@ static const keyslot_handler return LUKS2_keyslot_handler_type(cd, json_object_get_string(jobj2)); } -static crypt_keyslot_info LUKS2_keyslot_active(struct luks2_hdr *hdr, int keyslot) -{ - if (keyslot >= LUKS2_KEYSLOTS_MAX) - return CRYPT_SLOT_INVALID; - - return LUKS2_get_keyslot_jobj(hdr, keyslot) ? CRYPT_SLOT_ACTIVE : CRYPT_SLOT_INACTIVE; -} - int LUKS2_keyslot_find_empty(struct luks2_hdr *hdr, const char *type) { int i; @@ -82,6 +74,7 @@ int LUKS2_keyslot_find_empty(struct luks2_hdr *hdr, const char *type) return -EINVAL; } +/* Check if a keyslot is asssigned to specific segment */ int LUKS2_keyslot_for_segment(struct luks2_hdr *hdr, int keyslot, int segment) { int keyslot_digest, segment_digest; @@ -101,6 +94,7 @@ int LUKS2_keyslot_for_segment(struct luks2_hdr *hdr, int keyslot, int segment) return segment_digest == keyslot_digest ? 0 : -ENOENT; } +/* Number of keyslots assigned to a segment or all keyslots for CRYPT_ANY_SEGMENT */ int LUKS2_keyslot_active_count(struct luks2_hdr *hdr, int segment) { int num = 0; @@ -176,18 +170,38 @@ int LUKS2_keyslot_params_default(struct crypt_device *cd, struct luks2_hdr *hdr, return 0; } +static int LUKS2_keyslot_unbound(struct luks2_hdr *hdr, int keyslot) +{ + json_object *jobj_digest, *jobj_segments; + int digest = LUKS2_digest_by_keyslot(NULL, hdr, keyslot); + + if (digest < 0) + return 0; + + if (!(jobj_digest = LUKS2_get_digest_jobj(hdr, digest))) + return 0; + + json_object_object_get_ex(jobj_digest, "segments", &jobj_segments); + if (!jobj_segments || !json_object_is_type(jobj_segments, json_type_array) || + json_object_array_length(jobj_segments) == 0) + return 1; + + return 0; +} + crypt_keyslot_info LUKS2_keyslot_info(struct luks2_hdr *hdr, int keyslot) { - crypt_keyslot_info ki; - if(keyslot >= LUKS2_KEYSLOTS_MAX || keyslot < 0) return CRYPT_SLOT_INVALID; - ki = LUKS2_keyslot_active(hdr, keyslot); - if (ki != CRYPT_SLOT_ACTIVE) - return ki; + if (!LUKS2_get_keyslot_jobj(hdr, keyslot)) + return CRYPT_SLOT_INACTIVE; - if (LUKS2_keyslot_active_count(hdr, CRYPT_DEFAULT_SEGMENT) == 1 && !LUKS2_keyslot_for_segment(hdr, keyslot, CRYPT_DEFAULT_SEGMENT)) + if (LUKS2_keyslot_unbound(hdr, keyslot)) + return CRYPT_SLOT_UNBOUND; + + if (LUKS2_keyslot_active_count(hdr, CRYPT_DEFAULT_SEGMENT) == 1 && + !LUKS2_keyslot_for_segment(hdr, keyslot, CRYPT_DEFAULT_SEGMENT)) return CRYPT_SLOT_ACTIVE_LAST; return CRYPT_SLOT_ACTIVE; diff --git a/lib/luks2/luks2_token.c b/lib/luks2/luks2_token.c index 0876c1dd..95ca0292 100644 --- a/lib/luks2/luks2_token.c +++ b/lib/luks2/luks2_token.c @@ -397,7 +397,8 @@ int LUKS2_token_open_and_activate(struct crypt_device *cd, return r; r = LUKS2_keyslot_open_by_token(cd, hdr, token, - name ? CRYPT_DEFAULT_SEGMENT : CRYPT_ANY_SEGMENT, + (flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) ? + CRYPT_ANY_SEGMENT : CRYPT_DEFAULT_SEGMENT, buffer, buffer_len, &vk); LUKS2_token_buffer_free(cd, token, buffer, buffer_len); @@ -442,7 +443,8 @@ int LUKS2_token_open_and_activate_any(struct crypt_device *cd, continue; r = LUKS2_keyslot_open_by_token(cd, hdr, token, - name ? CRYPT_DEFAULT_SEGMENT : CRYPT_ANY_SEGMENT, + (flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) ? + CRYPT_ANY_SEGMENT : CRYPT_DEFAULT_SEGMENT, buffer, buffer_len, &vk); LUKS2_token_buffer_free(cd, token, buffer, buffer_len); if (r >= 0) diff --git a/lib/setup.c b/lib/setup.c index 32779fbe..ef301777 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -2916,6 +2916,9 @@ static int _activate_by_passphrase(struct crypt_device *cd, if ((flags & CRYPT_ACTIVATE_KEYRING_KEY) && !crypt_use_keyring_for_vk(cd)) return -EINVAL; + if ((flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) && name) + return -EINVAL; + /* plain, use hashed passphrase */ if (isPLAIN(cd->type)) { if (!name) @@ -2939,7 +2942,8 @@ static int _activate_by_passphrase(struct crypt_device *cd, } } else if (isLUKS2(cd->type)) { r = LUKS2_keyslot_open(cd, keyslot, - name ? CRYPT_DEFAULT_SEGMENT : CRYPT_ANY_SEGMENT, + (flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) ? + CRYPT_ANY_SEGMENT : CRYPT_DEFAULT_SEGMENT, passphrase, passphrase_size, &vk); if (r >= 0) { keyslot = r; @@ -4025,6 +4029,9 @@ int crypt_activate_by_token(struct crypt_device *cd, if ((flags & CRYPT_ACTIVATE_KEYRING_KEY) && !crypt_use_keyring_for_vk(cd)) return -EINVAL; + if ((flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) && name) + return -EINVAL; + if (token == CRYPT_ANY_TOKEN) return LUKS2_token_open_and_activate_any(cd, &cd->u.luks2.hdr, name, flags); diff --git a/python/pycryptsetup.c b/python/pycryptsetup.c index 6c805108..cf8bbce8 100644 --- a/python/pycryptsetup.c +++ b/python/pycryptsetup.c @@ -512,6 +512,8 @@ static PyObject *CryptSetup_killSlot(CryptSetupObject* self, PyObject *args, PyO case CRYPT_SLOT_INVALID: PyErr_SetString(PyExc_ValueError, "Invalid slot"); break; + default: + break; } return NULL; diff --git a/src/cryptsetup.c b/src/cryptsetup.c index b991a33b..16f182ce 100644 --- a/src/cryptsetup.c +++ b/src/cryptsetup.c @@ -156,6 +156,10 @@ static void _set_activation_flags(uint32_t *flags) /* In persistent mode, we use what is set on command line */ if (opt_persistent) *flags |= CRYPT_ACTIVATE_IGNORE_PERSISTENT; + + /* Only for LUKS2 but ignored elsewhere */ + if (opt_test_passphrase) + *flags |= CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY; } static int action_open_plain(void) @@ -1132,17 +1136,15 @@ out: return r; } -static int verify_keyslot(struct crypt_device *cd, int key_slot, +static int verify_keyslot(struct crypt_device *cd, int key_slot, crypt_keyslot_info ki, char *msg_last, char *msg_pass, char *msg_fail, const char *key_file, uint64_t keyfile_offset, int keyfile_size) { - crypt_keyslot_info ki; char *password = NULL; size_t passwordLen; int i, max, r; - ki = crypt_keyslot_status(cd, key_slot); if (ki == CRYPT_SLOT_ACTIVE_LAST && !opt_batch_mode && !key_file && msg_last && !yesDialog(msg_last, msg_fail)) return -EPERM; @@ -1188,6 +1190,7 @@ out: static int action_luksKillSlot(void) { struct crypt_device *cd = NULL; + crypt_keyslot_info ki; int r; if ((r = crypt_init(&cd, uuid_or_device_header(NULL)))) @@ -1198,9 +1201,11 @@ static int action_luksKillSlot(void) if ((r = crypt_load(cd, luksType(opt_type), NULL))) goto out; - switch (crypt_keyslot_status(cd, opt_key_slot)) { + ki = crypt_keyslot_status(cd, opt_key_slot); + switch (ki) { case CRYPT_SLOT_ACTIVE_LAST: case CRYPT_SLOT_ACTIVE: + case CRYPT_SLOT_UNBOUND: log_verbose(_("Keyslot %d is selected for deletion.\n"), opt_key_slot); break; case CRYPT_SLOT_INACTIVE: @@ -1211,7 +1216,7 @@ static int action_luksKillSlot(void) } if (!opt_batch_mode || opt_key_file || !isatty(STDIN_FILENO)) { - r = verify_keyslot(cd, opt_key_slot, + r = verify_keyslot(cd, opt_key_slot, ki, _("This is the last keyslot. Device will become unusable after purging this key."), _("Enter any remaining passphrase: "), _("Operation aborted, the keyslot was NOT wiped.\n"), diff --git a/src/cryptsetup_reencrypt.c b/src/cryptsetup_reencrypt.c index 0e634de2..95ceb6e1 100644 --- a/src/cryptsetup_reencrypt.c +++ b/src/cryptsetup_reencrypt.c @@ -533,8 +533,38 @@ static int set_pbkdf_params(struct crypt_device *cd, const char *dev_type) return crypt_set_pbkdf_type(cd, &pbkdf); } -static int create_new_header(struct reenc_ctx *rc, const char *cipher, - const char *cipher_mode, const char *uuid, +static int create_new_keyslot(struct reenc_ctx *rc, int keyslot, + struct crypt_device *cd_old, + struct crypt_device *cd_new) +{ + int r; + char *key = NULL; + size_t key_size; + + if (cd_old && crypt_keyslot_status(cd_old, keyslot) == CRYPT_SLOT_UNBOUND) { + key_size = 4096; + key = crypt_safe_alloc(key_size); + if (!key) + return -ENOMEM; + r = crypt_volume_key_get(cd_old, keyslot, key, &key_size, + rc->p[keyslot].password, rc->p[keyslot].passwordLen); + if (r == keyslot) { + r = crypt_keyslot_add_by_key(cd_new, keyslot, key, key_size, + rc->p[keyslot].password, rc->p[keyslot].passwordLen, + CRYPT_VOLUME_KEY_NO_SEGMENT); + } else + r = -EINVAL; + crypt_safe_free(key); + } else + r = crypt_keyslot_add_by_volume_key(cd_new, keyslot, NULL, 0, + rc->p[keyslot].password, rc->p[keyslot].passwordLen); + + return r; +} + +static int create_new_header(struct reenc_ctx *rc, struct crypt_device *cd_old, + const char *cipher, const char *cipher_mode, + const char *uuid, const char *key, int key_size, const char *type, void *params) @@ -564,8 +594,9 @@ static int create_new_header(struct reenc_ctx *rc, const char *cipher, for (i = 0; i < crypt_keyslot_max(type); i++) { if (!rc->p[i].password) continue; - if ((r = crypt_keyslot_add_by_volume_key(cd_new, i, - NULL, 0, rc->p[i].password, rc->p[i].passwordLen)) < 0) + + r = create_new_keyslot(rc, i, cd_old, cd_new); + if (r < 0) goto out; log_verbose(_("Activated keyslot %i.\n"), r); r = 0; @@ -732,7 +763,7 @@ static int backup_luks_headers(struct reenc_ctx *rc) if (r < 0) goto out; - r = create_new_header(rc, + r = create_new_header(rc, cd, opt_cipher ? cipher : crypt_get_cipher(cd), opt_cipher ? cipher_mode : crypt_get_cipher_mode(cd), crypt_get_uuid(cd), @@ -818,7 +849,7 @@ static int backup_fake_header(struct reenc_ctx *rc) goto out; params2.data_alignment = params.data_alignment = ROUND_SECTOR(opt_reduce_size); - r = create_new_header(rc, + r = create_new_header(rc, NULL, opt_cipher ? cipher : DEFAULT_LUKS1_CIPHER, opt_cipher ? cipher_mode : DEFAULT_LUKS1_MODE, NULL, NULL, @@ -1195,10 +1226,19 @@ static int initialize_uuid(struct reenc_ctx *rc) static int init_passphrase1(struct reenc_ctx *rc, struct crypt_device *cd, const char *msg, int slot_to_check, int check, int verify) { + crypt_keyslot_info ki; char *password; int r = -EINVAL, retry_count; size_t passwordLen; + /* mode ENCRYPT call this without header */ + if (cd && slot_to_check != CRYPT_ANY_SLOT) { + ki = crypt_keyslot_status(cd, slot_to_check); + if (ki < CRYPT_SLOT_ACTIVE) + return -ENOENT; + } else + ki = CRYPT_SLOT_ACTIVE; + retry_count = opt_tries ?: 1; while (retry_count--) { r = tools_get_key(msg, &password, &passwordLen, 0, 0, @@ -1214,7 +1254,7 @@ static int init_passphrase1(struct reenc_ctx *rc, struct crypt_device *cd, if (check) r = crypt_activate_by_passphrase(cd, NULL, slot_to_check, - password, passwordLen, 0); + password, passwordLen, CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY); else r = (slot_to_check == CRYPT_ANY_SLOT) ? 0 : slot_to_check; @@ -1225,10 +1265,12 @@ static int init_passphrase1(struct reenc_ctx *rc, struct crypt_device *cd, } if (r < 0 && r != -EPERM) return r; + if (r >= 0) { - rc->keyslot = r; rc->p[r].password = password; rc->p[r].passwordLen = passwordLen; + if (ki != CRYPT_SLOT_UNBOUND) + rc->keyslot = r; break; } tools_passphrase_msg(r); @@ -1283,11 +1325,10 @@ static int init_keyfile(struct reenc_ctx *rc, struct crypt_device *cd, int slot_ static int initialize_passphrase(struct reenc_ctx *rc, const char *device) { struct crypt_device *cd = NULL; - crypt_keyslot_info ki; char msg[256]; int i, r; - log_dbg("Passhrases initialization."); + log_dbg("Passphrases initialization."); if (rc->reencrypt_mode == ENCRYPT && !rc->in_progress) { r = init_passphrase1(rc, cd, _("Enter new passphrase: "), opt_key_slot, 0, 1); @@ -1314,12 +1355,12 @@ static int initialize_passphrase(struct reenc_ctx *rc, const char *device) rc->reencrypt_mode == DECRYPT) { r = init_passphrase1(rc, cd, msg, opt_key_slot, 1, 0); } else for (i = 0; i < crypt_keyslot_max(crypt_get_type(cd)); i++) { - ki = crypt_keyslot_status(cd, i); - if (ki != CRYPT_SLOT_ACTIVE && ki != CRYPT_SLOT_ACTIVE_LAST) - continue; - snprintf(msg, sizeof(msg), _("Enter passphrase for key slot %u: "), i); r = init_passphrase1(rc, cd, msg, i, 1, 0); + if (r == -ENOENT) { + r = 0; + continue; + } if (r < 0) break; } @@ -1504,6 +1545,7 @@ static int run_reencrypt(const char *device) if ((r = initialize_passphrase(&rc, hdr_device(&rc)))) goto out; + log_dbg("Storing backup of LUKS headers."); if (rc.reencrypt_mode == ENCRYPT) { /* Create fake header for exising device */ if ((r = backup_fake_header(&rc))) diff --git a/tests/api-test-2.c b/tests/api-test-2.c index 639c0a94..5f5a3686 100644 --- a/tests/api-test-2.c +++ b/tests/api-test-2.c @@ -1544,7 +1544,7 @@ static void Tokens(void) EQ_(crypt_token_assign_keyslot(cd, 0, 3), 0); EQ_(crypt_activate_by_token(cd, NULL, 2, PASSPHRASE, 0), 0); - EQ_(crypt_activate_by_token(cd, NULL, 0, PASSPHRASE1, 0), 3); + EQ_(crypt_activate_by_token(cd, NULL, 0, PASSPHRASE1, CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY), 3); // FIXME: useless error message here (or missing one to be specific) FAIL_(crypt_activate_by_token(cd, CDEVICE_1, 0, PASSPHRASE1, 0), "No volume key available in token keyslots"); EQ_(crypt_activate_by_token(cd, CDEVICE_1, 2, PASSPHRASE, 0), 0); @@ -2317,7 +2317,7 @@ static void Luks2KeyslotAdd(void) EQ_(crypt_keyslot_add_by_key(cd, 1, key2, key_size, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT), 1); EQ_(crypt_keyslot_add_by_volume_key(cd, 0, key, key_size, PASSPHRASE, strlen(PASSPHRASE)), 0); EQ_(crypt_keyslot_status(cd, 0), CRYPT_SLOT_ACTIVE_LAST); - EQ_(crypt_keyslot_status(cd, 1), CRYPT_SLOT_ACTIVE); + EQ_(crypt_keyslot_status(cd, 1), CRYPT_SLOT_UNBOUND); /* must not activate volume with keyslot unassigned to a segment */ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key2, key_size, 0), "Key doesn't match volume key digest"); FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, 1, PASSPHRASE1, strlen(PASSPHRASE1), 0), "Keyslot not assigned to volume"); @@ -2325,8 +2325,8 @@ static void Luks2KeyslotAdd(void) /* unusable for volume activation even in test mode */ FAIL_(crypt_activate_by_volume_key(cd, NULL, key2, key_size, 0), "Key doesn't match volume key digest"); /* otoh passphrase check should pass */ - EQ_(crypt_activate_by_passphrase(cd, NULL, 1, PASSPHRASE1, strlen(PASSPHRASE1), 0), 1); - EQ_(crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, PASSPHRASE1, strlen(PASSPHRASE1), 0), 1); + EQ_(crypt_activate_by_passphrase(cd, NULL, 1, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY), 1); + EQ_(crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY), 1); /* in general crypt_keyslot_add_by_key must allow any reasonable key size * even though such keyslot will not be usable for segment encryption */ EQ_(crypt_keyslot_add_by_key(cd, 2, key2, key_size-1, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT), 2); @@ -2391,7 +2391,7 @@ static void Luks2ActivateByKeyring(void) FAIL_(crypt_activate_by_keyring(cd, CDEVICE_1, KEY_DESC_TEST0, 0, 0), "already open"); OK_(crypt_deactivate(cd, CDEVICE_1)); EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE); - EQ_(crypt_activate_by_keyring(cd, NULL, KEY_DESC_TEST1, 1, 0), 1); + EQ_(crypt_activate_by_keyring(cd, NULL, KEY_DESC_TEST1, 1, CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY), 1); EQ_(crypt_activate_by_keyring(cd, NULL, KEY_DESC_TEST1, 2, 0), 2); FAIL_(crypt_activate_by_keyring(cd, CDEVICE_1, KEY_DESC_TEST1, 1, 0), "Keyslot not assigned to volume"); EQ_(crypt_activate_by_keyring(cd, CDEVICE_1, KEY_DESC_TEST1, 2, 0), 2); diff --git a/tests/compat-test2 b/tests/compat-test2 index 3d935182..de6bff35 100755 --- a/tests/compat-test2 +++ b/tests/compat-test2 @@ -792,21 +792,30 @@ $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV $KEY5 --key-slot # unbound key may have arbitrary size echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT --unbound -s 16 $LOOPDEV || fail echo $PWD2 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT --unbound -s 32 -S 2 $LOOPDEV || fail +$CRYPTSETUP luksDump $LOOPDEV | grep -q "2: luks2 (unbound)" || fail echo $PWD3 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT --unbound -s 8 -S 3 --master-key-file /dev/urandom $LOOPDEV || fail +$CRYPTSETUP luksDump $LOOPDEV | grep -q "3: luks2 (unbound)" || fail # unbound key size is required echo $PWD1 | $CRYPTSETUP -q luksAddKey --unbound $LOOPDEV 2>/dev/null && fail echo $PWD3 | $CRYPTSETUP -q luksAddKey --unbound --master-key-file /dev/urandom $LOOPDEV 2> /dev/null && fail # do not allow to replace keyslot by unbound slot echo $PWD1 | $CRYPTSETUP -q luksAddKey -S5 --unbound -s 32 $LOOPDEV 2>/dev/null && fail -echo $PWD2 | $CRYPTSETUP -q open $LOOPDDEV $DEV_NAME 2> /dev/null && fail -echo $PWD2 | $CRYPTSETUP -q open -S2 $LOOPDDEV $DEV_NAME 2> /dev/null && fail -echo $PWD1 | $CRYPTSETUP -q open $LOOPDDEV $DEV_NAME 2> /dev/null && fail +echo $PWD2 | $CRYPTSETUP -q open $LOOPDEV $DEV_NAME 2> /dev/null && fail +echo $PWD2 | $CRYPTSETUP -q open $LOOPDEV --test-passphrase || fail +echo $PWD2 | $CRYPTSETUP -q open -S2 $LOOPDEV $DEV_NAME 2> /dev/null && fail +echo $PWD2 | $CRYPTSETUP -q open -S2 $LOOPDEV --test-passphrase || fail +echo $PWD1 | $CRYPTSETUP -q open $LOOPDEV $DEV_NAME 2> /dev/null && fail +echo $PWD1 | $CRYPTSETUP -q open $LOOPDEV --test-passphrase || fail # do not allow adding keyslot by unbound keyslot echo -e "$PWD2\n$PWD1" | $CRYPTSETUP -q luksAddKey $LOOPDEV 2> /dev/null && fail # check adding keyslot works when there's unbound keyslot echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT $LOOPDEV --key-file $KEY5 -S8 || fail echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME || fail $CRYPTSETUP close $DEV_NAME || fail +$CRYPTSETUP luksKillSlot -q $LOOPDEV 2 +$CRYPTSETUP luksDump $LOOPDEV | grep -q "2: luks2 (unbound)" && fail +$CRYPTSETUP luksKillSlot -q $LOOPDEV 3 +$CRYPTSETUP luksDump $LOOPDEV | grep -q "3: luks2 (unbound)" && fail remove_mapping exit 0 diff --git a/tests/reencryption-compat-test2 b/tests/reencryption-compat-test2 index 7b395b59..8a64c575 100755 --- a/tests/reencryption-compat-test2 +++ b/tests/reencryption-compat-test2 @@ -398,5 +398,16 @@ $CRYPTSETUP isLuks $IMG && fail $CRYPTSETUP isLuks $IMG_HDR || fail $CRYPTSETUP luksDump $IMG_HDR | grep -q "0: luks2" || fail +echo "[14] Reencryption with unbound keyslot" +prepare 8192 +echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 $FAST_PBKDF_ARGON $IMG || fail +echo $PWD2 | $CRYPTSETUP -q luksAddKey -S 3 --unbound --key-size 64 $FAST_PBKDF_ARGON $IMG || fail +wipe $PWD1 +check_hash $PWD1 $HASH5 +$CRYPTSETUP luksDump $IMG | grep -q "3: luks2 (unbound)" || fail +echo $PWD2 | $REENC $IMG -q $FAST_PBKDF 2>/dev/null && fail +echo -e "$PWD1\n$PWD2" | $REENC $IMG -q $FAST_PBKDF || fail +$CRYPTSETUP luksDump $IMG | grep -q "3: luks2 (unbound)" || fail + remove_mapping exit 0