Retain keyslot number in luksChangeKey for LUKS2.

With JSON, we can actually retain the slot number in all cases
(except user intentionally set new slot #).

This patch changes the crypt_keyslot_change_by_passphrase() API
call to retain keyslot number for LUKS2.

Fixes: #464
This commit is contained in:
Milan Broz
2021-01-29 09:54:49 +01:00
parent 5a252c9166
commit 04b781d613
5 changed files with 68 additions and 16 deletions

View File

@@ -224,6 +224,11 @@ int LUKS2_keyslot_priority_set(struct crypt_device *cd,
crypt_keyslot_priority priority,
int commit);
int LUKS2_keyslot_swap(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
int keyslot2);
/*
* Generic LUKS2 token
*/

View File

@@ -935,3 +935,40 @@ int LUKS2_find_keyslot(struct luks2_hdr *hdr, const char *type)
return -ENOENT;
}
/* assumes valid header, it does not move references in tokens/digests etc! */
int LUKS2_keyslot_swap(struct crypt_device *cd, struct luks2_hdr *hdr,
int keyslot, int keyslot2)
{
json_object *jobj_keyslots, *jobj_keyslot, *jobj_keyslot2;
int r;
if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots))
return -EINVAL;
jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
if (!jobj_keyslot)
return -EINVAL;
jobj_keyslot2 = LUKS2_get_keyslot_jobj(hdr, keyslot2);
if (!jobj_keyslot2)
return -EINVAL;
/* This transfer owner of object, no need for json_object_put */
json_object_get(jobj_keyslot);
json_object_get(jobj_keyslot2);
json_object_object_del_by_uint(jobj_keyslots, keyslot);
r = json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot2);
if (r < 0) {
log_dbg(cd, "Failed to swap keyslot %d.", keyslot);
return r;
}
json_object_object_del_by_uint(jobj_keyslots, keyslot2);
r = json_object_object_add_by_uint(jobj_keyslots, keyslot2, jobj_keyslot);
if (r < 0)
log_dbg(cd, "Failed to swap keyslot2 %d.", keyslot2);
return r;
}

View File

@@ -3415,7 +3415,7 @@ int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
const char *new_passphrase,
size_t new_passphrase_size)
{
int digest = -1, r;
int digest = -1, r, keyslot_new_orig = keyslot_new;
struct luks2_keyslot_params params;
struct volume_key *vk = NULL;
@@ -3493,6 +3493,20 @@ int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
r = LUKS2_keyslot_store(cd, &cd->u.luks2.hdr,
keyslot_new, new_passphrase,
new_passphrase_size, vk, &params);
if (r < 0)
goto out;
/* Swap old & new so the final keyslot number remains */
if (keyslot_new_orig == CRYPT_ANY_SLOT && keyslot_old != keyslot_new) {
r = LUKS2_keyslot_swap(cd, &cd->u.luks2.hdr, keyslot_old, keyslot_new);
if (r < 0)
goto out;
/* Swap slot id */
r = keyslot_old;
keyslot_old = keyslot_new;
keyslot_new = r;
}
} else
r = -EINVAL;

View File

@@ -843,7 +843,7 @@ static void AddDeviceLuks2(void)
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_(6, crypt_keyslot_add_by_volume_key(cd, 6, key, key_size, passphrase2, strlen(passphrase2)));
EQ_(CRYPT_SLOT_ACTIVE, crypt_keyslot_status(cd, 6));
FAIL_(crypt_keyslot_destroy(cd, 8), "invalid keyslot");
@@ -853,6 +853,8 @@ static void AddDeviceLuks2(void)
EQ_(CRYPT_SLOT_INACTIVE, crypt_keyslot_status(cd, 7));
EQ_(CRYPT_SLOT_ACTIVE_LAST, crypt_keyslot_status(cd, 6));
EQ_(6, crypt_keyslot_change_by_passphrase(cd, 6, CRYPT_ANY_SLOT, passphrase2, strlen(passphrase2), passphrase, strlen(passphrase)));
EQ_(CRYPT_SLOT_ACTIVE_LAST, crypt_keyslot_status(cd, 6));
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));

View File

@@ -543,10 +543,10 @@ $CRYPTSETUP close $DEV_NAME || fail
add_scsi_device dev_size_mb=32 sector_size=4096
echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 $FAST_PBKDF_OPT $DEV || fail
echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
OLD_SIZE=$($CRYPTSETUP status $DEV_NAME | grep "^ \+size:" | sed 's/.* \([0-9]\+\) .*/\1/')
OLD_SIZE=$($CRYPTSETUP status $DEV_NAME | grep "^ \+size:" | sed 's/.* \([0-9]\+\) .*/\1/') #'
echo $PWD1 | $CRYPTSETUP resize $DEV_NAME -b 7 2> /dev/null && fail
dmsetup info $DEV_NAME | grep -q SUSPENDED && fail
NEW_SIZE=$($CRYPTSETUP status $DEV_NAME | grep "^ \+size:" | sed 's/.* \([0-9]\+\) .*/\1/')
NEW_SIZE=$($CRYPTSETUP status $DEV_NAME | grep "^ \+size:" | sed 's/.* \([0-9]\+\) .*/\1/') #'
test $OLD_SIZE -eq $NEW_SIZE || fail
$CRYPTSETUP close $DEV_NAME || fail
@@ -594,21 +594,15 @@ echo $PWD1 | $CRYPTSETUP luksAddKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 --key-slot
$CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 $KEY2 --key-slot 0 || fail
# passphrase [1] / passphrase [1]
echo -e "$PWD1\n$PWD2\n" | $CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT --key-slot 1 || fail
# keyfile [0] / keyfile [new]
# keyfile [0] / keyfile [new] - with LUKS2 it should stay
$CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY2 $KEY1 || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "0: luks2" && fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "0: luks2" || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "2: luks2" && fail
# passphrase [1] / passphrase [new]
echo -e "$PWD2\n$PWD1\n" | $CRYPTSETUP luksChangeKey $FAST_PBKDF_OPT $LOOPDEV || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "1: luks2" && fail
# use all slots
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT || fail
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT || fail
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT || fail
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT || fail
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT || fail
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT || fail
# still allows replace
#FIXME
$CRYPTSETUP luksDump $LOOPDEV | grep -q "1: luks2" || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "2: luks2" && fail
# FIXME: test out of raw area
#$CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 $KEY2 || fail
#$CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 $KEY2 2>/dev/null && fail