diff --git a/man/cryptsetup.8 b/man/cryptsetup.8 index bc7be6b8..7c87003c 100644 --- a/man/cryptsetup.8 +++ b/man/cryptsetup.8 @@ -341,10 +341,12 @@ the mapped device. \fIluksResume\fR .IP Resumes a suspended device and reinstates the encryption key. -Prompts interactively for a passphrase if \-\-key-file is not given. +Prompts interactively for a passphrase if no token is usable +(LUKS2 only) or \-\-key-file is not given. \fB\fR can be [\-\-key\-file, \-\-keyfile\-size, \-\-header, -\-\-disable\-keyring, \-\-disable\-locks, \-\-type] +\-\-disable\-keyring, \-\-disable\-locks, \-\-token\-id, +\-\-token\-only, \-\-token\-type, \-\-type] .PP \fIluksAddKey\fR [] .IP @@ -1362,14 +1364,14 @@ The \fIignored\fR priority means, that slot is never used, if not explicitly requested by \fI\-\-key\-slot\fR option. .TP .B "\-\-token\-id" -Specify what token to use in actions \fItoken\fR, \fIopen\fR or \fIresize\fR. -If omitted, all available tokens will be checked before proceeding further with -passphrase prompt. +Specify what token to use in actions \fItoken\fR, \fIopen\fR, \fIresize\fR or +\fIluksResume\fR. If omitted, all available tokens will be checked before +proceeding further with passphrase prompt. .TP .B "\-\-token\-only" -Do not proceed further with action (any of \fItoken\fR, \fIopen\fR or -\fIresize\fR) if token activation failed. Without the option, -action asks for passphrase to proceed further. +Do not proceed further with action (any of \fItoken\fR, \fIopen\fR, +\fIresize\fR or \fIluksResume\fR) if token based keyslot unlock failed. +Without the option, action asks for passphrase to proceed further. .TP .B "\-\-token\-type" Restrict tokens eligible for operation to specific token type (name). Mostly diff --git a/src/cryptsetup.c b/src/cryptsetup.c index 5322e3aa..edbb1881 100644 --- a/src/cryptsetup.c +++ b/src/cryptsetup.c @@ -94,7 +94,8 @@ static int _try_token_pin_unlock(struct crypt_device *cd, const char *activated_name, const char *token_type, uint32_t activate_flags, - int tries) + int tries, + bool activation) { size_t pin_len; char msg[64], *pin = NULL; @@ -116,8 +117,14 @@ static int _try_token_pin_unlock(struct crypt_device *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); + if (activation) + r = crypt_activate_by_token_pin(cd, activated_name, token_type, + ARG_INT32(OPT_TOKEN_ID_ID), + pin, pin_len, NULL, activate_flags); + else + r = crypt_resume_by_token_pin(cd, activated_name, token_type, + ARG_INT32(OPT_TOKEN_ID_ID), + pin, pin_len, NULL); crypt_safe_free(pin); pin = NULL; tools_keyslot_msg(r, UNLOCKED); @@ -710,7 +717,7 @@ static int action_resize(void) /* 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, ARG_STR(OPT_TOKEN_TYPE_ID), CRYPT_ACTIVATE_KEYRING_KEY, 1); + 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 || ARG_SET(OPT_TOKEN_ONLY_ID)) goto out; @@ -1476,7 +1483,7 @@ static int action_open_luks(void) /* 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, ARG_STR(OPT_TOKEN_TYPE_ID), activate_flags, set_tries_tty()); + 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 || ARG_SET(OPT_TOKEN_ONLY_ID)) goto out; @@ -2201,6 +2208,19 @@ static int action_luksResume(void) goto out; } + /* 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, 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), action_argv[0], ARG_STR(OPT_TOKEN_TYPE_ID), 0, set_tries_tty(), false); + + if (r >= 0 || ARG_SET(OPT_TOKEN_ONLY_ID)) + goto out; + tries = set_tries_tty(); do { r = tools_get_key(NULL, &password, &passwordLen, diff --git a/tests/compat-test2 b/tests/compat-test2 index b829ec20..e96ed291 100755 --- a/tests/compat-test2 +++ b/tests/compat-test2 @@ -853,6 +853,11 @@ if [ $HAVE_KEYRING -gt 0 -a -d /proc/sys/kernel/keys ]; then $CRYPTSETUP open --token-only $LOOPDEV --test-passphrase || fail $CRYPTSETUP open --token-only $LOOPDEV $DEV_NAME || fail $CRYPTSETUP status $DEV_NAME > /dev/null || fail + $CRYPTSETUP luksSuspend $DEV_NAME || fail + $CRYPTSETUP luksResume $DEV_NAME <&- || fail + $CRYPTSETUP -q status $DEV_NAME | grep -q "(suspended)" && fail + $CRYPTSETUP luksSuspend $DEV_NAME || fail + $CRYPTSETUP luksResume $DEV_NAME --token-type luks2-keyring <&- || fail $CRYPTSETUP close $DEV_NAME || fail # check --token-type sort of works (TODO: extend tests when native systemd tokens are available)