kanidm/webauthn-rs

Google Titan Security Key USB-C/NFC fails some compatibility tests

arthurgleckler opened this issue · 9 comments

I did this

I used the compatibility test with my Google Titan Security Key USB-C/NFC.

I expected the following

I expected it to pass all the tests.

What actually happened

Several tests failed.

Version (and git commit)

Operating System / Version

I'm using Chrome 119.0.6045.199 on Ubuntu 22.04.

Any other comments

titan-compatibility-results.json

Thank you for webauthn-rs. I'm hoping to use it in a site I run.

P.S.: I ran the compatibility test because I got UnknownError("AttestationChainNotTrusted(\"self-signed certificate\")") when I try this key with the demo site with Credential Type "Security Key" and Attestation Level "Any Known FIDO Device." I don't know whether the compatibility test failures are related, but it's a hunch.

This is model K40T.

The attestation failure is expected because this is not a FIDO certified key. Just because they claim "FIDO compatible" doesn't mean it's passed FIDO certification. This is why it's not in the "known fido list".

The compat results here are showing that the key doesn't support userverification - did the key prompt you for a PIN or for biometrics? from what I'm reading, this appears to be a single factor only key, meaning that it will not work with our "passkey" library interfaces. This is a limitation of the key - not webauthn-rs sorry.

Generally we wouldn't advise the titan key, as it's quite a limited device, and there are better options available (yubikeys especially).

Thank you very much for the quick response. I suspected that this might be the answer, so I ordered a Yubikey 5C last night. I'm excited to try it with webauthn-rs.

By the way, I'm in the middle of writing a command-line wrapper for webauthn-rs that works similarly to the Tide tutorial example. Instead of using a web server, though, it takes its input and produces its output in JSON form. That way, I can call it from a web server written in another programming language (Scheme, in my case) without having to deal with the complexity of an FFI. If this is at all interesting to you, I'd be happy to contribute the command-line wrapper to the project if and when I get it to work.

@micolous What do you think? I think it's an interesting idea, and could be a useful debugging/inspection tool, but my brain is also blanking on when I'd need it as a debugging/inspection tool?

As the same time, it also seems like a pretty thin layer over webauthn-rs, so maintenance wise it would be "low effort".

@arthurgleckler As always, happy to help with anything else. Good luck with the yubikeys (I have a fair few myself and I really do support that they are the best keys available!)

That interface sounds pretty small. It may be useful for integration testing, to reproduce browser flows in a more structured way, rather than trying to reproduce structures manually in Rust.

Re: Titan SK, it's only the 2023 version which does CTAP2 (and can do UV if you configure it), and older versions only do CTAP1/U2F (so no UV).

"Titan Security Key v2" (AAGUID 42b4fb4a-2866-43b2-9bf7-6c6669c2e5d3) appears in the FIDO MDS as of September 2023, and it lists supporting FIDO 2.0 (not 2.1-PRE or 2.1, the newer standards). I haven't checked whether its record is actually valid1, or whether our data is just out of date.

Currently, the product and support pages don't differentiate the different versions of the key - but it looks like K40T should be the CTAP2 version.

fido-key-manager info (in this repo) should tell you which key it actually is, and if the key only supports U2F then it won't be able to connect at all.

If you have an older version of the key, then you're out of luck.

But otherwise, I'd also echo the recommendation for the Yubikey.

Footnotes

  1. Many MDS records are not valid, and webauthn-rs attempts to correct them.

I think I've figured it out: the JSON provided shows the key reporting a fido-u2f attestation, but the MDS only lists a protocolFamily: fido2 certification for "Titan Security Key v2" (as shown in MDS Explorer):

Screenshot 2023-12-05 at 16 42 33

That'd only work if the authenticator provided a packed attestation, which it'd only get if running the key in CTAP2 mode.

Compare this with say, a "Security Key by Yubico with NFC" (SKY), which has an MDS listing for both protocolFamily: fido2 and protocolFamily: u2f:

Screenshot 2023-12-05 at 16 43 36

So the SKY can attest in both modes.

That would make me think Chrome is using the key in U2F mode, rather than CTAP2. The reason for that is in the CTAP 2.1 spec (not 2.0):

Note: For backwards compatibility, platforms must be aware that FIDO_2_0 (aka CTAP2.0) authenticators always require some form of user verification for authenticatorMakeCredential operations. If a platform attempts to create a non-discoverable credential on a CTAP2.0 authenticator without including the "uv" option key or the pinUvAuthToken parameter that authenticator will return an error. In contrast, a FIDO_2_1 (aka CTAP2.1) authenticator with the makeCredUvNotRqd option ID (set to true) in the authenticatorGetInfo response structure, will allow creation of non-discoverable credentials without requiring some form of user verification.

So if you haven't configured UV on a CTAP 2.0-only key (or CTAP 2.1 key that doesn't set makeCredUvNotRqd = true), Chrome won't be able to create a credential in CTAP2 mode.

So it falls back to using U2F, which gives the fido-u2f attestation, which is not in the MDS, because the key is not certified in U2F mode. That's a problem Google will need to fix.

A lot of this is hypothesis, we'd need to see the fido-key-manager info (authenticatorGetInfo) output to be certain... and that key is not sold in Australia.

Setting a PIN on the device should allow you to register credentials in FIDO2 mode, and give a packed attestation. I don't know whether there's other problems with the MDS record we'd need to fix.

I received my Yubikey 5C, and it works perfectly not only with the webauthn-rs demo site, but also with other sites. And my command-line wrapper now registers it correctly, too.

Thanks very much for the detailed, helpful replies.

I'm closing this issue.

No problem - glad we could help :)