Le protocole TLS 1.3 a été publié en 2018. Ce protocole permet de sécuriser (confidentialité, authentification, intégrité) les communications sur Internet de tout type (web, emails, messagerie instantanée, téléphonie, etc.) de point à point (d'un client à un serveur, par opposition à un chiffrement de bout en bout, c'est-à-dire d'un internaute à un autre). Pour plus d'infos sur TLS 1.3, voir le billet de blog de tonton Bortzmeyer, l'article Prise en main de TLS 1.3 avec OpenSSL 1.1.1 publié dans le numéro 226 de GLMF et l'article RFC 8446 - TLS 1.3 : que faut-il attendre de cette nouvelle version ? publié dans le numéro 105 de MISC.
Pour ma part, je retiens :
Grand nettoyage :
La poignée de main TLS est désormais partiellement confidentielle et intègre. Ça explique pourquoi, au sein d'un échange TLS, on voit très rapidement des messages du type « Application data » auparavant réservés au seul contenu applicatif protégé : ces messages contiennent désormais la fin de la poignée de main sous une forme chiffrée. C'est ça, qui rend envisageable ESNI, le chiffrement du SNI, c'est-à-dire le nom du serveur que l'on cherche à contacter (utile sur un serveur mutualisé afin que le serveur envoie le bon certificat x509, celui du service avec lequel on veut échanger). Les clés de session (je simplifie) sont échangées dans l'extension « Keyshare » des messages « (Client|Server)Hello » puis confirmées après l'échange du certificat du serveur (afin d'en garantir l'authenticité). L'authenticité de la poignée de main n'est garantie qu'à sa fin ;
Afin d'éviter les pare-feux mal-conçus et les boitiers de sécurité foireux massivement déployés, TLS 1.3 imite, au niveau réseau, TLS 1.2 : la version présentée dans le message « ClientHello » est toujours 1.2 alors que la vraie version est négociée dans une extension, on conserve le champ « CompressionMethod » dans les messages « *Hello » alors qu'il n'y a plus de compression TLS (voir ci-dessus), et l'on conserve les messages « ChangeCipherSpec » qui servent pourtant plus à rien, etc. Voilà où nous en sommes pour quelques enfoirés qui font nawak :( ;
Une poignée de main TLS < 1.3 se fait en 2 RTT (deux allers-retours entre le client et le serveur). Hors poignée de main TCP (1 RTT) et hors requête applicative (1 RTT). Je trouve cette présentation trompeuse, car, dans un même trajet (aller ou retour), plusieurs messages TLS seront échangés, potentiellement dans des paquets IP séparés. On tombe à 1 RTT lors de la reprise d'une session existante. Un mode 0 RTT (0-RTT / early-data) apparaît avec TLS 1.3 : lors de la reprise d'une session, on peut envoyer des données applicatives (chiffrées et intègres) dès le premier message. Cela a un coût : on perd la confidentialité persistante (car les données sont chiffrées avec la clé partagée, PSK, contenue dans le ticket de session) et on se rend vulnérable à un rejeu d'une requête capturée sur le réseau. L'application doit gérer cela… sauf qu'il est très compliqué de différencier une requête non-idempotente (donc problèmatique)… Sinon, le serveur TLS doit conserver un état… ce dont personne veut, toute la reprise d'une session est et a toujours été sans état. Je vois jamais une présentation de l'intérêt du mode 0-RTT : je trouve qu'il est utile entre un reverse proxy et un serveur backend afin d'être certain d'une absence de perte de performance, par exemple, sauf si le réseau entre eux est multi-datacenters / international (auquel cas, un risque de surveillance externe existe, et encore, mieux vaut chiffrer + 0-RTT que de faire du trafic en clair) ;
Dans TLS < 1.3, un même champ permettait d'indiquer l'algo pour l'échange de clés, celui pour l'authentification (du pair et des messages TLS), celui pour le chiffrement symétrique et éventuellement celui pour garantir l'intégrité. Désormais, il y a trois champs : échange de clés = « supported groups » (anciennement « supported elliptic curves », mais vu qu'on peut aussi faire du DHE, ce nom ne se justifiait plus et il a sauté avec le RFC 7919), auth = « signature algorithms », chiffrement symétrique et intégrité = « cipher suites » (le vieux champ). Les versions précédentes de TLS utilisent aussi les extensions « supported groups » et « signature algorithms », donc TLS 1.3 acte seulement le changement sémantique du champ « cipher suites » ;
Il n'y a plus d'ordre imposé dans la chaîne des certificats fournie à un client TLS à l'exception que le certificat du serveur doit être le premier. C'était déjà le cas en pratique, c'est désormais dans la norme ;
On note l'apparition d'une extension TLS sympa nommée « certificate_authorities ». Elle indique la liste des autorités de certification connues du client, et elle peut aider le serveur à choisir un certificat qu'il enverra (par exemple en n'envoyant le certificat CAcert que si le client connait cette AC). (j'ai copié cette phrase depuis le blog de tonton Bortz).
La bibliothèque de fonctions cryptographiques OpenSSL implémente TLS v1.3 à partir de sa version 1.1.1. Celle-ci est disponible dans la version Buster (10) de Debian. Donc ma récente mise à jour vers Debian Buster (voir mes notes sur ce qui change et/ou qui pose problème entre Stretch et Buster) m'en ouvre les portes. \o/ Notons que la protection contre le rejeu possible du mode 0-RTT (avec des états côtés serveurs ?) et l'utilisation des groupes finis DHE, entre autres, ne sont pas disponibles dans cette version.
Pour activer TLS 1.3, il y a rien à faire, ni côté client, ni côté serveur, puisque la version de TLS est négociée lors de l'établissement d'une communication chiffrée afin d'en retenir la plus élevée.
Néanmoins, attention aux configurations de serveurs applicatifs qui listent explicitement les versions de TLS utilisables. Exemples : un serveur d'emails Postfix configuré avec smtpd_tls_protocols = !SSLv2, !SSLv3 utilisera automatiquement TLS 1.3 si le client la prend en charge ; Idem pour un serveur IMAP/POP Dovecot configuré avec ssl_min_protocol = TLSv1.2. En revanche, un Apache httpd configure avec SSLProtocol +TLSv1.1 +TLSv1.2 n'utilisera pas TLSv1.3, il faudra le configurer explicitement (SSLProtocol +TLSv1.1 +TLSv1.2 +TLSv1.3) ou exclure les protocoles non-fiables plutôt que de lister les protocoles fiables (voir l'exemple Postfix ci-dessus).
Comment vérifier qu'un serveur applicatif n'utilise pas le mode 0-RTT / early-data (il est désactivé par défaut, c'est aux serveurs applicatifs de l'activer, lire ci-dessus) ? En testant nous-même. Quand un serveur applicatif accepte le mode 0-RTT, il en informe tout client en positionnant l'extension « early_data » dans un ticket de session TLS. Voyons ça en pratique :
openssl s_server -accept 4433 -cert <chemin_vers_certificat_x509> -key <chemin_vers_clé_privée> ;openssl s_client -connect <nom_serveur>:4433 -tlsv1_3. On remarque la ligne « Max Early Data: 0 » dans la section « New Session Ticket arrived » : 0-RTT n'est pas disponible ;openssl s_server -accept 4433 -cert <chemin_vers_certificat_x509> -key <chemin_vers_clé_privée> -early_data. On relance le client TLS. Cette fois-ci, on lit « Max Early Data: 16384 », donc 0-RTT est disponible ;-starttls <protocole> en fonction du cas. ;)-sess_out <nom_fichier_stockage_ticket_TLS>) puis une deuxième en donnant le ticket (-sess_in <nom_fichier_stockage_ticket_TLS>) et en envoyant du contenu (-early_data early_data.txt) qu'il faut créer d'abord (avec echo 'Bonjour' > early_data.txt, par exemple). Si le serveur a accepté nos données utilisateur, OpenSSL affichera « Early data was accepted ». Sinon, il affichera « Early data was not sent ». On peut contrôler tout ça avec Wireshark en déchiffrant l'échange TLS à l'aide de SSLKEYLOGFILE (puisque ces messages TLS sont désormais chiffrés).On peut aussi désactiver le mode 0-RTT dans les logiciels clients. Pour Firefox et Thunderbird, cela se fait en attribuant la valeur « false » à la clé « security.tls.enable_0rtt_data » dans about:config.