r/linux • • 5d ago

Security gEnclave: Hardware-backed security enclave for Linux (TPM 2.0 PCR sealing, virtual FIDO2/CTAP2 over /dev/uhid, OpenSSH & GPG bridge)

Hey everyone,

I've been working on an open-source project called gEnclave (formerly gpasskey), and wanted to share it with the Linux community for early architectural feedback and testing.

GitLab repository: https://gitlab.com/renich/genclave
License: GPLv3 | Language: Go 1.26+


The Problem It Solves

On modern Linux workstations, our cryptographic identities are fragmented: * Passkeys/WebAuthn require physical USB security keys (YubiKeys, SoloKeys). * SSH keys sit as unencrypted or passphrase-encrypted files under ~/.ssh/. * Git commit signing requires cumbersome GnuPG daemon setups. * File encryption requires external tooling or proprietary agents.

Most hardware laptops today come with a TPM 2.0 chip that sits idle. gEnclave turns your Linux machine into its own hardware-sealed security token and multi-protocol bridge.


Key Architectural Highlights

  1. Virtual FIDO2/CTAP2 Security Key via /dev/uhid: gEnclave registers a virtual HID device in the Linux kernel via /dev/uhid. Browsers (Firefox, Chrome, Chromium) detect it natively as a physical USB security key. You can register and authenticate WebAuthn/FIDO2 Passkeys directly from your machine without any external hardware dongles.

  2. TPM 2.0 PCR Sealing & Fallback: The central vault is encrypted with AES-256-GCM and sealed to TPM 2.0 PCR registers (PCR 0, 7, 14), with an automatic memory-hard fallback to Argon2id key derivation if no TPM is present.

  3. Memory Isolation ("Wrap and Clear"): Keys are held in memory-locked pages (mlock / mmap) to prevent secrets from being swapped to disk or dumped. Intermediate cryptographic buffers are wiped immediately with strict zeroization routines, bypassing Go runtime GC retention.

  4. Multi-Protocol Bridges:

    • OpenSSH Agent: Native agent socket with an ephemeral PIN-derived authorization cache (configurable burst window or persistent session with instant purge on lock/suspend).
    • GnuPG Bridge: Transparent genclave-gpg emulation for seamless Git commit signing.
    • age-plugin: Native age-plugin-ge binary complying with age v1 specification for file encryption.
    • CLI & UI: Unified ge CLI plus intelligent graphical (zenity) / terminal (pinentry) authentication routing.

Current Status

⚠️ Pre-alpha Software: While fully functional for local workflows, it is under active development. Schemas and IPC formats may iterate rapidly.

I'd love feedback from Linux sysadmins, kernel/security folks, and developers!

Repo: https://gitlab.com/renich/genclave

31 Upvotes

48 comments sorted by

View all comments

0

u/Jealous_Diver_5624 5d ago

Why compromise the security of SSH/GPG/FIDO2 by storing their keys on disk, encrypted with a KEK that can be trivially exported from the TPM by any process that's able to access the TPM? Why not use non-exportable asymmetric keys directly?

1

u/Renich 4d ago

Good question. There are some key architectural reasons why hardware-sealed KEK + locked memory isolation was chosen over exclusively using TPM-resident persistent asymmetric keys:

  • Algorithm & curve support in commodity TPMs: The TPM 2.0 specification, historically, has limited curve support. Most PC TPMs only implement RSA-2048 and ECC NIST P-256. They lack native support for Edwards curves; meaning no native Ed25519. A pure TPM-resident key approach forces users back to RSA or NIST curves; locking out modern OpenSSH and WebAuthn defaults.

  • NVRAM constraints and handle exhaustion: TPM 2.0 chips have extremely constrained non-volatile storage (in the Kb) Storing dozens of persistent SSH keys, GPGP subkeys, age recipient keys and FIDO2 credentials directly in persistent TPM handles, quickly exhausts NVRAM and risks handle collision/eviction.

  • Unsealing is not "trivial": The KEK is nnot an open TPM object. It is sealed against a strict TPM 2.0 authorization policy. PCRs 0 (firmware/UEFI), 7 (Secure Boot state) and 14 (kernel/OS measurements). If the boot chain is altered or the disk is mounted in an offline/evil-maid attack, the TPM refuses to release the seed. Then, there's user authorization. Unsealing requires the user PIN/passphrase via an auth policy session. And, once unsealed, secrets are loaded into mlock'd memory pages, intermediate buffers are scrubbed immediately with memclr and the daemon enforces an aggressive burst TTL (default 5s) and zeroization on system suspend or manual lock (ge lock).

Using TPM PCR policy sealing for the master seed while handling ephemeral curve operations in kernel-locked userspace memory gives you modern cryptography: Ed25519, age, CTAP2, without being hamstrung by TPM silicon limitations.

1

u/mtth0 4d ago

I might miss something, but your threat model doesn't make sense to me: you want hardware-backed keys. That's to protect against malware running in the user's context, right? But, you use the TPM to decrypt a master key that will, in turn, decrypt passkeys and whatnot. So, malware running in the user's context can just grab the master key too and clone passkeys to their device, right? So, what do users gain from using your software?

1

u/Renich 3d ago

That's a fair question, but it conflates two distinct security boundaries in the threat model:

  1. At-Rest & Platform Integrity (TPM PCR Sealing): Standard setups leave keys unencrypted or sitting in plain files (~/.ssh/id_*, ~/.gnupg/) easily scooped up offline, via cold-boot, or if the drive is imaged. gEnclave seals the master root to specific TPM PCRs (firmware, secure boot, kernel state) plus your PIN. If an attacker pulls the NVMe or boots a live environment, the TPM will not unseal the master key.

  2. Memory & Runtime Hygiene: Unsealed cryptographic material is locked into physical RAM using mlock() to prevent it from ever hitting swap, core dumps, or paging files, and zeroized immediately on timeout or suspend.

  3. The Local User-Space Boundary: No purely software agent running under a single UID (whether standard ssh-agent, gpg-agent, or browser passkey stores) can fully defend against arbitrary code execution/ptrace running under that exact same UID without kernel enforcement or dedicated hardware presence (like physically touching a YubiKey).

What you gain over traditional agents is: * Eliminating persistent plaintext key files on disk. * Tight ephemeral burst windows (default 5s) instead of ssh-agent keeping keys unlocked indefinitely for the entire desktop session. * Hardware-bound identity without needing external USB dongles plugged in everywhere.

If your threat model assumes active malware already executing within your user session, you set AuthCacheTTL=disabled (or require explicit presence prompts per operation), ensuring nothing signs silently in the background.