Yubico / Yubico.NET.SDK

A YubiKey SDK for .NET developers
Apache License 2.0
96 stars 48 forks source link

Clarify how PIV authentication works with TTLVs/auth challenge #39

Closed MarcusGrass closed 1 year ago

MarcusGrass commented 1 year ago

I'm writing a tiny raw lib to interface with a Yubikey and have been using the User's Manual to try to figure out how it works.

I'm using the raw USB interface to send messages, using the CCID protocol guide and sending apdus according to the docs. They're really good in general with a few bits missing, for example Put data I could provide some examples in those docs as soon as I figure that out.

To the problem at hand:

I'm trying to use Authenticate: Sign. The docs could be a bit clearer about the message being 3 TTLVs DynAuth(AuthResponse, AuthChallenge) and what to expect when you send that message.

When that is sent, and I request a bulk data transfer through the USB driver on the in-endpoint, I'm pulsed by empty responses. This is because my key is expecting touch, so I'm polling for responses through the driver, but when I touch the key I get an sw1=0x69, sw2=0x82 back, indicating wrong pin or no-touch. Before starting the auth sign I verify the pin, and the key returns a success so the pin shouldn't be the issue. It's like the key is expecting something more from the program after the touch happens but I can't quite figure out what. I have the touch policy 'Cached' on at the moment. If I then try running the sign again it immediately fails, again with sw1=0x69, sw2=0x82.

The APDU that I'm sending is below. The content is just the first 48 bytes of a random sha384 encoded string. 0, 87, 14, 9A, 36, 7C, 34, 82, 0, 81, 30, 66, 36, 34, 66, 32, 31, 61, 36, 36, 36, 62, 34, 34, 64, 36, 39, 36, 61, 32, 65, 66, 35, 34, 34, 66, 37, 61, 37, 64, 31, 38, 36, 64, 65, 35, 34, 37, 32, 66, 66, 32, 38, 64, 37, 32, 31, 33, 32.
The payload is identical to the one used in the example at auth sign 7C 34 82 00 81 30 <48-byte digest>.
Any pointers to what I need to do would be much appreciated!

GregDomzalski commented 1 year ago

What version of the SDK are you using? There was a subtle bug that was recently fixed that can cause some odd behavior around touch.

Are you using the IYubiKeyConnection.SendCommand() method to send the command?

If I recall correctly, the expected behavior of the PIV commands w/ touch is:

The bug in the SDK was around not respecting the YubiKey's reclaim timeout. Since the YubiKey exposes three different USB devices, but is a single threaded device, it requires a little bit of time to switch between active interfaces. Around 3 seconds, to be more precise. The SDK will talk to at least 2 of the 3 interfaces while enumerating keys which will then cause this timeout to be important. Previously the SDK was not waiting for the 3 seconds before sending the first command. Now it should.

If you (or the SDK) don't wait for this reclaim timeout - then the behavior looks something like this:

I am curious to see if this is indeed what is happening. However if you are running the latest version of the SDK, this should be resolved...

I look forward to your reply.

MarcusGrass commented 1 year ago

Thank you for the response. I realized today that I had misunderstood how PIN authentication works, touch works as expected, but the pin was "wrong" and that's the cause of the 0x6982. I have pin always toggled, and didn't realize that verify-pin has to be the command sent immediately before the authenticate-sign for it to work. I had done a get slot metadata in between verifying and authenticating, and that's why it bounced me. Maybe that's stated somewhere in the docs and I missed it, otherwise it'd be a good add.

I'll close this since it's solved.

Ps. I put this issue in the completely wrong place, sorry about that