diff --git a/src/cryptsetup/cryptsetup-fido2.c b/src/cryptsetup/cryptsetup-fido2.c index 3a870016d3..35d5dbe007 100644 --- a/src/cryptsetup/cryptsetup-fido2.c +++ b/src/cryptsetup/cryptsetup-fido2.c @@ -32,6 +32,7 @@ int acquire_fido2_key( _cleanup_strv_free_erase_ char **pins = NULL; _cleanup_free_ void *loaded_salt = NULL; + bool device_exists = false; const char *salt; size_t salt_size; char *e; @@ -89,13 +90,29 @@ int acquire_fido2_key( -ENOANO, /* needs pin */ -ENOLCK)) /* pin incorrect */ return r; - } - pins = strv_free_erase(pins); + device_exists = true; /* that a PIN is needed/wasn't correct means that we managed to + * talk to a device */ + } if (headless) return log_error_errno(SYNTHETIC_ERRNO(ENOPKG), "PIN querying disabled via 'headless' option. Use the '$PIN' environment variable."); + if (!device_exists) { + /* Before we inquire for the PIN we'll need, if we never talked to the device, check + * if the device actually is plugged in. Otherwise we'll ask for the PIN already when + * the device is not plugged in, which is confusing. */ + + r = fido2_have_device(device); + if (r < 0) + return r; + if (r == 0) /* no device found, return EAGAIN so that caller will wait/watch udev */ + return -EAGAIN; + + device_exists = true; /* now we know for sure, a device exists, no need to ask again */ + } + + pins = strv_free_erase(pins); r = ask_password_auto("Please enter security token PIN:", "drive-harddisk", NULL, "fido2-pin", "cryptsetup.fido2-pin", until, ask_password_flags, &pins); if (r < 0) return log_error_errno(r, "Failed to ask for user password: %m");