ADR-081 — Additifs crypto pour air-quic et air-ssh : primitives bas niveau (bloc AES, keystream ChaCha20, Poly1305) + RSA PKCS#1 v1.5 vérif. — descellement additif couche-1-v1.x
Statut : Proposé — ratification BDFL requise. Comme ADR-078,
touche la surface cryptographique ⇒ hors délégation additive automatique
(ADR-065 §Gouvernance) : ratification
explicite + KAT-gate (ADR-034) avant
tag. RFC de structure (ADR-015). Consommateurs :
air-quic + air-ssh.
Catégorie : Descellement additif de la couche 1 scellée (air-crypto) +
extension de dépendances crypto (exceptions 80 % ADR-024/034). Aucune rupture ;
complète ADR-078.
Contexte
ADR-078 a instruit les additifs crypto d’air-tls (AES-128-GCM, ECDSA/ECDH, RSA-PSS
vérif., ML-KEM-768). Les specs air-quic et
air-ssh — postérieures — révèlent des besoins que la
façade AEAD anti-mésusage d’air-crypto (nonces gérés, pas de primitive nue) ne
couvre pas :
- QUIC — header protection (RFC 9001 §5.4). Protéger l’en-tête d’un paquet QUIC exige un masque dérivé d’un échantillon du payload chiffré, calculé par un bloc AES brut (ECB single-block) pour les suites AES, ou un keystream ChaCha20 pour la suite ChaCha. Ce sont des primitives sous la couche AEAD.
- SSH — signatures RSA (
rsa-sha2-256/512). SSH utilise RSASSA-PKCS#1 v1.5 (vérification de clé d’hôte), différent du RSA-PSS d’ADR-078. - SSH —
chacha20-poly1305@openssh.com. Construction custom (deux clés ChaCha20 : une pour la longueur, une pour les données ; Poly1305 séparé) — exige ChaCha20 keystream + Poly1305 one-shot exposés, pas l’AEAD RFC 8439. - SSH — kex post-quantique. Résolu sans nouvel additif : voir §Décision.
Décision
(1) Module bas niveau air_crypto::lowlevel (opt-in, expert-only)
On ajoute un module explicitement bas niveau exposant les primitives nues requises par les implémenteurs de protocole (QUIC/SSH), séparé de la façade haut-niveau (qui reste le défaut anti-mésusage) :
#![allow(unused)]
fn main() {
pub mod lowlevel { // « advanced » : documenté expert-only, pas le chemin par défaut
/// Bloc AES brut (ECB single-block) — QUIC header protection (RFC 9001 §5.4.3).
pub struct AirAesBlock { /* aes crate */ }
impl AirAesBlock { pub fn new(key: &AirSymmetricKey<16|32>) -> Self;
pub fn encrypt_block(&self, block: [u8;16]) -> [u8;16]; }
/// Keystream ChaCha20 (RFC 8439 §2.4) — QUIC HP (ChaCha) + SSH cipher.
pub struct AirChaCha20 { /* chacha20 crate */ }
/// Poly1305 one-shot (RFC 8439 §2.5) — SSH chacha20-poly1305@openssh.
pub struct AirPoly1305 { /* poly1305 crate */ }
}
}
- Backends :
aes,chacha20,poly1305(RustCrypto) — déjà présents en transitif (viaaes-gcm/chacha20poly1305) ; ici promus dépendances directes. Zéro-C (pur Rust ; réserveaarch64/cpufeaturesd’aes-gcminchangée). - KAT : vecteurs RFC 8439 (ChaCha20/Poly1305), NIST (AES bloc).
(2) RSA PKCS#1 v1.5 — vérification seule (air_crypto::AirRsaPkcs1VerifyingKey)
#![allow(unused)]
fn main() {
/// Vérif. RSASSA-PKCS#1 v1.5 (SHA-256/512) — SSH rsa-sha2-256/512. Clé PUBLIQUE only.
pub struct AirRsaPkcs1VerifyingKey { /* rsa crate (déjà ADR-078) */ }
}
- Backend :
rsa(déjà additif ADR-078 pour le PSS). Aucune opération privée RSA ⇒ hors Marvin (RUSTSEC-2023-0071). PKCS#1 v1.5 signature ≠ chiffrement : la vérif. de signature v1.5 est sûre (Bleichenbacher vise le chiffrement v1.5, omis).
(3) Kex PQ SSH — réutilise ML-KEM-768 (ADR-078), sntrup761 différé
OpenSSH récent (≥ 9.9, 2024) fait de mlkem768x25519-sha256 son kex par défaut.
air-ssh réutilise ml-kem-768 (déjà instruit ADR-078) via
mlkem768x25519-sha256 — aucun nouvel additif. sntrup761x25519 est différé
(pas d’implémentation pure-Rust de calibre confirmé) ; à instruire si/quand une crate
RustCrypto sntrup761 vettée existe. La spec air-ssh est corrigée en ce sens.
Sécurité (cœur de la remontée BDFL)
- Baisse de garde anti-mésusage — bornée et assumée. Exposer des primitives nues
(bloc AES, keystream, MAC) affaiblit la posture « AEAD à nonce géré ». Mitigation :
module
lowlevelséparé, opt-in, documenté expert-only ; la façade haut-niveau reste le défaut. Les consommateurs sont des implémenteurs de protocole audités (QUIC/SSH maison), pas du code applicatif. - RSA vérif. seule (hors Marvin) ; PKCS#1 v1.5 chiffrement toujours omis.
- PQ en hybride only (ML-KEM via
mlkem768x25519, jamais seul) — cohérent ADR-078. - Zéro-C maintenu ;
no_std-strict (features aléa exclues,AirRandomcouche 0).
Gouvernance
- Surface crypto ⇒ ratification BDFL (comme ADR-078), hors délégation ADR-065.
- KAT-gated (ADR-034) ; exceptions 80 % :
aes/chacha20/poly1305promues directes dansEXCEPTIONS.md+DEPENDENCIES.md;rsa/ml-kemdéjà ADR-078. - Tags : rejoint le lot d’additifs crypto (
couche-1-v1.7, ADR-078) ou uncouche-1-v1.xsubséquent, après implémentation KAT-gated + barrière 2 arches.
Conséquences
air-quic: header protection réalisable (lowlevel::AirAesBlock/AirChaCha20).air-ssh:rsa-sha2(PKCS#1 v1.5 vérif.),chacha20-poly1305@openssh(lowlevel), kex PQ via ML-KEM-768. Specair-sshcorrigée (PQ =mlkem768x25519).- Précédent : tout protocole exigeant une primitive sous-AEAD passe par
lowlevel(opt-in), jamais par un affaiblissement de la façade par défaut.
Alternatives rejetées
- Mettre la construction header-protection / SSH-AEAD dans
air-crypto— pousserait de la connaissance protocolaire en couche 1 (primitives). Rejeté :air-crypto= primitives, la construction vit en couche 2 (air-quic/air-ssh). - Exposer un ECB général — trop dangereux (ECB mésusable). Rejeté :
AirAesBlocksingle-block, nommé/documenté pour la header-protection, pas un mode ECB. - Introduire
sntrup761maintenant — pas de crate pure-Rust vettée ; ML-KEM-768 (mlkem768x25519) couvre le besoin PQ SSH moderne. Différé. - Réécrire ces primitives — dogme zéro-crypto-maison (ADR-034). Rejeté.
Suite
- Section « Additifs planifiés — support
air-quic/air-ssh» ajoutée à la specair-crypto. Correctionair-ssh(PQ =mlkem768x25519,sntrup761différé). - Ratification BDFL puis implémentation KAT-gated. Câblage : registre, SUMMARY, INDEX,
EXCEPTIONS.md.