7. Échange de clés (Key Exchange)
7. Échange de clés (Key Exchange)
L'échange de clés (key exchange, kex) commence par l'envoi, de chaque côté, de listes de noms (name-lists) d'algorithmes pris en charge. Chaque côté dispose d'un algorithme préféré dans chaque catégorie, et l'on suppose que la plupart des implémentations utiliseront, à un instant donné, le même algorithme préféré. Chaque côté PEUT (MAY) deviner quel algorithme emploie l'autre côté, et PEUT (MAY) envoyer un paquet d'échange de clés initial conformément à l'algorithme, s'il convient à la méthode préférée.
La conjecture est considérée comme erronée si :
-
l'algorithme kex et/ou l'algorithme de clé d'hôte est mal deviné (le serveur et le client ont des algorithmes préférés différents), ou
-
si l'un des autres algorithmes ne peut pas faire l'objet d'un accord (la procédure est définie ci-dessous à la section 7.1).
Sinon, la conjecture est considérée comme correcte, et le paquet envoyé de façon optimiste DOIT (MUST) être traité comme le premier paquet d'échange de clés.
Toutefois, si la conjecture était erronée et qu'un paquet a été envoyé de façon optimiste par une ou les deux parties, de tels paquets DOIVENT (MUST) être ignorés (même si l'erreur de conjecture n'aurait pas affecté le contenu du ou des paquets initiaux), et le côté approprié DOIT (MUST) envoyer le paquet initial correct.
Une méthode d'échange de clés utilise une authentification explicite du serveur (explicit server authentication) si les messages d'échange de clés incluent une signature ou une autre preuve de l'authenticité du serveur. Une méthode d'échange de clés utilise une authentification implicite du serveur (implicit server authentication) si, pour prouver son authenticité, le serveur doit aussi prouver qu'il connaît le secret partagé K, en envoyant un message et un MAC correspondant que le client peut vérifier.
La méthode d'échange de clés définie par ce document utilise une authentification explicite du serveur. Cependant, des méthodes d'échange de clés avec authentification implicite du serveur PEUVENT (MAY) être utilisées avec ce protocole. Après un échange de clés avec authentification implicite du serveur, le client DOIT (MUST) attendre une réponse à son message de demande de service avant d'envoyer d'autres données.
7.1. Négociation d'algorithmes (Algorithm Negotiation)
L'échange de clés commence par l'envoi, de chaque côté, du paquet suivant :
byte SSH_MSG_KEXINIT
byte[16] cookie (random bytes)
name-list kex_algorithms
name-list server_host_key_algorithms
name-list encryption_algorithms_client_to_server
name-list encryption_algorithms_server_to_client
name-list mac_algorithms_client_to_server
name-list mac_algorithms_server_to_client
name-list compression_algorithms_client_to_server
name-list compression_algorithms_server_to_client
name-list languages_client_to_server
name-list languages_server_to_client
boolean first_kex_packet_follows
uint32 0 (reserved for future extension)
Chacune des listes de noms d'algorithmes DOIT (MUST) être une liste d'algorithmes séparés par des virgules (voir la dénomination des algorithmes dans [SSH-ARCH] et des informations complémentaires dans [SSH-NUMBERS]). Chaque algorithme pris en charge (autorisé) DOIT (MUST) figurer dans l'ordre de préférence, du plus au moins préféré.
Le premier algorithme de chaque liste de noms DOIT (MUST) être l'algorithme préféré (deviné). Chaque liste de noms DOIT (MUST) contenir au moins un nom d'algorithme.
cookie
The 'cookie' MUST be a random value generated by the sender.
Its purpose is to make it impossible for either side to fully
determine the keys and the session identifier.
kex_algorithms
Key exchange algorithms were defined above. The first
algorithm MUST be the preferred (and guessed) algorithm. If
both sides make the same guess, that algorithm MUST be used.
Otherwise, the following algorithm MUST be used to choose a key
exchange method: Iterate over client's kex algorithms, one at a
time. Choose the first algorithm that satisfies the following
conditions:
+ the server also supports the algorithm,
+ if the algorithm requires an encryption-capable host key,
there is an encryption-capable algorithm on the server's
server_host_key_algorithms that is also supported by the
client, and
+ if the algorithm requires a signature-capable host key,
there is a signature-capable algorithm on the server's
server_host_key_algorithms that is also supported by the
client.
If no algorithm satisfying all these conditions can be found, the
connection fails, and both sides MUST disconnect.
server_host_key_algorithms
A name-list of the algorithms supported for the server host
key. The server lists the algorithms for which it has host
keys; the client lists the algorithms that it is willing to
accept. There MAY be multiple host keys for a host, possibly
with different algorithms.
Some host keys may not support both signatures and encryption
(this can be determined from the algorithm), and thus not all
host keys are valid for all key exchange methods.
Algorithm selection depends on whether the chosen key exchange
algorithm requires a signature or an encryption-capable host
key. It MUST be possible to determine this from the public key
algorithm name. The first algorithm on the client's name-list
that satisfies the requirements and is also supported by the
server MUST be chosen. If there is no such algorithm, both
sides MUST disconnect.
encryption_algorithms
A name-list of acceptable symmetric encryption algorithms (also
known as ciphers) in order of preference. The chosen
encryption algorithm to each direction MUST be the first
algorithm on the client's name-list that is also on the
server's name-list. If there is no such algorithm, both sides
MUST disconnect.
Note that "none" must be explicitly listed if it is to be
acceptable. The defined algorithm names are listed in Section
6.3.
mac_algorithms
A name-list of acceptable MAC algorithms in order of
preference. The chosen MAC algorithm MUST be the first
algorithm on the client's name-list that is also on the
server's name-list. If there is no such algorithm, both sides
MUST disconnect.
Note that "none" must be explicitly listed if it is to be
acceptable. The MAC algorithm names are listed in Section 6.4.
compression_algorithms
A name-list of acceptable compression algorithms in order of
preference. The chosen compression algorithm MUST be the first
algorithm on the client's name-list that is also on the
server's name-list. If there is no such algorithm, both sides
MUST disconnect.
Note that "none" must be explicitly listed if it is to be
acceptable. The compression algorithm names are listed in
Section 6.2.
languages
This is a name-list of language tags in order of preference
[RFC3066]. Both parties MAY ignore this name-list. If there
are no language preferences, this name-list SHOULD be empty as
defined in Section 5 of [SSH-ARCH]. Language tags SHOULD NOT
be present unless they are known to be needed by the sending
party.
first_kex_packet_follows
Indicates whether a guessed key exchange packet follows. If a
guessed packet will be sent, this MUST be TRUE. If no guessed
packet will be sent, this MUST be FALSE.
After receiving the SSH_MSG_KEXINIT packet from the other side,
each party will know whether their guess was right. If the
other party's guess was wrong, and this field was TRUE, the
next packet MUST be silently ignored, and both sides MUST then
act as determined by the negotiated key exchange method. If
the guess was right, key exchange MUST continue using the
guessed packet.
Après l'échange des messages SSH_MSG_KEXINIT, l'algorithme d'échange de clés est exécuté. Il peut impliquer plusieurs échanges de paquets, comme spécifié par la méthode d'échange de clés.
Une fois qu'un côté a envoyé un message SSH_MSG_KEXINIT pour l'échange ou le ré-échange de clés, jusqu'à ce qu'il ait envoyé un message SSH_MSG_NEWKEYS (section 7.3), il NE DOIT PAS (MUST NOT) envoyer d'autres messages que :
-
les messages génériques de la couche transport (1 à 19) (mais SSH_MSG_SERVICE_REQUEST et SSH_MSG_SERVICE_ACCEPT NE DOIVENT PAS être envoyés) ;
-
les messages de négociation d'algorithmes (20 à 29) (mais d'autres messages SSH_MSG_KEXINIT NE DOIVENT PAS être envoyés) ;
-
les messages spécifiques à la méthode d'échange de clés (30 à 49).
Les dispositions de la section 11 s'appliquent aux messages non reconnus.
Notez toutefois que pendant un ré-échange de clés, après l'envoi d'un message SSH_MSG_KEXINIT, chaque partie DOIT (MUST) être prête à traiter un nombre arbitraire de messages pouvant être en vol avant de recevoir un message SSH_MSG_KEXINIT de l'autre partie.
7.2. Sortie de l'échange de clés (Output from Key Exchange)
L'échange de clés produit deux valeurs : un secret partagé K, et un hachage d'échange H. Les clés de chiffrement et d'authentification en sont dérivées. Le hachage d'échange H issu du premier échange de clés sert en outre d'identifiant de session (session identifier), identifiant unique pour cette connexion. Il est utilisé par les méthodes d'authentification comme partie des données signées en preuve de possession d'une clé privée. Une fois calculé, l'identifiant de session n'est pas modifié, même si les clés sont ré-échangées ultérieurement.
Chaque méthode d'échange de clés spécifie une fonction de hachage utilisée dans l'échange de clés. Le même algorithme de hachage DOIT (MUST) être utilisé dans la dérivation des clés. Nous l'appellerons ici HASH.
Les clés de chiffrement DOIVENT (MUST) être calculées comme HASH, d'une valeur connue et K, comme suit :
-
Vecteur d'initialisation initial (Initial IV) client vers serveur : HASH(K || H || "A" || session_id) (Ici K est encodé en mpint et « A » en octet et session_id en données brutes. « A » désigne le seul caractère A, ASCII 65).
-
IV initial serveur vers client : HASH(K || H || "B" || session_id)
-
Clé de chiffrement client vers serveur : HASH(K || H || "C" || session_id)
-
Clé de chiffrement serveur vers client : HASH(K || H || "D" || session_id)
-
Clé d'intégrité client vers serveur : HASH(K || H || "E" || session_id)
-
Clé d'intégrité serveur vers client : HASH(K || H || "F" || session_id)
Les données de clé DOIVENT (MUST) être prises au début de la sortie du hachage. On prend autant d'octets que nécessaire au début de la valeur de hachage. Si la longueur de clé requise est supérieure à la sortie de HASH, la clé est étendue en calculant HASH de la concaténation de K et H et de l'intégralité de la clé obtenue jusqu'alors, et en ajoutant les octets résultants (autant que HASH en produit) à la clé. Ce processus est répété jusqu'à disposer de suffisamment de matériel de clé ; la clé est prise au début de cette valeur. En d'autres termes :
K1 = HASH(K || H || X || session_id) (X is e.g., "A")
K2 = HASH(K || H || K1)
K3 = HASH(K || H || K1 || K2)
...
key = K1 || K2 || K3 || ...
Ce processus entraînera une perte d'entropie si la quantité d'entropie dans K est supérieure à la taille d'état interne de HASH.
7.3. Mise en service des clés (Taking Keys Into Use)
L'échange de clés se termine par l'envoi, de chaque côté, d'un message SSH_MSG_NEWKEYS. Ce message est envoyé avec les anciennes clés et algorithmes. Tous les messages envoyés après ce message DOIVENT (MUST) utiliser les nouvelles clés et algorithmes.
Lorsque ce message est reçu, les nouvelles clés et algorithmes DOIVENT (MUST) être utilisés pour la réception.
Le rôle de ce message est de garantir qu'une partie est capable de répondre par un message SSH_MSG_DISCONNECT que l'autre partie peut comprendre si quelque chose tourne mal pendant l'échange de clés.
byte SSH_MSG_NEWKEYS