fidoyubikey

Yubikey attestation returns 39 byte authenticator data instead of 37 bytes


I am using fido2-assert to obtain an assertion from a Yubikey C NFC (5.7.1 firmware). The tool returns a four line file:

PQhSX/O9HYEvIbUZH/fWyCKg1nqXS5t41sztwV745nQ=
chainfrog
WCVnaHBXPn50f21/ute5h879H92zhpX0EtNrad3xx1KnPgEAAAAy
MEYCIQCmAFE4jOiHVIoxIn00ecjAhDb3uUL61CFDl/d5RokTFQIhANYpiBUnRADTVDC6TvtpiDzMdzw+UzGXGfR/YZizQgBe

Line 3 is meant to be the authenticator data, which according to https://www.w3.org/TR/webauthn/#authenticator-data is supposed to be a 32-bit SHA256 hash output of the relying party identifier (line two in the returned file), a 1 byte collection of flags, and a 4 byte counter.

When I decode the base64 authenticator data with base64 -d | xxd -p -r I get:

5825676870573e7e747f6d7fbad7b987cefd1fddb38695f412d36b69ddf1c752a73e0100000032

That's 39 bytes, not 37 bytes as it should be, and clearly does not contain optional extensions, because the last four bytes, 00000032 are the counter, and the first 35 bytes are always the same for similar assertion requests.

I am also unable to find the SHA256 hash of the relying party (in this case a hash of "chainfrog") in the authenticator data, and I'm unable to verify the signature with openssl pkeyutl when I check the signature using the public key and the concatenation of the client data hash (the first line) and the authenticator data.


Solution

  • The string

    5825676870573e7e747f6d7fbad7b987cefd1fddb38695f412d36b69ddf1c752a73e0100000032 seems to be CBOR encoded. I didn't think fido-assert returned it as CBOR, but I might be wrong or something might have changed.

    We can see it is CBOR by looking at the first byte in the response, 58. If we split this into binary we have 0101 1000. CBOR defines the first 3 bits as the type, with 010 indicating that it is a byte string. The following 5 bits, 11000 equal 24 in decimal, which in CBOR means the next byte is the length of the byte string. In our case this is 25 hex which would be 37 in decimal which is the length of the remainder of the string in question.

    That string the conforms to the correct setup for a authenticator data with the first 32 bytes being the ID, 1 byte for flags and then 4 bytes for the counter.