Aller au contenu principal

RFC 6347 - 4.1. Couche d'enregistrement (Record Layer)

4. Différences par rapport à TLS

Comme indiqué à la section 3, DTLS est volontairement très proche de TLS. Au lieu de présenter DTLS comme un nouveau protocole, nous le présentons comme une série de deltas par rapport à TLS 1.2 [TLS12]. Là où aucune différence n'est explicitement mentionnée, DTLS est identique à [TLS12].

4.1. Record Layer

La couche d'enregistrement DTLS est extrêmement similaire à celle de TLS 1.2. Le seul changement est l'inclusion d'un numéro de séquence explicite dans l'enregistrement. Ce numéro permet au destinataire de vérifier correctement le MAC TLS. Le format d'enregistrement DTLS est illustré ci-dessous :

struct {
ContentType type;
ProtocolVersion version;
uint16 epoch; // New field
uint48 sequence_number; // New field
uint16 length;
opaque fragment[DTLSPlaintext.length];
} DTLSPlaintext;

type

Équivalent au champ type d'un enregistrement TLS 1.2.

version

La version du protocole employée. Ce document décrit DTLS 1.2, qui utilise la version { 254, 253 }. La valeur 254.253 est le complément à 1 de la version DTLS 1.2. Cet écart maximal entre les numéros de version TLS et DTLS permet de distinguer facilement les enregistrements des deux protocoles. Les numéros de version sur le fil de DTLS diminueront à l'avenir tandis que le vrai numéro de version augmentera.

epoch

Un compteur incrémenté à chaque changement d'état de chiffrement.

sequence_number

Le numéro de séquence de cet enregistrement.

length

Identique au champ length d'un enregistrement TLS 1.2. Comme en TLS 1.2, la longueur ne doit pas dépasser 2^14.

fragment

Identique au champ fragment d'un enregistrement TLS 1.2.

DTLS utilise un numéro de séquence explicite dans sequence_number plutôt qu'implicite. Les numéros de séquence sont gérés séparément pour chaque epoch, initialement à 0. Par exemple, si un message de handshake de l'epoch 0 est retransmis, il peut avoir un numéro de séquence postérieur à un message de l'epoch 1 même si ce dernier a été envoyé en premier. Pendant le handshake, il faut veiller à ce que les retransmissions utilisent le bon epoch et les bonnes clés.

Si plusieurs handshakes se succèdent rapidement, plusieurs enregistrements peuvent avoir le même numéro de séquence mais des états de chiffrement différents. Le champ epoch permet de les distinguer. L'epoch est initialement zéro et est incrémentée à chaque message ChangeCipherSpec. Pour garantir l'unicité de chaque couple séquence/epoch, les implémentations NE DOIVENT PAS réutiliser la même valeur d'epoch dans un intervalle inférieur à deux fois la durée de vie maximale de segment TCP. En pratique, les re-handshakes TLS sont rares.

Comme les enregistrements DTLS peuvent être réordonnés, un enregistrement de l'epoch 1 peut arriver après le début de l'epoch 2. En général, les implémentations DEVRAIENT rejeter les paquets des epochs antérieures, mais si la perte de paquets pose problème, elles PEUVENT conserver le matériel de clé des epochs précédentes jusqu'au MSL par défaut de TCP [TCP] pour tolérer le réordonnancement. (L'intention est d'utiliser les indications IETF actuelles sur le MSL, pas d'interroger la pile TCP du système.) Jusqu'à la fin du handshake, les implémentations DOIVENT accepter les paquets de l'ancienne epoch.

Inversement, des enregistrements protégés par le nouveau contexte peuvent arriver avant la fin du handshake. Par exemple, le serveur peut envoyer Finished puis des données. Les implémentations PEUVENT mettre en buffer ou rejeter ces paquets ; sur un transport fiable (p. ex. SCTP), elles DEVRAIENT les mettre en buffer jusqu'à la fin du handshake. Les règles TLS sur l'envoi de paquets s'appliquent toujours ; le récepteur les traite comme s'ils étaient dans le bon ordre. En particulier, il reste interdit d'envoyer des données avant la fin du premier handshake.

Dans le cas particulier d'un re-handshake sur une association existante, il est sûr de traiter immédiatement un paquet de données si la reprise reprend la session existante ou utilise exactement les mêmes paramètres de sécurité. Sinon, l'implémentation DOIT attendre Finished pour éviter une attaque par rétrogradation.

Comme en TLS, les implémentations DOIVENT abandonner l'association ou refaire un handshake avant que le numéro de séquence ne boucle.

De même, les implémentations NE DOIVENT PAS permettre à l'epoch de boucler ; elles DOIVENT établir une nouvelle association et terminer l'ancienne comme à la section 4.2.8.

4.1.1. Transport Layer Mapping

Chaque enregistrement DTLS DOIT tenir dans un seul datagramme. Pour éviter la fragmentation IP, les clients de la couche d'enregistrement DTLS DEVRAIENT dimensionner les enregistrements pour qu'ils tiennent dans les estimations PMTU disponibles.

