95 lines
4.7 KiB
Diff
95 lines
4.7 KiB
Diff
From 42330aae7a15eb353e4554b84731ee552bf2d3c2 Mon Sep 17 00:00:00 2001
|
|
From: Bryan Jacobs <b@q3q.us>
|
|
Date: Tue, 16 Apr 2024 13:12:22 +1000
|
|
Subject: [PATCH] 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.
|
|
|
|
(cherry picked from commit 12cf745cceb3dfec858bab6152636e42f1c23bb9)
|
|
|
|
Related: RHEL-36276
|
|
---
|
|
src/shared/libfido2-util.c | 29 ++++++++++++++++++++++++++---
|
|
src/shared/libfido2-util.h | 1 +
|
|
2 files changed, 27 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/src/shared/libfido2-util.c b/src/shared/libfido2-util.c
|
|
index 525849ee19..a7b00ae5be 100644
|
|
--- a/src/shared/libfido2-util.c
|
|
+++ b/src/shared/libfido2-util.c
|
|
@@ -40,6 +40,7 @@ const unsigned char* (*sym_fido_cred_id_ptr)(const fido_cred_t *) = NULL;
|
|
fido_cred_t* (*sym_fido_cred_new)(void) = NULL;
|
|
int (*sym_fido_cred_set_clientdata_hash)(fido_cred_t *, const unsigned char *, size_t) = NULL;
|
|
int (*sym_fido_cred_set_extensions)(fido_cred_t *, int) = NULL;
|
|
+int (*sym_fido_cred_set_prot)(fido_cred_t *, int) = NULL;
|
|
int (*sym_fido_cred_set_rk)(fido_cred_t *, fido_opt_t) = NULL;
|
|
int (*sym_fido_cred_set_rp)(fido_cred_t *, const char *, const char *) = NULL;
|
|
int (*sym_fido_cred_set_type)(fido_cred_t *, int) = NULL;
|
|
@@ -89,6 +90,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),
|
|
@@ -632,10 +634,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)
|
|
@@ -686,7 +699,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)
|
|
diff --git a/src/shared/libfido2-util.h b/src/shared/libfido2-util.h
|
|
index a04a3768a5..5a24814fd9 100644
|
|
--- a/src/shared/libfido2-util.h
|
|
+++ b/src/shared/libfido2-util.h
|
|
@@ -41,6 +41,7 @@ extern const unsigned char* (*sym_fido_cred_id_ptr)(const fido_cred_t *);
|
|
extern fido_cred_t* (*sym_fido_cred_new)(void);
|
|
extern int (*sym_fido_cred_set_clientdata_hash)(fido_cred_t *, const unsigned char *, size_t);
|
|
extern int (*sym_fido_cred_set_extensions)(fido_cred_t *, int);
|
|
+extern int (*sym_fido_cred_set_prot)(fido_cred_t *, int);
|
|
extern int (*sym_fido_cred_set_rk)(fido_cred_t *, fido_opt_t);
|
|
extern int (*sym_fido_cred_set_rp)(fido_cred_t *, const char *, const char *);
|
|
extern int (*sym_fido_cred_set_type)(fido_cred_t *, int);
|