authenticator-rs icon indicating copy to clipboard operation
authenticator-rs copied to clipboard

Issue with handles > 64 bytes

Open obelisk opened this issue 2 years ago • 22 comments

Maybe I'm just doing something wrong, but when my handles are 64 bytes, everything works normally. But when it's greater than that it cannot find the key.

Again, not sure if I'm doing something wrong but I can't seem to figure out what's going on. It definitely fails inside u2f_is_keyhandle_valid where status != SW_CONDITIONS_NOT_SATISFIED but all other checks on the key handle pass

obelisk avatar Feb 21 '22 23:02 obelisk

This occurs at least on macOS aarch64 and Linux amd64

obelisk avatar Feb 22 '22 00:02 obelisk

Can you determine what the value of status is when it fails and also whether this occurs with other devices as well?

rmartinho avatar Feb 22 '22 16:02 rmartinho

The status is set to 0x6A80, seems to happen with both my Yubikey bio and 5C

obelisk avatar Feb 25 '22 22:02 obelisk

When using ECDSA keys I get: 0x6985

obelisk avatar Feb 25 '22 22:02 obelisk

Those are

SW_CONDITIONS_NOT_SATISFIED (0x6985): The request was rejected due to test-of-user-presence being required.
SW_WRONG_DATA (0x6A80): The request was rejected due to an invalid key handle.

I'm not quite sure what you mean by "handle". The key handle is selected by the token upon registering. Do you mean, sometimes your tokens returns a handle, that is >64 bytes and then it fails, when trying to sign in? Do you have some kind of reproducer? (Maybe a modified examples/main.rs or something like that?)

msirringhaus avatar Mar 14 '22 10:03 msirringhaus

The closest thing I have to that (currently) is this code that I am working on to sign SSH certificates with a FIDO key. https://github.com/obelisk/sshcerts/blob/new_fido2_authenticator_rs/src/ssh/privkey.rs#L302

This code works perfectly well for ECDSA256 keys which are 64 bytes long, but Ed25519 keys fail and the only real difference I see is that the Ed25519 key handle is 128 bytes (since the code is almost identical).

I also know the key key supports it because using the CTAP2 library in this branch works will both key types, on the same hardware keys.

CTAP2 branch: https://github.com/obelisk/sshcerts/tree/new_fido2

obelisk avatar Mar 15 '22 01:03 obelisk

This example illustrates the point: https://github.com/obelisk/sshcerts/blob/new_fido2_authenticator_rs/examples/sign-with-file.rs

You can generate Ed25519 and Ecdsa256 key handles using ssh-keygen -t ed25519-sk and ssh-keygen -t ecdsa-sk

obelisk avatar Mar 15 '22 01:03 obelisk

Hm, it might be not due to the length, but because the old CTAP1/U2F-protocol seems to only support ECDSA256-keys, as far as I can tell. You could try to use the ctap2-2021-branch of this repo, which has FIDO2/CTAP2 support.

msirringhaus avatar Mar 15 '22 09:03 msirringhaus

So I've been trying to get that branch to work but I've been hitting an issue linking against nssckbi. It seems that library (on macOS) is compiled as MH_BUNDLE which you cannot link against, it must be MH_DYLIB.

Have you run into this issue and have a resolution for it? I've tried recompiling that library from source but it still is MH_BUNDLE, obviously Firefox still compiles and exists so there must be something to do but I'm just not sure what.

obelisk avatar Mar 22 '22 01:03 obelisk

This issue also applies to the examples in the ctap2-2021 branch, they do not link because of this dylib issue

obelisk avatar Mar 22 '22 05:03 obelisk

I found using the crypto_openssl works to build :)

obelisk avatar Mar 22 '22 05:03 obelisk

Alright, a lot of experimentation later I've found that I cannot get the Yubikey Bio to be recognized using any CTAP2 settings I could think of in the ctap-2021 branch.

Not sure if I'm doing something wrong as it sees that a compatible device is there, but on registration the device never blinks and the code eventually throws a NotAllowed error.

obelisk avatar Mar 22 '22 06:03 obelisk

sigh Sorry about that! In don't have a mac, so I'm not really sure about the linkage stuff, but yes using openssl-feature is a good workaround. The ctap2-branch is still WIP, and not yet part of Firefox. I was under the impression that mac works, but apparently not. I've been looking in the code now, but l need to find a way (or person) to debug this further. Without the actual hardware, its hard to find out, where things go south.

