Date de publication du RFC : Juillet 2026
Auteur(s) du RFC : E. Rescorla (Independent)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tls
Première rédaction de cet article le 12 juillet 2026
Ce RFC met à jour la norme de la version 1.3 du protocole de cryptographie TLS. Il n'y a pas de grand changement par rapport à son prédécesseur, le RFC 8446.
Regardons un peu en détail le protocole TLS 1.3. Revenons d'abord sur les fondamentaux : TLS est un mécanisme permettant aux applications client/serveur de communiquer au travers d'un réseau non sûr (par exemple l'Internet) tout en empêchant l'écoute et la modification des messages. TLS suppose un mécanisme sous-jacent pour acheminer les bits dans l'ordre, et sans perte. En général, ce mécanisme est TCP (mais une partie de TLS est aussi utilisée pour QUIC). Avec ce mécanisme de transport, et les techniques cryptographiques mises en œuvre par dessus, TLS garantit :
Ces propriétés sont vraies même si l'attaquant contrôle complètement le réseau entre le client et le serveur (le modèle de menace est détaillé dans la section 3 - surtout la 3.3 - du RFC 3552, et dans l'annexe F de notre RFC).
TLS est un protocole gros et compliqué (ce qui n'est pas forcément optimum pour la sécurité). Le RFC fait 161 pages. Pour dompter cette complexité, TLS est séparé en deux composants :
Pour comprendre le rôle de ces deux protocoles, imaginons un protocole fictif simple, qui n'aurait qu'un seul algorithme de cryptographie symétrique, et qu'une seule clé, connue des deux parties (par exemple dans leur fichier de configuration). Avec un tel protocole, on pourrait se passer du protocole de salutation, et n'avoir qu'un protocole des enregistrements, indiquant comment encoder les données chiffrées. Le client et le serveur pourraient se mettre à communiquer immédiatement, sans salutation, poignée de mains et négociation, réduisant ainsi la latence. Un tel protocole serait très simple, donc sa sécurité serait bien plus facile à analyser, ce qui est une bonne chose. Mais il n'est pas du tout réaliste : changer la clé utilisée serait complexe (il faudrait synchroniser exactement les deux parties), remplacer l'algorithme si la cryptanalyse en venait à bout (comme c'est arrivé à RC4, cf. RFC 7465) créerait un nouveau protocole incompatible avec l'ancien, communiquer avec un serveur qu'on n'a jamais vu serait impossible (puisque on ne partagerait pas de clé commune), etc. D'où la nécessité du protocole de salutation, où les partenaires :
Notez que TLS n'est en général pas utilisé tel quel mais via un protocole de haut niveau, comme HTTPS pour sécuriser HTTP. TLS ne suppose pas un usage particulier : on peut s'en servir pour HTTP, pour SMTP (RFC 7672), pour le DNS (RFC 7858), etc. Cette intégration dans un protocole de plus haut niveau pose parfois elle-même des surprises en matière de sécurité, par exemple si l'application utilisatrice ne fait pas attention à la sécurité (Voir mon exposé à Devoxx, et ses transparents.)
TLS 1.3 est plutôt un nouveau protocole qu'une nouvelle version, et il n'est pas directement compatible avec son prédécesseur, TLS 1.2 (une application qui ne connait que 1.3 ne peut pas parler avec une application qui ne connait que 1.2.) En pratique, les bibliothèques qui mettent en œuvre TLS incluent en général les différentes versions, et un mécanisme de négociation de la version utilisée permet normalement de découvrir la version maximum que les deux parties acceptent (historiquement, plusieurs failles sont venues de ce point, avec des pare-feux stupidement configurés qui interféraient avec la négociation).
La section 1.3 de notre RFC liste les différences importantes entre TLS 1.2 (qui était normalisé dans le RFC 5246) et 1.3 :
Un bon résumé de ce protocole est dans l'article de Mark Nottingham.
Ce RFC concerne TLS 1.3 mais il contient aussi quelques changements pour la version 1.2 (section 1.4 du RFC), comme un mécanisme pour limiter les attaques par repli portant sur le numéro de version, et des mécanismes de la 1.3 « portés » vers la 1.2 sous forme d'extensions TLS.
Et les changements depuis le RFC 8446, le
premier qui avait normalisé TLS 1.3 ? Ils sont peu importants, le
plus spectaculaire étant le remplacement de toutes les occurrences de
master par main dans les noms
de variable. Ainsi, resumption_master_secret
est devenu resumption_secret et le
extended_master_secret du RFC 7627 est
devenu extended_main_secret. Il s'agissait de
répondre à une obsession étatsunienne mais je ne sais pas si ce
changement sera propagé dans les programmes qui mettent en œuvre
TLS (noms des variables et texte affiché, regardez l'exemple
Wireshark plus bas). Tous ces changements depuis le RFC 8446
sont résumés dans la section 1.2 mais il s'agit surtout de détails
et de précisions : la version 1.3 du protocole ne change pas.
La section 2 du RFC est un survol général de TLS 1.3 (le RFC fait 161 pages, et peu de gens le liront intégralement). Au début d'une session TLS, les deux parties, avec le protocole de salutation, négocient les paramètres (version de TLS, algorithmes cryptographiques) et définissent les clés qui seront utilisées pour le chiffrement de la session. En simplifiant, il y a trois phases dans l'établissement d'une session TLS :
ClientHello, le serveur répond avec un ServerHello,CertificateRequest d'un certificat client), cette partie est
chiffrée, contrairement à la précédente,Certificate (qui ne contient pas
forcément un certificat, cela peut être une clé brute - RFC 7250 ou une clé d'une session précédente -
RFC 7924).
Un message Finished termine cette ouverture
de session.
(Si vous êtes fana de futurisme, notez que seule la première étape
pourrait être remplacée par la distribution quantique
de clés, les autres resteraient
indispensables. Contrairement à ce que promettent ses promoteurs,
la QKD ne dispense pas d'utiliser les protocoles existants.)
Comment les deux parties se mettent-elles d'accord sur les clés ? Trois méthodes :
Si vous connaissez la cryptographie, vous savez que les PSK, les clés partagées, sont difficiles à gérer, puisque devant être transmises de manière sûre avant l'établissement de la connexion. Mais, dans TLS, une autre possibilité existe : si une session a été ouverte sans PSK, en n'utilisant que de la cryptographie asymétrique, elle peut être enregistrée, et resservir, afin d'ouvrir les futures discussions plus rapidement. TLS 1.3 utilise le même mécanisme pour des « vraies » PSK, et pour celles issues de cette reprise de sessions précédentes (contrairement aux précédentes versions de TLS, qui utilisaient un mécanisme séparé, celui du RFC 5077, désormais abandonné).
Si on a une PSK (gérée manuellement, ou bien via la reprise de session), on peut même avoir un dialogue TLS dit « 0-RTT ». Le premier paquet du client peut contenir des données, qui seront acceptées et traitées par le serveur. Cela permet une importante diminution de la latence, dont il faut rappeler qu'elle est souvent le facteur limitant des performances. Par contre, comme rien n'est idéal dans cette vallée de larmes, cela se fait au détriment de la sécurité :
La section 8 du RFC et l'annexe F.5 détaillent ces limites, et les mesures qui peuvent être prises.
Le protocole TLS est décrit avec un langage spécifique, décrit de manière relativement informelle dans la section 3 du RFC. Ce langage manipule des types de données classiques :
uint8, uint16),Datum[3] ou
variable, avec indication de la longueur au début -
uint16 longer<0..800>,enum { red(3), blue(5), white(7) }
Color;),Par exemple, tirés de la section 4 (l'annexe B fournit la liste complète), voici, dans ce langage, la liste des types de messages pendant les salutations, une énumération :
enum {
client_hello(1),
server_hello(2),
new_session_ticket(4),
end_of_early_data(5),
encrypted_extensions(8),
certificate(11),
certificate_request(13),
certificate_verify(15),
finished(20),
key_update(24),
message_hash(254),
(255)
} HandshakeType;
Et le format de base d'un message du protocole de salutation :
struct {
HandshakeType msg_type; /* handshake type */
uint24 length; /* bytes in message */
select (Handshake.msg_type) {
case client_hello: ClientHello;
case server_hello: ServerHello;
case end_of_early_data: EndOfEarlyData;
case encrypted_extensions: EncryptedExtensions;
case certificate_request: CertificateRequest;
case certificate: Certificate;
case certificate_verify: CertificateVerify;
case finished: Finished;
case new_session_ticket: NewSessionTicket;
case key_update: KeyUpdate;
};
} Handshake;
La section 4 fournit tous les détails sur le protocole de
salutation, notamment sur la délicate négociation des paramètres
cryptographiques. Notez que la renégociation en cours de session a
disparu, donc un ClientHello ne peut
désormais plus être envoyé qu'au début.
Un problème auquel a toujours dû faire face TLS est celui de la
négociation de version, en présence de mises en œuvre boguées, et,
surtout, en présence de boitiers intermédiaires encore plus
bogués (pare-feux ignorants, par exemple, que
des DSI ignorantes placent un peu
partout). Le modèle original de TLS pour un client était d'annoncer
dans le ClientHello le plus grand numéro de
version qu'on gère, et de voir dans ServerHello
le maximum imposé par le serveur. Ainsi, un client TLS 1.2 parlant à
un serveur qui ne gère que 1.1 envoyait
ClientHello(client_version=1.2) et, en recevant
ServerHello(server_version=1.1), se repliait
sur TLS 1.1, la version la plus élevée que les deux parties
gèraient. En pratique, cela ne marche pas aussi bien. On voyait par
exemple des serveurs (ou, plus vraisemblablement, des pare-feux
bogués) qui raccrochaient brutalement en présence d'un numéro de
version plus élevé, au lieu de suggérer un repli. Le client n'avait
alors que le choix de renoncer, ou bien de se lancer dans une série
d'essais/erreurs (qui peut être longue, si le serveur ou le pare-feu
bogué ne répond pas).
TLS 1.3 change donc complètement le
mécanisme de négociation. Le client annonce toujours la version 1.2
(en fait 0x303, pour des raisons historiques), et la vraie version
est mise dans une extension, supported_versions
(section 4.2.1), dont on espère qu'elle sera ignorée par les
serveurs mal gérés. (L'annexe D du RFC détaille ce problème de la
négociation de version.) Dans la réponse
ServerHello, un serveur 1.3 doit inclure cette
extension, autrement, il faut se rabattre sur TLS 1.2.
En
parlant d'extensions, concept qui avait été introduit originellement
dans le RFC 4366, notre RFC reprend des
extensions déjà normalisées, comme le SNI (Server Name
Indication) du RFC 6066, le
battement de cœur du RFC 6520, le remplissage
du ClientHello du RFC 7685, et en ajoute dix, dont
supported_versions. Certaines de ces extensions
doivent être présentes dans les messages Hello,
car la sélection des paramètres cryptographiques en dépend, d'autres
peuvent être uniquement dans les messages
EncryptedExtensions, une nouveauté de TLS 1.3,
pour les extensions qu'on n'enverra qu'une fois le chiffrement
commencé. Le RFC en profite pour rappeler que les messages
Hello ne sont pas protégés cryptographiquement,
et peuvent donc être modifiés (le message
Finished résume les décisions prises et peut
donc protéger contre ce genre d'attaques).
Autrement, parmi les autres nouvelles extensions :
La section 5 décrit le protocole des enregistrements (record protocol). C'est ce sous-protocole qui va prendre un flux d'octets, le découper en enregistrements, les protéger par le chiffrement puis, à l'autre bout, déchiffrer et reconstituer le flux… Notez que « protégé » signifie à la fois confidentialité et intégrité puisque TLS 1.3, contrairement à ses prédécesseurs, impose AEAD (RFC 5116).
Les enregistrements sont typés et marqués handshake (la salutation, vue dans la section précédente), change cipher spec, alert (pour signaler un problème) et application data (les données elle-mêmes) :
enum {
invalid(0),
change_cipher_spec(20),
alert(21),
handshake(22),
application_data(23),
(255)
} ContentType;
Le contenu des données est évidemment incompréhensible, en raison du chiffrement (voici un enregistrement de type 23, données, vu par tshark) :
TLSv1.3 Record Layer: Application Data Protocol: http-over-tls
Opaque Type: Application Data (23)
Version: TLS 1.2 (0x0303)
Length: 6316
Encrypted Application Data: eb0e21f124f82eee0b7a37a1d6d866b075d0476e6f00cae7...
Et décrite par la norme dans son langage formel :
struct {
ContentType opaque_type = application_data; /* 23 */
ProtocolVersion legacy_record_version = 0x0303; /* TLS v1.2 */
uint16 length;
opaque encrypted_record[TLSCiphertext.length];
} TLSCiphertext;
(Oui, le numéro de version reste à TLS 1.2 pour éviter d'énerver les stupides middleboxes.) Notez que des extensions à TLS peuvent introduire d'autres types d'enregistrements.
Une faiblesse classique de TLS est que la taille des données chiffrées n'est pas dissimulée. Si on veut savoir à quelle page d'un site Web un client HTTP a accédé, on peut parfois le déduire de l'observation de cette taille. D'où la possibilité de faire du remplissage pour dissimuler cette taille (section 5.4 du RFC). Notez que le RFC ne suggère pas de politique de remplissage spécifique (ajouter un nombre aléatoire ? Tout remplir jusqu'à la taille maximale ?), c'est un choix compliqué. Il note aussi que certaines applications font leur propre remplissage, et qu'il n'est alors pas nécessaire que TLS le fasse.
La section 6 du RFC est dédiée au cas des alertes. C'est un des types d'enregistrements possibles, et, comme les autres, il est chiffré, et les alertes sont donc confidentielles. Une alerte a un niveau et une description :
struct {
AlertLevel level;
AlertDescription description;
} Alert;
Le niveau indiquait si l'alerte est fatale mais n'est plus utilisé en TLS 1.2, où il faut se fier uniquement à la description, une énumération des problèmes possibles (message de type inconnu, mauvais certificat, enregistrement non décodable - rappelez-vous que TLS 1.3 n'utilise que du chiffrement intègre -, problème interne au client ou au serveur, extension non acceptée, etc). La section 6.2 donne une liste des erreurs fatales, qui doivent mener à terminer immédiatement la session TLS.
La section 8 du RFC est entièrement consacrée à une nouveauté délicate, le « 0-RTT ». Ce terme désigne la possibilité d'envoyer des données dès le premier paquet, sans les nombreux échanges de paquets qui sont normalement nécessaires pour établir une session TLS. C'est très bien du point de vue des performances, mais pas forcément du point de vue de la sécurité puisque, sans échanges, on ne peut plus vérifier à qui on parle. Un attaquant peut réaliser une attaque par rejeu en envoyant à nouveau un paquet qu'il a intercepté. Un serveur doit donc se défendre en se souvenant des données déjà envoyées et en ne les acceptant pas deux fois. (Ce qui peut être plus facile à dire qu'à faire ; le RFC contient une bonne discussion très détaillée des techniques possibles, et de leurs limites. Il y en a des subtiles, comme d'utiliser des systèmes de mémorisation ayant des faux positifs, comme les filtres de Bloom, parce qu'ils ne produiraient pas d'erreurs, ils rejetteraient juste certains essais 0-RTT légitimes, cela ne serait donc qu'une légère perte de performance.)
La section 9 de notre RFC se penche sur un problème difficile, la
conformité des mises en œuvres de TLS. D'abord, les algorithmes
obligatoires. Afin de permettre l'interopérabilité,
toute mise en œuvre de TLS doit avoir la suite
de chiffrement TLS_AES_128_GCM_SHA256
(AES en
mode GCM avec
SHA-256). D'autres suites sont recommandées
(cf. annexe B.4). Pour l'authentification, RSA avec SHA-256
et ECDSA sont obligatoires. Ainsi, deux
programmes différents sont sûrs de pouvoir trouver des algorithmes
communs. La possibilité
d'authentification par certificats PGP du RFC 6091 a été
retirée.
De plus, certaines extensions à TLS sont obligatoires, un pair TLS 1.3 ne peut pas les refuser :
supported_versions, nécessaire pour
annoncer TLS 1.3,cookie,signature_algorithms,
signature_algorithms_cert,
supported_groups et
key_share,server_name, c'est à dire SNI
(Server Name Indication), souvent nécessaire
pour pouvoir choisir le bon certificat (cf. section 3 du RFC 6066).La section 9 précise aussi le comportement attendu des équipements intermédiaires. Ces dispositifs (pare-feux, par exemple, mais pas uniquement) ont toujours été une plaie pour TLS. Alors que TLS vise à fournir une communication sûre, à l'abri des équipements intermédiaires, ceux-ci passent leur temps à essayer de s'insérer dans la communication, et souvent la cassent. Normalement, TLS 1.3 est conçu pour que ces interférences ne puissent pas mener à un repli (le repli est l'utilisation de paramètres moins sûrs que ce que les deux machines auraient choisi en l'absence d'interférence).
Il y a deux grandes catégories d'intermédiaires, ceux qui tripotent la session TLS sans être le client ou le serveur, et ceux qui terminent la session TLS de leur côté. Attention, dans ce contexte, « terminer » ne veut pas dire « y mettre fin », mais « la sécurité TLS se termine ici, de manière à ce que l'intermédiaire puisse accéder au contenu de la communication ». Typiquement, une middlebox qui « termine » une session TLS va être serveur TLS pour le client et client TLS pour le serveur, s'insérant complètement dans la conversation. Normalement, l'authentification vise à empêcher ce genre de pratiques, et l'intermédiaire ne sera donc accepté que s'il a un certificat valable. C'est pour cela qu'en entreprise, les machines officielles sont souvent installées avec une AC contrôlée par le vendeur du boitier intermédiaire, de manière à permettre l'interception.
Le RFC ne se penche pas sur la légitimité de ces pratiques, uniquement sur leurs caractéristiques techniques. (Les boitiers intermédiaires sont souvent programmés avec les pieds, et ouvrent de nombreuses failles.) Le RFC rappelle notamment que l'intermédiaire qui termine une session doit suivre le RFC à la lettre (ce qui devrait aller sans dire…)
Depuis le RFC 4346, il existe plusieurs registres IANA pour TLS, décrits en section 11, avec leurs nouveautés. En effet, plusieurs choix pour TLS ne sont pas « câblés en dur » dans le RFC mais peuvent évoluer indépendamment. Par exemple, le registre de suites cryptographiques a une politique d'enregistrement « spécification nécessaire » (cf. RFC 8126, sur les politiques d'enregistrement). La cryptographie fait régulièrement des progrès, et il faut donc pouvoir modifier la liste des suites acceptées (par exemple lorsqu'il faudra y ajouter les algorithmes post-quantiques) sans avoir à toucher au RFC (l'annexe B.4 donne la liste actuelle). Le registre des types de contenu, lui, a une politique d'enregistrement bien plus stricte, « action de normalisation ». On crée moins souvent des types que des suites cryptographiques. Même chose pour le registre des alertes ou pour celui des salutations.
L'annexe C du RFC plaira aux programmeurs, elle donne plusieurs conseils pour une mise en œuvre correcte de TLS 1.3 (ce n'est pas tout d'avoir un protocole correct, il faut encore qu'il soit programmé correctement). Pour aider les développeurs à déterminer s'ils ont correctement fait le travail, le RFC 8448 fournit des vecteurs de test.
Un des conseils les plus importants est évidemment de faire
attention au générateur de nombres aléatoires, source de
tant de failles de sécurité en cryptographie. TLS utilise des
nombres qui doivent être imprévisibles à un attaquant pour générer
des clés de session. Si ces nombres sont prévisibles, toute la
cryptographie s'effondre. Le RFC conseille fortement d'utiliser un
générateur existant (comme /dev/urandom sur les
systèmes Unix) plutôt que d'écrire le sien,
ce qui est bien plus difficile qu'il ne semble. (Si on tient quand
même à le faire, le RFC 4086 est une lecture
indispensable.)
Le RFC conseille également de vérifier le certificat du partenaire par défaut (quitte à fournir un moyen de débrayer cette vérification). Si ce n'est pas le cas, beaucoup d'utilisateurs du programme ou de la bibliothèque oublieront de le faire. Il suggère aussi de ne pas accepter certains certificats trop faibles (clé RSA de seulement 1 024 bits, par exemple).
Il existe plusieurs moyens avec TLS de ne pas avoir d'authentification du serveur : les clés brutes du RFC 7250 (à la place des certificats), ou bien les certificats auto-signés. Dans ces conditions, une attaque de l'homme du milieu est parfaitement possible, et il faut donc prendre des précautions supplémentaires (par exemple DANE, normalisé dans le RFC 6698, que le RFC oublie malheureusement de citer).
Autre bon conseil de cryptographie, se méfier des attaques fondées sur la mesure du temps de calcul, et prendre des mesures appropriées (par exemple en vérifiant que le temps de calcul est le même pour des données correctes et incorrectes).
Il n'y a aucune bonne raison d'utiliser certains algorithmes faibles (comme RC4, abandonné depuis le RFC 7465), et le RFC demande que le code pour ces algorithmes ne soit pas présent, afin d'éviter une attaque par repli (annexes C.3 et D.5 du RFC). De la même façon, il demande de ne jamais accepter SSL v3 (RFC 7568).
L'expérience a prouvé que beaucoup de mises en œuvre de TLS ne réagissaient pas correctement à des options inattendues, et le RFC rappelle donc qu'il faut ignorer les suites cryptographiques inconnues (autrement, on ne pourrait jamais introduire une nouvelle suite, puisqu'elle casserait les programmes), et ignorer les extensions inconnues (pour la même raison).
L'annexe D, elle, est consacrée au problème de la communication
avec un vieux partenaire, qui ne connait pas TLS 1.3. Le mécanisme
de négociation de la version du protocole à utiliser a complètement
changé en 1.3. Dans la 1.3, le champ version du
ClientHello contient 1.2, la vraie version
étant dans l'extension supported_versions. Si
un client 1.3 parle avec un serveur <= 1.2, le serveur ne
connaitra pas cette extension et répondra sans l'extension,
avertissant ainsi le client qu'il faudra parler en 1.2 (ou plus
vieux). Ça, c'est si le serveur est correct. S'il ne l'est pas ou,
plus vraisemblablement, s'il est derrière une middlebox
boguée, on verra des problèmes comme par exemple le refus de
répondre aux clients utilisant des extensions inconnues (ce qui sera
le cas pour supported_versions), soit en
rejettant ouvertement la demande soit, encore pire, en
l'ignorant. Arriver à gérer des
serveurs/middleboxes incorrects est un problème
complexe. Le client peut être tenté de re-essayer avec d'autres
options (par exemple tenter du 1.2, sans l'extension
supported_versions). Cette méthode n'est pas
conseillée. Non seulement elle peut prendre du temps (attendre
l'expiration du délai de garde, re-essayer…) mais surtout, elle
ouvre la voie à des attaques par repli : l'attaquant bloque les
ClientHello 1.3 et le client, croyant bien
faire, se replie sur une version plus ancienne et sans doute moins
sûre de TLS.
En parlant de compatibilité, le « 0-RTT » n'est évidemment pas
compatible avec les vieilles versions. Le client qui envoie du
« 0-RTT » (des données dans le ClientHello)
doit donc savoir que, si la réponse est d'un serveur <= 1.2,
la session ne pourra pas être établie, et il faudra donc réessayer
sans 0-RTT.
Naturellement, les plus gros problèmes ne surviennent pas avec
les clients et les serveurs mais avec les
middleboxes. Plusieurs études ont montré leur
caractère néfaste (cf. présentation
à l'IETF 100, mesures
avec Chrome (qui indique également que certains serveurs TLS
sont gravement en tort, comme celui installé dans les imprimantes
Canon), mesures
avec Firefox, et encore
d'autres mesures). Le RFC suggère qu'on limite les risques en
essayant d'imiter le plus possible une salutation de TLS 1.2, par
exemple en envoyant des messages
change_cipher_spec, qui ne sont plus utilisés
en TLS 1.3, mais qui peuvent rassurer la
middlebox (annexe D.4).
Enfin, le RFC se termine par l'annexe E, qui énumère les propriétés de sécurité de TLS 1.3 : même face à un attaquant actif (RFC 3552), le protocole de salutation de TLS garantit des clés de session communes et secrètes, une authentification du serveur (et du client si on veut), et une sécurité persistante, même en cas de compromission ultérieure des clés (sauf en cas de 0-RTT, un autre des inconvénients sérieux de ce service, avec le risque de rejeu). De nombreuses analyses détaillées de la sécurité de TLS sont listées dans l'annexe E.1.6. À lire si vous voulez travailler ce sujet.
Quant au protocole des enregistrements, celui de TLS 1.3 garantit confidentialité et intégrité (RFC 5116).
TLS 1.3 a fait l'objet de nombreuses analyses de sécurité par des chercheurs, avant même sa normalisation, ce qui est une bonne chose (et qui explique en partie les retards). Notre annexe E pointe également les limites restantes de TLS :
Le 0-RTT introduit un nouveau risque, celui de rejeu. (Et 0-RTT a sérieusement contribué aux délais qu'à connu le projet TLS 1.3, plusieurs participants à l'IETF protestant contre cette introduction risquée.) Si l'application est idempotente, ce n'est pas très grave. Si, par contre, les effets d'une requête précédentes peuvent être rejoués, c'est plus embêtant (imaginez un transfert d'argent répété…) TLS ne promet rien en ce domaine, c'est à chaque serveur de se défendre contre le rejeu (la section 8 donne des idées à ce sujet). Voilà pourquoi le RFC demande que les requêtes 0-RTT ne soient pas activées par défaut, mais uniquement quand l'application au-dessus de TLS le demande. (Cloudflare, par exemple, n'active pas le 0-RTT par défaut.)
Voilà, vous avez maintenant fait un tour complet du RFC, mais vous savez que la cryptographie est une chose difficile, et pas seulement dans les algorithmes cryptographiques (TLS n'en invente aucun, il réutilise des algorithmes existants comme AES ou ECDSA), mais aussi dans les protocoles cryptographiques, un art complexe. N'hésitez donc pas à lire le RFC en détail, et à vous méfier des résumés forcément toujours sommaires, comme cet article.
À part le 0-RTT, le plus gros débat lors de la création de TLS
1.3 avait été autour du concept que ses partisans nomment
« visibilité » et ses adversaires « surveillance ». C'est l'idée
qu'il serait bien pratique si on (on : le patron, la police, le
FAI…)
pouvait accéder au contenu des communications TLS. « Le chiffrement,
c'est bien, à condition que je puisse lire les données quand même »
est l'avis des partisans de la visibilité. Cela avait été proposé
dans les Internet-Drafts draft-green-tls-static-dh-in-tls13
et draft-rhrd-tls-tls13-visibility. Je
ne vais pas ici pouvoir capturer la totalité du débat, juste noter
quelques points qui sont parfois oubliés dans la discussion. Côté
partisans de la visibilité :
Et du côté des adversaires de la surveillance :
Revenons maintenant aux choses sérieuses, avec les mises en œuvre de TLS 1.3. Il y en existe au moins une dizaine à l'heure actuelle et la version 1.3 est désormais largement déployée.
Par exemple, avec un GnuTLS récent, on peut utiliser le
programme en ligne de commande gnutls-cli avec
un serveur qui accepte TLS 1.3 :
% gnutls-cli -V gmail.com ... - Description: (TLS1.3-X.509)-(ECDHE-SECP256R1)-(ECDSA-SECP256R1-SHA256)-(AES-256-GCM) - Ephemeral EC Diffie-Hellman parameters - Using curve: SECP256R1 - Curve size: 256 bits - Version: TLS1.3 - Server Signature: ECDSA-SECP256R1-SHA256 - Cipher: AES-256-GCM - MAC: AEAD ...
Et ça marche, on fait du TLS 1.3. Si vous préférez écrire le
programme vous-même, regardez ce petit
programme. Si GnuTLS est en /local, il
se compilera avec cc -I/local/include -Wall -Wextra -o
test-tls13 test-tls13.c -L/local/lib -lgnutls et
s'utilisera avec :
% ./test-tls13 www.ietf.org TLS connection using "TLS1.3 AES-256-GCM" % ./test-tls13 gmail.com TLS connection using "TLS1.3 AES-256-GCM" % ./test-tls13 blog.cloudflare.com TLS connection using "TLS1.3 AES-256-GCM" % ./test-tls13 cr.yp.to TLS connection using "TLS1.2 CHACHA20-POLY1305"
Cela vous donne une petite idée des serveurs qui acceptent TLS 1.3 (le dernier testé ne l'accepte pas).
Un pcap d'une session TLS 1.3 est
disponible en tls13-2.pcap. Regardez le numéro de
version de TLS dans l'extension (0x304), qui identifie TLS 1.3. Voici la
session vue par tshark :
1 0.000000 2001:41d0:302:2200::180 → 2606:4700::6810:7b60 TCP 94 56462 → 443 [SYN] Seq=0 Win=64800 Len=0 MSS=1440 SACK_PERM TSval=2022119812 TSecr=0 WS=1024
2 0.005516 2606:4700::6810:7b60 → 2001:41d0:302:2200::180 TCP 94 443 → 56462 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1360 SACK_PERM TSval=4271324975 TSecr=2022119812 WS=8192
3 0.005539 2001:41d0:302:2200::180 → 2606:4700::6810:7b60 TCP 86 56462 → 443 [ACK] Seq=1 Ack=1 Win=65536 Len=0 TSval=2022119818 TSecr=4271324975
4 0.005837 2001:41d0:302:2200::180 → 2606:4700::6810:7b60 TLSv1 492 Client Hello (SNI=www.cloudflare.com)
5 0.011387 2606:4700::6810:7b60 → 2001:41d0:302:2200::180 TCP 86 443 → 56462 [ACK] Seq=1 Ack=407 Win=131072 Len=0 TSval=4271324981 TSecr=2022119818
6 0.013523 2606:4700::6810:7b60 → 2001:41d0:302:2200::180 TLSv1.3 1434 Server Hello, Change Cipher Spec
7 0.013523 2606:4700::6810:7b60 → 2001:41d0:302:2200::180 TCP 520 [TCP Previous segment not captured] 443 → 56462 [PSH, ACK] Seq=2697 Ack=407 Win=131072 Len=434 TSval=4271324983 TSecr=2022119818 [TCP segment of a reassembled PDU]
8 0.013523 2606:4700::6810:7b60 → 2001:41d0:302:2200::180 TCP 1434 [TCP Out-Of-Order] 443 → 56462 [ACK] Seq=1349 Ack=407 Win=131072 Len=1348 TSval=4271324983 TSecr=2022119818
9 0.013543 2001:41d0:302:2200::180 → 2606:4700::6810:7b60 TCP 86 56462 → 443 [ACK] Seq=407 Ack=1349 Win=68608 Len=0 TSval=2022119826 TSecr=4271324983
10 0.013555 2001:41d0:302:2200::180 → 2606:4700::6810:7b60 TCP 98 [TCP Dup ACK 9#1] 56462 → 443 [ACK] Seq=407 Ack=1349 Win=68608 Len=0 TSval=2022119826 TSecr=4271324983 SLE=2697 SRE=3131
11 0.013560 2001:41d0:302:2200::180 → 2606:4700::6810:7b60 TCP 86 56462 → 443 [ACK] Seq=407 Ack=3131 Win=68608 Len=0 TSval=2022119826 TSecr=4271324983
12 0.013799 2001:41d0:302:2200::180 → 2606:4700::6810:7b60 TLSv1.3 92 Change Cipher Spec
13 0.028771 2001:41d0:302:2200::180 → 2606:4700::6810:7b60 TLSv1.3 160 Application Data
14 0.034250 2606:4700::6810:7b60 → 2001:41d0:302:2200::180 TCP 86 443 → 56462 [ACK] Seq=3131 Ack=488 Win=131072 Len=0 TSval=4271325004 TSecr=2022119826
15 0.035800 2606:4700::6810:7b60 → 2001:41d0:302:2200::180 TCP 86 443 → 56462 [FIN, ACK] Seq=3131 Ack=488 Win=131072 Len=0 TSval=4271325005 TSecr=2022119826
16 0.035821 2001:41d0:302:2200::180 → 2606:4700::6810:7b60 TCP 86 56462 → 443 [ACK] Seq=488 Ack=3132 Win=69632 Len=0 TSval=2022119848 TSecr=4271325005
Et, complètement décodée par tshark :
Transport Layer Security
TLSv1 Record Layer: Handshake Protocol: Client Hello
Content Type: Handshake (22)
Version: TLS 1.0 (0x0301)
Length: 401
Handshake Protocol: Client Hello
Handshake Type: Client Hello (1)
Length: 397
Version: TLS 1.2 (0x0303)
Cipher Suites Length: 58
Cipher Suites (29 suites)
Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)
Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 (0x1303)
…
Compression Methods Length: 1
Compression Methods (1 method)
Compression Method: null (0)
Extensions Length: 266
Extension: ec_point_formats (len=2)
Type: ec_point_formats (11)
Length: 2
EC point formats Length: 1
Elliptic curves point formats (1)
EC point format: uncompressed (0)
Extension: key_share (len=107) secp256r1, x25519
Type: key_share (51)
Length: 107
Key Share extension
Client Key Share Length: 105
Key Share Entry: Group: secp256r1, Key Exchange length: 65
Group: secp256r1 (23)
Key Exchange Length: 65
Key Exchange: 04baaae9e5261e75a052917c5266e92491905e012c8403dacdb3ae5cd4edc025d87d6d1131fb01e1c71d031cd5c1e4eaa49a8db64dceea2238a2f459206f5e592a
Key Share Entry: Group: x25519, Key Exchange length: 32
Group: x25519 (29)
Key Exchange Length: 32
Key Exchange: 81f6e52c0e771d320529cdff1729c1c290842a68044f86223a80cf608926be5d
Extension: server_name (len=23) name=www.cloudflare.com
Type: server_name (0)
Length: 23
Server Name Indication extension
Server Name list length: 21
Server Name Type: host_name (0)
Server Name length: 18
Server Name: www.cloudflare.com
Extension: status_request (len=5)
Type: status_request (5)
Length: 5
Certificate Status Type: OCSP (1)
Responder ID list Length: 0
Request Extensions Length: 0
Extension: session_ticket (len=0)
Type: session_ticket (35)
Length: 0
Session Ticket: <MISSING>
Extension: supported_groups (len=22)
Type: supported_groups (10)
Length: 22
Supported Groups List Length: 20
Supported Groups (10 groups)
Supported Group: secp256r1 (0x0017)
Supported Group: secp384r1 (0x0018)
Supported Group: secp521r1 (0x0019)
Supported Group: x25519 (0x001d)
Supported Group: x448 (0x001e)
Supported Group: ffdhe2048 (0x0100)
Supported Group: ffdhe3072 (0x0101)
Supported Group: ffdhe4096 (0x0102)
Supported Group: ffdhe6144 (0x0103)
Supported Group: ffdhe8192 (0x0104)
Extension: record_size_limit (len=2)
Type: record_size_limit (28)
Length: 2
Record Size Limit: 16385
Extension: encrypt_then_mac (len=0)
Type: encrypt_then_mac (22)
Length: 0
Extension: supported_versions (len=9) TLS 1.3, TLS 1.2, TLS 1.1, TLS 1.0
Type: supported_versions (43)
Length: 9
Supported Versions length: 8
Supported Version: TLS 1.3 (0x0304)
Supported Version: TLS 1.2 (0x0303)
Supported Version: TLS 1.1 (0x0302)
Supported Version: TLS 1.0 (0x0301)
Extension: psk_key_exchange_modes (len=3)
Type: psk_key_exchange_modes (45)
Length: 3
PSK Key Exchange Modes Length: 2
PSK Key Exchange Mode: PSK with (EC)DHE key establishment (psk_dhe_ke) (1)
PSK Key Exchange Mode: PSK-only key establishment (psk_ke) (0)
Extension: extended_master_secret (len=0)
Type: extended_master_secret (23)
Length: 0
Extension: signature_algorithms (len=40)
Type: signature_algorithms (13)
Length: 40
Signature Hash Algorithms Length: 38
Signature Hash Algorithms (19 algorithms)
Signature Algorithm: Unknown SM2 (0x0904)
Signature Hash Algorithm Hash: Unknown (9)
Signature Hash Algorithm Signature: SM2 (4)
Signature Algorithm: Unknown Unknown (0x0905)
Signature Hash Algorithm Hash: Unknown (9)
Signature Hash Algorithm Signature: Unknown (5)
…
Extension: renegotiation_info (len=1)
Type: renegotiation_info (65281)
Length: 1
Renegotiation Info extension
Renegotiation info extension length: 0
Le texte complet est en tls13-2.txt. Notez bien que la négociation est
en clair. D'autres exemples de traces TLS 1.3 figurent dans le RFC 8448.
Quelques autres articles à lire :
Version PDF de cette page (mais vous pouvez aussi imprimer depuis votre navigateur, il y a une feuille de style prévue pour cela)
Source XML de cette page (cette page est distribuée sous les termes de la licence GFDL)