Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fido2: user verification switch "-v" causes fido2-cred to return FIDO_ERR_UNSUPPORTED_OPTION when device has no biometric function #571

Closed
GaelC92 opened this issue Jun 3, 2021 · 23 comments
Assignees
Labels

Comments

@GaelC92
Copy link

GaelC92 commented Jun 3, 2021

default compilation results in the output below, with reported error 'FIDO_ERR_UNSUPPORTED_OPTION'

$ gocryptfs -init -d -fido2="IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/XHC1@14/XHC1@14000000/HS05@14200000/YubiKey OTP+FIDO+CCID@14200000/IOUSBHostInterface@1/AppleUserUSBHostHIDDevice" foo.gocryptfs
OpenSSL disabled, using Go GCM
FIDO2 Register: interact with your device ...
callFidoCommand: executing "/usr/local/bin/fido2-cred" with args [fido2-cred -M -h -v IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/XHC1@14/XHC1@14000000/HS05@14200000/YubiKey OTP+FIDO+CCID@14200000/IOUSBHostInterface@1/AppleUserUSBHostHIDDevice]
fido2-cred: fido_dev_make_cred: FIDO_ERR_UNSUPPORTED_OPTION
fido2-cred failed with exit status 1

calling the reported command line shows that the space in the device string is the troublemaker [Edit : wrong assumption. -v was the root cause]
$ fido2-cred -M -h -v IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/XHC1@14/XHC1@14000000/HS05@14200000/YubiKey OTP+FIDO+CCID@14200000/IOUSBHostInterface@1/AppleUserUSBHostHIDDevice
fido2-cred: unknown type OTP+FIDO+CCID@14200000/IOUSBHostInterface@1/AppleUserUSBHostHIDDevice

I added the patch below to the brew formula in order to have the space escaped :

inreplace "./internal/fido2/fido2.go",
          " device)",
          ' fmt.Sprintf("%s",strings.ReplaceAll(device," ","\\\\\\\\ ")))'

results after the patch : the space is now escaped, and the reported error changed to 'FIDO_ERR_INTERNAL'

$ gocryptfs -init -d -fido2="IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/XHC1@14/XHC1@14000000/HS05@14200000/YubiKey OTP+FIDO+CCID@14200000/IOUSBHostInterface@1/AppleUserUSBHostHIDDevice" foo.gocryptfs
OpenSSL disabled, using Go GCM
FIDO2 Register: interact with your device ...
callFidoCommand: executing "/usr/local/bin/fido2-cred" with args [fido2-cred -M -h -v IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/XHC1@14/XHC1@14000000/HS05@14200000/YubiKey\ OTP+FIDO+CCID@14200000/IOUSBHostInterface@1/AppleUserUSBHostHIDDevice]
fido2-cred: fido_dev_open IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/XHC1@14/XHC1@14000000/HS05@14200000/YubiKey\ OTP+FIDO+CCID@14200000/IOUSBHostInterface@1/AppleUserUSBHostHIDDevice: FIDO_ERR_INTERNAL
fido2-cred failed with exit status 1

invoking fido2-creds with the latest reported command line does not report any error. I'm still investigating to find what goes wrong.

@GaelC92 GaelC92 changed the title The device string on Mac OS may contain spaces The device string on Mac OS may contain spaces not handled properly Jun 3, 2021
@GaelC92 GaelC92 changed the title The device string on Mac OS may contain spaces not handled properly The device string on Mac OS may contain spaces which appear not to be handled properly Jun 3, 2021
rfjakob added a commit that referenced this issue Jun 3, 2021
Tested using

  gocryptfs -init -debug -fido2 "hello world" cipherdir

Output before:

  callFidoCommand: executing "/usr/bin/fido2-cred" with args [fido2-cred -M -h -v hello world]

After:

  callFidoCommand: executing "/usr/bin/fido2-cred" with args ["fido2-cred" "-M" "-h" "-v" "hello world"]

Related: #571
@rfjakob rfjakob changed the title The device string on Mac OS may contain spaces which appear not to be handled properly fido2: The device string on Mac OS may contain spaces which appear not to be handled properly Jun 3, 2021
@rfjakob
Copy link
Owner

rfjakob commented Jun 3, 2021

Hi, gocryptfs actually runs

fido2-cred -M -h -v "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/XHC1@14/XHC1@14000000/HS05@14200000/YubiKey OTP+FIDO+CCID@14200000/IOUSBHostInterface@1/AppleUserUSBHostHIDDevice"

can you check what you get when you run this in the shell?

I have updated the debug output to show that in 015cd06 .

@GaelC92
Copy link
Author

GaelC92 commented Jun 5, 2021

Hi, here is the debug output (this is the head code) :