Contrairement à IPsec, les enregistrements DTLS n'ont pas d'identifiant d'association. Les applications doivent multiplexer entre associations ; avec UDP, vraisemblablement par hôte/port.

Plusieurs enregistrements DTLS peuvent être placés dans un même datagramme, encodés consécutivement. Le cadrage DTLS suffit pour délimiter. Le premier octet du payload doit être le début d'un enregistrement ; un enregistrement ne peut pas chevaucher deux datagrammes.

Certains transports (p. ex. DCCP [DCCP]) ont leurs propres numéros de séquence ; DTLS et le transport coexistent. Peu d'inefficacité, mais des rôles différents ; pour la clarté conceptuelle, les deux séquences sont utilisées. Des extensions futures pourraient n'en garder qu'une en environnements contraints.

Sur DCCP, le contrôle de congestion peut retarder les retransmissions du handshake. [DCCPDTLS] définit un mappage DTLS sur DCCP qui en tient compte.

4.1.1.1. PMTU Issues

En général, la philosophie de DTLS est de laisser la découverte de PMTU à l'application. Cependant, DTLS ne peut pas complètement ignorer la PMTU pour trois raisons :

  • Le cadrage des enregistrements DTLS augmente la taille du datagramme, abaissant ainsi la PMTU effective du point de vue de l'application.

  • Dans certaines implémentations, l'application peut ne pas parler directement au réseau, auquel cas la pile DTLS peut absorber les indications ICMP [RFC1191] « Datagram Too Big » ou les indications ICMPv6 [RFC4443] « Packet Too Big ».

  • Les messages de handshake DTLS peuvent dépasser la PMTU.

Afin de traiter les deux premiers problèmes, la couche d'enregistrement DTLS DEVRAIT se comporter comme décrit ci-dessous.

Si des estimations PMTU sont disponibles auprès du protocole de transport sous-jacent, elles devraient être mises à disposition des protocoles de couche supérieure. En particulier :

  • Pour DTLS sur UDP, le protocole de couche supérieure DEVRAIT être autorisé à obtenir l'estimation PMTU maintenue dans la couche IP.

  • Pour DTLS sur DCCP, le protocole de couche supérieure DEVRAIT être autorisé à obtenir l'estimation courante de la PMTU.

  • Pour DTLS sur TCP ou SCTP, qui fragmentent et réassemblent automatiquement les datagrammes, il n'y a pas de limitation PMTU. Cependant, le protocole de couche supérieure NE DOIT PAS écrire d'enregistrement qui dépasse la taille maximale d'enregistrement de 2^14 octets.

La couche d'enregistrement DTLS DEVRAIT permettre au protocole de couche supérieure de découvrir la quantité d'expansion d'enregistrement attendue par le traitement DTLS. Notez que ce nombre n'est qu'une estimation en raison du remplissage de bloc et de l'utilisation potentielle de la compression DTLS.

S'il y a une indication du protocole de transport (soit via ICMP, soit via un refus d'envoi du datagramme comme dans la section 14 de [DCCP]), alors la couche d'enregistrement DTLS DOIT informer le protocole de couche supérieure de l'erreur.

La couche d'enregistrement DTLS NE DEVRAIT PAS interférer avec les protocoles de couche supérieure effectuant la découverte PMTU, que ce soit via les mécanismes [RFC1191] ou [RFC4821]. En particulier :

  • Lorsque cela est permis par le protocole de transport sous-jacent, le protocole de couche supérieure DEVRAIT être autorisé à définir l'état du bit DF (en IPv4) ou à interdire la fragmentation locale (en IPv6).

  • Si le protocole de transport sous-jacent permet à l'application de demander un sondage PMTU (par exemple, DCCP), la couche d'enregistrement DTLS devrait honorer cette demande.

Le dernier problème est le protocole de handshake DTLS. Du point de vue de la couche d'enregistrement DTLS, il s'agit simplement d'un autre protocole de couche supérieure. Cependant, les handshakes DTLS se produisent rarement et n'impliquent que quelques allers-retours ; par conséquent, la gestion PMTU du protocole de handshake privilégie l'achèvement rapide plutôt que la découverte précise de la PMTU. Afin de permettre les connexions dans ces circonstances, les implémentations DTLS DEVRAIENT suivre les règles suivantes :

  • Si la couche d'enregistrement DTLS informe la couche de handshake DTLS qu'un message est trop volumineux, elle DEVRAIT immédiatement tenter de le fragmenter, en utilisant toute information existante sur la PMTU.

  • Si des retransmissions répétées n'aboutissent pas à une réponse, et que la PMTU est inconnue, les retransmissions ultérieures DEVRAIENT reculer vers une taille d'enregistrement plus petite, en fragmentant le message de handshake de manière appropriée. Cette norme ne spécifie pas un nombre exact de retransmissions à tenter avant de reculer, mais 2 à 3 semble approprié.

4.1.2. Record Payload Protection

Comme TLS, DTLS envoie des données sous forme d'enregistrements protégés.

