Replies: 1 comment
|
Thanks for sharing this. I have now reviewed the proof of concept, the relevant Passless and I think the central idea is sound, and it would provide a meaningful security improvement over the current Passless TPM backend. The key point is that this is not relying merely on two TPM vendors happening to serialize Your imported parent contains the same private key, public area and storage This differs significantly from what Passless currently does. The present Passless TPM backend generates an ordinary software WebAuthn credential, serializes the complete credential—including its private signing key—encrypts it with AES-GCM and seals the AES key with a device-local TPM object. On authentication, Passless unseals the AES key and reconstructs the complete software credential in process memory. It may also cache that credential. That protects credentials at rest, but it does not make the WebAuthn signing key non-exportable during use. Your design would: newly created signing keys would be generated by the TPM, and Passless would retain only the TPM public/private blobs needed for I also agree with your statement that this cannot be implemented as merely another Passless storage backend. The current limitation is lower in the stack:
We therefore need a credential-crypto provider abstraction in
The default implementation would preserve the existing software ES256 and EdDSA behavior. The TPM implementation would use the stored Passless should retain its existing UHID/CTAP architecture rather than adopting the Firefox interception layer from the proof of concept: That keeps origin processing, There are several areas we would need to design carefully. Parent provisioning and recoveryThe recovery seed is effectively a cloning capability for the portable parent. It does not derive the individual randomly generated credential keys, but anyone with the seed and the synchronized credential blobs can provision another TPM and use them. Provisioning therefore needs:
The seed should not remain on the machine after provisioning. Authorization and active compromiseThe proof of concept uses empty parent and child authorization values and no TPM policy. That is reasonable for a proof of concept, but it means that a process with access to both the blob and the TPM can load and use the key. The architecture prevents private-key extraction; it does not prevent active malware on an enrolled system from requesting signatures. We should investigate whether the equivalent parent can use a per-device local Passless user presence and user verification must remain a separate security boundary. A successful TPM signature is not proof that UP or UV occurred, so the CTAP flags must continue to reflect Passless’s actual notification or PIN flow. Metadata and extensionsThe TPM signing blob protects the signing key, but it does not protect the rest of the credential record. Passless still needs to protect:
One possible approach is to retain hybrid AES-GCM encryption for metadata and seal the metadata key as another portable object under the shared parent. The metadata key may enter host memory, but the WebAuthn signing key would not. Synchronization countersA mutable signature counter is difficult to synchronize correctly across multiple offline machines. Concurrent use or rollback could create repeated or decreasing values that some relying parties interpret as authenticator cloning. Portable credentials should probably use a constant zero counter unless we design a genuinely synchronized monotonic counter. MigrationExisting Passless TPM credentials should not be rewritten silently. For ES256, we could potentially preserve existing registrations by unsealing the legacy private key once and importing it as a TPM signing object under the portable parent. That would preserve the existing public key, although it would not retroactively provide the guarantee that the key had never existed outside hardware. The simpler first release would support the legacy format for existing credentials and use the portable format only for newly registered credentials. Comparison with OS solutionsWindows Hello normally combines device-protected keys with OS-managed PIN or biometric verification. Google Password Manager and Android Credential Manager instead synchronize end-to-end encrypted credentials and authorize new environments using a device screen lock or password-manager PIN. This proposal occupies an interesting middle ground for Linux: synchronized opaque credential blobs, hardware-isolated signing on every enrolled machine and no required cloud credential provider. However, it does not automatically inherit the OS-level UV, account recovery, revocation or anti-rollback mechanisms supplied by those platforms. I have opened a detailed implementation issue covering the The proposed implementation order is:
Thanks again for bringing this up. The proof of concept changes my view of what the TPM backend should ultimately be: instead of using the TPM only to unlock software credentials, Passless should use it as the actual credential signing boundary. |
Uh oh!
There was an error while loading. Please reload this page.
You already flag that software-stored keys are exposed to system compromise. I've been working on a different architecture that gets hardware-backed keys but stays portable, and I thought it might be worth sharing with you.
I have the following idea. Provision each device's TPM with the same deterministic parent key derived from a master seed. Credentials are random signing keys created inside the TPM under that shared parent. The private key never leaves hardware, but the encrypted blob loads on any TPM provisioned with the same seed. A leaked blob is useless without a provisioned TPM, so the blobs are safe to sync however you like.
No Intel SGX or enclave needed. SGX is Intel-only and dead on consumer CPUs, so it's a non-starter for a run-anywhere Linux tool. TPM 2.0 is on basically every modern PC (Windows 11 requires it) and works on AMD and Intel.
To be clear, this isn't a new backend. It completely changes the storage model.
I have a working Firefox + Python implementation:
https://github.com/mimi89999/webauthn_tpm_portable
All reactions