gocryptfs -init -d -fido2="IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/XHC1@14/XHC1@14000000/HS05@14200000/YubiKey OTP+FIDO+CCID@14200000/IOUSBHostInterface@1/AppleUserUSBHostHIDDevice" foo.gocryptfs
OpenSSL disabled, using Go GCM
FIDO2 Register: interact with your device ...
callFidoCommand: executing "/usr/local/bin/fido2-cred" with args ["fido2-cred" "-M" "-h" "-v" "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/XHC1@14/XHC1@14000000/HS05@14200000/YubiKey OTP+FIDO+CCID@14200000/IOUSBHostInterface@1/AppleUserUSBHostHIDDevice"]
fido2-cred: fido_dev_make_cred: FIDO_ERR_UNSUPPORTED_OPTION
fido2-cred failed with exit status 1

gocryptfs --version
gocryptfs [unknown]; go-fuse v2.1.1-0.20210508151621-62c5aa1919a7; 2021-06-05 go1.16.4 darwin/amd64

@GaelC92
Copy link
Author

GaelC92 commented Jun 5, 2021

When run in the shell, the command fido2-cred -M -h -v "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/XHC1@14/XHC1@14000000/HS05@14200000/YubiKey OTP+FIDO+CCID@14200000/IOUSBHostInterface@1/AppleUserUSBHostHIDDevice" there is no reported error, although the call would need input and output files, so it just stays there waiting.

I wonder if the following thread systemd/systemd#17784 is not related to the problem, since I use a yubikey 5 NFC, and the -v switch is requested

I checked that the fido2 lib works properly by following the example of the fido2-cred man page :
$ 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 "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/XHC1@14/XHC1@14000000/HS05@14200000/YubiKey OTP+FIDO+CCID@14200000/IOUSBHostInterface@1/AppleUserUSBHostHIDDevice" | fido2-cred -V -o cred

@GaelC92
Copy link
Author

GaelC92 commented Jun 5, 2021

Ok, I confirm that removing the "-v" switch is enough to make it work.

for those that may be insterested in working around this, I added the following block to the brew formula :

inreplace "./internal/fido2/fido2.go",
          ' "-v",',
          ''

@GaelC92 GaelC92 changed the title fido2: The device string on Mac OS may contain spaces which appear not to be handled properly fido2: user verification switch "-v" causes fido2-cred to return FIDO_ERR_UNSUPPORTED_OPTION Jun 5, 2021
@rfjakob rfjakob added the macOS Apple macOS ("darwin") specific issue label Jun 6, 2021
@rfjakob
Copy link
Owner

rfjakob commented Jun 6, 2021

From man fido2-cred:

     -v      If making a credential, request user verification.  If verifying a credential, check
             whether the user verification bit was signed by the authenticator.

This looks kinda important :)

Why doesn't your fido2-cred have this option? Maybe an older version? I have fido2-tools-1.6.0-2.fc34.x86_64 here.

@GaelC92
Copy link
Author

GaelC92 commented Jun 6, 2021

my libfido2 is 1.7.0.

On my Yubikey 5, removing the -v switch from the command line does NOT bypass the need to touch the yubikey in order to decrypt.

However, I can't tell if -v is required for biometric devices, since I have none.

Below, I quote some excerpts from the link I mentioned above, which explain the reason for the error. Basically it's because user verification (-v switch) is related to biometry functions, which are not necessarily present :

"The unsupported option in this case is likely UV, which is set to false in https://github.com/systemd/systemd/blob/master/src/home/homectl-fido2.c#L253. YubiKeys do not support UV, only PIN. Older YubiKeys ignore the UV parameter. Newer YubiKeys return FIDO_ERR_UNSUPPORTED_OPTION if UV is set to anything other than FIDO_OPT_OMIT, since that is the normative behaviour defined in the CTAP2 spec."

(...)

"clientPin and uv are separate options in CTAP2 (second table). clientPin is defined as "the device is capable of accepting a PIN from the client". uv is defined as "the device is capable of verifying the user within itself. For example, devices with UI, biometrics fall into this category". Both achieve the same thing: when creating a credential, the UV bit is set in the signed data returned by the authenticator.

The spec defines the steps an authenticator is expected to follow when creating a credential. Step 3 reads:

If the options parameter is present, process all the options. If the option is known but not supported, terminate this procedure and return CTAP2_ERR_UNSUPPORTED_OPTION. If the option is known but not valid for this command, terminate this procedure and return CTAP2_ERR_INVALID_OPTION. Ignore any options that are not understood. Note that because this specification defines normative behaviors for them, all authenticators MUST understand the "rk", "up", and "uv" options.
which is why newer YubiKeys return FIDO_ERR_UNSUPPORTED_OPTION if uv is set to either true (explicitly enabled) or false (explicitly disabled)."

