ADR-113 — Doctrine de sourcing cryptographique : pur Rust os-free d’abord, ne pas porter de C, DIY sérieux sinon, fiable > performant
Statut : Accepté (2026-07-26, décision BDFL). RFC de direction (ADR-015). Raffine ADR-034 (discipline des dépendances crypto), ADR-024 (règle des 80 % + vendoring). S’appuie sur ADR-088 (sans libc C), ADR-110 (ML-KEM — premier cas d’application), ADR-108 (formats de clés possédés).
Catégorie : Doctrine d’ingénierie (transverse crypto). Vague 2 #1 du triage des écarts OpenSSH — formalise une doctrine déjà appliquée aux ADR crypto de la vague 1.
Contexte
La règle générale « on ne réinvente pas la crypto » tient. Mais Air est un OS à part
entière ([ADR-088]) : os-free, zéro glibc, cible *-linux-air sans libc C. Or peu de
piles crypto sont (1) écrites en Rust et (2) réellement C-free / os-free : beaucoup
s’appuient sur des bouts de C et d’assembleur. Cette contrainte a déjà forcé des décisions
concrètes (ML-KEM [ADR-110] : choix d’une crate aux deps C-free vérifiées ; formats de clés
[ADR-108] : possédés). Elle mérite d’être formalisée en doctrine, pour que chaque futur
choix crypto soit tranché de la même manière.
Directive BDFL (2026-07-26). « En crypto, on ne refait pas de la crypto, on utilise ce qui est fait. MAIS peu de stacks sont 1) en Rust 2) sans s’appuyer sur du C et de l’assembleur. L’assembleur ne me pose pas de problème. Le C, si : le code doit être os-free. Et s’il le faut, on fait notre propre crypto, mais sérieusement. Je préfère du secure, fiable à de la performance — la performance est toujours secondaire. »
Décision
1. Arbre de décision du sourcing
Pour toute primitive/format cryptographique, dans l’ordre :
- Pur Rust + C-free + os-free + mûr/audité + qualifie la règle des 80 % ([ADR-024]) → utiliser (vendoré + pinné). La majorité de RustCrypto.
- Seules des options C-tainted / couplées à un OS existent → NE PAS LES PORTER. Chercher une alternative pur-Rust ; sinon écrire nous-mêmes à notre standard.
- Rien d’acceptable → DIY sérieux (§3).
2. L’assembleur oui, le C non
Le refus vise le C (hypothèses d’ownership mémoire exclusif, non-interruptibilité,
absence de context-switch, dépendance glibc), pas l’assembleur : les intrinsics
core::arch ou un .S sont acceptables. Le BDFL est développeur C senior — le refus du
C est informé, pas dogmatique : il protège l’invariant os-free d’Air.
Fait connexe à surveiller : un contact C/libc caché existe déjà — cpufeatures (tiré
par aes/sha2) passe par la libc sur aarch64 ⇒ « pur Rust » n’est pas toujours
vraiment C-free. Chantier séparé ; à re-vérifier à chaque dépendance ([ADR-110] l’a fait pour
ml-kem).
3. Standard exigé d’un DIY crypto (ce qui le rend défendable)
Un composant crypto écrit maison n’est acceptable que s’il est tenu au niveau des couches
fondatrices (Principe 1) : KATs officiels · constant-time prouvé par dudect
(crates/*/tests/dudect_*, gaté AIR_DUDECT=1, job CI dédié [ADR-107]) · fuzz
(cargo-fuzz sur toute entrée externe) · Miri · proptest · air-fault · zeroize
des secrets · unsafe banni/borné + // SAFETY: · conception informée par les CVE
(cf. [[audit-musl-corpus]]). Fiable > performant, toujours — la performance est secondaire
et ne se paie jamais en sécurité (Principe 5 : sur-sécuriser puis dégraisser après mesure).
4. Gradient de risque (pondère le « DIY vs adopter »)
- 🟢 Formats / protocoles (certif SSH, formats de clés OpenSSH/PEM,
known_hosts, wire) : DIY faible risque → on possède (gros du keystore/CA [ADR-108], codec cert [ADR-109]). - 🟢 Symétrique (SHA-2/3, HMAC, ChaCha20, Poly1305, AES-GCM, HKDF, Argon2) : déjà RustCrypto pur → garder.
- 🟠 Asymétrique — corps (Ed25519/X25519) : DIY haut risque (side-channels, formules
incomplètes) → garder l’implémentation éprouvée (dalek) sauf si elle traîne du C
(re-vérifier
cpufeatures). - 🔴 Post-quantique (ML-KEM) : DIY très haut risque → crate pur-Rust auditée
([ADR-110] :
ml-kem), DIY en dernier recours + spec formellement vérifiée. Le combineur hybride (assemblage de primitives sûres) reste 🟢 (possédé).
5. Frontière inchangée
air-crypto reste primitives pures, no-IO ([ADR-034]) ; le cycle de vie / stockage
vit dans les managers ([ADR-108] keystore, [[managers-domaine-couche1-mediateurs]]). Cette
doctrine ne déplace aucune responsabilité ; elle cadre le sourcing.
Conséquences
Positives.
- Décisions crypto reproductibles : un arbre unique, appliqué de la même façon à chaque primitive/format (déjà validé rétroactivement par [ADR-110]/[ADR-108]/[ADR-109]).
- Invariant os-free protégé : le C ne rentre pas par une dépendance crypto « pur Rust » en apparence.
- DIY discipliné : quand on écrit de la crypto, le standard (KATs/dudect/fuzz/Miri) est explicite — pas de « crypto maison » au rabais.
Négatives / coûts assumés.
- Coût de vérification récurrent : chaque adoption exige un audit de l’arbre de deps (C-free ?) et, pour un DIY, tout l’appareil de preuve. Assumé (fiable > rapide).
- Perf secondaire explicitement : on peut renoncer à une implémentation plus rapide mais C-tainted. Assumé et voulu.
- Surface DIY = surface à maintenir (formats possédés) : suivre les CVE de l’écosystème même sur ce qu’on a réécrit.
Note. Cette doctrine formalise l’existant ; elle n’invalide aucune décision crypto déjà prise, elle en explicite le fondement. Application immédiate : toute nouvelle brique crypto de la vague 2 (agent, hostbased) s’y conforme.
Alternatives rejetées
Aucune alternative n’a été consignée lors de l’instruction.