| Summary: | SSH should skip sk-* keys that don't match the connected security key | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| Product: | Portable OpenSSH | Reporter: | Erik Jensen <businesscorrespondence+openssh> | ||||||
| Component: | ssh | Assignee: | Assigned to nobody <unassigned-bugs> | ||||||
| Status: | NEW --- | ||||||||
| Severity: | minor | CC: | djm | ||||||
| Priority: | P5 | ||||||||
| Version: | 8.8p1 | ||||||||
| Hardware: | amd64 | ||||||||
| OS: | Linux | ||||||||
| Attachments: |
|
||||||||
|
Description
Erik Jensen
2021-11-20 20:03:42 AEDT
There is no way to test whether a given FIDO key handle belongs to a particular token without trying to make a signature using one, so that is what we do. If they key doesn't match the token, then the token should not require a touch to return an error. What tokens are you using? Can you capture a debug log (ssh -vvv ...) Created attachment 3553 [details]
-vvv connection log requiring two touches
Created attachment 3554 [details]
-vvv connection log with patch requiring only one touch
They are both standard YubiKey 5 NFC. I've attached two logs. The first is with plain OpenSSH_8.6p1, which requires two touches. The second is with OpenSSH patched to revert https://anongit.mindrot.org/openssh.git/commit/?id=b969072cc3d62d05cb41bc6d6f3c22c764ed932f, which only requires one touch. Because it's not otherwise obvious from the log output, I added "*** WAITS FOR SK TOUCH HERE ***" lines to the logs at the points where ssh stopped and waited for a touch. As you can see, the patched version still prints out "Confirm user presence for key ECDSA-SK SHA256:…" for both keys, but only *actually* waits for the key associated with the connected token. The unpatched version waits for a touch for both keys. From Pedro, who knows way more about this than me: > Reverting b969072c would break the "uv handled by token" logic implemented in > f3c34df8. (I am including links to both commits at the bottom of this message). > > With f3c34df8, -O verify-required credentials without a corresponding PIN/UV > gesture and a credential unknown to the token (#3366) are indistinguishable to > the middleware: an attempt to sign results in ERR_NO_CREDENTIALS and > SSH_SK_USER_VERIFICATION_REQD is clear. > > Reverting both commits would address #3366 but break builtin UV (f3c34df8). A > best-effort compromise would be to attempt to sign if a) there's only one token; > b) the token supports builtin UV (so we can't tell whether the credential exists > on the token without asking the user to complete UV, i.e. supply a PIN or > perform UV gesture): > > - if (skvcnt == 1) { > + if (skvcnt == 1 && fido_dev_has_uv(skv[0]->dev)) { > > b969072c: https://github.com/openssh/openssh-portable/commit/b969072c > f3c34df8: https://github.com/openssh/openssh-portable/commit/f3c34df8 I've committed a version of this as https://github.com/openssh/openssh-portable/commit/b560120214 but it will only improve matters for biometric keys. I don't think this can be avoidable in the general case. If I'm understanding correctly, shouldn't that be "it will only improve matters for *non-biometric* keys"? If I'm reading Pedro's explanation right, it sounds like the problem for biometric/uv tokens is that there's no way to test whether a credential belongs to the token without requiring a gesture, as attempting to sign an unknown credential and attempting to sign a known credential without a user-verification gesture both fail with the same error, so the only option is to assume the credential might belong to the token and try it with a user-verification gesture. The change in b5601202, then, keeps the logic introduced in b969072c intact for biometric/uv keys: if there is a single token connected, and that token supports on-token user verification, that key will be selected for signing with a uv gesture unconditionally, since there's no way to test whether the credential belongs to the token ahead of time. However, with b5601202, ssh will no longer try to use a single non-biometric, non-uv token unconditionally, as such a token *can* be tested before requiring a user gesture. Instead, sk_select_by_cred will now invoke sk_try for the key, the same as it would if multiple keys were attached, and only return it if that succeeds. (Given this understanding, I think the commit message for b5601202 is incorrect, though the change itself is correct, since it is actually tokens that do *not* support on-token user-verification that are now asked if the credential belongs to them.) In any event, with b5601202 applied to my ssh-agent, I now see my desired behavior with my YubiKey 5s: when only one token is attached, attempting to use the key that doesn't match that token immediately fails, so I only have to touch my token once, even when the matching key is tried second. Thanks! |