ADR-042 — Pile TLS : rustls + aws-lc-rs (exception C nommée, étroite), TLS 1.3, air-tls maison en contingence
Statut : Accepté (2026-06-25, validé par le BDFL).
Companion de la note docs/notes/reseau-architecture-crates-fr.md (architecture des
crates réseau) ; déroge ponctuellement à la politique « zéro surface C » (audit 082,
check-c-surface, deny.toml) via une exception nommée au sens
ADR-024/ADR-034 ;
impacte ADR-025 (toolchain C au build). Cohérent
avec le choix RustCrypto d’air-crypto.
Catégorie : Architecture (couche 2 — air-tls/réseau) / Sécurité.
Contexte
La pile TLS conditionne toute la connectivité sécurisée d’Air (HTTPS, QUIC/HTTP-3, demain les services AirCom distants). C’est aussi la surface de sécurité la plus critique d’un système. Deux dogmes Air s’y opposaient en apparence : « on ne réécrit pas de crypto » et « zéro surface C ». Une analyse a été menée explicitement (cette session) ; cet ADR en consigne le résultat et le raisonnement.
Démarche d’analyse (consignée pour transparence)
- Frontière primitives / protocole. « Pile TLS maison » ne signifierait jamais réécrire des primitives crypto (AES, ChaCha20, SHA, X25519, Ed25519…) — celles-ci restent RustCrypto/équivalent. Seul le protocole (record layer, handshake, key schedule, machine à états, X.509) serait « à nous ». C’est exactement ce que fait rustls : le protocole, au-dessus d’un provider crypto enfichable.
- Classes de vulnérabilités TLS : (a) sûreté mémoire (Heartbleed-class —
empiriquement dominante, vit dans le C) ; (b) machine à états / protocole
(
goto fail, downgrade) ; (c) side-channel / primitives (Lucky13, Bleichenbacher). « Sécurité maximale » veut neutraliser les trois. - Comparaison des piles (focus sécurité) : la plus sûre n’est pas une pile tout-C (même la meilleure, s2n-tls d’AWS — petite, machine à états formellement vérifiée — ne peut éliminer la classe (a) par construction). La combinaison la plus sûre disponible = protocole memory-safe + primitives formellement vérifiées.
- Providers rustls :
ring(C+asm, maintenance irrégulière),aws-lc-rs(AWS-LC : C+asm, équipe AWS financée, asm formellement vérifié, FIPS 140-3, devenu défaut de rustls),rustls-rustcrypto(pur Rust, non-défaut, moins éprouvé).
Décision
La pile TLS d’Air est
rustls(protocole, pur Rust, memory-safe) +aws-lc-rs(provider crypto, AWS-LC) +rustls-webpki(validation X.509, pur Rust). TLS 1.3 ciblé. Le C est admis par EXCEPTION NOMMÉE, ÉTROITE : il ne concerne QUE les primitives crypto (aws-lc-sys), jamais le protocole ni le parseur X.509, qui restent memory-safe Rust.
Justification (sécurité + fiabilité) :
- La partie bug-prone reste memory-safe. Record layer, handshake, machine à états et parsing X.509/ASN.1 (la surface hostile, là où vivent les CVE catastrophiques) sont en Rust (rustls + rustls-webpki) → la classe (a) est éliminée par construction là où elle compte.
- Le C est confiné là où il a une valeur prouvée : les primitives d’
aws-lc-rs, asm formellement vérifié, FIPS 140-3, constant-time, équipe AWS financée (réponse sécurité rapide — fiabilité sur 10-20 ans). C’est une petite surface auditée, pas le protocole tentaculaire. - rustls : protocole moderne TLS 1.2/1.3 only (zéro legacy), financé ISRG (Let’s Encrypt), testé contre BoGo, largement déployé. C’est le défaut qu’AWS/ISRG recommandent.
→ C’est la combinaison la plus secure objectivement disponible aujourd’hui : memory-safety + vérification formelle + TLS 1.3 + maintenance financée — qu’aucune pile seule (ni full-C, ni full-pur-Rust) n’égale.
Périmètre
- TLS 1.3 ciblé ; rustls est configuré 1.3-first (1.2 admis seulement si un besoin d’interop réel l’impose, configurable — par défaut on minimise la surface legacy).
- X.509 :
rustls-webpki(pur Rust). Pas de parseur ASN.1 maison. - Exception C : limitée à
aws-lc-sys/aws-lc-rs(+ ses outils de buildcc/cmake). Aucune autre surface C n’est ouverte par cet ADR.
Contingence — air-tls maison reste une porte de sortie
Un air-tls maison (protocole TLS implémenté par Air, sur le patron sans-IO 9-composants
de la note réseau, primitives RustCrypto, régime d’homologation IETF — RFC 8448, tlsfuzzer,
interop, fuzzing) pourra voir le jour SI le choix rustls devient un passif :
faille de sécurité non corrigée en temps voulu, abandon/maintenance dégradée, ou
complexité d’intégration rédhibitoire. Cette option est explicitement gardée
ouverte (souveraineté + valeur de démonstration), mais n’est pas le choix présent :
on ne porte pas le pari le plus risqué tant que rustls fait le travail.
Conséquences
- Exception nommée à appliquer à l’implémentation (pas maintenant — aucun code réseau
encore). Quand la dépendance rustls entrera (crate
air-tls/air-network) :deny.toml: lever le ban deaws-lc-sys(etcc/cmakesur ce sous-arbre) par une entrée nominative justifiée ;ringreste banni (on prend aws-lc-rs, pas ring).docs/EXCEPTIONS.md: entrée nommée (motif = sécurité par crypto formellement vérifiée/FIPS + memory-safety du protocole ; plan de sortie =air-tlsmaison en contingence).check-c-surface: ajuster pour autoriser uniquementaws-lc-sys(le ban générique*-sysreste pour tout le reste).
- Builds reproductibles (ADR-025) :
aws-lc-rstire un build C (cmake) → pinner la toolchain C ou utiliser les bindings pré-générés ; à traiter dans la specair-tls(sinon la repro cargo-only ne tient plus pour ce crate). - Homologation : même sans pile maison, on impose et publie un régime de test/ interop sur notre intégration (matrice d’interop OpenSSL/rustls, RFC 8448 rejouées via rustls, fuzzing de notre couche d’intégration) — la rigueur reste, l’effort est moindre.
- air-tls maison : tracé comme option de contingence dans la note réseau.
Alternatives écartées
- air-tls maison d’emblée : le pari maison le plus risqué (historique TLS brutal) ; tout à prouver ; reporté en contingence plutôt qu’écarté.
- rustls + provider RustCrypto (zéro-C total) : séduisant (pas d’exception C), mais provider non-défaut, moins éprouvé, sans vérification formelle ni FIPS → moins sûr que aws-lc-rs sur la classe (c). Recevable comme repli si l’exception C devait être refermée.
- Pile tout-C (OpenSSL/BoringSSL/s2n) : protocole+parsing en C → expose la classe (a) (mémoire), la plus dommageable. Rejeté.
Adoption
Documentaire immédiat (ADR-042 + registre/INDEX/SUMMARY + correction de la ligne air-tls
de la note réseau). Les changements deny.toml/EXCEPTIONS.md/check-c-surface et le
pinning toolchain C (ADR-025) sont appliqués à l’implémentation d’air-tls/air-network
(spec à venir), pas avant.