Skip to content

fix(ctap2): do not send uv option together with pinUvAuthParam#265

Merged
AlfioEmanueleFresta merged 2 commits into
linux-credentials:masterfrom
Nisker:fix/ctap2-uv
Jun 10, 2026
Merged

fix(ctap2): do not send uv option together with pinUvAuthParam#265
AlfioEmanueleFresta merged 2 commits into
linux-credentials:masterfrom
Nisker:fix/ctap2-uv

Conversation

@Nisker

@Nisker Nisker commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

This was tested with libwebauthn 0.5.1 in credentialsd master branch (7c13749) in a modified Teams for linux (FIDO2 passkey login login).
Token2 version 3.1 logins without problems.
Yubikey triggers Ctap(InvalidOption) error right after a PIN has been entered.

The FIDO 2.1 spec.§6.1.2. authenticatorMakeCredential and §6.2.2. authenticatorGetAssertion says "If the pinUvAuthParam is present, let the "uv" option be treated as being present with the value false."
So having UV=true and pinUvAuthParam will cause errors on a strict key like Yubikey.

@AlfioEmanueleFresta AlfioEmanueleFresta changed the title fix(ctap2): uv and uv_auth_param mutually exclusive. fix(ctap2): do not send uv option together with pinUvAuthParam Jun 10, 2026

@AlfioEmanueleFresta AlfioEmanueleFresta left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix and the clear report @Nisker, and for testing against both Token2 and YubiKey hardware. This is spec-correct. The CTAP 2.1 options tables for authenticatorMakeCredential and authenticatorGetAssertion both state: "Platforms MUST NOT include both the 'uv' option key and the pinUvAuthParam parameter in the same request."

YubiKeys seem to enforce this strictly, which is exactly the CTAP2_ERR_INVALID_OPTION you saw. Reproduced here on a YubiKey (firmware 5.x, userVerification: "required" assertion after PIN entry). On master:

TRACE ctap2_get_assertion: request=Ctap2GetAssertionRequest { relying_party_id: "example.org", [..]
  options: Some(Ctap2GetAssertionOptions { require_user_presence: true, require_user_verification: true }),
  pin_auth_param: Some([184, 209, 64, ..]), pin_auth_proto: Some(2) }
DEBUG ctap2_get_assertion: Received CBOR response status=InvalidOption

With this PR, same device and request:

TRACE ctap2_get_assertion: request=Ctap2GetAssertionRequest { relying_party_id: "example.org", [..]
  options: Some(Ctap2GetAssertionOptions { require_user_presence: true, require_user_verification: false }),
  pin_auth_param: Some([208, 153, 182, ..]), pin_auth_proto: Some(2) }
DEBUG ctap2_get_assertion: CTAP2 GetAssertion successful
  flags: AuthenticatorDataFlags(USER_PRESENT | USER_VERIFIED)

User verification still happens through the pinUvAuthToken, as the UV flag in the response shows.

I pushed a small commit on top of your branch adding regression tests for both request types, and tweaked the PR title to match our commit conventions. Nice catch, thanks again!

@AlfioEmanueleFresta AlfioEmanueleFresta merged commit c466fbf into linux-credentials:master Jun 10, 2026
4 checks passed
@AlfioEmanueleFresta

Copy link
Copy Markdown
Member

This is now released in libwebauthn 0.7.1 if you want to test, thanks again @Nisker!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants