Repository navigation
ctap2, fidohid: support silent GetAssertion pre-flight, MakeCredential blink probe, and CTAPHID_CANCEL - #42
Open
HmFlashy wants to merge 1 commit into
Conversation
…l blink probe, and CTAPHID_CANCEL
Browsers (notably Firefox via authenticator-rs and Chromium) perform
several CTAP 2.1 / CTAPHID probes during WebAuthn authentication that
previously caused Passkey sign-in to time out or fail:
1. Silent GetAssertion pre-flight (CTAP 2.1 §6.2.2):
Firefox probes allowList credentials with options.up = false before
requesting interactive verification. Previously, handleGetAssertion
ignored options.up and blocked on VerifyUser (e.g. fprintd), causing
the browser's silent pre-flight to time out or consume a fingerprint
scan prematurely.
- Parse options.up (default true) and reject invalid up=false + uv=true
combinations with CTAP2_ERR_INVALID_OPTION (0x2C).
- Skip VerifyUser, clear UP/UV flags, and omit the user entity (key 4)
when options.up == false.
- Match allowList entries against the resident credential store first
before falling back to TPM dummy signing, and select the most
recently stored credential when multiple exist for an RP.
2. Dummy MakeCredential blink probe (CTAP 2.1 §6.1.2 steps 2 & 4):
Firefox ("make.me.blink") and Chromium (".dummy") send MakeCredential
with a zero-length pinUvAuthParam to collect user presence and expect
CTAP2_ERR_PIN_NOT_SET (0x35) when clientPin is not configured.
Previously, pinUvAuthParam was ignored and a spurious credential was
minted with StatusOK (0x00).
- Handle zero-length pinUvAuthParam by requesting user presence and
returning StatusPinNotSet (0x35) without persisting a credential.
- Reject non-empty pinUvAuthParam immediately with StatusPinNotSet
(0x35) without requesting user presence.
3. CTAPHID_CANCEL and unknown command framing (CTAPHID §11.2.9.1.4 / .6):
- Handle CmdCancel (0x11) silently with no response frame instead of
writing an invalid U2F 0x6D00 status word on the cancel command byte.
- Support CmdPing (0x01) echo and return CmdError (0x3F) with
ERR_INVALID_CMD (0x01) for unsupported HID commands.
Includes unit tests covering all three behaviors.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes FIDO2 / Passkey authentication in Firefox (
authenticator-rs) and improves CTAP 2.1 / CTAPHID compliance for Chromium-based browsers when usinglinux-id(tested end-to-end with hardware TPM 2.0 +--auth fprintdagainst Google Passkeys on Linux).Root Cause & Changes
Silent
authenticatorGetAssertionpre-flight (options.up = false, CTAP 2.1 §6.2.2)allowList, Firefox first probes authenticators silently withoptions: {"up": false}to discover which token holds a matching credential before prompting the user.handleGetAssertionignoredoptions.upand immediately invokedVerifyUser(blocking onfprintd/pinentry), causing Firefox's silent pre-flight to time out or consume a fingerprint touch prematurely.options.up(defaulting totrue).up=false && uv=truecombinations withCTAP2_ERR_INVALID_OPTION(0x2C).up == false, skipVerifyUser, clearUP/UVflags (0x00), and omit theuserentity (response[4]) so PII is never leaked without user presence.FindByRPID) first onallowListlookups to avoid an unnecessary TPM round-trip during pre-flight, and select the most recently saved resident credential when multiple exist for the same RP.Dummy
authenticatorMakeCredentialblink probe (pinUvAuthParam, CTAP 2.1 §6.1.2 steps 2 & 4)rp.id = "make.me.blink") and Chromium (rp.id = ".dummy") sendMakeCredentialwith a zero-lengthpinUvAuthParam(h"") to trigger a user-presence check and expectCTAP2_ERR_PIN_NOT_SET(0x35) whenclientPinis not supported/set.pinUvAuthParamwas ignored andlinux-idminted and stored a dummy credential returningStatusOK(0x00).len(pinUvAuthParam) == 0, perform user-presence verification viaVerifyUserand returnStatusPinNotSet(0x35) without minting or persisting a credential.len(pinUvAuthParam) > 0, returnStatusPinNotSet(0x35) immediately without prompting for user presence.CTAPHID_CANCEL(0x11) & unknown command error framing (CTAPHID §11.2.9.1.4 & §11.2.9.1.6)CTAPHID_CANCEL(0x11) hitdefault:inSoftToken.Runand wrote a0x6D00payload back on command0x11, violating CTAPHID §11.2.9.1.4 ("CTAPHID_CANCEL has no response") and confusing browser HID state machines when cancelling sibling probes.CmdCancel(0x11) without writing a response frame, echoCmdPing(0x01), and returnCmdError(0x3F) withERR_INVALID_CMD(0x01) for unknown CTAPHID commands.Test Plan
go test ./...passes, including 4 new unit tests:TestRealWorld_FirefoxSilentPreFlightThenUVAssertionTestGetAssertion_RejectUVTrueWithUPFalseTestMakeCredential_ZeroLengthPinUvAuthParamBlinkProbeTestMakeCredential_NonEmptyPinUvAuthParamRejectedWithoutUP/dev/tpmrm0, Goodix fingerprint sensor via--auth fprintd) registering and signing in with Passkeys onaccounts.google.comin Firefox.