ssh_kex_dh.c
Go to the documentation of this file.
1 /**
2  * @file ssh_kex_dh.c
3  * @brief Diffie-Hellman key exchange
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2019-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneSSH Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL SSH_TRACE_LEVEL
33 
34 //Dependencies
35 #include "ssh/ssh.h"
36 #include "ssh/ssh_algorithms.h"
37 #include "ssh/ssh_transport.h"
38 #include "ssh/ssh_kex.h"
39 #include "ssh/ssh_kex_dh.h"
40 #include "ssh/ssh_packet.h"
41 #include "ssh/ssh_key_material.h"
42 #include "ssh/ssh_exchange_hash.h"
43 #include "ssh/ssh_modp_groups.h"
44 #include "ssh/ssh_key_verify.h"
45 #include "ssh/ssh_cert_verify.h"
46 #include "ssh/ssh_misc.h"
47 #include "debug.h"
48 
49 //Check SSH stack configuration
50 #if (SSH_SUPPORT == ENABLED && SSH_DH_KEX_SUPPORT == ENABLED)
51 
52 
53 /**
54  * @brief Send SSH_MSG_KEX_DH_INIT message
55  * @param[in] connection Pointer to the SSH connection
56  * @return Error code
57  **/
58 
60 {
61 #if (SSH_CLIENT_SUPPORT == ENABLED)
62  error_t error;
63  size_t length;
64  uint8_t *message;
65  SshContext *context;
66 
67  //Point to the SSH context
68  context = connection->context;
69 
70  //Point to the buffer where to format the message
71  message = connection->buffer + SSH_PACKET_HEADER_SIZE;
72 
73  //Load the MODP group that matches the key exchange algorithm name
74  error = sshLoadDhModpGroup(&connection->dhContext.params,
75  connection->kexAlgo);
76 
77  //Check status code
78  if(!error)
79  {
80  //Generate an ephemeral key pair
81  error = dhGenerateKeyPair(&connection->dhContext, context->prngAlgo,
82  context->prngContext);
83  }
84 
85  //Check status code
86  if(!error)
87  {
88  //Format SSH_MSG_KEX_DH_INIT message
89  error = sshFormatKexDhInit(connection, message, &length);
90  }
91 
92  //Check status code
93  if(!error)
94  {
95  //Debug message
96  TRACE_INFO("Sending SSH_MSG_KEX_DH_INIT message (%" PRIuSIZE " bytes)...\r\n", length);
98 
99  //Send message
100  error = sshSendPacket(connection, message, length);
101  }
102 
103  //Check status code
104  if(!error)
105  {
106  //The server responds with an SSH_MSG_KEX_DH_REPLY message
107  connection->state = SSH_CONN_STATE_KEX_DH_REPLY;
108  }
109 
110  //Return status code
111  return error;
112 #else
113  //Client operation mode is not implemented
114  return ERROR_NOT_IMPLEMENTED;
115 #endif
116 }
117 
118 
119 /**
120  * @brief Send SSH_MSG_KEX_DH_REPLY message
121  * @param[in] connection Pointer to the SSH connection
122  * @return Error code
123  **/
124 
126 {
127 #if (SSH_SERVER_SUPPORT == ENABLED)
128  error_t error;
129  size_t length;
130  uint8_t *message;
131  SshContext *context;
132 
133  //Point to the SSH context
134  context = connection->context;
135 
136  //Point to the buffer where to format the message
137  message = connection->buffer + SSH_PACKET_HEADER_SIZE;
138 
139  //Generate an ephemeral key pair
140  error = dhGenerateKeyPair(&connection->dhContext, context->prngAlgo,
141  context->prngContext);
142 
143  //Check status code
144  if(!error)
145  {
146  //Format SSH_MSG_KEX_DH_REPLY message
147  error = sshFormatKexDhReply(connection, message, &length);
148  }
149 
150  //Check status code
151  if(!error)
152  {
153  //Debug message
154  TRACE_INFO("Sending SSH_MSG_KEX_DH_REPLY message (%" PRIuSIZE " bytes)...\r\n", length);
156 
157  //Send message
158  error = sshSendPacket(connection, message, length);
159  }
160 
161  //Check status code
162  if(!error)
163  {
164  //Key exchange ends by each side sending an SSH_MSG_NEWKEYS message
165  connection->state = SSH_CONN_STATE_SERVER_NEW_KEYS;
166  }
167 
168  //Return status code
169  return error;
170 #else
171  //Server operation mode is not implemented
172  return ERROR_NOT_IMPLEMENTED;
173 #endif
174 }
175 
176 
177 /**
178  * @brief Format SSH_MSG_KEX_DH_INIT message
179  * @param[in] connection Pointer to the SSH connection
180  * @param[out] p Buffer where to format the message
181  * @param[out] length Length of the resulting message, in bytes
182  * @return Error code
183  **/
184 
186  size_t *length)
187 {
188 #if (SSH_CLIENT_SUPPORT == ENABLED)
189  error_t error;
190  size_t n;
191 
192  //Total length of the message
193  *length = 0;
194 
195  //Set message type
196  p[0] = SSH_MSG_KEX_DH_INIT;
197 
198  //Point to the first field of the message
199  p += sizeof(uint8_t);
200  *length += sizeof(uint8_t);
201 
202  //Format client's ephemeral public key (e)
203  error = sshFormatMpint(&connection->dhContext.ya, p, &n);
204  //Any error to report?
205  if(error)
206  return error;
207 
208  //Total length of the message
209  *length += n;
210 
211  //Successful processing
212  return NO_ERROR;
213 #else
214  //Client operation mode is not implemented
215  return ERROR_NOT_IMPLEMENTED;
216 #endif
217 }
218 
219 
220 /**
221  * @brief Format SSH_MSG_KEX_DH_REPLY message
222  * @param[in] connection Pointer to the SSH connection
223  * @param[out] p Buffer where to format the message
224  * @param[out] length Length of the resulting message, in bytes
225  * @return Error code
226  **/
227 
229  size_t *length)
230 {
231 #if (SSH_SERVER_SUPPORT == ENABLED)
232  error_t error;
233  size_t n;
234 
235  //Total length of the message
236  *length = 0;
237 
238  //Set message type
239  p[0] = SSH_MSG_KEX_DH_REPLY;
240 
241  //Point to the first field of the message
242  p += sizeof(uint8_t);
243  *length += sizeof(uint8_t);
244 
245  //Format server's public host key (K_S)
246  error = sshFormatHostKey(connection, p + sizeof(uint32_t), &n);
247  //Any error to report?
248  if(error)
249  return error;
250 
251  //The octet string value is preceded by a uint32 containing its length
252  STORE32BE(n, p);
253 
254  //Point to the next field
255  p += sizeof(uint32_t) + n;
256  *length += sizeof(uint32_t) + n;
257 
258  //Format server's ephemeral public key (f)
259  error = sshFormatMpint(&connection->dhContext.ya, p, &n);
260  //Any error to report?
261  if(error)
262  return error;
263 
264  //Update exchange hash H with f (exchange value sent by the server)
265  error = sshUpdateExchangeHashRaw(connection, p, n);
266  //Any error to report?
267  if(error)
268  return error;
269 
270  //Point to the next field
271  p += n;
272  *length += n;
273 
274  //Compute the shared secret K
275  error = sshComputeDhSharedSecret(connection);
276  //Any error to report?
277  if(error)
278  return error;
279 
280  //Update exchange hash H with K (shared secret)
281  error = sshUpdateExchangeHashRaw(connection, connection->k,
282  connection->kLen);
283  //Any error to report?
284  if(error)
285  return error;
286 
287  //Compute the signature on the exchange hash
288  error = sshGenerateExchangeHashSignature(connection, p + sizeof(uint32_t),
289  &n);
290  //Any error to report?
291  if(error)
292  return error;
293 
294  //The octet string value is preceded by a uint32 containing its length
295  STORE32BE(n, p);
296 
297  //Total length of the message
298  *length += sizeof(uint32_t) + n;
299 
300  //The ephemeral private key shall be destroyed as soon as possible (refer
301  //to RFC 9212, section 6)
302  dhFree(&connection->dhContext);
303  dhInit(&connection->dhContext);
304 
305  //Successful processing
306  return NO_ERROR;
307 #else
308  //Server operation mode is not implemented
309  return ERROR_NOT_IMPLEMENTED;
310 #endif
311 }
312 
313 
314 /**
315  * @brief Parse SSH_MSG_KEX_DH_INIT message
316  * @param[in] connection Pointer to the SSH connection
317  * @param[in] message Pointer to message
318  * @param[in] length Length of the message, in bytes
319  * @return Error code
320  **/
321 
322 error_t sshParseKexDhInit(SshConnection *connection, const uint8_t *message,
323  size_t length)
324 {
325 #if (SSH_SERVER_SUPPORT == ENABLED)
326  error_t error;
327  const uint8_t *p;
328  SshBinaryString publicKey;
329 
330  //Debug message
331  TRACE_INFO("SSH_MSG_KEX_DH_INIT message received (%" PRIuSIZE " bytes)...\r\n", length);
333 
334  //Check operation mode
335  if(connection->context->mode != SSH_OPERATION_MODE_SERVER)
337 
338  //Check connection state
339  if(connection->state != SSH_CONN_STATE_KEX_DH_INIT)
341 
342  //Sanity check
343  if(length < sizeof(uint8_t))
344  return ERROR_INVALID_MESSAGE;
345 
346  //Point to the first field of the message
347  p = message + sizeof(uint8_t);
348  //Remaining bytes to process
349  length -= sizeof(uint8_t);
350 
351  //Decode client's ephemeral public key (e)
352  error = sshParseBinaryString(p, length, &publicKey);
353  //Any error to report?
354  if(error)
355  return error;
356 
357  //Point to the next field
358  p += sizeof(uint32_t) + publicKey.length;
359  length -= sizeof(uint32_t) + publicKey.length;
360 
361  //Malformed message?
362  if(length != 0)
363  return ERROR_INVALID_MESSAGE;
364 
365  //Update exchange hash H with e (exchange value sent by the client)
366  error = sshUpdateExchangeHash(connection, publicKey.value,
367  publicKey.length);
368  //Any error to report?
369  if(error)
370  return error;
371 
372  //Load the MODP group that matches the key exchange algorithm name
373  error = sshLoadDhModpGroup(&connection->dhContext.params,
374  connection->kexAlgo);
375  //Any error to report?
376  if(error)
377  return error;
378 
379  //Load client's ephemeral public key
380  error = mpiImport(&connection->dhContext.yb, publicKey.value,
381  publicKey.length, MPI_FORMAT_BIG_ENDIAN);
382  //Any error to report?
383  if(error)
384  return error;
385 
386  //Ensure the public key is acceptable
387  error = dhCheckPublicKey(&connection->dhContext.params,
388  &connection->dhContext.yb);
389  //Any error to report?
390  if(error)
391  return error;
392 
393  //The server responds with an SSH_MSG_KEX_DH_REPLY message
394  return sshSendKexDhReply(connection);
395 #else
396  //Server operation mode is not implemented
398 #endif
399 }
400 
401 
402 /**
403  * @brief Parse SSH_MSG_KEX_DH_REPLY message
404  * @param[in] connection Pointer to the SSH connection
405  * @param[in] message Pointer to message
406  * @param[in] length Length of the message, in bytes
407  * @return Error code
408  **/
409 
410 error_t sshParseKexDhReply(SshConnection *connection, const uint8_t *message,
411  size_t length)
412 {
413 #if (SSH_CLIENT_SUPPORT == ENABLED)
414  error_t error;
415  const uint8_t *p;
416  SshString hostKeyAlgo;
417  SshBinaryString hostKey;
418  SshBinaryString publicKey;
419  SshBinaryString signature;
420 
421  //Debug message
422  TRACE_INFO("SSH_MSG_KEX_DH_REPLY message received (%" PRIuSIZE " bytes)...\r\n", length);
424 
425  //Check operation mode
426  if(connection->context->mode != SSH_OPERATION_MODE_CLIENT)
428 
429  //Check connection state
430  if(connection->state != SSH_CONN_STATE_KEX_DH_REPLY)
432 
433  //Sanity check
434  if(length < sizeof(uint8_t))
435  return ERROR_INVALID_MESSAGE;
436 
437  //Point to the first field of the message
438  p = message + sizeof(uint8_t);
439  //Remaining bytes to process
440  length -= sizeof(uint8_t);
441 
442  //Decode server's public host key (K_S)
443  error = sshParseBinaryString(p, length, &hostKey);
444  //Any error to report?
445  if(error)
446  return error;
447 
448  //Point to the next field
449  p += sizeof(uint32_t) + hostKey.length;
450  length -= sizeof(uint32_t) + hostKey.length;
451 
452  //Decode server's ephemeral public key (f)
453  error = sshParseBinaryString(p, length, &publicKey);
454  //Any error to report?
455  if(error)
456  return error;
457 
458  //Point to the next field
459  p += sizeof(uint32_t) + publicKey.length;
460  length -= sizeof(uint32_t) + publicKey.length;
461 
462  //Decode the signature field
463  error = sshParseBinaryString(p, length, &signature);
464  //Any error to report?
465  if(error)
466  return error;
467 
468  //Point to the next field
469  p += sizeof(uint32_t) + signature.length;
470  length -= sizeof(uint32_t) + signature.length;
471 
472  //Malformed message?
473  if(length != 0)
474  return ERROR_INVALID_MESSAGE;
475 
476  //Get the selected server's host key algorithm
477  hostKeyAlgo.value = connection->serverHostKeyAlgo;
478  hostKeyAlgo.length = osStrlen(connection->serverHostKeyAlgo);
479 
480 #if (SSH_CERT_SUPPORT == ENABLED)
481  //Certificate-based authentication?
482  if(sshIsCertPublicKeyAlgo(&hostKeyAlgo))
483  {
484  //Verify server's certificate
485  error = sshVerifyServerCertificate(connection, &hostKeyAlgo, &hostKey);
486  }
487  else
488 #endif
489  {
490  //Verify server's host key
491  error = sshVerifyServerHostKey(connection, &hostKeyAlgo, &hostKey);
492  }
493 
494  //If the client fails to verify the server's host key, it should disconnect
495  //from the server by sending an SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE
496  //message
497  if(error)
498  return ERROR_INVALID_KEY;
499 
500  //Update exchange hash H with K_S (server's public host key)
501  error = sshUpdateExchangeHash(connection, hostKey.value, hostKey.length);
502  //Any error to report?
503  if(error)
504  return error;
505 
506  //Update exchange hash H with e (exchange value sent by the client)
507  error = sshDigestClientDhPublicKey(connection);
508  //Any error to report?
509  if(error)
510  return error;
511 
512  //Update exchange hash H with f (exchange value sent by the server)
513  error = sshUpdateExchangeHash(connection, publicKey.value, publicKey.length);
514  //Any error to report?
515  if(error)
516  return error;
517 
518  //Load server's ephemeral public key
519  error = mpiImport(&connection->dhContext.yb, publicKey.value,
520  publicKey.length, MPI_FORMAT_BIG_ENDIAN);
521  //Any error to report?
522  if(error)
523  return error;
524 
525  //Ensure the public key is acceptable
526  error = dhCheckPublicKey(&connection->dhContext.params,
527  &connection->dhContext.yb);
528  //Any error to report?
529  if(error)
530  return error;
531 
532  //Compute the shared secret K
533  error = sshComputeDhSharedSecret(connection);
534  //Any error to report?
535  if(error)
536  return error;
537 
538  //Update exchange hash H with K (shared secret)
539  error = sshUpdateExchangeHashRaw(connection, connection->k,
540  connection->kLen);
541  //Any error to report?
542  if(error)
543  return error;
544 
545  //Verify the signature on the exchange hash
546  error = sshVerifyExchangeHashSignature(connection, &hostKey, &signature);
547  //Any error to report?
548  if(error)
549  return error;
550 
551  //The ephemeral private key shall be destroyed as soon as possible (refer
552  //to RFC 9212, section 6)
553  dhFree(&connection->dhContext);
554  dhInit(&connection->dhContext);
555 
556  //Key exchange ends by each side sending an SSH_MSG_NEWKEYS message
557  return sshSendNewKeys(connection);
558 #else
559  //Client operation mode is not implemented
561 #endif
562 }
563 
564 
565 /**
566  * @brief Parse Diffie-Hellman specific messages
567  * @param[in] connection Pointer to the SSH connection
568  * @param[in] type SSH message type
569  * @param[in] message Pointer to message
570  * @param[in] length Length of the message, in bytes
571  * @return Error code
572  **/
573 
575  const uint8_t *message, size_t length)
576 {
577  error_t error;
578 
579 #if (SSH_CLIENT_SUPPORT == ENABLED)
580  //Client operation mode?
581  if(connection->context->mode == SSH_OPERATION_MODE_CLIENT)
582  {
583  //Check message type
585  {
586  //Parse SSH_MSG_KEX_DH_REPLY message
587  error = sshParseKexDhReply(connection, message, length);
588  }
589  else
590  {
591  //Unknown message type
592  error = ERROR_INVALID_TYPE;
593  }
594  }
595  else
596 #endif
597 #if (SSH_SERVER_SUPPORT == ENABLED)
598  //Server operation mode?
599  if(connection->context->mode == SSH_OPERATION_MODE_SERVER)
600  {
601  //Check message type
603  {
604  //Parse SSH_MSG_KEX_DH_INIT message
605  error = sshParseKexDhInit(connection, message, length);
606  }
607  else
608  {
609  //Unknown message type
610  error = ERROR_INVALID_TYPE;
611  }
612  }
613  else
614 #endif
615  //Invalid operation mode?
616  {
617  //Report an error
618  error = ERROR_INVALID_TYPE;
619  }
620 
621  //Return status code
622  return error;
623 }
624 
625 
626 /**
627  * @brief Diffie-Hellman shared secret calculation
628  * @param[in] connection Pointer to the SSH connection
629  * @return Error code
630  **/
631 
633 {
634  error_t error;
635 
636  //Compute the shared secret K
637  error = dhComputeSharedSecret(&connection->dhContext, connection->k,
639 
640  //Check status code
641  if(!error)
642  {
643  //Log shared secret (for debugging purpose only)
644  sshDumpKey(connection, "SHARED_SECRET", connection->k, connection->kLen);
645 
646  //Convert the shared secret K to mpint representation
647  error = sshConvertArrayToMpint(connection->k, connection->kLen,
648  connection->k, &connection->kLen);
649  }
650 
651  //Return status code
652  return error;
653 }
654 
655 
656 /**
657  * @brief Update exchange hash with client's ephemeral public key
658  * @param[in] connection Pointer to the SSH connection
659  * @return Error code
660  **/
661 
663 {
664  error_t error;
665  size_t n;
666  uint8_t *buffer;
667 
668  //Allocate a temporary buffer
669  buffer = sshAllocMem(SSH_BUFFER_SIZE);
670 
671  //Successful memory allocation?
672  if(buffer != NULL)
673  {
674  //Format client's ephemeral public key
675  error = sshFormatMpint(&connection->dhContext.ya, buffer, &n);
676 
677  //Check status code
678  if(!error)
679  {
680  //Update exchange hash H with e (exchange value sent by the client)
681  error = sshUpdateExchangeHashRaw(connection, buffer, n);
682  }
683 
684  //Release previously allocated memory
685  sshFreeMem(buffer);
686  }
687  else
688  {
689  //Failed to allocate memory
690  error = ERROR_OUT_OF_MEMORY;
691  }
692 
693  //Return status code
694  return error;
695 }
696 
697 #endif
Modular exponentiation (MODP) groups.
@ SSH_MSG_KEX_DH_REPLY
Definition: ssh.h:951
error_t sshGenerateExchangeHashSignature(SshConnection *connection, uint8_t *p, size_t *written)
Compute the signature on the exchange hash.
error_t sshSendKexDhInit(SshConnection *connection)
Send SSH_MSG_KEX_DH_INIT message.
Definition: ssh_kex_dh.c:59
SSH host key verification.
Binary string.
Definition: ssh_types.h:67
Diffie-Hellman key exchange.
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
@ ERROR_UNEXPECTED_MESSAGE
Definition: error.h:194
void sshDumpKey(SshConnection *connection, const char_t *label, const uint8_t *key, size_t keyLen)
Dump secret key (for debugging purpose only)
uint8_t p
Definition: ndp.h:300
uint8_t message[]
Definition: chap.h:154
error_t dhCheckPublicKey(DhParameters *params, const Mpi *publicKey)
Check Diffie-Hellman public value.
Definition: dh.c:183
error_t sshParseKexDhInit(SshConnection *connection, const uint8_t *message, size_t length)
Parse SSH_MSG_KEX_DH_INIT message.
Definition: ssh_kex_dh.c:322
error_t sshFormatKexDhReply(SshConnection *connection, uint8_t *p, size_t *length)
Format SSH_MSG_KEX_DH_REPLY message.
Definition: ssh_kex_dh.c:228
error_t sshVerifyServerHostKey(SshConnection *connection, const SshString *publicKeyAlgo, const SshBinaryString *hostKey)
Verify server's host key.
error_t sshVerifyExchangeHashSignature(SshConnection *connection, const SshBinaryString *serverHostKey, const SshBinaryString *signature)
Verify the signature on the exchange hash.
SSH transport layer protocol.
error_t sshUpdateExchangeHashRaw(SshConnection *connection, const void *data, size_t length)
Update exchange hash calculation (raw data)
uint8_t type
Definition: coap_common.h:176
SSH certificate verification.
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
size_t length
Definition: ssh_types.h:58
@ ERROR_INVALID_MESSAGE
Definition: error.h:105
#define SSH_MAX_SHARED_SECRET_LEN
Definition: ssh.h:842
#define osStrlen(s)
Definition: os_port.h:165
error_t sshLoadDhModpGroup(DhParameters *params, const char_t *kexAlgo)
Load Diffie-Hellman parameters.
error_t mpiImport(Mpi *r, const uint8_t *data, uint_t length, MpiFormat format)
Octet string to integer conversion.
Definition: mpi.c:624
#define SSH_PACKET_HEADER_SIZE
Definition: ssh_packet.h:38
error_t sshSendPacket(SshConnection *connection, uint8_t *payload, size_t payloadLen)
Send SSH packet.
Definition: ssh_packet.c:57
bool_t sshIsCertPublicKeyAlgo(const SshString *publicKeyAlgo)
Test if the specified public key algorithm is using certificates.
error_t sshSendNewKeys(SshConnection *connection)
Send SSH_MSG_NEWKEYS message.
Definition: ssh_kex.c:194
size_t length
Definition: ssh_types.h:69
Key material generation.
error_t dhComputeSharedSecret(DhContext *context, uint8_t *output, size_t outputSize, size_t *outputLen)
Compute Diffie-Hellman shared secret.
Definition: dh.c:223
error_t sshConvertArrayToMpint(const uint8_t *value, size_t length, uint8_t *p, size_t *written)
Convert a binary string to mpint representation.
Definition: ssh_misc.c:1531
@ SSH_MSG_KEX_DH_INIT
Definition: ssh.h:950
#define SshContext
Definition: ssh.h:870
const char_t * value
Definition: ssh_types.h:57
#define SSH_MAX_MPINT_OVERHEAD
Definition: ssh.h:861
error_t
Error codes.
Definition: error.h:43
@ SSH_OPERATION_MODE_SERVER
Definition: ssh.h:893
@ SSH_OPERATION_MODE_CLIENT
Definition: ssh.h:892
error_t sshVerifyServerCertificate(SshConnection *connection, const SshString *publicKeyAlgo, const SshBinaryString *hostKey)
Verify server's certificate.
void dhFree(DhContext *context)
Release Diffie-Hellman context.
Definition: dh.c:71
error_t sshDigestClientDhPublicKey(SshConnection *connection)
Update exchange hash with client's ephemeral public key.
Definition: ssh_kex_dh.c:662
@ ERROR_INVALID_TYPE
Definition: error.h:115
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t length
Definition: tcp.h:368
@ SSH_CONN_STATE_SERVER_NEW_KEYS
Definition: ssh.h:1052
String.
Definition: ssh_types.h:56
SSH key exchange.
const uint8_t * value
Definition: ssh_types.h:68
error_t sshFormatMpint(const Mpi *value, uint8_t *p, size_t *written)
Format a multiple precision integer.
Definition: ssh_misc.c:1487
#define sshFreeMem(p)
Definition: ssh.h:729
error_t sshComputeDhSharedSecret(SshConnection *connection)
Diffie-Hellman shared secret calculation.
Definition: ssh_kex_dh.c:632
error_t sshParseKexDhMessage(SshConnection *connection, uint8_t type, const uint8_t *message, size_t length)
Parse Diffie-Hellman specific messages.
Definition: ssh_kex_dh.c:574
@ SSH_CONN_STATE_KEX_DH_INIT
Definition: ssh.h:1041
uint8_t n
Exchange hash calculation.
#define SshConnection
Definition: ssh.h:874
SSH helper functions.
@ MPI_FORMAT_BIG_ENDIAN
Definition: mpi.h:71
error_t sshFormatHostKey(SshConnection *connection, uint8_t *p, size_t *written)
Format host key structure.
Definition: ssh_misc.c:863
@ SSH_CONN_STATE_KEX_DH_REPLY
Definition: ssh.h:1042
SSH packet encryption/decryption.
error_t sshUpdateExchangeHash(SshConnection *connection, const void *data, size_t length)
Update exchange hash calculation.
error_t sshParseBinaryString(const uint8_t *p, size_t length, SshBinaryString *string)
Parse a binary string.
Definition: ssh_misc.c:1189
error_t sshFormatKexDhInit(SshConnection *connection, uint8_t *p, size_t *length)
Format SSH_MSG_KEX_DH_INIT message.
Definition: ssh_kex_dh.c:185
#define sshAllocMem(size)
Definition: ssh.h:724
error_t sshSendKexDhReply(SshConnection *connection)
Send SSH_MSG_KEX_DH_REPLY message.
Definition: ssh_kex_dh.c:125
error_t dhGenerateKeyPair(DhContext *context, const PrngAlgo *prngAlgo, void *prngContext)
Diffie-Hellman key pair generation.
Definition: dh.c:119
#define PRIuSIZE
Secure Shell (SSH)
SSH algorithm negotiation.
void dhInit(DhContext *context)
Initialize Diffie-Hellman context.
Definition: dh.c:54
#define SSH_BUFFER_SIZE
Definition: ssh.h:866
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
@ ERROR_INVALID_KEY
Definition: error.h:106
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
error_t sshParseKexDhReply(SshConnection *connection, const uint8_t *message, size_t length)
Parse SSH_MSG_KEX_DH_REPLY message.
Definition: ssh_kex_dh.c:410
#define TRACE_VERBOSE_ARRAY(p, a, n)
Definition: debug.h:125