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:
Ondrej Kozina
2023-10-13 15:31:00 +02:00
committed by Milan Broz
parent 20bfec91d8
commit 1f007061d6
2 changed files with 120 additions and 45 deletions

View File

@@ -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);
}
static int _try_token_pin_unlock(struct crypt_device *cd,
int token_id,
const char *activated_name,
const char *token_type,
uint32_t activate_flags,
int tries,
bool activation)
static int _try_token_unlock(struct crypt_device *cd,
int keyslot,
int token_id,
const char *activated_name,
const char *token_type,
uint32_t activate_flags,
int tries,
bool activation,
bool token_only)
{
int r;
struct crypt_keyslot_context *kc;
size_t pin_len;
char msg[64], *pin = NULL;
int r;
assert(tries >= 1);
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)
r = snprintf(msg, sizeof(msg), _("Enter token PIN: "));
else
r = snprintf(msg, sizeof(msg), _("Enter token %d PIN: "), token_id);
if (r < 0 || (size_t)r >= sizeof(msg))
return -EINVAL;
if (r < 0 || (size_t)r >= sizeof(msg)) {
r = -EINVAL;
goto out;
}
do {
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)
break;
r = crypt_keyslot_context_set_pin(cd, pin, pin_len, kc);
if (r < 0) {
crypt_safe_free(pin);
break;
}
if (activation)
r = crypt_activate_by_token_pin(cd, activated_name, token_type,
token_id, pin, pin_len, NULL,
activate_flags);
r = crypt_activate_by_keyslot_context(cd, activated_name, keyslot,
kc, activate_flags);
else
r = crypt_resume_by_token_pin(cd, activated_name, token_type,
token_id, pin, pin_len, NULL);
r = crypt_resume_by_keyslot_context(cd, activated_name, keyslot, kc);
crypt_safe_free(pin);
pin = NULL;
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);
} while (r == -ENOANO && (--tries > 0));
out:
crypt_keyslot_context_free(kc);
return r;
}
@@ -859,16 +887,9 @@ static int action_resize(void)
}
/* try load VK in kernel keyring using token */
r = crypt_activate_by_token_pin(cd, NULL, ARG_STR(OPT_TOKEN_TYPE_ID),
ARG_INT32(OPT_TOKEN_ID_ID), NULL, 0, NULL,
CRYPT_ACTIVATE_KEYRING_KEY);
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);
r = _try_token_unlock(cd, ARG_INT32(OPT_KEY_SLOT_ID), ARG_INT32(OPT_TOKEN_ID_ID),
NULL, ARG_STR(OPT_TOKEN_TYPE_ID), CRYPT_ACTIVATE_KEYRING_KEY,
1, true, ARG_SET(OPT_TOKEN_ONLY_ID));
if (r >= 0 || quit || ARG_SET(OPT_TOKEN_ONLY_ID))
goto out;
@@ -1795,15 +1816,10 @@ static int action_open_luks(void)
if (r)
goto out;
} else {
r = crypt_activate_by_token_pin(cd, activated_name, ARG_STR(OPT_TOKEN_TYPE_ID),
ARG_INT32(OPT_TOKEN_ID_ID), NULL, 0, NULL, activate_flags);
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), activated_name, ARG_STR(OPT_TOKEN_TYPE_ID), activate_flags, set_tries_tty(), true);
r = _try_token_unlock(cd, ARG_INT32(OPT_KEY_SLOT_ID),
ARG_INT32(OPT_TOKEN_ID_ID), activated_name,
ARG_STR(OPT_TOKEN_TYPE_ID), activate_flags,
set_tries_tty(), true, ARG_SET(OPT_TOKEN_ONLY_ID));
if (r >= 0 || r == -EEXIST || quit || ARG_SET(OPT_TOKEN_ONLY_ID))
goto out;
@@ -2673,15 +2689,9 @@ static int action_luksResume(void)
}
/* try to resume LUKS2 device by token first */
r = crypt_resume_by_token_pin(cd, action_argv[0], ARG_STR(OPT_TOKEN_TYPE_ID),
ARG_INT32(OPT_TOKEN_ID_ID), NULL, 0, NULL);
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), action_argv[0], ARG_STR(OPT_TOKEN_TYPE_ID), 0, set_tries_tty(), false);
r = _try_token_unlock(cd, ARG_INT32(OPT_KEY_SLOT_ID), ARG_INT32(OPT_TOKEN_ID_ID),
action_argv[0], ARG_STR(OPT_TOKEN_TYPE_ID), 0,
set_tries_tty(), false, ARG_SET(OPT_TOKEN_ONLY_ID));
if (r >= 0 || quit || ARG_SET(OPT_TOKEN_ONLY_ID))
goto out;