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.
This commit is contained in:
Milan Broz
2018-04-19 15:22:28 +02:00
parent 879403a172
commit aa1551c6e8
12 changed files with 145 additions and 54 deletions

View File

@@ -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;
/**

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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)

View File

@@ -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);

View File

@@ -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;

View File

@@ -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"),

View File

@@ -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)))

View File

@@ -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);

View File

@@ -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

View File

@@ -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