W3C home > Mailing lists > Public > public-webauthn@w3.org > December 2016

Re: Mapping out the U2F Attestation Format

From: Alexei Czeskis <aczeskis@google.com>
Date: Mon, 19 Dec 2016 11:25:51 -0800
Message-ID: <CAM_SUqcbsMpjrvvNpzLAAf455odJXcS2gfG3Gt0AsGsyfUPVmw@mail.gmail.com>
To: Jakob Ehrensvärd <jakob@yubico.com>
Cc: "J.C. Jones" <jc@mozilla.com>, W3C WebAuthn WG <public-webauthn@w3.org>
We're in the process of defining a U2F attestation format.  We're just slow.

I'm thinking that we just shouldn't include an authenticatorData at all
(like it should be null) for a ScopedCredentialInfo object that's generated
by a U2F device.  It seems to both serve no purpose and require crazy UX.
I'm trying to recall what purpose the authenticatorData serves in the
makeCredential response.  I guess it's proof that the authenticator
actually has the private key that it claims to have generated?  But if we
don't have that, I'm not convinced that things will fall apart -- I don't
see any vulnerability that it induces.



Thanks!
-Alexei

*____**_**__**_**_**_**_**_**_**_**_**_*

 . Alexei Czeskis .:. Securineer .:. 317.698.4740 .

On Thu, Dec 15, 2016 at 5:12 AM, Jakob Ehrensvärd <jakob@yubico.com> wrote:

> Thanks for bringing this up. I may restate certain obvious things, but
> I believe the outcome of this is important so I'd just like to be sure
> to be aligned on the fundamentals.
>
> I believe the only problem is the MakeCredential call, as the
> authenticatorData field and the way the signature is generated is
> identical in U2F.
>
> GetAssertion authenticatorData:
> - rpidHash (32 bytes)
> - flags (1 byte). ED always cleared in U2F
> - Counter (4)
> - Optional ED (never present in U2F)
> - clientDataHash (32 bytes
>
> Hash to be signed is then SHA256(authenticatorData || clientDataHash)
>
>
> As there is no flags + counter fields in a U2F register (=
> MakeCredential) response, it seems to me that the authenticator data
> format needs to be different. Having to perform two actions (register
> + authenticate) to get a counter value + signature seems very awkward
> and still won’t provide a single signature that can be verified on the
> RP side.
>
> U2F authenticatorData:
> - HashId (=0) (1 byte)
> - rpidHash (32)
> - clientDataHash (32)
> - attestationCert (n)
> - DER-coded public key
>
> Hash to be signed is then SHA256(authenticatorData)
>
> Webauthn authenticatorData
> - rpidHash (32 bytes)
> - Counter (4)
> - aaguid (16)
> - credentialId (2 + n)
> - CBOR encoded algorithm specifier
> - Optional CBOR encoded extensions
>
> Hash to be signed is then SHA256(authenticatorData || clientDataHash)
>
> So for the RP to find out how to construct the hash and verify the
> signature, we'll have to have something that specifies the format.
>
> - Have a new key "format": "U2F", which implicitly defines both the
> U2F attestation format as well as the authenticator data format
> OR
> - Define a new CBOR key for authenticatorDataV1
>
> An RP storing the last counter value will have to make up something
> for the missing counter field here. I believe this is quite
> straight-forward to handle.
>
>
> Thank you,
>
> Jakob Ehrensvard
> CTO
> Skype: jehrensvard
> US mobile: +1 650-283-1537
> SE mobile: +46 (0) 708 24 63 53
>
> http://www.yubico.com
>
> On Wed, Dec 14, 2016 at 10:53 AM, J.C. Jones <jc@mozilla.com> wrote:
> > 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 Monday, 19 December 2016 19:26:40 UTC

This archive was generated by hypermail 2.4.0 : Tuesday, 5 July 2022 07:26:24 UTC