What is the "check-only" equivalent in CTAP2?

78 views Asked by At

I am trying to use the libfido2 library (the python3 version, though) and wondering how to deal with multiple devices. The problem being that if there are multiple security keys present I want to find the one that created a certain credential id I know without having to tap on each key or enter a pin to find out which one it is.

According to this blog post in CTAP1 there was a "check-only" flag that you could set in an assertion:

Browsers implement this by sending a series of assertion requests to each security key to see whether any of the credential IDs are valid for them. That’s why there’s a “check only” mode in the assertion request: it causes the security key to report whether the credential ID was recognised without requiring a touch.

Could someone please point me to how this quiet checking can be done with the latest protocol version of CTAP2 and WebAuthN?

1

There are 1 answers

2
Asthor On BEST ANSWER

In theory yes, but there is a lot of factors that can affect this. But shorter answer would be to send an assertion request with up=false, uv=false and no pinUvAuthParam. This would result in the device returning FIDO_ERR_NO_CREDENTIALS when there is no credentials or info on the credential if it exists.

However, there are a lot caveats here. If the device is configured as alwaysUv the device will request user verification. This also requires that either the credential is discoverable or that you have the id of the key in your request. This also requires that the key's credProtect settings are fit with requirements for this. So there is plenty of things that can make this impossible to do.

It should also be noted that WebAuthn's discouraged for UserVerificationRequirement only applies to UV as the User Presence flag in WebAuthn is a constant true boolean flag.

I haven't used the python version of Yubico's libfido2 but have used the CLI tool from Yubico and will exemplify this with that tool.

By creating a key on a Fido 2 device with it through their description from their manpage, man fido2-cred, one can create a credential the following way

$ echo credential challenge | openssl sha256 -binary | base64 > cred_param
$ echo relying party >> cred_param
$ echo user name >> cred_param
$ dd if=/dev/urandom bs=1 count=32 | base64 >> cred_param
$ fido2-cred -M -i cred_param /path/to/usb | fido2-cred -V -o cred 

Following the man page, man fido2-assert, for assertion one can create an assertion for that key. This on having created the cred file from the creation of the credentials in the first code example.

$ echo assertion challenge | openssl sha256 -binary | base64 > assert_param
$ echo relying party >> assert_param
$ head -1 cred >> assert_param
$ tail -n +2 cred > pubkey
$ fido2-assert -G -i assert_param /path/to/usb | fido2-assert -V pubkey es256

The above code example would require a User Presence check by the key as that is default. However changing the last line into just

$ fido2-assert -G -t up=false -i assert_param /path/to/usb

Would remove the UP check and then return either credential information or fido2-assert: fido_dev_get_assert: FIDO_ERR_NO_CREDENTIALS in case no credentials with that ID exists.

Note that I only supplied UP flag to it, as UV flag is in general defaulted as false.