xous-core
xous-core copied to clipboard
U2F registration fails (FIDO2 works)
This issue report stems from this comment. While FIDO2 works fine, it seems the older U2F fails where a different device, a NitroKey 3, works fine.
I installed libu2f-server and libu2f-host, simply by installing the Debian bookworm/stable packages, versions 1.1.0-4+b1 (u2f-server) and 1.1.10-3 (u2f-host).
These two programs should allow you to register a U2F device and have it validate authentication challenges, and it works with the Nitrokey 3. However, with the Precursor, it cannot be registered, the u2f-host
program that talks to the device gives an error
error (-2): error in transport layer
Here is how to reproduce, and I also included USB traffic dumps for both Precursor and Nitrokey.
Generate challenge
The following invocation will make u2f-server
generate a registration challenge, save the key handle to keyhandle-precursor.dat
and the user key to userkey-precursor.dat
:
$ u2f-server -aregister -o https://example.org -i https://example.org -k keyhandle-precursor.dat -p userkey-precursor.dat
This will print to stdout
some JSON:
{ "challenge": "-736B0R1cxJXorY77D3dp1T3ovnvj5pppwGAt-xxQmE", "version": "U2F_V2", "appId": "https:\/\/example.org" }
Note that for exact reproduction, you can make it reuse that exact challenge again by passing it in with -c "[...challenge...]"
as such:
$ u2f-server -aregister -o https://digitalbrains.com -i https://digitalbrains.com -k keyhandle-precursor.dat -p userkey-precursor.dat -c "-736B0R1cxJXorY77D3dp1T3ovnvj5pppwGAt-xxQmE"
Pass challenge to Precursor
Invoke u2f-host
as:
$ u2f-host -aregister -o https://example.org
and then copy-paste the JSON output by u2f-server
on stdin
of the u2f-host
process. End with a newline and EOF (Ctrl-D).
The Precursor will now prompt:
Clicking accept will make u2f-host
error out:
error (-2): error in transport layer
at which point you cannot continue with registration. The USB conversation between u2f-host
and the Precursor, as captured by Wireshark, should be this:
precursor-u2f-register-fail.pcapng.gz
Pass challenge to Nitrokey
Again, invoke u2f-host
as:
$ u2f-host -aregister -o https://digitalbrains.com
and then copy-paste the JSON output by u2f-server
on stdin
of the u2f-host
process. End with a newline and EOF (Ctrl-D). I used the exact same challenge as for the Precursor.
The Nitrokey starts to blink, touch it.
u2f-host
outputs some JSON on stdout
:
{ "registrationData": "BQTjF9hE8yPDZdhLuLcPmZSotCH942Alte4MQRhmjifdh6huMTdPLVXFC9uJNaPs8NH4vTx8PQC3Px8nNZ5z0wj_tqMAWJIDZkGxCfKIG-fb0TrB_pvHyT6m_vFFndxkYmCtXohO--CnlBtGJYLXaJ5KnHZIG93eqbRZSHnx0PbSRfT6F2p7wuITYF8xOPz4XyzYfUV4rhJv_3btbHT8dwJS4VglAtBBzGdM1_2q6np2fD33p0kPF66mIm26GziBEwTFBCOhQAjAbvbJK-6l-ZFOsiATRKQ7XwFMRsY2Gfs3Ir8TzJG0AlDc-I7Rmgx0C1dRv-oIPbLnMIICLjCCAdSgAwIBAgIEAMzMzDAKBggqhkjOPQQDAjA5MQswCQYDVQQGEwJERTEWMBQGA1UECgwNTml0cm9rZXkgR21iSDESMBAGA1UEAwwJRklETyBDQSAzMCAXDTIyMDQwNjExMjUyOFoYDzIwNzIwMzI0MTEyNTI4WjBtMQswCQYDVQQGEwJERTEWMBQGA1UECgwNTml0cm9rZXkgR21iSDEiMCAGA1UECwwZQXV0aGVudGljYXRvciBBdHRlc3RhdGlvbjEiMCAGA1UEAwwZTml0cm9rZXkgRklETyBBdHRlc3RhdGlvbjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCq6VUCC4Of2hGSyM7O9_uw4B_-pcLgYnFLQllKGO5wmK1I9sNNMpW-ubz52uyMOMUr7hbuuiZBZZj-dBD0ijaCjgZMwgZAwHQYDVR0OBBYEFDOBXdHoZV9fBKa27eCRiBPdwhnJMB8GA1UdIwQYMBaAFMFz5URWwMhuWGifn2LOKMiRlXYkMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgTwMCEGCysGAQQBguUcAQEEBBIEEOyZ2xnNH0wGoqmUDxemowswEwYLKwYBBAGC5RwCAQEEBAMCBDAwCgYIKoZIzj0EAwIDSAAwRQIhAIcFpLaFPfU3XV-pA0ePZrpdukN06yOAijhpXnzGHO8IAiA8-1RKaNurtgplX5IYG4V9pPYcTgrVvdzfOmHZDS_JqDBGAiEAnpEA3G9YicGaha1ZjaSnC2qITmDXUfcD1yxhloDSOj8CIQDcfPNwX9DA6KOvs_MQACHc6BxWOX59PP_A5-RuuA98EA", "clientData": "eyAiY2hhbGxlbmdlIjogIi03MzZCMFIxY3hKWG9yWTc3RDNkcDFUM292bnZqNXBwcHdHQXQteHhRbUUiLCAib3JpZ2luIjogImh0dHBzOlwvXC9leGFtcGxlLm9yZyIsICJ0eXAiOiAibmF2aWdhdG9yLmlkLmZpbmlzaEVucm9sbG1lbnQiIH0" }
(I did it twice with the same challenge. registrationData
changed, clientData
stayed the same)
I am hoping that the following capture by Wireshark is the correct conversation for this exact response: nitrokey-u2f-success.pcapng.gz
Finish registration of Nitrokey
Paste the JSON that u2f-host
outputted on stdin of the still running u2f-server
process, ending in newline and EOF. u2f-host
will reply:
Registration successful
and will save the credentials in the two files: key handle and user key.
Authenticate with Nitrokey
Very similar to the steps we did up to now, but instead of -aregister
we now do -aauthenticate
and the files are now input instead of output.
$ u2f-server -aauthenticate -o https://digitalbrains.com -i https://digitalbrains.com -k keyhandle-nitrokey.dat -p userkey-nitrokey.dat
gives us some JSON:
{ "keyHandle": "owBYkgNmQbEJ8ogb59vROsH-m8fJPqb-8UWd3GRiYK1eiE774KeUG0Ylgtdonkqcdkgb3d6ptFlIefHQ9tJF9PoXanvC4hNgXzE4_PhfLNh9RXiuEm__du1sdPx3AlLhWCUC0EHMZ0zX_arqenZ8PfenSQ8XrqYibbobOIETBMUEI6FACMBu9skr7qX5kU6yIBNEpDtfAUxGxjYZ-zcivxPMkbQCUNz4jtGaDHQLV1G_6gg9suc", "version": "U2F_V2", "challenge": "Ni590tN3zf-MJmkZD9cArRXH5P5tetfAWWvv6YRF9sw", "appId": "https:\/\/example.org" }
u2f-host -aauthenticate -o https://example.org
Paste the JSON from u2f-server
into u2f-host
as before, touch the Nitrokey, and u2f-host
will output the challenge response:
{ "signatureData": "AQAAAIcwRgIhAPatcIRyUp7u8wpf7BKZGLvcQ8YtWiA6FWBp1BKr5VzBAiEA-SKkkF6bDijVNnStKFycqrWsPm_2ARO07IhpuV2HnxY", "clientData": "eyAiY2hhbGxlbmdlIjogIk5pNTkwdE4zemYtTUpta1pEOWNBclJYSDVQNXRldGZBV1d2djZZUkY5c3ciLCAib3JpZ2luIjogImh0dHBzOlwvXC9leGFtcGxlLm9yZyIsICJ0eXAiOiAibmF2aWdhdG9yLmlkLmdldEFzc2VydGlvbiIgfQ", "keyHandle": "owBYkgNmQbEJ8ogb59vROsH-m8fJPqb-8UWd3GRiYK1eiE774KeUG0Ylgtdonkqcdkgb3d6ptFlIefHQ9tJF9PoXanvC4hNgXzE4_PhfLNh9RXiuEm__du1sdPx3AlLhWCUC0EHMZ0zX_arqenZ8PfenSQ8XrqYibbobOIETBMUEI6FACMBu9skr7qX5kU6yIBNEpDtfAUxGxjYZ-zcivxPMkbQCUNz4jtGaDHQLV1G_6gg9suc" }
Paste that back again to u2f-server
and it will say:
Successful authentication, counter: 135, user presence 1
I suspect that with all this data, people might be able to pose as the https://example.org
server to my Nitrokey. But that server is not going to exist and it seems like a weird attacker model anyway; what should protect me from people posing as example.org
is a signed SSL certificate, not this exchange above. Still, I decided not to use a real hostname.
Ah. This is with latest bleeding edge:
ver xous
Xous version: v0.9.15-459-g38855960
Thu, 01 Feb 2024 13:55:23 +0800
But it doesn't work with the stable release either. I just thought you'd prefer testing with bleeding edge.
Thank you for the incredibly detailed notes. This will help debugging it more later.
As I mentioned elsewhere, I might de-prioritize this until this actually is a blocker for someone's workflow -- at the moment slogging through upgrading the crypto APIs to support the Signal client effort.
Yes, in practice the places where I actually use Precursor with FIDO work fine, so this issue might not be a problem for anyone.
at the moment slogging through upgrading the crypto APIs to support the Signal client effort.
Operator: We get signal. Captain: What ! Operator: Main screen turn on.
:-D Good luck!