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

systemd-cryptenroll not requesting a PIN when enrolling a token using fido2-with-client-pin #31443

Open
BryanJacobs opened this issue Feb 22, 2024 · 3 comments
Labels
bug 🐛 Programming errors, that need preferential fixing cryptsetup

Comments

@BryanJacobs
Copy link
Contributor

systemd version the issue has been seen with

255.3-1-arch

Used distribution

Arch

Linux kernel version used

6.6.17-1-lts

CPU architectures issue was seen on

x86_64

Component

systemd-cryptsetup

Expected behaviour you didn't see

When enrolling a token with the --fido2-with-client-pin=yes option, systemd-cryptenroll must ask for the token PIN, but it does not.

The reason it needs to ask for the token PIN is because the way the CTAP2.1 hmac-secret extension is defined, the key used inside the authenticator is different depending on whether user verification was performed (such as by a client PIN). So if the device is to be unlocked with a client PIN, it also needs to be locked with a client PIN.

Unexpected behaviour you saw

Because of the above, unlocking the volume fails - and tries twice, prompting for the PIN each time!

Debug output:

Verifying key from keyslot 2, digest 0.                                                                  
Digest 0 (pbkdf2) verify failed with -1.

The keyslot is actually locked using the authenticator's no-client-PIN key, despite what was requested.

Steps to reproduce the problem

  1. Use a CTAP2.1 compliant authenticator that supports hmac-secret in the CTAP2.1 way (not CTAP2.0)
  2. systemd-cryptenroll --fido2-device=auto --fido2-with-client-pin=yes --fido2-with-user-verification=no --fido2-with-user-presence=no
  3. Observe no PIN requested, although one should have been
  4. Attempt to unlock the device
  5. Observe failure

Additional program output to the terminal or log subsystem illustrating the issue

No response

@BryanJacobs BryanJacobs added the bug 🐛 Programming errors, that need preferential fixing label Feb 22, 2024
@BryanJacobs
Copy link
Contributor Author

Relevant sections from https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-hmac-secret-extension :

The authenticator chooses which CredRandom to use for next step based on whether user verification was done or not in above steps.

    If uv bit is set to 1 in the response, let CredRandom be CredRandomWithUV.

    If uv bit is set to 0 in the response, let CredRandom be CredRandomWithoutUV.

and from the getAssertion section:

    If pinUvAuthParam parameter is present (implying the "uv" option is treated as false, see Step 4):

        Call verify(pinUvAuthToken, clientDataHash pinUvAuthParam).

            If the verification returns error, return CTAP2_ERR_PIN_AUTH_INVALID error.

            If the verification returns success, set the "uv" bit to true in the response.

In other words, if a pinUvAuthParam is passed to getAssertion (in even simpler terms, if a client PIN is used for getting the assertion), the uv bit will be true in the response. And if the uv bit is true in the response, the key for that is used.

The authenticator has two keys per credential, key A and key B. Using the client PIN or a built-in UV method (EITHER!) gets key A. Using neither gets key B.

@BryanJacobs
Copy link
Contributor Author

Note: you can work around this issue and make the unlock succeed by enabling the alwaysUv FIDO2 feature prior to enrollment. If you do this, the authenticator reject's systemd's attempt to enroll without a PIN, and so the correct key is used for the enrollment (the one for the client PIN...) and the unlock will later succeed.

@BryanJacobs
Copy link
Contributor Author

One more comment: I'd recommend sending the credProtect extension with the value 3 if the user asks to require a client PIN. That way the authenticator will (if it supports credProtect...) respond appropriately and reject requests failing to use the PIN, instead of the current behavior of silently using the wrong/unexpected key.

yuwata pushed a commit that referenced this issue Apr 17, 2024
When enrolling a new FIDO2 token with a client PIN, this tells the authenticator to require the PIN on all uses.

It also collects a PIN before attempting to create a credential.

Works around #31443 in most (not all) scenarios.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Programming errors, that need preferential fixing cryptsetup
Development

No branches or pull requests

1 participant