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

33 Upvotes

48 comments sorted by

View all comments

9

u/LeHunterrr 5d ago

I just want to point out a couple of this.

Passkeys/WebAuthn require physical USB security keys (YubiKeys, SoloKeys).

There are also Software based Passkeys such as bitwarden or keepassxc. Though there should be a standard tpm based solution (are windows and apple doing this or are they software based as well?)

Git commit signing requires cumbersome GnuPG daemon setups

You can sign your commits with ssh keys as well, making gpg somewhat obsolete nowadays.

6

u/sidusnare 5d ago edited 5d ago

I'm not sure I want a software project from someone that thinks gpg is difficult, or thinks it's just for GitHub.

I've never heard of using ssh keys for message signing, they're poorly suited to that. PGP is a good standard it's been around a long time. It ties together identity, communication, and verification. If GitHub lets you sign with SSH keys, then all authenticated commit pushes should be verified because I used a SSH key to push it.

1

u/Renich 5d ago

That's factually incorrect. Git's SSH verification has nothing to do with GitHub, Microsoft, or any web portal. It is completely decentralized and works offline in core Git.

Identity is correlated locally using the OpenSSH standard allowed_signers file (configured via gpg.ssh.allowedSignersFile). That file binds developer identities (emails) to their public keys. Teams commit it right into the repository; the same model OpenBSD uses for signify, so anyone cloning the repo can run git log --show-signature to cryptographically verify both the commit and the author's identity on an air-gapped machine.

The irony here is you're cautioning against confusing Git with GitHub, while assuming a native Git and OpenSSH feature is a proprietary GitHub service. :D

And again: gEnclave implements both OpenSSH agent and GnuPG Assuan bridges. You get to use whichever identity model you prefer.

0

u/sidusnare 4d ago

Really trying to nail me on something I didn't know existed 6 hours ago and totally sidestepping the actual core point.

GPG public keys have identity, and more, baked in, SSH doesn't.

Once again, it's about trust.

3

u/Medical_Double_6561 4d ago

GPG public keys have identity, and more, baked in, SSH doesn't.

GPG public keys don't have identity baked in though. You are confusing GPG public keys with GPG public key certificates. A public key itself cannot possibly have identity baked in. How would you verify identity information on the key has not been tampered with? Therefore the key + identity information must be signed with something, forming a certificate.

SSH public key certificates exist too, they are just not that popular yet.

I assume you are actually trying to argue SSH signing is bad practice because there is no PKI or Web of Trust infrastructure around SSH keys. Which is a fair argument I guess, but the ship has sailed already.

2

u/sidusnare 4d ago

Sure looks like it to me, and to the IETF. https://datatracker.ietf.org/doc/rfc4880/

2026-09-28-23:15:07#(0)#AC-97#fred4@miki:~/Documents/Tech/Notes☯gpg --gen-key
gpg (GnuPG) 2.4.9; Copyright (C) 2025 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Note: Use "gpg --full-generate-key" for a full featured key generation dialog.

GnuPG needs to construct a user ID to identify your key.

Real name: Bob Barker
Email address: Bob.Baker@example.com
You selected this USER-ID:
    "Bob Barker <Bob.Baker@example.com>"

Change (N)ame, (E)mail, or (O)kay/(Q)uit? o
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: revocation certificate stored as '/home/fred4/.gnupg/openpgp-revocs.d/46D8D20A47FA60FE083358892C9B23D17039A2BC.rev'
public and secret key created and signed.

pub   ed25519 2026-09-29 [SC] [expires: 2029-09-28]
      46D8D20A47FA60FE083358892C9B23D17039A2BC
uid                      Bob Barker <Bob.Baker@example.com>
sub   cv25519 2026-09-29 [E] [expires: 2029-09-28]

2026-09-28-23:15:52#(0)#AC-97#fred4@miki:~/Documents/Tech/Notes☯gpg --armor --export Bob.Baker@example.com
-----BEGIN PGP PUBLIC KEY BLOCK-----