[EDIT] : re-reading this, it appears that specifying -v might be needed when calling libfido2 with a biometry-providing authentication device, but should not be used otherwise. If that is the case, then the use of "user verification" (in the strict meaning explained above) should probably become a cli option of gocryptfs.

[EDIT 2] : a call to "fido2-token -I " (uppercase i) could also be used to check device capabilities and construct the args list accordingly before calling fido2-cred"

@rfjakob
Copy link
Owner

rfjakob commented Jun 17, 2021

@prusnak what do you think, can we drop the "-v" flag to fido2-cred ?

@prusnak
Copy link
Contributor

prusnak commented Jun 17, 2021

I think this is a bug in Yubikey and or libfido2 interaction with Yubikey. I'd keep -v because we want to verify user's presence.

@GaelC92
Copy link
Author

GaelC92 commented Jun 17, 2021

@rfjakob @prusnak : have you read my latest message ?

-v should be used for biometry-capable tokens.
it should however not be used with non-biometric capable tokens.

this is not a yubikey bug, libfido2 appears to have been deliberately changed to adhere to the standard : when no biometry is available, then there is no mean to check user's presence (anybody could press the button, or even enter the pin)

so the proper behaviour would be to check if the device is biometric, and if not call fido2-cred without -v, if yes, call it with.

@GaelC92 GaelC92 changed the title fido2: user verification switch "-v" causes fido2-cred to return FIDO_ERR_UNSUPPORTED_OPTION fido2: user verification switch "-v" causes fido2-cred to return FIDO_ERR_UNSUPPORTED_OPTION when device has no biometric function Jun 17, 2021
@GaelC92
Copy link
Author

GaelC92 commented Jun 17, 2021

@rfjakob @prusnak – I have updated my previous message for clarity.

@rfjakob
Copy link
Owner

rfjakob commented Jun 27, 2021

So about auto-detecting what to do using fido2-token -I: My Trezor Model T gives this:

$ fido2-token -I /dev/hidraw1 
proto: 0x02
major: 0x02
minor: 0x00
build: 0x00
caps: 0x04 (nowink, cbor, msg)
version strings: U2F_V2, FIDO_2_0
extension strings: hmac-secret
aaguid: d6d0bdc362eec4dbde8d7a656e4a4487
options: rk, up, uv
maxmsgsiz: 0
maxcredcntlst: 10
maxcredlen: 1024
fwversion: 0x0
pin protocols: 1
pin retries: undefined
uv retries: undefined

What does the Yubikey give you?

@GaelC92
Copy link
Author

GaelC92 commented Jun 27, 2021

Hello Jakob

see below : no "uv" option.

fido2-token -I "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/XHC1@14/XHC1@14000000/HS05@14200000/YubiKey OTP+FIDO+CCID@14200000/IOUSBHostInterface@1/AppleUserUSBHostHIDDevice"
proto: 0x02
major: 0x05
minor: 0x02
build: 0x06
caps: 0x05 (wink, cbor, msg)
version strings: U2F_V2, FIDO_2_0, FIDO_2_1_PRE
extension strings: credProtect, hmac-secret
aaguid: 2fc0579f811347eab116bb5a8db9202a
options: rk, up, noplat, noclientPin, credentialMgmtPreview
maxmsgsiz: 1200
maxcredcntlst: 8
maxcredlen: 128
fwversion: 0x0
pin protocols: 1
pin retries: undefined
uv retries: undefined

@rfjakob
Copy link
Owner

rfjakob commented Jun 27, 2021

Thanks!

Looking at the table https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#makecred-option-key we see that up = user presence, and uv = user verification with PIN or Fingerprint.

Yubikey does not have a touchscreen or keyboard so cannot do PIN I guess.

With the Trezor Model T, it prompts for PIN on the touchscreen. Without -v, it requests yes/no confirmation but no PIN.

rfjakob added a commit that referenced this issue Jun 27, 2021
@rfjakob
Copy link
Owner

rfjakob commented Jun 27, 2021

I dropped -v, things still work fine with the Trezor Model T, and as reported by @GaelC92, it should also work with Yubikey now. Please speak up if still broken :)

Thanks!

@rfjakob rfjakob added bug and removed macOS Apple macOS ("darwin") specific issue bug outside gocryptfs labels Jun 27, 2021
@GaelC92
Copy link
Author

GaelC92 commented Jun 27, 2021

thanks ;)

@JokerQyou
Copy link
Contributor

JokerQyou commented Jul 28, 2021

I just tried building from master branch but this issue persists:

