Token bytearray is 64 bytes whereas only 16 or 32 are allowed
Hi
I am experimenting with this library to prepare FIDO2 security keys with pin, admin provisioning with Entra ID credentials etc. It works very well and quite easy when using YubiKeys.
It sounds as if it should work generally with FIDO2 keys, and not only YubiKeys.
However, if I try to manage a HID Crescendo Enabled card with it, I get an error saying: PIN/UV token must be 16 or 32 bytes when calling client.make_credential.
I do not know the protocols, but when I Google it, I seem to find that this is according to specification.
If I modify pin.py, and in the methodPinProtocolV1:validate_token print the length of the token it says 64.
And if I also modify it to allow a length of 64 it works also with the HID Crescendo Enabled card...
Is it this security key not being compliant with the specification? Or could it be some conversion going wrong somewhere in the class?, it seems as if YubiKeys use PinProtocolV2 instead.
Device: HID Crescendo Enabled Aaguid: 54d9fee8-e621-4291-8b18-7157b99c5bec NFC reader: Omnikey 5022 CL OS: Windows 11 24H2 Python: v3.12.4 Fido2: v1.2.0
~I'm not entirely sure where the check for 16 or 32 came from, it might be that this was in an earlier version of the spec (perhaps a draft). Anyway, you're absolutely right that the spec now allows for any multiple of 16 for the PIN token length for V1, so we'll fix this in the next version of python-fido2!~
EDIT: Sorry! I haven't had my coffee yet! I misread both your message and the spec. Please disregard this message, and I will follow up with another one once I've regained my mental capacities...
It looks like you're correct in that the device seems to be non-compliant. The portion of the spec you've linked to does indeed state that for PIN protocol V1 the PIN token must be exactly 16 or 32 bytes long, so a value that is 64 bytes long is not compliant.
This library supports both PIN protocols V1 and V2, and will use the first supported version that the authenticator presents in a call to getInfo. If the authenticator also support V2 then you can explicitly select V2 from the calling code rather than let the library negotiate a version, but that assumes both that the authenticator supports it, and that the PIN token returned is valid (V2 requires the token be exactly 16 bytes).