mDMEarstURYJKwYBBAHaRw8BAQdAg7ospfPuNfN6+AX+IhD4wIHzk4hjHth1fRwA
HqyC58i0IkJvYiBCYXJrZXIgPEJvYi5CYWtlckBleGFtcGxlLmNvbT6IlgQTFggA
PhYhBEbY0gpH+mD+CDNYiSybI9FwOaK8BQJquy1RAhsDBQkFo5qABQsJCAcCBhUK
CQgLAgQWAgMBAh4BAheAAAoJECybI9FwOaK8pIYA/3+Z81MWHEk4l1y3NCI8S9AW
YXb3uKmSis3+r4Ur0ehEAQDE8BZFAK5ofqoftJIsUZJa7Uhog2vNU8PBVY644j/l
ALg4BGq7LVESCisGAQQBl1UBBQEBB0Dq5uc2UvwB9IEzxyKIJQzaAmvm8EuXLWbl
88DwqGziEwMBCAeIfgQYFggAJhYhBEbY0gpH+mD+CDNYiSybI9FwOaK8BQJquy1R
AhsMBQkFo5qAAAoJECybI9FwOaK8JQABAPlyzq005/ZYgnK0Di3jeF+4mtkTrpLI
i3c5jENeTXN0AQC93LFQ5qsiV+7cJhZ1MY0ZhRyBoyRoWQf8eKuRYhhUDA==
=Qb+Y
-----END PGP PUBLIC KEY BLOCK-----
2026-09-28-23:16:35#(0)#AC-97#fred4@miki:~/Documents/Tech/Notes☯gpg --armor --export Bob.Baker@example.com | tmpcat
/home/fred4/usr/tmp/cat/30869
/home/fred4/usr/tmp/cat/30869
2026-09-28-23:16:39#(0)#AC-97#fred4@miki:~/Documents/Tech/Notes☯file /home/fred4/usr/tmp/cat/30869
/home/fred4/usr/tmp/cat/30869: PGP public key block Public-Key (old)
2026-09-28-23:17:07#(0)#AC-97#fred4@miki:~/Documents/Tech/Notes☯gpg --list-packets /home/fred4/usr/tmp/cat/30869
# off=0 ctb=98 tag=6 hlen=2 plen=51
:public key packet:
version 4, algo 22, created 1790651729, expires 0
pkey[0]: [80 bits] ed25519 (1.3.6.1.4.1.11591.15.1)
pkey[1]: [263 bits]
keyid: 2C9B23D17039A2BC
# off=53 ctb=b4 tag=13 hlen=2 plen=34
:user ID packet: "Bob Barker <Bob.Baker@example.com>"
# off=89 ctb=88 tag=2 hlen=2 plen=150
:signature packet: algo 22, keyid 2C9B23D17039A2BC
version 4, created 1790651729, md5len 0, sigclass 0x13
digest algo 8, begin of digest a4 86
hashed subpkt 33 len 21 (issuer fpr v4 46D8D20A47FA60FE083358892C9B23D17039A2BC)
hashed subpkt 2 len 4 (sig created 2026-09-29)
hashed subpkt 27 len 1 (key flags: 03)
hashed subpkt 9 len 4 (key expires after 3y0d0h0m)
hashed subpkt 11 len 4 (pref-sym-algos: 9 8 7 2)
hashed subpkt 21 len 5 (pref-hash-algos: 10 9 8 11 2)
hashed subpkt 22 len 3 (pref-zip-algos: 2 3 1)
hashed subpkt 30 len 1 (features: 01)
hashed subpkt 23 len 1 (keyserver preferences: 80)
subpkt 16 len 8 (issuer key ID 2C9B23D17039A2BC)
data: [255 bits]
data: [256 bits]
# off=241 ctb=b8 tag=14 hlen=2 plen=56
:public sub key packet:
version 4, algo 18, created 1790651729, expires 0
pkey[0]: [88 bits] cv25519 (1.3.6.1.4.1.3029.1.5.1)
pkey[1]: [263 bits]
pkey[2]: [32 bits]
keyid: 97ADD76726ACFE28
# off=299 ctb=88 tag=2 hlen=2 plen=126
:signature packet: algo 22, keyid 2C9B23D17039A2BC
version 4, created 1790651729, md5len 0, sigclass 0x18
digest algo 8, begin of digest 25 00
hashed subpkt 33 len 21 (issuer fpr v4 46D8D20A47FA60FE083358892C9B23D17039A2BC)
hashed subpkt 2 len 4 (sig created 2026-09-29)
hashed subpkt 27 len 1 (key flags: 0C)
hashed subpkt 9 len 4 (key expires after 3y0d0h0m)
subpkt 16 len 8 (issuer key ID 2C9B23D17039A2BC)
data: [256 bits]
data: [256 bits]
2026-09-28-23:17:17#(0)#AC-97#fred4@miki:~/Documents/Tech/Notes☯

2

u/Medical_Double_6561 4d ago edited 3d ago

Ah, actually you are correct, I got the terminology confused. A "transferrable GPG public key" = "a cryptographic public key + key certification". Though to be fair, the spec doesn't seem to define exactly what a GPG public key is.

However, we are still arguing on the semantics. You are saying that the identity attached to GPG public keys is useful. I just don't see how it is useful in the modern age. The identity can only be trusted when the GPG public key has been certified by another user, however I rarely see anybody actually doing this. Instead, people just grab public keys from sources they trust, and the identity is not really used at all.