danstiner / rust-u2f

U2F security token emulator written in Rust
Apache License 2.0
293 stars 43 forks source link

TPM2 Support #85

Open danstiner opened 2 years ago

danstiner commented 2 years ago

Currently we store keys in the user's keychain, or if that's not available just in a file in their home directory. This is sufficient for many use cases, such as providing a 2nd factor that is phishing resistant. Passwordless login as allowed in the newer FIDO2 specification is different however, it acts as two factors simultaneously, being both something you have (the device storing secret keys) and then either one thing you know (pin based unlock) or one thing you are (biometric unlock).

Security concerns

For passwordless login, some sites may require that secrets cannot be copied to another device in order to have a strong guarantee you are using the exact same device to login that you originally used to register for the site. The only way to reliably accomplish this is to make the secrets not accessible to any software on the computer, and the only way to do that I am aware of is doing the encryption and signing entirely in hardware. This is possible with the newer TPM2 standard and with ARM's secure enclave approach.

The threat model is other software on the computer with access to the user's session stealing private keys. Storing key in a TPM prevents copying them, but such an attacker would likely be able to access the TPM also and ask it to use the secrets to sign whatever it wants. This effectively lets the attacker authenticate as the user whenever they want, as long as access to the user's session is maintained.

To have equivalent security to a real hardware authenticator, we basically would need the same architecture. Namely a TPM or secure enclave that requires a manual unlock for each signing via a special button or biometric scan. As far as I know only Apple's laptops with Touch ID / Face ID have this level of integration. Modern smartphones also have this capability. (Note this changes with FIDO2 which supports PINs)

So to implement this more research would be needed on how to provide meaningful security. Potentially the answer is to wait for new hardware to hit the market with better security hardware. Or to store keys on a smartphone's secure enclave and relay all authentication requests to the phone.

Complexity concerns

A big downside is this adds a lot of complexity to the project. Both inherit complexity of managing keys in a hardware device, and incidental complexity that comes with the complex TPM APIs, needing the TPM to be initialized correctly, and potentially sharing the TPM with other software on the computer.

The most interesting effort to support TPM2 on Linux seems to be https://tpm2-software.github.io/. In theory support is as simple as making sure systemd-abrmd is installed and talk to the tpm device through that using the https://crates.io/crates/tss-esapi library.

Open questions

chrysn commented 2 years ago

incidental complexity that comes with the complex TPM APIs, needing the TPM to be initialized correctly, and potentially sharing the TPM with other software on the computer.

Given that having this would be beneficial to other users of the secret service, maybe it'd be worth bringing the issue to their attention, or to the attention of one of the implementations that might do pioneer work. If gnome keyring were to gain the capacity to store SSH keys in a TPM, rust-u2f could use that infrastructure for sharing the TPM.

(I might have a use case in a completely different area, which doesn't have the workforce behind it to drive it either, but I'm slowly starting to gather momentum).

NWater23 commented 6 months ago

There is already a Go-based implementation: psanford/tpm-fido

I'm not sure if this is exactly what you want. But it shows a way to communicate with a TPM device.