msirringhaus avatar Mar 22 '22 13:03 msirringhaus

I think the issue with NSS is that it's designed to be loaded at runtime which on macOS is of type MH_BUNDLE. Unlike linux systems, this is different from a dylib and cannot be linked against. So there might be a fundamental incompatibility with the way NSS builds and is expected to be used (on linux both linked against and loaded at runtime) and macOS (where these two concepts are fundamentally incompatible because Apple says so).

obelisk avatar Mar 22 '22 23:03 obelisk

Ok, after hunting down a few people with the proper hardware, I think Mac actually works fine in principle (NSS linking issues aside), so this seems to be a general problem with recognizing the "Yubikey Bio". Could you checkout this fork https://github.com/msirringhaus/authenticator-rs/tree/ctap2-2021 which contains a fix we will probably need, and run

RUST_LOG=trace cargo run --example ctap2 --features crypto_openssl --no-default-features

and after that do

sed -i 's/user_verification: Some(true)/user_verification: None/' examples/ctap2.rs

and run the same example again and send me both logs?

msirringhaus avatar Mar 24 '22 07:03 msirringhaus

It seems the key handles for the Solo 1 USB-A keys are longer than 256 bytes, which was preventing me from logging into GitHub in Firefox (GitHub uses WebAuthn's allowedCredentials property). It looks like the length check is unchanged on the ctap2-2021 branch.

terinjokes avatar Jul 07 '22 22:07 terinjokes

👋🏽 Hey all - thank you @terinjokes for raising this to our attention at GitHub. We're looking at possible workarounds (presumably just not sending allowCredentials in Firefox), but would love to understand if there's a sign of this being fixed on the horizon, so we can have expectations for how long our work needs to be in prod.

hpsin avatar Jul 11 '22 23:07 hpsin

A limit of 256 bytes seems to be correct for CTAP1/U2F (main-branch). From the U2F-spech:

A key handle length byte [1 byte], which specifies the length of the key handle (see below). The value is unsigned (range 0-255).

The protocol itself does not support key handles longer than that, because only 1 byte is reserved for specifying the key handle length.

CTAP2 needs to be backwards compatible, which means has to be able to re-package incoming CTAP2-requests into CTAP1-requests, if the token does not support CTAP2. Here, the same limit applies.

Only if the request is CTAP2 and the token speaks CTAP2, the key handle could indeed be longer. Or at least now the spec is vague about it. It is IMHO rather unfortunate that Solo decides to have longer key handles here. Especially since the token supports both CTAP2 and CTAP1/U2F. I'm even tempted to call this a bug.

But on the ctap2-branch I can have a look at relaxing this rule for CTAP2-requests and maybe simply ignore keys in the list that are longer, if we have to repackage, instead of rejecting the request altogether right away.

msirringhaus avatar Jul 12 '22 07:07 msirringhaus

We at Nitrokey use the same code base as Solokeys and reducing the key handle length's was the first issue we fixed because it didn't work with several services. Definitely we consider this a bug.

jans23 avatar Jul 12 '22 09:07 jans23

I'd have a Solo Key on my account across many services and across many devices for months without issue. I switched to Firefox, and I suddenly couldn't log into GitHub with my Yubikey 5. The page would immediately get a rejected promise with a DOM exception that contained no information of what was wrong.

As an end user, the fact things worked on some websites and not others, and even worked on some platforms (like Android and Windows) and not others was extremely confusing. When coupled with the lack of any user affordances to indicate what was wrong, it made it seem like I was doing something wrong and made me second guess the choice to switch browsers.

These are real keys being added by real end users. The WebAuthn spec says keys IDs can be upto 1023 bytes, so there's no reason GitHub should suspect anything is wrong.

terinjokes avatar Jul 12 '22 15:07 terinjokes

I fully understand. It is, IMHO, yet another very unfortunate thing that the webauthn-spec and the CTAP-spec are two separate specs that are sometimes at odds with each other. As I said, there is sadly no fix possible for the main-branch, but Firefox is trying to hop over to the ctap2-branch soon, and I'll try to make a PR that relaxes the length-checks a bit.

msirringhaus avatar Jul 14 '22 06:07 msirringhaus

See #181

msirringhaus avatar Jul 14 '22 14:07 msirringhaus