Add hmac-secret-mc CTAP 2.2 extension for PRF at MakeCredential time#167
Add hmac-secret-mc CTAP 2.2 extension for PRF at MakeCredential time#167
Conversation
|
Don't create a PR until you have some changes to show. |
Co-authored-by: AlfioEmanueleFresta <621062+AlfioEmanueleFresta@users.noreply.github.com>
AlfioEmanueleFresta
left a comment
There was a problem hiding this comment.
Please address the comments. You now have access to fetch the FIDO specs, so you can try those requests again.
| }); | ||
| } | ||
|
|
||
| fn prf_eval_to_hmac_input( |
There was a problem hiding this comment.
You should reuse the existing HMAC <-> PRF logic (eg. Ctap2GetAssertionRequestExtensions.prf_to_hmac_input), refactoring it so it can be shared across MC and GA.
There was a problem hiding this comment.
Extracted prf_value_to_hmac_input as a shared pub(crate) function in get_assertion.rs that both GA's prf_to_hmac_input and MC's from_webauthn_request now call. Removed the duplicate prf_eval_to_hmac_input from MC. See commit 2ea1691.
| /// With hmac-secret-mc (CTAP 2.2), PRF evaluation can occur at registration time. | ||
| /// We still accept the raw JSON value for backward compatibility. | ||
| #[serde(rename = "eval")] | ||
| pub _eval: Option<JsonValue>, |
There was a problem hiding this comment.
You do not need to keep the old _eval value. You can break compatibility with old libwebauthn versions.
There was a problem hiding this comment.
Removed _eval: Option<JsonValue> entirely. MakeCredentialPrfInput now has just eval: Option<PRFValue> with proper Deserialize support. Added Deserialize to PRFValue so it works for both JSON and binary deserialization paths. See commit 2ea1691.
…akeCredentialPrfInput Co-authored-by: AlfioEmanueleFresta <621062+AlfioEmanueleFresta@users.noreply.github.com>
Co-authored-by: AlfioEmanueleFresta <621062+AlfioEmanueleFresta@users.noreply.github.com>
All three review comments addressed in commits
All 112 tests pass. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
| /// https://w3c.github.io/webauthn/#prf | ||
| /// | ||
| /// Shared between GetAssertion (hmac-secret) and MakeCredential (hmac-secret-mc). | ||
| pub(crate) fn prf_value_to_hmac_input(ev: &PRFValue) -> HMACGetSecretInput { |
There was a problem hiding this comment.
Can you move this to its own module, as it's not get_assertion specific. proto::extensions::prf, maybe.
There was a problem hiding this comment.
Moved prf_value_to_hmac_input and CalculatedHMACGetSecretInput to proto::extensions::prf module. Both get_assertion.rs and make_credential.rs now import from crate::proto::extensions::prf. See commit 8395abe.
| @@ -100,7 +100,7 @@ async fn run_test_battery(channel: &mut HidChannel<'_>, using_pin: bool) { | |||
| let challenge: [u8; 32] = thread_rng().gen(); | |||
|
|
|||
| let extensions = MakeCredentialsRequestExtensions { | |||
There was a problem hiding this comment.
Modify this test to actually include PRF evaluation.
There was a problem hiding this comment.
Updated the test to include PRF eval values (first: [1; 32]) in the MakeCredentialPrfInput. The virtual authenticator doesn't support hmac-secret-mc, so the result is still None, but the eval input is now exercised through the code path. See commit 8395abe.
| pub eval: Option<super::PRFValue>, | ||
| } | ||
|
|
||
| impl MakeCredentialPrfInput { |
There was a problem hiding this comment.
Constructor seems unnecessary.
There was a problem hiding this comment.
Removed the constructor. See commit 8395abe.
…, remove constructor Co-authored-by: AlfioEmanueleFresta <621062+AlfioEmanueleFresta@users.noreply.github.com>
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. |
Adds support for the
hmac-secret-mcCTAP 2.2 extension, enabling PRF evaluation during credential registration rather than requiring a subsequent GetAssertion roundtrip.Shared PRF→HMAC logic
prf_value_to_hmac_input()andCalculatedHMACGetSecretInputinto a dedicatedproto::extensions::prfmodule, shared between GetAssertion (hmac-secret) and MakeCredential (hmac-secret-mc)DeserializetoPRFValuewith properdefaultserde attributes for JSON/CBOR deserialization supportCTAP request layer
hmac-secret-mcfield (Option<CalculatedHMACGetSecretInput>) toCtap2MakeCredentialsRequestExtensions, reusing the same wire format ashmac-secretin GetAssertioncalculate_hmac_secret_mc()— mirrorscalculate_hmac()from GetAssertion: encrypts PRF-derived salts with the ECDH shared secretprf_inputstored internally (#[serde(skip)]), calculated after user verification using the sharedprf_value_to_hmac_input()Shared secret negotiation
needs_shared_secret()forCtap2MakeCredentialRequestto returntruewhen the authenticator advertiseshmac-secret-mcand PRF eval input is present — per @msirringhaus's note on PR Allow for shared secret to be created even if no PIN is set on the device #146CTAP response layer
hmac-secret-mcfield (Option<Ctap2HMACGetSecretOutput>) toCtap2MakeCredentialsResponseExtensionsdecrypt_output()infrastructureWebAuthn-level types
MakeCredentialPrfInput: useseval: Option<PRFValue>with proper serde support for both JSON and binary deserializationMakeCredentialPrfOutput: addedresults: Option<PRFValue>to carry decrypted PRF outputOrchestration
_webauthn_make_credential_fido2now callscalculate_hmac_secret_mc()after user verification and passesauth_datathrough to response processing for decryptionUsage
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.