Étude — Keyring kernel Linux vs fichier 0600 + air-keysign, pour le matériel privé du keystore
Statut : note d’étude (exploration, ne tranche rien — 2026-07-30). Répond à la question
« la couche 0 devrait-elle wrapper add_key/request_key/keyctl, et Air devrait-il stocker
le matériel privé dans le keyring kernel plutôt qu’en fichier scellé 0600 + courtier
air-keysign ? ». Contexte : idée parquée d’un keystore système multi-owner
([mémoire], services non-root sans home) et protection au repos différée (ADR-108 §2).
1. Ce qu’est le keyring kernel (rappel factuel)
Un service noyau de stockage de clés en mémoire avec ACL appliquée par le kernel :
- Trousseaux hiérarchiques : thread / process / session / user / user-session / persistent (par-uid) / nommés. Un process « possède » une clé si elle est liée dans l’un de ses trousseaux (sémantique de possession, distincte du propriétaire uid/gid).
- Permissions par clé :
possessor/user/group/other×view/read/write/search/link/setattr,chown/setperm/set_timeout. Contrôle d’accès kernel, pas filesystem.
- Types de clés :
user— blob opaque relisible par userspace (≤ ~32 KiB) ;logon— commeusermais non relisible depuis userspace (readback bloqué) ; seuls des consommateurs noyau (dm-crypt, fscrypt, NFS/CIFS…) le récupèrent ;asymmetric— clé asymétrique ; peut exposerKEYCTL_PKEY_{SIGN,VERIFY,ENCRYPT,DECRYPT}sans livrer la clé, si le sous-type et l’algo sont supportés par l’akciphernoyau ;trusted/encrypted— scellées par un TPM (la clé n’est jamais en clair sur disque) ;keyring,big_key.
- Syscalls :
add_key(2),request_key(2)(+ upcall d’instanciation à la demande),keyctl(2)(add/update/read/revoke/search/link/setperm/chown/timeout/pkey_*…).
2. La contrainte décisive pour Air : signer de l’Ed25519 sans exposer la clé
Le besoin structurant d’Air (SSH) est l’émission/signature Ed25519 oracle-safe : un service non-root obtient une signature sans jamais détenir la graine.
- Le seul type de keyring qui signe sans livrer la clé est
asymmetricviaKEYCTL_PKEY_SIGN. Or le supportakcipherlogiciel du noyau vise historiquement RSA/ECDSA (signature de modules, IMA) ; le support Ed25519 pourKEYCTL_PKEY_SIGNn’est pas portablement garanti (dépend deCONFIG_*, de la version, du parseurpkcs8). À vérifier sur le kernel cible — mais on ne peut pas s’appuyer dessus pour une brique fondatrice validée jusqu’au Pi 4. logonprotège le readback mais n’est utilisable que par le noyau — pas de signature SSH userspace possible.userest relisible ⇒ le service détiendrait la graine ⇒ fuite à la compromission : exactement ce que le privsep/air-keysigncombat.
Conséquence : pour l’Ed25519 SSH, le keyring ne fournit pas « signer sans exposer ».
air-keysign (courtier userspace privilégié, ADR-108 §5), lui, le fait pour n’importe quel
algorithme (dont Ed25519), avec notre crypto Rust ([doctrine-sourcing-crypto]), en
validant la structure et en restreignant l’appelant (peer credentials). Sur le cœur du besoin,
air-keysign gagne.
3. Deux limites structurelles du keyring comme « stockage »
- Éphémère. Les trousseaux meurent avec leur session/process ; le trousseau
persistent(par-uid) survit à la déconnexion mais est récupéré après un délai sans session active. Le keyring est donc un cache runtime, pas un système de référence durable. Un magasin fichier reste nécessaire pour recharger au boot. Le keyring ne remplace pas les*.aircfg. - Crypto/scellé = du C noyau. La signature
asymmetricet le scellétrusted/encryptedreposent sur le crypto noyau (C) et, pour le scellé, sur un TPM (pile Ctpm2). Cela heurte la doctrine pur-Rust / C-free ([doctrine-sourcing-crypto]) et le TPM n’existe pas sur tous les cibles d’Air (Pi 4). Les cléstrustedne sont donc pas universellement disponibles.
4. Comparaison par dimension
| Dimension | Keyring kernel | Fichier 0600 scellé + air-keysign |
|---|---|---|
| Signer Ed25519 sans exposer la clé | ✗ (akcipher Ed25519 non portable ; logon = noyau only ; user = fuite) | ✅ courtier, tout algo, notre crypto Rust |
| Contrôle d’accès multi-owner | ✅ ACL kernel par-clé (uid/gid/perms/possession) | ✅ le courtier applique l’ACL (owner/shared) + peer creds |
| Protection au repos | ✅✅ trusted/encrypted scellé TPM (jamais en clair) — si TPM | ⚠️ aujourd’hui 0600 clair (Argon2 différé ADR-108 §2) |
| Durabilité (référence) | ✗ éphémère (cache runtime) | ✅ fichier = système de référence |
| Doctrine pur-Rust / C-free | ✗ crypto/scellé = C noyau + TPM C | ✅ notre stack Rust |
| Universalité matériel (jusqu’au Pi 4) | ⚠️ dépend CONFIG_* ; TPM absent sur Pi | ✅ partout |
| Alimenter un consommateur NOYAU (fscrypt/dm-crypt) | ✅✅ seul mécanisme (via logon/encrypted) | ✗ non concerné |
5. Là où le keyring est réellement le bon outil (drivers futurs légitimes)
Le keyring n’est pas le bon véhicule pour la signature SSH, mais il l’est pour :
- Chiffrement au repos adossé au TPM : sur une machine avec TPM, sceller les magasins
d’Air (ou une clé maître Argon2) par une clé
trusted/encrypteddonne un « jamais en clair sur disque » que le fichier0600n’offre pas. Optionnel, matériel-dépendant — un durcissement, pas un socle. - Consommateurs noyau : si Air adopte un jour fscrypt (répertoire keystore chiffré) ou
dm-crypt, la clé doit transiter par le keyring (
logon/encrypted) — c’est l’unique interface. C’est le driver le plus solide pour, alors, wrapperadd_key/request_key/keyctl.
6. Recommandation
- Mécanisme primaire du matériel privé =
air-keysign(déjà contractualisé ADR-108 §5) + magasins fichier0600comme référence durable. Il résout à la fois l’ACL multi-owner et le « ne jamais livrer la clé », pour tout algorithme, en Rust. C’est aussi la réponse à la tension de l’idée parquée (services non-root) : ils passent par le courtier, pas par une lecture directe. - Keyring = complément optionnel, différé. Garder
keyctl/add_key/request_keyen « à évaluer » dansUNSUPPORTED.mdetfamily-security, priorité basse. Ne les wrapper en couche 0 que lorsqu’un consommateur concret existe : (a) un durcissement at-rest TPM conçu, ou (b) l’adoption fscrypt/dm-crypt. Le faire « au cas où » violerait « optimiser après mesure » (Principe 5) et ajouterait de la surface non consommée. - Si/quand on l’attaque : suivre le motif Landlock/seccomp — couche 0 primitive
(wrappers typés
Result<_, Errno>, fuzz sur ce qui parse de l’externe), API déclarative en couche 1, intégration keystore en couche 2. Un ADR dédié (amende ADR-108) au moment venu.
En une phrase : pour signer de l’Ed25519 sans fuite, air-keysign bat le keyring ; le keyring
sera pertinent le jour où Air voudra du scellé TPM au repos ou nourrir un consommateur
noyau — deux chantiers optionnels et matériel-dépendants, à instruire alors, pas maintenant.
Références : ADR-108 (air-keystore/air-keysign, §5 oracle-safe), ADR-004 (Linux
tier-1), Principe 5 (mesurer avant d’optimiser), doctrine crypto pur-Rust,
crates/air-sys-syscall/UNSUPPORTED.md, docs/specs/layer-0/family-security.md,
docs/specs/config-specification-proposal.md (TPM/keyring pour le chiffrement de config).