Skip to content

feat(webauthn): support hmac-secret-mc CTAP 2.2 extension (fix #147)#212

Draft
AlfioEmanueleFresta wants to merge 1 commit into
masterfrom
pr-147
Draft

feat(webauthn): support hmac-secret-mc CTAP 2.2 extension (fix #147)#212
AlfioEmanueleFresta wants to merge 1 commit into
masterfrom
pr-147

Conversation

@AlfioEmanueleFresta
Copy link
Copy Markdown
Member

@AlfioEmanueleFresta AlfioEmanueleFresta commented May 12, 2026

Adds CTAP 2.2 hmac-secret-mc so prf.eval at create() time skips the GA round-trip on authenticators that advertise it. Falls back to hmac-secret: true (PRF via GA) when unsupported.

Wire format and decryption reuse the GA hmac-secret helpers (CalculatedHMACGetSecretInput / Ctap2HMACGetSecretOutput). Ctap2MakeCredentialRequest::needs_shared_secret gates ECDH on advertised support + buffered input; hmac-secret-mc is never sent without hmac-secret: true (§ 12.8). The PRF→HMAC salt mapping is extracted to PRFValue::to_hmac_secret_input and shared with the GA path.

Test plan

  • cargo test --workspace --all-features — 182 unit + 5 integration
  • cargo clippy --workspace --all-features --tests --examples -- -D warnings, cargo fmt --check --all
  • Virtual HID integration test for graceful degradation (test_webauthn_prf_eval_at_create_degrades_when_unsupported)
  • Smoke test on a CTAP 2.1 YubiKey: graceful degradation works, GA replay unaffected (see comment below)
  • Success path on a CTAP 2.2 authenticator advertising hmac-secret-mc — not available to me; reviewers welcome to validate

Enables PRF evaluation at MakeCredential time on authenticators that
advertise hmac-secret-mc. Falls back gracefully to hmac-secret: true
(PRF via GetAssertion) when the extension is unsupported.

Wire format and processing reuse the existing GA hmac-secret path.
@AlfioEmanueleFresta
Copy link
Copy Markdown
Member Author

AlfioEmanueleFresta commented May 12, 2026

Smoke-tested against a YubiKey reporting CTAP 2.1 (hmac-secret yes, hmac-secret-mc no). Exercises the graceful-degradation path only.

extensions  = ["credProtect", "hmac-secret", "largeBlobKey", "credBlob", "minPinLength"]
MC response  = hmac_secret: Some(true), hmac_secret_mc: None
prf output   = enabled: Some(true), results: None
GA replay    = first=fee01481…, second=ac3a6831…

Credential created with hmac-secret: true only, no hmac-secret-mc on the wire, GA replay returns expected PRF outputs. The success path still needs validation on a CTAP 2.2 authenticator.

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.

1 participant