Le chiffrement de transport au sein des réseaux privés virtuels exige des algorithmes symétriques alliant un débit soutenu à une résistance rigoureuse face aux attaques par canaux auxiliaires microarchitecturaux. Longtemps, le standard de chiffrement avancé en mode Galois/Counter (AES-GCM) a dominé les déploiements d'entreprise comme IPsec et OpenVPN. Toutefois, sur les architectures matérielles dépourvues d'instructions cryptographiques dédiées, AES-GCM présente d'importantes baisses de performance et des risques sécuritaires avérés.

Lorsque des implémentations logicielles exécutent les tours AES sur des routeurs embarqués ou des processeurs mobiles sans extensions AES-NI ou ARMv8 Crypto, elles s'appuient sur des tables de substitution précalculées en mémoire (S-box). Ces accès mémoire engendrent des variations de latence exploitables par analyse temporelle du cache du processeur. De surcroît, la multiplication GHASH dans le corps de Galois $\mathbb{F}_{2^{128}}$ consomme de lourds cycles CPU en l'absence de multiplieurs matériels sans retenue (PCLMULQDQ).

WireGuard a neutralisé cette contrainte matérielle en adoptant exclusivement l'algorithme ChaCha20-Poly1305 AEAD (RFC 8439). Fondé sur l'architecture ARX (Addition-Rotation-XOR) et un serrage mathématique de clé, ChaCha20-Poly1305 garantit une exécution à temps constant sur l'ensemble des gammes de processeurs.

Les limites cryptographiques d'AES sans support matériel

Pour comprendre pourquoi les protocoles modernes ont délaissé AES-GCM sur des parcs d'équipements hétérogènes, il convient d'analyser le fonctionnement interne des chiffrements par blocs. AES repose sur un réseau de substitution-permutation. L'étape non linéaire de substitution (SubBytes) applique la boîte S de Rijndael sur chaque octet d'entrée.

Dans les bibliothèques logicielles optimisées, cette étape est compilée sous la forme de quatre tables de correspondance de 1 Ko (Te0, Te1, Te2, Te3) :

// Tour de calcul AES logiciel avec consultation de tables S-box
state[0] = Te0[(s0 >> 24)       ] ^ Te1[(s1 >> 16) & 0xff] ^ 
           Te2[(s2 >>  8) & 0xff] ^ Te3[(s3      ) & 0xff] ^ rk[0];

Comme les adresses mémoire interrogées dépendent directement des octets de la clé secrète et des données, ces lectures créent des empreintes mesurables dans la hiérarchie du cache. Un attaquant local peut évaluer les latences d'accès au cache pour extraire la clé privée.

À l'opposé, ChaCha20 bannit entièrement les tables en mémoire. Ce chiffrement par flux repose exclusivement sur trois opérations algébriques fondamentales : l'addition modulo $2^{32}$ (Addition), la rotation binaire fixe (Rotation) et le OU exclusif (XOR). Sur les unités arithmétiques et logiques (ALU), ces instructions s'exécutent en un nombre invariable de cycles d'horloge, neutralisant nativement les attaques par canaux auxiliaires temporels.

L'architecture ARX et la matrice d'état 4x4 de ChaCha20

Conçu par Daniel J. Bernstein, ChaCha20 opère sur un état interne de 512 bits représenté sous la forme d'une matrice 4x4 de seize mots non signés de 32 bits :

+---------------+---------------+---------------+---------------+
|  Constant 0   |  Constant 1   |  Constant 2   |  Constant 3   |
|  0x61707865   |  0x3320646e   |  0x79622d32   |  0x6b206574   |
+---------------+---------------+---------------+---------------+
|  Key Word 0   |  Key Word 1   |  Key Word 2   |  Key Word 3   |
+---------------+---------------+---------------+---------------+
|  Key Word 4   |  Key Word 5   |  Key Word 6   |  Key Word 7   |
+---------------+---------------+---------------+---------------+
| Block Counter |    Nonce 0    |    Nonce 1    |    Nonce 2    |
+---------------+---------------+---------------+---------------+

Cette organisation structurelle garantit une stricte intégrité :

  • Mots 0 à 3 : constante fixe de 128 bits "expand 32-byte k", assurant un état initial non nul.
  • Mots 4 à 11 : clé de session symétrique de 256 bits.
  • Mot 12 : compteur de blocs de 32 bits, incrémenté pour chaque bloc de flux de 64 octets.
  • Mots 13 à 15 : vecteur d'initialisation unique (nonce) de 96 bits.

La transformation mathématique s'articule autour de la fonction de quart de tour QR(a, b, c, d) :

// Fonction de quart de tour ChaCha20 Quarter-Round
#define ROTL32(v, n) (((v) << (n)) | ((v) >> (32 - (n))))
#define QR(a, b, c, d) { \
    a += b; d ^= a; d = ROTL32(d, 16); \
    c += d; b ^= c; b = ROTL32(d, 12); \
    a += b; d ^= a; d = ROTL32(d,  8); \
    c += d; b ^= c; b = ROTL32(d,  7); \
}

