- From: J.C. Jones <jc@mozilla.com>
- Date: Wed, 14 Dec 2016 11:53:58 -0700
- To: W3C WebAuthn WG <public-webauthn@w3.org>
- Message-ID: <CAObDDPCzmPp46-FgVHOnPV3TC-WuEd82A6gbaKLtO8SvrVOF+A@mail.gmail.com>
All, I have a work-in-progress patch in out for initial feedback[1] to enable WebAuthn WD-{02/03} support in Firefox, tied to our U2F soft token. I know we don't yet have a definition of how the various fields in WebAuthn are mapped to the data that comes back from a U2F token, so I just mashed some things together to start a conversation. Note: I've attached this implementation to our U2F soft token, as we're still working on USB HID support, but in theory this should work about the same. First thing's first: makeCredential - After checking isRegistered, we call Register on the RP ID and Client Data hashes, and get back the Register Response. The Register Response gets put into the WebAuthnAttestation.Attestation field. Then the Response is pulled apart to get the Key Handle buffer for the ScopedCredential.ID field. Then we call Sign on the RP ID and Client Data hashes - again - using the Key Handle from Register, in order to get a Signature Response. That Response is concatenated onto the RP ID Hash (RP ID Hash || Signature Response), and stored into WebAuthnAttestation.AuthenticatorData, since that ... sort of ... looks like the correct format. By which I mean it includes the counter, while Register's output does not. This is assuming the counter is important to security at this stage of the process, which is not clear to me. You can see this part of the algorithm here [2]. This is obviously pretty hacky, as U2F devices used to register here would have to be touched / inserted twice. As for getAssertion - It's more straightforward; we just call Sign this time. No double-test-of-user-presenceing. So we Sign the RP ID and Client Data hashes to get a Signature Response. [3] That Response is concatenated onto the RP ID Hash (RP ID Hash || Signature Response), and stored into WebAuthnAssertion.AuthenticatorData, similar to before. The WebAuthnAssertion.SignatureData is set to the Signature Response, and the WebAuthnAssertion.ClientData to the serialized Client Data. The Credential.ID is copied from the Allow List. So semi-visually, here's how I mashed things up: *ScopedCredentialInfo* - *Credential* -- *ID*: Key Handle buffer extracted from U2F Register() Response -- *Type*: "ScopedCred" - *WebAuthnAttestation* -- *Format*: "u2f" -- *ClientData*: serialized JSON -- *AuthenticatorData*: RP ID Hash || U2F Sign() Response -- *Attestation*: U2F Register() Response *WebAuthnAssertion* - *Credential* -- *ID*: ID of Credential from AllowList that succeeded -- *Type*: "ScopedCred" - *ClientData*: serialized JSON - *AuthenticatorData*: RP ID Hash || U2F Sign() Response - *Signature*: U2F Sign() Response Question 1: For Attestation Format=U2F, should AuthenticatorData be omitted, or defined to not include a counter? Question 2: For Assertion Format=U2F, should AuthenticatorData be likewise omitted as duplicating the Signature field? Question 3: Does the general mapping make sense? [1] https://reviewboard.mozilla.org/r/97088 [2] https://reviewboard-hg.mozilla.org/gecko/rev/ 04fe96701f18e3261fd1e24d8377b4012f143911#l13.404 [3] https://reviewboard-hg.mozilla.org/gecko/rev/ 04fe96701f18e3261fd1e24d8377b4012f143911#l13.559 Cheers, J.C.
Received on Wednesday, 14 December 2016 18:54:52 UTC