4.1.2.1. MAC

Le MAC DTLS est celui de TLS 1.2, mais le numéro de séquence pour le MAC est la valeur 64 bits formée en concaténant epoch et numéro de séquence dans l'ordre sur le fil (même longueur que le séquence TLS). Le calcul MAC utilise la version sur le fil, {254, 253} pour DTLS 1.2.

En TLS, une erreur MAC impose de fermer la connexion ; en DTLS, l'implémentation PEUT simplement rejeter l'enregistrement et continuer. En général, les implémentations DEVRAIENT rejeter silencieusement les enregistrements invalides ; elles PEUVENT journaliser. Si une alerte est émise pour MAC invalide, elle DOIT être bad_record_mac au niveau fatal et terminer l'état. Les piles DTLS sont des oracles d'erreur plus efficaces ; suivre [TLS12] section 6.2.3.2 est crucial.

4.1.2.2. Null or Standard Stream Cipher

Le chiffrement NULL DTLS est identique à TLS 1.2. RC4 ne permet pas l'accès aléatoire ; RC4 NE DOIT PAS être utilisé avec DTLS.

4.1.2.3. Block Cipher

Chiffrement et déchiffrement par blocs comme TLS 1.2.

4.1.2.4. AEAD Ciphers

Les suites AEAD de [ECCGCM] et [RSAGCM] s'utilisent comme en TLS 1.2.

4.1.2.5. New Cipher Suites

À l'enregistrement, chaque nouvelle suite DOIT indiquer si elle convient à DTLS et quelles adaptations sont nécessaires (section 7).

4.1.2.6. Anti-Replay

Les enregistrements DTLS contiennent un numéro de séquence pour fournir une protection contre la relecture (replay protection). La vérification du numéro de séquence DEVRAIT être effectuée en utilisant la procédure de fenêtre glissante suivante, empruntée à la section 3.4.3 de [ESP].

Le compteur de paquets reçus pour cette session DOIT être initialisé à zéro lorsque la session est établie. Pour chaque enregistrement reçu, le récepteur DOIT vérifier que l'enregistrement contient un numéro de séquence qui ne duplique pas le numéro de séquence de tout autre enregistrement reçu pendant la durée de vie de cette session. Cette vérification DEVRAIT être la première vérification appliquée à un paquet après qu'il ait été associé à une session, afin d'accélérer le rejet des enregistrements dupliqués.

Les doublons sont rejetés par l'utilisation d'une fenêtre de réception glissante. (La manière dont la fenêtre est implémentée est une question locale, mais le texte suivant décrit la fonctionnalité que l'implémentation doit présenter.) Une taille de fenêtre minimale de 32 DOIT être supportée, mais une taille de fenêtre de 64 est préférée et DEVRAIT être employée par défaut. Une autre taille de fenêtre (plus grande que le minimum) PEUT être choisie par le récepteur. (Le récepteur ne notifie pas l'expéditeur de la taille de la fenêtre.)

Le bord « droit » de la fenêtre représente la valeur de numéro de séquence validée la plus élevée reçue sur cette session. Les enregistrements qui contiennent des numéros de séquence inférieurs au bord « gauche » de la fenêtre sont rejetés. Les paquets tombant dans la fenêtre sont vérifiés par rapport à une liste de paquets reçus dans la fenêtre. Un moyen efficace d'effectuer cette vérification, basé sur l'utilisation d'un masque de bits, est décrit dans la section 3.4.3 de [ESP].

Si l'enregistrement reçu tombe dans la fenêtre et est nouveau, ou si le paquet est à droite de la fenêtre, alors le récepteur procède à la vérification du MAC. Si la validation du MAC échoue, le récepteur DOIT rejeter l'enregistrement reçu comme invalide. La fenêtre de réception n'est mise à jour que si la vérification du MAC réussit.

4.1.2.7. Handling Invalid Records

Contrairement à TLS, DTLS est résilient face aux enregistrements invalides (par exemple, formatage invalide, longueur, MAC, etc.). En général, les enregistrements invalides DEVRAIENT être silencieusement rejetés, préservant ainsi l'association ; cependant, une erreur PEUT être enregistrée à des fins de diagnostic. Les implémentations qui choisissent de générer une alerte à la place DOIVENT générer des alertes de niveau fatal pour éviter les attaques où l'attaquant sonde de manière répétée l'implémentation pour voir comment elle répond à divers types d'erreurs. Notez que si DTLS est exécuté sur UDP, alors toute implémentation qui fait cela sera extrêmement susceptible aux attaques par déni de service (DoS) parce que la contrefaçon UDP est si facile. Ainsi, cette pratique N'EST PAS RECOMMANDÉE (NOT RECOMMENDED) pour de tels transports.

Si DTLS est transporté sur un transport résistant à la contrefaçon (par exemple, SCTP avec SCTP-AUTH), alors il est plus sûr d'envoyer des alertes car un attaquant aura des difficultés à contrefaire un datagramme qui ne sera pas rejeté par la couche de transport.