cryptenroll: Use CTAP2.1 credProtect extension

When enrolling a new FIDO2 token with a client PIN, this tells the authenticator to require the PIN on all uses.

It also collects a PIN before attempting to create a credential.

Works around #31443 in most (not all) scenarios.
This commit is contained in:
Bryan Jacobs
2024-04-16 13:12:22 +10:00
committed by Yu Watanabe
parent d398a2e004
commit 12cf745cce
2 changed files with 27 additions and 3 deletions

View File

@@ -40,6 +40,7 @@ DLSYM_FUNCTION(fido_cred_id_ptr);
DLSYM_FUNCTION(fido_cred_new);
DLSYM_FUNCTION(fido_cred_set_clientdata_hash);
DLSYM_FUNCTION(fido_cred_set_extensions);
DLSYM_FUNCTION(fido_cred_set_prot);
DLSYM_FUNCTION(fido_cred_set_rk);
DLSYM_FUNCTION(fido_cred_set_rp);
DLSYM_FUNCTION(fido_cred_set_type);
@@ -97,6 +98,7 @@ int dlopen_libfido2(void) {
DLSYM_ARG(fido_cred_new),
DLSYM_ARG(fido_cred_set_clientdata_hash),
DLSYM_ARG(fido_cred_set_extensions),
DLSYM_ARG(fido_cred_set_prot),
DLSYM_ARG(fido_cred_set_rk),
DLSYM_ARG(fido_cred_set_rp),
DLSYM_ARG(fido_cred_set_type),
@@ -776,10 +778,21 @@ int fido2_generate_hmac_hash(
if (!c)
return log_oom();
r = sym_fido_cred_set_extensions(c, FIDO_EXT_HMAC_SECRET);
int extensions = FIDO_EXT_HMAC_SECRET;
if (FLAGS_SET(lock_with, FIDO2ENROLL_PIN) || FLAGS_SET(lock_with, FIDO2ENROLL_UV)) {
/* Attempt to use the "cred protect" extension, requiring user verification (UV) for this
* credential. If the authenticator doesn't support the extension, it will be ignored. */
extensions |= FIDO_EXT_CRED_PROTECT;
r = sym_fido_cred_set_prot(c, FIDO_CRED_PROT_UV_REQUIRED);
if (r != FIDO_OK)
log_warning("Failed to set protection level on FIDO2 credential, ignoring: %s", sym_fido_strerr(r));
}
r = sym_fido_cred_set_extensions(c, extensions);
if (r != FIDO_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to enable HMAC-SECRET extension on FIDO2 credential: %s", sym_fido_strerr(r));
"Failed to enable extensions on FIDO2 credential: %s", sym_fido_strerr(r));
r = sym_fido_cred_set_rp(c, rp_id, rp_name);
if (r != FIDO_OK)
@@ -830,7 +843,17 @@ int fido2_generate_hmac_hash(
emoji_enabled() ? special_glyph(SPECIAL_GLYPH_TOUCH) : "",
emoji_enabled() ? " " : "");
r = sym_fido_dev_make_cred(d, c, NULL);
/* If we are using the user PIN, then we must pass that PIN to the get_assertion call below, or
* the authenticator will use the non-user-verification HMAC secret (which differs from the one when
* the PIN is passed).
*
* Rather than potentially trying and failing to create the credential, just collect the PIN first
* and then pass it to both the make_credential and the get_assertion operations. */
if (FLAGS_SET(lock_with, FIDO2ENROLL_PIN))
r = FIDO_ERR_PIN_REQUIRED;
else
r = sym_fido_dev_make_cred(d, c, NULL);
if (r == FIDO_ERR_PIN_REQUIRED) {
if (!has_client_pin)

View File

@@ -43,6 +43,7 @@ DLSYM_PROTOTYPE(fido_cred_id_ptr);
DLSYM_PROTOTYPE(fido_cred_new);
DLSYM_PROTOTYPE(fido_cred_set_clientdata_hash);
DLSYM_PROTOTYPE(fido_cred_set_extensions);
DLSYM_PROTOTYPE(fido_cred_set_prot);
DLSYM_PROTOTYPE(fido_cred_set_rk);
DLSYM_PROTOTYPE(fido_cred_set_rp);
DLSYM_PROTOTYPE(fido_cred_set_type);