mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-16 21:29:59 +01:00
Respect keyslot id while activating device by token.
Also by using --test-passphrase option this patch allows cryptsetup to check if specific token (--token-id) is able to unlock specific keyslot (--key-slot/-S). It uses recently added crypt_activate_by_keyslot_context API. Fixes: #784.
This commit is contained in:
committed by
Milan Broz
parent
20bfec91d8
commit
1f007061d6
100
src/cryptsetup.c
100
src/cryptsetup.c
@@ -89,27 +89,49 @@ static int _set_keyslot_encryption_params(struct crypt_device *cd)
|
|||||||
return crypt_keyslot_set_encryption(cd, ARG_STR(OPT_KEYSLOT_CIPHER_ID), ARG_UINT32(OPT_KEYSLOT_KEY_SIZE_ID) / 8);
|
return crypt_keyslot_set_encryption(cd, ARG_STR(OPT_KEYSLOT_CIPHER_ID), ARG_UINT32(OPT_KEYSLOT_KEY_SIZE_ID) / 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _try_token_pin_unlock(struct crypt_device *cd,
|
static int _try_token_unlock(struct crypt_device *cd,
|
||||||
int token_id,
|
int keyslot,
|
||||||
const char *activated_name,
|
int token_id,
|
||||||
const char *token_type,
|
const char *activated_name,
|
||||||
uint32_t activate_flags,
|
const char *token_type,
|
||||||
int tries,
|
uint32_t activate_flags,
|
||||||
bool activation)
|
int tries,
|
||||||
|
bool activation,
|
||||||
|
bool token_only)
|
||||||
{
|
{
|
||||||
|
int r;
|
||||||
|
struct crypt_keyslot_context *kc;
|
||||||
size_t pin_len;
|
size_t pin_len;
|
||||||
char msg[64], *pin = NULL;
|
char msg[64], *pin = NULL;
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(tries >= 1);
|
assert(tries >= 1);
|
||||||
assert(token_id >= 0 || token_id == CRYPT_ANY_TOKEN);
|
assert(token_id >= 0 || token_id == CRYPT_ANY_TOKEN);
|
||||||
|
assert(keyslot >= 0 || keyslot == CRYPT_ANY_SLOT);
|
||||||
|
|
||||||
|
r = crypt_keyslot_context_init_by_token(cd, token_id, token_type, NULL, 0, NULL, &kc);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (activation)
|
||||||
|
r = crypt_activate_by_keyslot_context(cd, activated_name, keyslot, kc, activate_flags);
|
||||||
|
else
|
||||||
|
r = crypt_resume_by_keyslot_context(cd, activated_name, keyslot, kc);
|
||||||
|
|
||||||
|
tools_keyslot_msg(r, UNLOCKED);
|
||||||
|
tools_token_error_msg(r, token_type, token_id, false);
|
||||||
|
|
||||||
|
/* Token requires PIN (-ENOANO). Ask for it if there is evident preference for tokens */
|
||||||
|
if (r != -ENOANO || (!token_only && !token_type && token_id == CRYPT_ANY_TOKEN))
|
||||||
|
goto out;
|
||||||
|
|
||||||
if (token_id == CRYPT_ANY_TOKEN)
|
if (token_id == CRYPT_ANY_TOKEN)
|
||||||
r = snprintf(msg, sizeof(msg), _("Enter token PIN: "));
|
r = snprintf(msg, sizeof(msg), _("Enter token PIN: "));
|
||||||
else
|
else
|
||||||
r = snprintf(msg, sizeof(msg), _("Enter token %d PIN: "), token_id);
|
r = snprintf(msg, sizeof(msg), _("Enter token %d PIN: "), token_id);
|
||||||
if (r < 0 || (size_t)r >= sizeof(msg))
|
if (r < 0 || (size_t)r >= sizeof(msg)) {
|
||||||
return -EINVAL;
|
r = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
r = tools_get_key(msg, &pin, &pin_len, 0, 0, NULL,
|
r = tools_get_key(msg, &pin, &pin_len, 0, 0, NULL,
|
||||||
@@ -117,20 +139,26 @@ static int _try_token_pin_unlock(struct crypt_device *cd,
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
r = crypt_keyslot_context_set_pin(cd, pin, pin_len, kc);
|
||||||
|
if (r < 0) {
|
||||||
|
crypt_safe_free(pin);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (activation)
|
if (activation)
|
||||||
r = crypt_activate_by_token_pin(cd, activated_name, token_type,
|
r = crypt_activate_by_keyslot_context(cd, activated_name, keyslot,
|
||||||
token_id, pin, pin_len, NULL,
|
kc, activate_flags);
|
||||||
activate_flags);
|
|
||||||
else
|
else
|
||||||
r = crypt_resume_by_token_pin(cd, activated_name, token_type,
|
r = crypt_resume_by_keyslot_context(cd, activated_name, keyslot, kc);
|
||||||
token_id, pin, pin_len, NULL);
|
|
||||||
crypt_safe_free(pin);
|
crypt_safe_free(pin);
|
||||||
pin = NULL;
|
pin = NULL;
|
||||||
tools_keyslot_msg(r, UNLOCKED);
|
tools_keyslot_msg(r, UNLOCKED);
|
||||||
tools_token_error_msg(r, ARG_STR(OPT_TOKEN_TYPE_ID), token_id, true);
|
tools_token_error_msg(r, token_type, token_id, true);
|
||||||
check_signal(&r);
|
check_signal(&r);
|
||||||
} while (r == -ENOANO && (--tries > 0));
|
} while (r == -ENOANO && (--tries > 0));
|
||||||
|
out:
|
||||||
|
crypt_keyslot_context_free(kc);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -859,16 +887,9 @@ static int action_resize(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* try load VK in kernel keyring using token */
|
/* try load VK in kernel keyring using token */
|
||||||
r = crypt_activate_by_token_pin(cd, NULL, ARG_STR(OPT_TOKEN_TYPE_ID),
|
r = _try_token_unlock(cd, ARG_INT32(OPT_KEY_SLOT_ID), ARG_INT32(OPT_TOKEN_ID_ID),
|
||||||
ARG_INT32(OPT_TOKEN_ID_ID), NULL, 0, NULL,
|
NULL, ARG_STR(OPT_TOKEN_TYPE_ID), CRYPT_ACTIVATE_KEYRING_KEY,
|
||||||
CRYPT_ACTIVATE_KEYRING_KEY);
|
1, true, ARG_SET(OPT_TOKEN_ONLY_ID));
|
||||||
tools_keyslot_msg(r, UNLOCKED);
|
|
||||||
tools_token_error_msg(r, ARG_STR(OPT_TOKEN_TYPE_ID), ARG_INT32(OPT_TOKEN_ID_ID), false);
|
|
||||||
|
|
||||||
/* Token requires PIN. Ask if there is evident preference for tokens */
|
|
||||||
if (r == -ENOANO && (ARG_SET(OPT_TOKEN_ONLY_ID) || ARG_SET(OPT_TOKEN_TYPE_ID) ||
|
|
||||||
ARG_SET(OPT_TOKEN_ID_ID)))
|
|
||||||
r = _try_token_pin_unlock(cd, ARG_INT32(OPT_TOKEN_ID_ID), NULL, ARG_STR(OPT_TOKEN_TYPE_ID), CRYPT_ACTIVATE_KEYRING_KEY, 1, true);
|
|
||||||
|
|
||||||
if (r >= 0 || quit || ARG_SET(OPT_TOKEN_ONLY_ID))
|
if (r >= 0 || quit || ARG_SET(OPT_TOKEN_ONLY_ID))
|
||||||
goto out;
|
goto out;
|
||||||
@@ -1795,15 +1816,10 @@ static int action_open_luks(void)
|
|||||||
if (r)
|
if (r)
|
||||||
goto out;
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
r = crypt_activate_by_token_pin(cd, activated_name, ARG_STR(OPT_TOKEN_TYPE_ID),
|
r = _try_token_unlock(cd, ARG_INT32(OPT_KEY_SLOT_ID),
|
||||||
ARG_INT32(OPT_TOKEN_ID_ID), NULL, 0, NULL, activate_flags);
|
ARG_INT32(OPT_TOKEN_ID_ID), activated_name,
|
||||||
tools_keyslot_msg(r, UNLOCKED);
|
ARG_STR(OPT_TOKEN_TYPE_ID), activate_flags,
|
||||||
tools_token_error_msg(r, ARG_STR(OPT_TOKEN_TYPE_ID), ARG_INT32(OPT_TOKEN_ID_ID), false);
|
set_tries_tty(), true, ARG_SET(OPT_TOKEN_ONLY_ID));
|
||||||
|
|
||||||
/* Token requires PIN. Ask if there is evident preference for tokens */
|
|
||||||
if (r == -ENOANO && (ARG_SET(OPT_TOKEN_ONLY_ID) || ARG_SET(OPT_TOKEN_TYPE_ID) ||
|
|
||||||
ARG_SET(OPT_TOKEN_ID_ID)))
|
|
||||||
r = _try_token_pin_unlock(cd, ARG_INT32(OPT_TOKEN_ID_ID), activated_name, ARG_STR(OPT_TOKEN_TYPE_ID), activate_flags, set_tries_tty(), true);
|
|
||||||
|
|
||||||
if (r >= 0 || r == -EEXIST || quit || ARG_SET(OPT_TOKEN_ONLY_ID))
|
if (r >= 0 || r == -EEXIST || quit || ARG_SET(OPT_TOKEN_ONLY_ID))
|
||||||
goto out;
|
goto out;
|
||||||
@@ -2673,15 +2689,9 @@ static int action_luksResume(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* try to resume LUKS2 device by token first */
|
/* try to resume LUKS2 device by token first */
|
||||||
r = crypt_resume_by_token_pin(cd, action_argv[0], ARG_STR(OPT_TOKEN_TYPE_ID),
|
r = _try_token_unlock(cd, ARG_INT32(OPT_KEY_SLOT_ID), ARG_INT32(OPT_TOKEN_ID_ID),
|
||||||
ARG_INT32(OPT_TOKEN_ID_ID), NULL, 0, NULL);
|
action_argv[0], ARG_STR(OPT_TOKEN_TYPE_ID), 0,
|
||||||
tools_keyslot_msg(r, UNLOCKED);
|
set_tries_tty(), false, ARG_SET(OPT_TOKEN_ONLY_ID));
|
||||||
tools_token_error_msg(r, ARG_STR(OPT_TOKEN_TYPE_ID), ARG_INT32(OPT_TOKEN_ID_ID), false);
|
|
||||||
|
|
||||||
/* Token requires PIN. Ask if there is evident preference for tokens */
|
|
||||||
if (r == -ENOANO && (ARG_SET(OPT_TOKEN_ONLY_ID) || ARG_SET(OPT_TOKEN_TYPE_ID) ||
|
|
||||||
ARG_SET(OPT_TOKEN_ID_ID)))
|
|
||||||
r = _try_token_pin_unlock(cd, ARG_INT32(OPT_TOKEN_ID_ID), action_argv[0], ARG_STR(OPT_TOKEN_TYPE_ID), 0, set_tries_tty(), false);
|
|
||||||
|
|
||||||
if (r >= 0 || quit || ARG_SET(OPT_TOKEN_ONLY_ID))
|
if (r >= 0 || quit || ARG_SET(OPT_TOKEN_ONLY_ID))
|
||||||
goto out;
|
goto out;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
PS4='$LINENO:'
|
PS4='$LINENO:'
|
||||||
[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
|
[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
|
||||||
CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
|
CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
|
||||||
|
CRYPTSETUP_RAW=$CRYPTSETUP
|
||||||
|
|
||||||
CRYPTSETUP_VALGRIND=../.libs/cryptsetup
|
CRYPTSETUP_VALGRIND=../.libs/cryptsetup
|
||||||
CRYPTSETUP_LIB_VALGRIND=../.libs
|
CRYPTSETUP_LIB_VALGRIND=../.libs
|
||||||
@@ -342,6 +343,36 @@ test_vk_link_and_reactivate() {
|
|||||||
keyctl unlink $KEYCTL_KEY_NAME "$2" || fail
|
keyctl unlink $KEYCTL_KEY_NAME "$2" || fail
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function expect_run()
|
||||||
|
{
|
||||||
|
export INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}"
|
||||||
|
expect "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
# expected unlocked keyslot id
|
||||||
|
# command arguments
|
||||||
|
function expect_unlocked_keyslot()
|
||||||
|
{
|
||||||
|
command -v expect >/dev/null || {
|
||||||
|
echo "WARNING: expect tool missing, interactive test will be skipped."
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_TIMEOUT=60
|
||||||
|
EXPECT_KEY=$1
|
||||||
|
|
||||||
|
expect_run - >/dev/null <<EOF
|
||||||
|
proc abort {} { send_error "Timeout. "; exit 2 }
|
||||||
|
set timeout $EXPECT_TIMEOUT
|
||||||
|
eval spawn $CRYPTSETUP_RAW $2
|
||||||
|
expect timeout abort "Key slot $EXPECT_KEY unlocked."
|
||||||
|
expect timeout abort "Command successful."
|
||||||
|
expect timeout abort eof
|
||||||
|
exit
|
||||||
|
EOF
|
||||||
|
[ $? -eq 0 ] || return 1
|
||||||
|
}
|
||||||
|
|
||||||
export LANG=C
|
export LANG=C
|
||||||
|
|
||||||
[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
|
[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
|
||||||
@@ -1000,6 +1031,40 @@ if [ $HAVE_KEYRING -gt 0 -a -d /proc/sys/kernel/keys ]; then
|
|||||||
$CRYPTSETUP token unassign --token-id 0 -S0 $LOOPDEV 2>/dev/null && fail
|
$CRYPTSETUP token unassign --token-id 0 -S0 $LOOPDEV 2>/dev/null && fail
|
||||||
$CRYPTSETUP token unassign --token-id 0 -S44 $LOOPDEV 2>/dev/null && fail
|
$CRYPTSETUP token unassign --token-id 0 -S44 $LOOPDEV 2>/dev/null && fail
|
||||||
$CRYPTSETUP token unassign --token-id 44 -S0 $LOOPDEV 2>/dev/null && fail
|
$CRYPTSETUP token unassign --token-id 44 -S0 $LOOPDEV 2>/dev/null && fail
|
||||||
|
|
||||||
|
$CRYPTSETUP token remove $LOOPDEV --token-id 0 || fail
|
||||||
|
$CRYPTSETUP token add $LOOPDEV --key-description $TEST_TOKEN0 -S0 --token-id 0 || fail
|
||||||
|
|
||||||
|
# token 8 assigned to keyslot 0 and 5. Unlocks only 5
|
||||||
|
echo "$PWD2" | $CRYPTSETUP luksAddKey -q -S5 $FAST_PBKDF_OPT --token-id 0 $LOOPDEV || fail
|
||||||
|
echo -n "{\"type\":\"luks2-keyring\",\"keyslots\":[\"0\",\"5\"],\"key_description\":\"$TEST_TOKEN1\"}" | $CRYPTSETUP token import $LOOPDEV --token-id 8 || fail
|
||||||
|
load_key user $TEST_TOKEN1 "$PWD2" "$TEST_KEYRING" || fail "Cannot load 32 byte user key type"
|
||||||
|
|
||||||
|
# token 3 assigned to keyslot 1 (wrong passphrase)
|
||||||
|
echo "$PWD3" | $CRYPTSETUP luksAddKey -q -S1 $FAST_PBKDF_OPT --token-id 0 $LOOPDEV || fail
|
||||||
|
$CRYPTSETUP token add $LOOPDEV --key-description $TEST_TOKEN2 -S1 --token-id 3 || fail
|
||||||
|
load_key user $TEST_TOKEN2 "blabla" "$TEST_KEYRING" || fail "Cannot load 32 byte user key type"
|
||||||
|
|
||||||
|
# specific token, specific keyslot
|
||||||
|
$CRYPTSETUP open --test-passphrase --token-id 0 -S0 $LOOPDEV --token-only <&- || fail
|
||||||
|
# specific keyslot unlocked by any token
|
||||||
|
$CRYPTSETUP open --test-passphrase -S0 $LOOPDEV --token-only <&- || fail
|
||||||
|
|
||||||
|
# token 0 unusable for keyslot 5
|
||||||
|
$CRYPTSETUP open --test-passphrase --token-id 0 -S5 $LOOPDEV --token-only <&- >/dev/null && fail
|
||||||
|
# backup interactive prompt should work
|
||||||
|
echo $PWD2 | $CRYPTSETUP open --test-passphrase --token-id 0 -S5 $LOOPDEV || fail
|
||||||
|
|
||||||
|
$CRYPTSETUP open --test-passphrase -S5 --token-id 8 $LOOPDEV <&- || fail
|
||||||
|
$CRYPTSETUP open --test-passphrase -S5 $LOOPDEV <&- || fail
|
||||||
|
|
||||||
|
expect_unlocked_keyslot 5 "open -v --test-passphrase --token-id 8 -S5 $LOOPDEV" || fail
|
||||||
|
expect_unlocked_keyslot 5 "open -v --test-passphrase --token-id 8 $LOOPDEV" || fail
|
||||||
|
|
||||||
|
$CRYPTSETUP open --test-passphrase -S0 --token-id 8 $LOOPDEV --token-only >/dev/null && fail
|
||||||
|
[ $? -ne 2 ] && fail "open should return EPERM exit code."
|
||||||
|
$CRYPTSETUP open --test-passphrase -S1 $LOOPDEV --token-only && fail
|
||||||
|
[ $? -ne 2 ] && fail "open should return EPERM exit code."
|
||||||
fi
|
fi
|
||||||
echo -n "$IMPORT_TOKEN" | $CRYPTSETUP token import $LOOPDEV --token-id 10 || fail
|
echo -n "$IMPORT_TOKEN" | $CRYPTSETUP token import $LOOPDEV --token-id 10 || fail
|
||||||
echo -n "$IMPORT_TOKEN" | $CRYPTSETUP token import $LOOPDEV --token-id 11 --json-file - || fail
|
echo -n "$IMPORT_TOKEN" | $CRYPTSETUP token import $LOOPDEV --token-id 11 --json-file - || fail
|
||||||
|
|||||||
Reference in New Issue
Block a user