diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 03:50:40 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 03:50:40 +0000 |
commit | fc53809803cd2bc2434e312b19a18fa36776da12 (patch) | |
tree | b4b43bd6538f51965ce32856e9c053d0f90919c8 /src/shared/libfido2-util.c | |
parent | Adding upstream version 255.5. (diff) | |
download | systemd-fc53809803cd2bc2434e312b19a18fa36776da12.tar.xz systemd-fc53809803cd2bc2434e312b19a18fa36776da12.zip |
Adding upstream version 256.upstream/256
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/shared/libfido2-util.c')
-rw-r--r-- | src/shared/libfido2-util.c | 143 |
1 files changed, 89 insertions, 54 deletions
diff --git a/src/shared/libfido2-util.c b/src/shared/libfido2-util.c index 1cc3afe..37f6898 100644 --- a/src/shared/libfido2-util.c +++ b/src/shared/libfido2-util.c @@ -16,53 +16,54 @@ static void *libfido2_dl = NULL; -int (*sym_fido_assert_allow_cred)(fido_assert_t *, const unsigned char *, size_t) = NULL; -void (*sym_fido_assert_free)(fido_assert_t **) = NULL; -size_t (*sym_fido_assert_hmac_secret_len)(const fido_assert_t *, size_t) = NULL; -const unsigned char* (*sym_fido_assert_hmac_secret_ptr)(const fido_assert_t *, size_t) = NULL; -fido_assert_t* (*sym_fido_assert_new)(void) = NULL; -int (*sym_fido_assert_set_clientdata_hash)(fido_assert_t *, const unsigned char *, size_t) = NULL; -int (*sym_fido_assert_set_extensions)(fido_assert_t *, int) = NULL; -int (*sym_fido_assert_set_hmac_salt)(fido_assert_t *, const unsigned char *, size_t) = NULL; -int (*sym_fido_assert_set_rp)(fido_assert_t *, const char *) = NULL; -int (*sym_fido_assert_set_up)(fido_assert_t *, fido_opt_t) = NULL; -int (*sym_fido_assert_set_uv)(fido_assert_t *, fido_opt_t) = NULL; -size_t (*sym_fido_cbor_info_extensions_len)(const fido_cbor_info_t *) = NULL; -char **(*sym_fido_cbor_info_extensions_ptr)(const fido_cbor_info_t *) = NULL; -void (*sym_fido_cbor_info_free)(fido_cbor_info_t **) = NULL; -fido_cbor_info_t* (*sym_fido_cbor_info_new)(void) = NULL; -size_t (*sym_fido_cbor_info_options_len)(const fido_cbor_info_t *) = NULL; -char** (*sym_fido_cbor_info_options_name_ptr)(const fido_cbor_info_t *) = NULL; -const bool* (*sym_fido_cbor_info_options_value_ptr)(const fido_cbor_info_t *) = NULL; -void (*sym_fido_cred_free)(fido_cred_t **) = NULL; -size_t (*sym_fido_cred_id_len)(const fido_cred_t *) = NULL; -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_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; -int (*sym_fido_cred_set_user)(fido_cred_t *, const unsigned char *, size_t, const char *, const char *, const char *) = NULL; -int (*sym_fido_cred_set_uv)(fido_cred_t *, fido_opt_t) = NULL; -void (*sym_fido_dev_free)(fido_dev_t **) = NULL; -int (*sym_fido_dev_get_assert)(fido_dev_t *, fido_assert_t *, const char *) = NULL; -int (*sym_fido_dev_get_cbor_info)(fido_dev_t *, fido_cbor_info_t *) = NULL; -void (*sym_fido_dev_info_free)(fido_dev_info_t **, size_t) = NULL; -int (*sym_fido_dev_info_manifest)(fido_dev_info_t *, size_t, size_t *) = NULL; -const char* (*sym_fido_dev_info_manufacturer_string)(const fido_dev_info_t *) = NULL; -const char* (*sym_fido_dev_info_product_string)(const fido_dev_info_t *) = NULL; -fido_dev_info_t* (*sym_fido_dev_info_new)(size_t) = NULL; -const char* (*sym_fido_dev_info_path)(const fido_dev_info_t *) = NULL; -const fido_dev_info_t* (*sym_fido_dev_info_ptr)(const fido_dev_info_t *, size_t) = NULL; -bool (*sym_fido_dev_is_fido2)(const fido_dev_t *) = NULL; -int (*sym_fido_dev_make_cred)(fido_dev_t *, fido_cred_t *, const char *) = NULL; -fido_dev_t* (*sym_fido_dev_new)(void) = NULL; -int (*sym_fido_dev_open)(fido_dev_t *, const char *) = NULL; -int (*sym_fido_dev_close)(fido_dev_t *) = NULL; -void (*sym_fido_init)(int) = NULL; -void (*sym_fido_set_log_handler)(fido_log_handler_t *) = NULL; -const char* (*sym_fido_strerr)(int) = NULL; +DLSYM_FUNCTION(fido_assert_allow_cred); +DLSYM_FUNCTION(fido_assert_free); +DLSYM_FUNCTION(fido_assert_hmac_secret_len); +DLSYM_FUNCTION(fido_assert_hmac_secret_ptr); +DLSYM_FUNCTION(fido_assert_new); +DLSYM_FUNCTION(fido_assert_set_clientdata_hash); +DLSYM_FUNCTION(fido_assert_set_extensions); +DLSYM_FUNCTION(fido_assert_set_hmac_salt); +DLSYM_FUNCTION(fido_assert_set_rp); +DLSYM_FUNCTION(fido_assert_set_up); +DLSYM_FUNCTION(fido_assert_set_uv); +DLSYM_FUNCTION(fido_cbor_info_extensions_len); +DLSYM_FUNCTION(fido_cbor_info_extensions_ptr); +DLSYM_FUNCTION(fido_cbor_info_free); +DLSYM_FUNCTION(fido_cbor_info_new); +DLSYM_FUNCTION(fido_cbor_info_options_len); +DLSYM_FUNCTION(fido_cbor_info_options_name_ptr); +DLSYM_FUNCTION(fido_cbor_info_options_value_ptr); +DLSYM_FUNCTION(fido_cred_free); +DLSYM_FUNCTION(fido_cred_id_len); +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); +DLSYM_FUNCTION(fido_cred_set_user); +DLSYM_FUNCTION(fido_cred_set_uv); +DLSYM_FUNCTION(fido_dev_free); +DLSYM_FUNCTION(fido_dev_get_assert); +DLSYM_FUNCTION(fido_dev_get_cbor_info); +DLSYM_FUNCTION(fido_dev_info_free); +DLSYM_FUNCTION(fido_dev_info_manifest); +DLSYM_FUNCTION(fido_dev_info_manufacturer_string); +DLSYM_FUNCTION(fido_dev_info_product_string); +DLSYM_FUNCTION(fido_dev_info_new); +DLSYM_FUNCTION(fido_dev_info_path); +DLSYM_FUNCTION(fido_dev_info_ptr); +DLSYM_FUNCTION(fido_dev_is_fido2); +DLSYM_FUNCTION(fido_dev_make_cred); +DLSYM_FUNCTION(fido_dev_new); +DLSYM_FUNCTION(fido_dev_open); +DLSYM_FUNCTION(fido_dev_close); +DLSYM_FUNCTION(fido_init); +DLSYM_FUNCTION(fido_set_log_handler); +DLSYM_FUNCTION(fido_strerr); static void fido_log_propagate_handler(const char *s) { log_debug("libfido2: %s", strempty(s)); @@ -71,6 +72,11 @@ static void fido_log_propagate_handler(const char *s) { int dlopen_libfido2(void) { int r; + ELF_NOTE_DLOPEN("fido2", + "Support fido2 for encryption and authentication", + ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED, + "libfido2.so.1"); + r = dlopen_many_sym_or_warn( &libfido2_dl, "libfido2.so.1", LOG_DEBUG, DLSYM_ARG(fido_assert_allow_cred), @@ -97,6 +103,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), @@ -574,7 +581,7 @@ static int fido2_use_hmac_hash_specific_token( /* COSE_ECDH_ES256 is not usable with fido_cred_set_type() thus it's not listed here. */ static const char *fido2_algorithm_to_string(int alg) { - switch(alg) { + switch (alg) { case COSE_ES256: return "es256"; case COSE_RS256: @@ -686,7 +693,8 @@ int fido2_generate_hmac_hash( const char *user_name, const char *user_display_name, const char *user_icon, - const char *askpw_icon_name, + const char *askpw_icon, + const char *askpw_credential, Fido2EnrollFlags lock_with, int cred_alg, void **ret_cid, size_t *ret_cid_size, @@ -775,10 +783,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_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) @@ -829,7 +848,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) @@ -838,8 +867,14 @@ int fido2_generate_hmac_hash( for (;;) { _cleanup_strv_free_erase_ char **pin = NULL; - - r = ask_password_auto("Please enter security token PIN:", askpw_icon_name, NULL, "fido2-pin", "fido2-pin", USEC_INFINITY, 0, &pin); + AskPasswordRequest req = { + .message = "Please enter security token PIN:", + .icon = askpw_icon, + .keyring = "fido2-pin", + .credential = askpw_credential, + }; + + r = ask_password_auto(&req, USEC_INFINITY, /* flags= */ 0, &pin); if (r < 0) return log_error_errno(r, "Failed to acquire user PIN: %m"); |