Implement the Touch ID credential picker.
During passwordless authentication, when more than one login is present in
Enclave credentials, `tsh` now asks the end user to pick their desired login.
Credential picker terminal prompts are preceded by a system Touch ID prompt,
which is then reused for authentication, provided less than 10 seconds pass in
the meantime.
I've done a couple of refactors to make the `CredentialInfo` structs similar
between the `webauthncli` and `touchid` packages, so it's easier to trace
parallels between them.
#13901
* Refactor touchid.CredentialInfo
* Refactor wancli.CredentialInfo
* Move fido2_prompt*.go to prompt*.go
* Define the touchid credential picker API
* Add Touch ID credential picker tests
* Implement touchid credential picker
Allow explicit Touch ID prompts to be triggered via Go code, which will be used
to guard the (upcoming) credential picker prompt.
To avoid double-prompting users during Touch ID authentication we have to set a
grace period in the underlying LAContext and share it between the functions.
Note that AuthContextGuard (native) uses the LAContext explicitly, whereas
Authenticate (native) uses it through the SecItemCopyMatching query dictionary.
No UX visible changes are made in the PR, despite the fact that prompting occurs
a bit earlier.
#13901
* Allow explicit Touch ID prompts
Favor newer Touch ID credentials in the allowed set for MFA, or just the newer
credential for passwordless.
Fixes a capture-by-reference bug and adds coverage for it.
Issue #13340.
* Add tests for Touch ID credential-choosing logic
* Favor newer Touch ID credentials within the allowed set
* Warn about origin vs RPID mismatch
Change the Touch ID registration interface so `tsh` explicitly confirms or
rollbacks MFA registrations.
Before resident keys, MFA keys from U2F or WebAuthn only truly existed
server-side, but with resident keys/passwordless some cleanup is necessary if
the server-side registration goes awry.
The PR also changes Touch ID authentication so that newer keys are preferred,
which allows re-registration to be used as sort of a self-healing mechanism.
#9160
* Read creation time from Keychain entries
* Explicitly confirm or rollback Touch ID registrations
Since #12794 we now build `tsh` binaries with touch ID capabilities. This calls
for a more sophisticated mechanism to determine if touch ID functions should be
enabled, as compile-time support only is not enough.
I've added the following checks, on top of compile-time / `touchid` build tag:
Binary is signed
Binary has entitlements
Machine is touch ID capable
Machine has a Secure Enclave
Put together this give us a much better proxy on whether to enable touch ID.
I've also added the `tsh touchid diag` command, mentioned in the Passwordless
macOS RFD (see
https://github.com/gravitational/teleport/blob/master/rfd/0054-passwordless-macos.md#tsh-support-commands).
#9160
* Improved touch ID availability and diagnostics
* Add the `tsh touchid diag` command
* Set min macOS version to 10.12 (macOS Sierra)
Implement touch ID credential management via tsh touchid ls and tsh touchid rm.
Departs slightly from RFD command names in order to better match the tsh mfa.
See https://github.com/gravitational/teleport/blob/master/rfd/0054-passwordless-macos.md.
#9160
* Implement touch ID credential listing
* Add the `tsh touchid ls` command
* Implement touch ID credential deletion
* Add the `tsh touchid rm` command
* Delegate MFA prompts to WebAuthn
* Undo changes to tsh.go command switch
* Prompt newline. Trace errors.
* Update e/ to 6abb96b
* Var initialization. Guard against NULL. Return all credentials.
* Address review comments: simplifications and style
Introduce the touchid package and add the ability to register and login using
Secure Enclave keys.
The code is not yet wired to tsh, plus there are additional parts to come
(listing and deleting keys). This is tricky to properly execute, as the Secure
Enclave requires, at the very least, a signed binary and a provisioning profile
installed. Future PRs will attempt to bridge that gap and provide ways for
Teleport devs to compile and run this locally as well (but not for external
devs, sorry).
I've elected to keep native as simple as I could. Objc uses ARC for memory
management and good old C uses malloc/free, but there are relatively few naked
pointers (many of which are handled by Go with defer-frees). I've kept the
language boundary in plan C, so it's easier to reason about the Go<->C bridge.
The package is protected by the touchid build tag, but a good part of it exists
outside of it - that is in hope that it gets well exercised by CI. In the near
future the build tag will be used as a proxy for good builds (ie, if tagged then
we assume signed, notarized, etc) - this makes releasing safer in the short time,
without us having to code too many safeguards.
#9160
* Implement touch ID registration and login
* Validate raw public key length
* Use string concatenation in place of fmt.Sprintf
* Keep pubKeyFromRawAppleKey calls centered on api.go
* Compare strings using NSString (instead of string.h)
* Break early in params loop. Comments.
* Add license to headers
* Move native var. Non-pointer receiver. C tweaks.
* Use SecCopyErrorMessageString
* Guard against overflows. Release infos without defer.