Search code examples
fidoyubicofido-u2f

Wrapped private key with libfido2?


I am currently working my way into libfido2 and trying to figure out how to use wrapped private keys with it.

Yubico says in the FAQs that with YubiKey 5 unlimited key pairs can be used for FIDO U2F; however, for FIDO2 only space for 25 resident keys is promised.

  1. Does "FIDO2" mean that resident keys are used and that FIDO2 cannot be used with (external) wrapped private keys?

  2. If this is the case, does libfido2 offer any possibility to work with FIDO U2F and wrapped keys instead?

  3. If so, how does libfido2 need to be configured to do this? How can I provide the library with the appropriate protected private key. At least in "fido2-assert" I don't see a way to do this when I want to create an assertion on the client.

(The function accepts four specific parameters description here, and the only one that I understand could bring the private key is the "credential id". But the name makes me doubt if my request is possible with this parameter).

I am grateful for any answer!

EDIT: In the meantime I found this link to some Solo Keys developer pages describing how it works on Solo Keys. It seems the private key is calculated on the fly - in this case credential id would work as seed for the calculation)


Solution

  • FIDO2 encompasses both WebAuthn (browser API) and CTAP2 (USB/Bluetooth/NFC APIs for externally connected authenticators). CTAP2 supports both client-side and server-side credentials, and specifies how backwards compatibility with U2F/CTAP1 authenticators works. Since you're working with libfido2, the CTAP documentation might be useful to understand what it does under the hood.

    Client-side discoverable credentials (previously known as resident keys) are used for usernameless flows where no Credential IDs are specified during authentication. These keys are generated randomly and require storage space. Server-side credentials (non-resident keys) are represented as Credential IDs. What type of key is created is requested during the registration process but both FIDO2 standards default to server-side credentials if not specified. U2F only supported server-side credentials.

    For external authenticators with limited storage space, server-side credentials are typically wrapped private keys encrypted by a single 'master' key stored in the authenticator. Since the entire state is stored outside of the authenticator this allows for practically infinite keys to be generated even with limited storage space. But it does mean that the Credential ID generated during registration must be stored on the server, and in order to generate an assertion it must be offered back to the authenticator later for authentication. In WebAuthn these Credential ID(s) are typically presented after the user is identified (e.g. via username and password) in the allowCredentials argument, CTAP2 calls this allowList.

    With the terminology now (hopefully) clarified, yes libfido2 supports both types of credentials according to the assert example:

    Asks <device> for a FIDO2 assertion corresponding to [cred_id], which may be omitted for resident keys. The obtained assertion is verified using <pubkey>.