$ ./gocryptfs -debug -fido2 'IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/XHC@14/XHC@14000000/HS01@14100000/YubiKey OTP+FIDO+CCID@14100000/IOUSBHostInterface@1/AppleUserUSBHostHIDDevice' -init test
cli args: ["./gocryptfs" "-debug" "-fido2" "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/XHC@14/XHC@14000000/HS01@14100000/YubiKey OTP+FIDO+CCID@14100000/IOUSBHostInterface@1/AppleUserUSBHostHIDDevice" "-init" "test"]
FIDO2 Register: interact with your device ...
callFidoCommand cred: executing "/usr/local/bin/fido2-cred" with args ["fido2-cred" "-M" "-h" "-v" "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/XHC@14/XHC@14000000/HS01@14100000/YubiKey OTP+FIDO+CCID@14100000/IOUSBHostInterface@1/AppleUserUSBHostHIDDevice"]
fido2-cred: fido_dev_make_cred: FIDO_ERR_UNSUPPORTED_OPTION
fido2-cred failed with exit status 1
$ ./gocryptfs --version
gocryptfs v2.0.1-31-g2a9d70d without_openssl; go-fuse v2.1.1-0.20210611132105-24a1dfe6b4f8; 2021-07-28 go1.15.7 darwin/amd64

The error was triggered when gocryptfs executes fido2-cred, but the commit I referenced only removed -v from fido2-assert. Am I missing something here?

@rfjakob
Copy link
Owner

rfjakob commented Jul 28, 2021

Looks like I missed something here

@rfjakob rfjakob reopened this Jul 28, 2021
@rfjakob rfjakob self-assigned this Jul 28, 2021
@rfjakob
Copy link
Owner

rfjakob commented Jul 29, 2021

Commit e83b79b should fix this.

Could you confirm? MacOS Intel binary: gocryptfs.e83b79b.gz

@JokerQyou
Copy link
Contributor

I tested both init and mount, works fine now.

@prusnak
Copy link
Contributor

prusnak commented Jul 29, 2021

@rfjakob Have you tested the change with Trezor Model T?

@rfjakob
Copy link
Owner

rfjakob commented Jul 29, 2021

Yes, trezor model t works

@nickray
Copy link

nickray commented Aug 30, 2022

A bit late to the party, but:

  • compliant FIDO2 devices must always check user presence (e.g. touch the device, or "tap" over NFC - some kind of physical signal of user intent)
  • the -v flag means set the "uv" bit, which (cf. CTAP2 spec) means "user verification: Indicates that the device is capable of verifying the user within itself. For example, devices with UI, biometrics fall into this category." This is for credential creation; the CLI tools are a bit inconsistent about this.

This "user verification" is AFAIK only implemented in biometric devices, and not the same as the device's PIN (if set).

It would be nice for remote use cases to be able to require a credential with a PIN, so one could use a (non-compliant) silent authenticator (i.e. which doesn't check user presence) to store the secret, but remotely unlock a directory by typing the PIN (e.g. with systemd-ask-password).

@IzzySoft
Copy link

IzzySoft commented Sep 1, 2022

It seems that if a PIN is set, it does not work (using the currently latest version, i.e. v2.3):

$ gocryptfs -debug -fido2 '/dev/hidraw2' -init cipher
cli args: ["gocryptfs" "-debug" "-fido2" "/dev/hidraw2" "-init" "cipher"]
FIDO2 Register: interact with your device ...
callFidoCommand cred: executing "/usr/bin/fido2-cred" with args ["fido2-cred" "-M" "-h" "/dev/hidraw2"]
Enter PIN for /dev/hidraw2: 
fido2-cred: fido_dev_make_cred: FIDO_ERR_AUTH_BLOCKED

As you can see I'm asked for a PIN. Whatever I try, it fails as shown: Tapping the Yubikey as requested immediately brings the above result, entering the PIN and hitting ENTER as well, and the same if I enter the PIN and then tap the Yubikey. Could it be that my Yubikey is too old? Looks to be a bit older than Gael's:

$ fido2-token -L
/dev/hidraw2: vendor=0x1050, product=0x0407 (Yubico YubiKey OTP+FIDO+CCID)

$ fido2-token -I /dev/hidraw2
proto: 0x02
major: 0x05
minor: 0x01
build: 0x02
caps: 0x05 (wink, cbor, msg)
version strings: U2F_V2, FIDO_2_0
extension strings: hmac-secret
aaguid: fa2b99dc9e3942578f924a30d23c4118
options: rk, up, noplat, clientPin
maxmsgsiz: 1200
pin protocols: 1
pin retries: 5

OS is Linux Mint 20.3 in case it's relevant. As pin_retries was never decreased, it should be the correct PIN I've entered 😉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants