diff --git a/src/cryptsetup.c b/src/cryptsetup.c index bc683c5c..87c80c89 100644 --- a/src/cryptsetup.c +++ b/src/cryptsetup.c @@ -180,6 +180,44 @@ static int _set_tries_tty(void) return (tools_is_stdin(ARG_STR(OPT_KEY_FILE_ID)) && isatty(STDIN_FILENO)) ? ARG_UINT32(OPT_TRIES_ID) : 1; } +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) +{ + size_t pin_len; + char msg[64], *pin = NULL; + int r; + + assert(tries >= 1); + assert(token_id >= 0 || token_id == CRYPT_ANY_TOKEN); + + 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; + + do { + r = tools_get_key(msg, &pin, &pin_len, 0, 0, NULL, + ARG_UINT32(OPT_TIMEOUT_ID), _verify_passphrase(0), 0, cd); + if (r < 0) + break; + + r = crypt_activate_by_token_pin(cd, activated_name, token_type, ARG_INT32(OPT_TOKEN_ID_ID), + pin, pin_len, NULL, activate_flags); + crypt_safe_free(pin); + pin = NULL; + tools_keyslot_msg(r, UNLOCKED); + check_signal(&r); + } while (r == -ENOANO && (--tries > 0)); + + return r; +} + static int action_open_plain(void) { struct crypt_device *cd = NULL, *cd1 = NULL; @@ -758,6 +796,10 @@ static int action_resize(void) CRYPT_ACTIVATE_KEYRING_KEY); tools_keyslot_msg(r, UNLOCKED); + /* Token requires PIN, but ask only if there is no password query later */ + if (ARG_SET(OPT_TOKEN_ONLY_ID) && r == -ENOANO) + r = _try_token_pin_unlock(cd, ARG_INT32(OPT_TOKEN_ID_ID), NULL, NULL, CRYPT_ACTIVATE_KEYRING_KEY, 1); + if (r >= 0 || ARG_SET(OPT_TOKEN_ONLY_ID)) goto out; @@ -1537,16 +1579,9 @@ static int action_open_luks(void) r = crypt_activate_by_token(cd, activated_name, ARG_INT32(OPT_TOKEN_ID_ID), NULL, activate_flags); tools_keyslot_msg(r, UNLOCKED); - /* Token requires PIN, but ask only there will be no password query later */ - if (ARG_SET(OPT_TOKEN_ONLY_ID) && r == -ENOANO) { - r = tools_get_key(_("Enter token PIN:"), &password, &passwordLen, 0, 0, NULL, - ARG_UINT32(OPT_TIMEOUT_ID), _verify_passphrase(0), 0, cd); - if (r < 0) - goto out; - r = crypt_activate_by_token_pin(cd, activated_name, NULL, ARG_INT32(OPT_TOKEN_ID_ID), - password, passwordLen, NULL, activate_flags); - tools_keyslot_msg(r, UNLOCKED); - } + /* Token requires PIN, but ask only if there is no password query later */ + if (ARG_SET(OPT_TOKEN_ONLY_ID) && r == -ENOANO) + r = _try_token_pin_unlock(cd, ARG_INT32(OPT_TOKEN_ID_ID), activated_name, NULL, activate_flags, _set_tries_tty()); if (r >= 0 || ARG_SET(OPT_TOKEN_ONLY_ID)) goto out;