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
libfido2-util: fix a regression in the pre-flight mechanism #32515
Conversation
Important An -rc1 tag has been created and a release is being prepared, so please note that PRs introducing new features and APIs will be held back until the new version has been released. |
cc @BryanJacobs |
If you want to discover tokens without requiring a PIN (knowing that to use that token later the PIN will be required), then using credProtect level 2 is appropriate. Doing this would make possible (again) the problem from the other ticket though: if the token is created without a PIN then the disk will be encrypted using the "wrong" secret, and decryption will fail. Is systemd-homed using the hmac-secret extension the same as systemd-cryptenroll? If so, it might be better to change the path to prompt the user for their PIN if the home directory was set up with a credential requiring a PIN... |
My understanding of the state of things if this PR is merged:
Seems generally okay, but I think the ideal solution would be to track whether a certain credential requires UV for usage, and if so, also require UV for discovery. That's one user interaction in the case the correct credential is present, and unlike the other proposed solutions, it works in every case (including alwaysUv authenticators). |
Then I guess we could use the credProtect extension only when using UV, but not when using a PIN without UV. This wouldn't break the pre-flight, as it explicitly doesn't support UV: systemd/src/shared/libfido2-util.c Lines 321 to 330 in eb1ec9c
So then instead of completely removing credProtect support, we could just do something like this: int extensions = FIDO_EXT_HMAC_SECRET;
if (FLAGS_SET(lock_with, FIDO2ENROLL_UV)) {
/* Attempt to use the "cred protect" extension, requiring user verification (UV) for this
* credential. If the authenticator doesn't support the extension, it will be ignored. */
extensions |= FIDO_EXT_CRED_PROTECT;
r = sym_fido_cred_set_prot(c, FIDO_CRED_PROT_UV_REQUIRED);
if (r != FIDO_OK)
log_warning("Failed to set protection level on FIDO2 credential, ignoring: %s", sym_fido_strerr(r));
} What do you think? |
I think it might be worth testing how systemd-homed behaves when attempting to use it with a token that has What you've proposed above is better in my opinion than entirely removing the use of credProtect, but I think there's still an underlying issue - the current code assumes that credentials requiring UV to use can always be discovered without user interaction. That assumption isn't true, by design. First, some authenticators have alwaysUv=true. Second, some authenticators have makeCredUvNotRequired=false. I still think it's better to check if any of the credentials to be used will require PIN/UV, and if they will, prompt for the PIN (or touch, or whatever) - and thus authenticator selection - prior to trying "discovery". But that's more work, and at least it's not broken for everybody if you only use credProtect for non-PIN UV, so still an improvement. |
I unfortunately don't own any FIDO2 tokens with proper UV, so I can't test this properly, but I guess the best solution for this problem would be to parse the make credential response and if
The pre-flight exits early, returning
I guess that's the problem that pre-flights solved. If the user has multiple FIDO2 tokens plugged in, they don't have to enter the PIN for each one of them to find the right one. |
No,
That's not great.
You can check all the ones that definitely don't have a PIN at once :-P. But yes, sorry, there is no way to get that convenience reliably that I see. |
Here's a crazy idea - what about using the CTAP2.1 authenticatorSelection command when available to find the right authenticator? As users get rid of older non-2.1 tokens, the hassle would go away. |
I don't think we should be modifying the
Would this work for non-resident keys that we use? Sorry, but I'm still learning about FIDO2 and CTAP. systemd/src/shared/libfido2-util.c Lines 822 to 827 in eb1ec9c
|
Not what I was suggesting. I'm pointing out that when creating the home directory it can be not-set, and when trying to unlock the home directory it can be set. The user could have turned it on in the intervening time. If at any point systemd relies on a user-verification-less discovery mechanism, then the user will be locked out. Also, authenticators can support turning on alwaysUv and not-support disabling it: it's valid to have the transition be one-way unless a reset is performed.
authenticatorSelection doesn't have anything to do with the credentials. It makes all the tokens flash/whatever, and the user explicitly chooses the one they want to use. |
The recently merged PR systemd#32295 introduced support for the credProtect extension, but in doing so, it broke the discoverability of credentials by setting the policy to FIDO_CRED_PROT_UV_REQUIRED for UV-less, PIN-protected credentials. This policy would require us to pass the PIN to the token in the pre-flight request to be able to discover it, which defeats the purpose of pre-flight requests as they're supposed to be non-interactive. This commit restricts the usage of credProtect to UV credentials only.
ccf621c
to
cbe3d52
Compare
Good points, but I think we should create separate RFEs for those issues and resolve the issue at hand in this PR. /please-review |
Agreed! |
The recently merged PR #32295 introduced support for the credProtect extension, but in doing so, it broke the discoverability of credentials by setting the policy to
FIDO_CRED_PROT_UV_REQUIRED
. This policy would require us to pass the PIN to the token in the pre-flight request to be able to discover it, which defeats the purpose of pre-flight requests as they're supposed to be non-interactive.Instead of completely removing credProtect support, we could just relax the policy to
FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID
, but I decided against that for two reasons:This issue would still occur for an edge case described in the CTAP 2.1 specification.
FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID
policy seems to be useful only for resident keys, because you always have to pass the credential ID anyway for non-resident keys, so this policy would always be fulfilled, as we use non-resident keys.I stumbled upon this issue while trying to create a user's home directory with a FIDO2 token using homectl, systemd-homed and systemd-homework from the tip of the main branch.
Snippet from systemd-homed's journal (running with
SYSTEMD_LOG_LEVEL=debug
)