Une passe complète effectue 20 tours (10 tours de colonnes alternés avec 10 tours diagonaux). L'état obtenu est ensuite additionné mot à mot à la matrice initiale, puis combiné par XOR avec 64 octets de texte en clair. Ne sollicitant que les registres du processeur, le calcul ne subit aucune déviation temporelle.

Authentificateur unique Poly1305 et serrage de clé

La confidentialité ne saurait suffire : sans contrôle d'intégrité, un tiers peut altérer les paquets chiffrés en transit. ChaCha20 s'associe au code d'authentification de message Poly1305 pour constituer une suite AEAD robuste.

Poly1305 est un authentificateur polynomial de Carter-Wegman calculé sur le corps premier $\mathbb{F}_{2^{130}-5}$. Le message est subdivisé en blocs de 16 octets formant les coefficients d'un polynôme :

$$A(r) = \left( \sum_{i=1}^{L} c_i \cdot r^{L-i+1} \right) \pmod{2^{130}-5} + s \pmod{2^{128}}$$

La paire de clés à usage unique de 256 bits $(r, s)$ est générée à partir du bloc d'indice zéro produit par ChaCha20 pour chaque paquet :

  • Les mots 0 à 3 fournissent la clé d'évaluation polynomiale $r$ de 128 bits.
  • Les mots 4 à 7 fournissent la clé de masquage $s$ de 128 bits.

Afin d'éviter tout débordement de retenue lors des multiplications multi-membres, la clé $r$ subit un serrage binaire (clamping) :

// Serrage de clé Poly1305 selon la RFC 8439
r[3] &= 15;  r[7] &= 15;  r[11] &= 15; r[15] &= 15;
r[4] &= 252; r[8] &= 252; r[12] &= 252;

Le serrage efface 22 bits déterminés dans la clé $r$. Cette contrainte borne l'amplitude des résultats intermédiaires ($r < 2^{124}$), permettant aux processeurs 32 bits et 64 bits d'exécuter la réduction modulo par décalages et additions sans propagation incontrôlée de retenue.

Encapsulation WireGuard et optimisation par rapport à la RFC 8439

Bien que la RFC 8439 établisse un cadre général, WireGuard applique une structure optimisée pour le transport de paquets :

Format RFC 8439 standard :   [ Compteur 32 bits ] [ Nonce aléatoire 96 bits ] -> Authentifie AAD + Chiffré
Format optimisé WireGuard :  [ Remplissage 32 zéros ] [ Compteur 64 bits ]     -> Compteur transmis en clair

Dans l'architecture de WireGuard :

  1. Compteur de paquet 64 bits : L'en-tête de chaque paquet transmet un compteur 64 bits incrémenté strictement à chaque émission.
  2. Construction du Nonce 96 bits : Le nonce de ChaCha20 est constitué en plaçant 32 zéros en poids fort, suivis du compteur 64 bits en little-endian.
  3. Rotation stricte des clés : Si une même clé chiffrait deux paquets sous le même nonce, Poly1305 serait irrémédiablement compromis. WireGuard impose donc un renouvellement forcé de la session après $2^{60}$ paquets ou 120 secondes.

Les paquets de données standard n'incluent pas de données associées supplémentaires (AAD), car le tag Poly1305 de 16 octets valide directement la charge utile chiffrée, tandis que l'indice de réception est vérifié par la table Cryptokey Routing.

Accélération vectorielle SIMD : AVX2, AVX-512 et ARM NEON

L'un des avantages majeurs de ChaCha20 réside dans son parallélisme intrinsèque. Contrairement aux modes chaînés (CBC), les blocs de flux de ChaCha20 sont totalement indépendants les uns des autres.

Cette propriété permet une exploitation optimale des registres vectoriels :

  • ARM NEON : Les registres 128 bits calculent simultanément deux fonctions de quart de tour en parallèle.
  • x86_64 AVX2 : Les registres 256 bits traitent quatre blocs complets de 64 octets de front, produisant 256 octets par itération.
  • x86_64 AVX-512 : Les registres 512 bits traitent huit blocs simultanément, délivrant 512 octets par cycle vectoriel.

Comme les instructions vectorielles s'exécutent avec une latence prévisible, ces gains de débit (supérieurs à 3 Go/s par cœur) s'opèrent avec une sécurité absolue contre les canaux auxiliaires.

Traitement multicoeur et assainissement de mémoire dans RiceGuard

Sur les passerelles réseau haut débit, RiceGuard renforce l'utilisation de ChaCha20-Poly1305 :

  1. Répartition multicoeur parallèle : Intégré à l'infrastructure noyau padata, le flux réseau entrant est scindé et traité en parallèle sur tous les cœurs CPU disponibles avant réordonnancement.
  2. Validation à temps constant du tag : Le tag Poly1305 est confronté via la fonction crypto_memneq. Tout paquet invalide est rejeté avant tout début de déchiffrement.
  3. Purge immédiate de la mémoire : Les sous-clés ($r, s$) sont effacées de la mémoire vive par memzero_explicit dès la vérification complétée.

L'harmonie entre l'architecture ARX, le déroulement sans branchement et le contrôle rigoureux de la mémoire confère à ChaCha20-Poly1305 une efficacité et une fiabilité exemplaires pour les tunnels VPN modernes.

Télécharger VPNRice