WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
NEW
314934
WebAuthn PRF results return `null` during `navigator.credentials.get()` for YubiKey C Bio - FIDO Edition (firmware 5.7.4)
https://bugs.webkit.org/show_bug.cgi?id=314934
Summary
WebAuthn PRF results return `null` during `navigator.credentials.get()` for Y...
jonathan.underwood4649
Reported
2026-05-15 21:03:06 PDT
The issue reproduces consistently across multiple authentication attempts. Tested on: * macOS 26.5 on MacBook Pro M5 Max * iOS 26.5 on iPhone 17 Pro Max Using: * YubiKey C Bio - FIDO Edition (Firmware version: 5.7.4) Behavior (both macOS and iOS): * Registration (`navigator.credentials.create()`) succeeds in Safari * Authentication (`navigator.credentials.get()`) succeeds overall, but the WebAuthn PRF extension does not return PRF results when using a YubiKey C Bio - FIDO Edition * Non-Bio YubiKeys correctly return PRF results in Safari Behavior (macOS only): * The same YubiKey successfully returns PRF results in Chrome on the same MacBook --- Observed PRF extension output during `navigator.credentials.get()`: ``` { "prf": { "results": { "first": null } } } ``` Expected behavior: `results.first` should contain the derived PRF output buffer rather than `null`. --- This appears to specifically affect PRF (`prf` / `hmac-secret`) handling during authentication assertions (`get()`) for the YubiKey C Bio - FIDO Edition in WebKit/Safari. Because the same hardware succeeds in Chrome on the same machine, this appears to be a Safari/WebKit interoperability issue rather than a hardware or firmware issue. --- Possible additional context: I previously investigated a similar issue involving FIDO-backed SSH keys, where the root cause ended up relating to how the YubiKey Bio handles the UV (User Verification) flag within libfido2. In that codebase this distinction is represented as `internal_uv`. Given that this issue appears specific to the YubiKey C Bio - FIDO Edition, it may be worth checking whether Safari/WebKit's PRF (`hmac-secret`) handling during `navigator.credentials.get()` depends on UV semantics that differ for Bio authenticators. In particular, the PRF code path may not be accounting for the same "internal UV" behavior that libfido2 had to handle. --- Thank you for all your work. I appreciate your time. - Jonathan
Attachments
A simple fix for the issue (super rough)
(7.20 KB, patch)
2026-05-16 11:14 PDT
,
jonathan.underwood4649
no flags
Details
Formatted Diff
Diff
More complex fix
(20.49 KB, patch)
2026-05-29 09:50 PDT
,
jonathan.underwood4649
no flags
Details
Formatted Diff
Diff
View All
Add attachment
proposed patch, testcase, etc.
jonathan.underwood4649
Comment 1
2026-05-16 10:46:15 PDT
I seem to have found the bug. CtapAuthenticator::prepareHmacSecretParameters returns at the top with a `return std::nullopt;` under the condition `if (!m_cachedPeerKey)` However, m_cachedPeerKey is only populated during the PIN entry flow in /WebKit/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp Since BIO does not follow the PIN entry flow, this function that SHOULD fill the PRF parameters does not. I am currently looking through the code (I'm not too familiar) and can't really think of anything that isn't super hacky... I think it needs to somehow detect internalUV and ensure that we somehow send a `pin::KeyAgreementRequest` in spite of skipping over the PIN entry, and somehow pull off a call to storing the cache ie. `protectedThis->m_cachedPeerKey = keyAgreement->peerKey.ptr();` ... Sorry I can't think of anything more elegant... but I'm glad I was able to find the source of the issue. Let me know if you'd like me to help out with a hacky patch, or if you want me to test something. Thanks.
jonathan.underwood4649
Comment 2
2026-05-16 11:14:01 PDT
Created
attachment 479693
[details]
A simple fix for the issue (super rough) This is a very simple patch that I don't expect to be merged, but hopefully it quickly describes the issue. Just before the two calls to prepareHmacSecretParameters (once in the creation flow and once in the auth flow) I place a conditional block that checks for the cache and if it doesn't exist and all the other bools that need to be set (to actually call prepareHmacSecretParameters below) are in place, then it will run a little helper function I made to populate the cache. I'm also not sure whether the creation flow requires this fix... but I will keep it in the patch just for clarity on what I'm thinking are the two problem areas that are affected by the PIN-entry-only-populated cache. I apologize if this patch makes things less clear, but it seems like the minimal change needed to fix the issue. A more elegant fix should probably be used.
Radar WebKit Bug Importer
Comment 3
2026-05-22 21:04:11 PDT
<
rdar://problem/177761451
>
jonathan.underwood4649
Comment 4
2026-05-29 09:50:54 PDT
Created
attachment 479887
[details]
More complex fix This diff gets a little bit smaller when viewed with git diff -w to clear out white space diff lines. I have essentially changed CtapAuthenticator::prepareHmacSecretParameters to be async and fetch m_cachedPeerKey when they are not present, adding an extra round trip for a KeyAgreementRequest. This seems like a reasonable solution. Please let me know if you have any questions.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug