ssh_kex_ecdh.c
Go to the documentation of this file.
1 /**
2  * @file ssh_kex_ecdh.c
3  * @brief ECDH key exchange
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2019-2025 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.5.2
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_ecdh.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_key_verify.h"
44 #include "ssh/ssh_cert_verify.h"
45 #include "ssh/ssh_misc.h"
46 #include "debug.h"
47 
48 //Check SSH stack configuration
49 #if (SSH_SUPPORT == ENABLED && SSH_ECDH_KEX_SUPPORT == ENABLED)
50 
51 
52 /**
53  * @brief Send SSH_MSG_KEX_ECDH_INIT message
54  * @param[in] connection Pointer to the SSH connection
55  * @return Error code
56  **/
57 
59 {
60 #if (SSH_CLIENT_SUPPORT == ENABLED)
61  error_t error;
62  size_t length;
63  uint8_t *message;
64 
65  //Point to the buffer where to format the message
66  message = connection->buffer + SSH_PACKET_HEADER_SIZE;
67 
68  //Select ECDH domain parameters
69  error = sshSelectEcdhCurve(connection);
70 
71  //Check status code
72  if(!error)
73  {
74  //Generate an ephemeral key pair
75  error = sshGenerateEcdhKeyPair(connection);
76  }
77 
78  //Check status code
79  if(!error)
80  {
81  //Format SSH_MSG_KEX_ECDH_INIT message
82  error = sshFormatKexEcdhInit(connection, message, &length);
83  }
84 
85  //Check status code
86  if(!error)
87  {
88  //Debug message
89  TRACE_INFO("Sending SSH_MSG_KEX_ECDH_INIT message (%" PRIuSIZE " bytes)...\r\n", length);
91 
92  //Send message
93  error = sshSendPacket(connection, message, length);
94  }
95 
96  //Check status code
97  if(!error)
98  {
99  //The server responds with an SSH_MSG_KEX_ECDH_REPLY message
100  connection->state = SSH_CONN_STATE_KEX_ECDH_REPLY;
101  }
102 
103  //Return status code
104  return error;
105 #else
106  //Client operation mode is not implemented
107  return ERROR_NOT_IMPLEMENTED;
108 #endif
109 }
110 
111 
112 /**
113  * @brief Send SSH_MSG_KEX_ECDH_REPLY message
114  * @param[in] connection Pointer to the SSH connection
115  * @return Error code
116  **/
117 
119 {
120 #if (SSH_SERVER_SUPPORT == ENABLED)
121  error_t error;
122  size_t length;
123  uint8_t *message;
124 
125  //Point to the buffer where to format the message
126  message = connection->buffer + SSH_PACKET_HEADER_SIZE;
127 
128  //Generate an ephemeral key pair
129  error = sshGenerateEcdhKeyPair(connection);
130 
131  //Check status code
132  if(!error)
133  {
134  //Format SSH_MSG_KEX_ECDH_REPLY message
135  error = sshFormatKexEcdhReply(connection, message, &length);
136  }
137 
138  //Check status code
139  if(!error)
140  {
141  //Debug message
142  TRACE_INFO("Sending SSH_MSG_KEX_ECDH_REPLY message (%" PRIuSIZE " bytes)...\r\n", length);
144 
145  //Send message
146  error = sshSendPacket(connection, message, length);
147  }
148 
149  //Check status code
150  if(!error)
151  {
152  //Key exchange ends by each side sending an SSH_MSG_NEWKEYS message
153  connection->state = SSH_CONN_STATE_SERVER_NEW_KEYS;
154  }
155 
156  //Return status code
157  return error;
158 #else
159  //Server operation mode is not implemented
160  return ERROR_NOT_IMPLEMENTED;
161 #endif
162 }
163 
164 
165 /**
166  * @brief Format SSH_MSG_KEX_ECDH_INIT message
167  * @param[in] connection Pointer to the SSH connection
168  * @param[out] p Buffer where to format the message
169  * @param[out] length Length of the resulting message, in bytes
170  * @return Error code
171  **/
172 
174  size_t *length)
175 {
176 #if (SSH_CLIENT_SUPPORT == ENABLED)
177  error_t error;
178  size_t n;
179 
180  //Total length of the message
181  *length = 0;
182 
183  //Set message type
185 
186  //Point to the first field of the message
187  p += sizeof(uint8_t);
188  *length += sizeof(uint8_t);
189 
190  //Format client's ephemeral public key (Q_C)
191  error = ecdhExportPublicKey(&connection->ecdhContext, p + sizeof(uint32_t),
193  //Any error to report?
194  if(error)
195  return error;
196 
197  //The octet string value is preceded by a uint32 containing its length
198  STORE32BE(n, p);
199 
200  //Total length of the message
201  *length += sizeof(uint32_t) + n;
202 
203  //Successful processing
204  return NO_ERROR;
205 #else
206  //Client operation mode is not implemented
207  return ERROR_NOT_IMPLEMENTED;
208 #endif
209 }
210 
211 
212 /**
213  * @brief Format SSH_MSG_KEX_ECDH_REPLY message
214  * @param[in] connection Pointer to the SSH connection
215  * @param[out] p Buffer where to format the message
216  * @param[out] length Length of the resulting message, in bytes
217  * @return Error code
218  **/
219 
221  size_t *length)
222 {
223 #if (SSH_SERVER_SUPPORT == ENABLED)
224  error_t error;
225  size_t n;
226 
227  //Total length of the message
228  *length = 0;
229 
230  //Set message type
232 
233  //Point to the first field of the message
234  p += sizeof(uint8_t);
235  *length += sizeof(uint8_t);
236 
237  //Format server's public host key (K_S)
238  error = sshFormatHostKey(connection, p + sizeof(uint32_t), &n);
239  //Any error to report?
240  if(error)
241  return error;
242 
243  //The octet string value is preceded by a uint32 containing its length
244  STORE32BE(n, p);
245 
246  //Point to the next field
247  p += sizeof(uint32_t) + n;
248  *length += sizeof(uint32_t) + n;
249 
250  //Format server's ephemeral public key (Q_S)
251  error = ecdhExportPublicKey(&connection->ecdhContext, p + sizeof(uint32_t),
253  //Any error to report?
254  if(error)
255  return error;
256 
257  //Update exchange hash H with Q_S (server's ephemeral public key octet string)
258  error = sshUpdateExchangeHash(connection, p + sizeof(uint32_t), n);
259  //Any error to report?
260  if(error)
261  return error;
262 
263  //The octet string value is preceded by a uint32 containing its length
264  STORE32BE(n, p);
265 
266  //Point to the next field
267  p += sizeof(uint32_t) + n;
268  *length += sizeof(uint32_t) + n;
269 
270  //Compute the shared secret K
271  error = sshComputeEcdhSharedSecret(connection);
272  //Any error to report?
273  if(error)
274  return error;
275 
276  //Update exchange hash H with K (shared secret)
277  error = sshUpdateExchangeHashRaw(connection, connection->k,
278  connection->kLen);
279  //Any error to report?
280  if(error)
281  return error;
282 
283  //Compute the signature on the exchange hash
284  error = sshGenerateExchangeHashSignature(connection, p + sizeof(uint32_t),
285  &n);
286  //Any error to report?
287  if(error)
288  return error;
289 
290  //The octet string value is preceded by a uint32 containing its length
291  STORE32BE(n, p);
292 
293  //Total length of the message
294  *length += sizeof(uint32_t) + n;
295 
296  //The ephemeral private key shall be destroyed as soon as possible (refer
297  //to RFC 9212, section 6)
298  ecdhFree(&connection->ecdhContext);
299  ecdhInit(&connection->ecdhContext);
300 
301  //Successful processing
302  return NO_ERROR;
303 #else
304  //Server operation mode is not implemented
305  return ERROR_NOT_IMPLEMENTED;
306 #endif
307 }
308 
309 
310 /**
311  * @brief Parse SSH_MSG_KEX_ECDH_INIT message
312  * @param[in] connection Pointer to the SSH connection
313  * @param[in] message Pointer to message
314  * @param[in] length Length of the message, in bytes
315  * @return Error code
316  **/
317 
318 error_t sshParseKexEcdhInit(SshConnection *connection, const uint8_t *message,
319  size_t length)
320 {
321 #if (SSH_SERVER_SUPPORT == ENABLED)
322  error_t error;
323  const uint8_t *p;
324  SshBinaryString publicKey;
325 
326  //Debug message
327  TRACE_INFO("SSH_MSG_KEX_ECDH_INIT message received (%" PRIuSIZE " bytes)...\r\n", length);
329 
330  //Check operation mode
331  if(connection->context->mode != SSH_OPERATION_MODE_SERVER)
333 
334  //Check connection state
335  if(connection->state != SSH_CONN_STATE_KEX_ECDH_INIT)
337 
338  //Sanity check
339  if(length < sizeof(uint8_t))
340  return ERROR_INVALID_MESSAGE;
341 
342  //Point to the first field of the message
343  p = message + sizeof(uint8_t);
344  //Remaining bytes to process
345  length -= sizeof(uint8_t);
346 
347  //Decode client's ephemeral public key (Q_C)
348  error = sshParseBinaryString(p, length, &publicKey);
349  //Any error to report?
350  if(error)
351  return error;
352 
353  //Point to the next field
354  p += sizeof(uint32_t) + publicKey.length;
355  length -= sizeof(uint32_t) + publicKey.length;
356 
357  //Malformed message?
358  if(length != 0)
359  return ERROR_INVALID_MESSAGE;
360 
361  //Update exchange hash H with Q_C (client's ephemeral public key octet string)
362  error = sshUpdateExchangeHash(connection, publicKey.value, publicKey.length);
363  //Any error to report?
364  if(error)
365  return error;
366 
367  //Select ECDH domain parameters
368  error = sshSelectEcdhCurve(connection);
369  //Any error to report?
370  if(error)
371  return error;
372 
373  //Load client's ephemeral public key
374  error = ecdhImportPeerPublicKey(&connection->ecdhContext, publicKey.value,
375  publicKey.length, EC_PUBLIC_KEY_FORMAT_X963);
376  //Any error to report?
377  if(error)
378  return error;
379 
380  //The server responds with an SSH_MSG_KEX_ECDH_REPLY message
381  return sshSendKexEcdhReply(connection);
382 #else
383  //Server operation mode is not implemented
385 #endif
386 }
387 
388 
389 /**
390  * @brief Parse SSH_MSG_KEX_ECDH_REPLY message
391  * @param[in] connection Pointer to the SSH connection
392  * @param[in] message Pointer to message
393  * @param[in] length Length of the message, in bytes
394  * @return Error code
395  **/
396 
397 error_t sshParseKexEcdhReply(SshConnection *connection, const uint8_t *message,
398  size_t length)
399 {
400 #if (SSH_CLIENT_SUPPORT == ENABLED)
401  error_t error;
402  const uint8_t *p;
403  SshString hostKeyAlgo;
404  SshBinaryString hostKey;
405  SshBinaryString publicKey;
406  SshBinaryString signature;
407  SshContext *context;
408 
409  //Point to the SSH context
410  context = connection->context;
411 
412  //Debug message
413  TRACE_INFO("SSH_MSG_KEX_ECDH_REPLY message received (%" PRIuSIZE " bytes)...\r\n", length);
415 
416  //Check operation mode
417  if(context->mode != SSH_OPERATION_MODE_CLIENT)
419 
420  //Check connection state
421  if(connection->state != SSH_CONN_STATE_KEX_ECDH_REPLY)
423 
424  //Sanity check
425  if(length < sizeof(uint8_t))
426  return ERROR_INVALID_MESSAGE;
427 
428  //Point to the first field of the message
429  p = message + sizeof(uint8_t);
430  //Remaining bytes to process
431  length -= sizeof(uint8_t);
432 
433  //Decode server's public host key (K_S)
434  error = sshParseBinaryString(p, length, &hostKey);
435  //Any error to report?
436  if(error)
437  return error;
438 
439  //Point to the next field
440  p += sizeof(uint32_t) + hostKey.length;
441  length -= sizeof(uint32_t) + hostKey.length;
442 
443  //Decode server's ephemeral public key (Q_S)
444  error = sshParseBinaryString(p, length, &publicKey);
445  //Any error to report?
446  if(error)
447  return error;
448 
449  //Point to the next field
450  p += sizeof(uint32_t) + publicKey.length;
451  length -= sizeof(uint32_t) + publicKey.length;
452 
453  //Decode the signature field
454  error = sshParseBinaryString(p, length, &signature);
455  //Any error to report?
456  if(error)
457  return error;
458 
459  //Point to the next field
460  p += sizeof(uint32_t) + signature.length;
461  length -= sizeof(uint32_t) + signature.length;
462 
463  //Malformed message?
464  if(length != 0)
465  return ERROR_INVALID_MESSAGE;
466 
467  //Get the selected server's host key algorithm
468  hostKeyAlgo.value = connection->serverHostKeyAlgo;
469  hostKeyAlgo.length = osStrlen(connection->serverHostKeyAlgo);
470 
471 #if (SSH_CERT_SUPPORT == ENABLED)
472  //Certificate-based authentication?
473  if(sshIsCertPublicKeyAlgo(&hostKeyAlgo))
474  {
475  //Verify server's certificate
476  error = sshVerifyServerCertificate(connection, &hostKeyAlgo, &hostKey);
477  }
478  else
479 #endif
480  {
481  //Verify server's host key
482  error = sshVerifyServerHostKey(connection, &hostKeyAlgo, &hostKey);
483  }
484 
485  //If the client fails to verify the server's host key, it should disconnect
486  //from the server by sending an SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE message
487  if(error)
488  return ERROR_INVALID_KEY;
489 
490  //Update exchange hash H with K_S (server's public host key)
491  error = sshUpdateExchangeHash(connection, hostKey.value, hostKey.length);
492  //Any error to report?
493  if(error)
494  return error;
495 
496  //Update exchange hash H with Q_C (client's ephemeral public key octet
497  //string)
498  error = sshDigestClientEcdhPublicKey(connection);
499  //Any error to report?
500  if(error)
501  return error;
502 
503  //Update exchange hash H with Q_S (server's ephemeral public key octet
504  //string)
505  error = sshUpdateExchangeHash(connection, publicKey.value,
506  publicKey.length);
507  //Any error to report?
508  if(error)
509  return error;
510 
511  //Load server's ephemeral public key
512  error = ecdhImportPeerPublicKey(&connection->ecdhContext, publicKey.value,
513  publicKey.length, EC_PUBLIC_KEY_FORMAT_X963);
514  //Any error to report?
515  if(error)
516  return error;
517 
518  //Compute the shared secret K
519  error = sshComputeEcdhSharedSecret(connection);
520  //Any error to report?
521  if(error)
522  return error;
523 
524  //Update exchange hash H with K (shared secret)
525  error = sshUpdateExchangeHashRaw(connection, connection->k,
526  connection->kLen);
527  //Any error to report?
528  if(error)
529  return error;
530 
531  //Verify the signature on the exchange hash
532  error = sshVerifyExchangeHashSignature(connection, &hostKey, &signature);
533  //Any error to report?
534  if(error)
535  return error;
536 
537  //The ephemeral private key shall be destroyed as soon as possible (refer
538  //to RFC 9212, section 6)
539  ecdhFree(&connection->ecdhContext);
540  ecdhInit(&connection->ecdhContext);
541 
542  //Key exchange ends by each side sending an SSH_MSG_NEWKEYS message
543  return sshSendNewKeys(connection);
544 #else
545  //Client operation mode is not implemented
547 #endif
548 }
549 
550 
551 /**
552  * @brief Parse ECDH specific messages
553  * @param[in] connection Pointer to the SSH connection
554  * @param[in] type SSH message type
555  * @param[in] message Pointer to message
556  * @param[in] length Length of the message, in bytes
557  * @return Error code
558  **/
559 
561  const uint8_t *message, size_t length)
562 {
563  error_t error;
564 
565 #if (SSH_CLIENT_SUPPORT == ENABLED)
566  //Client operation mode?
567  if(connection->context->mode == SSH_OPERATION_MODE_CLIENT)
568  {
569  //Check message type
571  {
572  //Parse SSH_MSG_KEX_ECDH_REPLY message
573  error = sshParseKexEcdhReply(connection, message, length);
574  }
575  else
576  {
577  //Unknown message type
578  error = ERROR_INVALID_TYPE;
579  }
580  }
581  else
582 #endif
583 #if (SSH_SERVER_SUPPORT == ENABLED)
584  //Server operation mode?
585  if(connection->context->mode == SSH_OPERATION_MODE_SERVER)
586  {
587  //Check message type
589  {
590  //Parse SSH_MSG_KEX_ECDH_INIT message
591  error = sshParseKexEcdhInit(connection, message, length);
592  }
593  else
594  {
595  //Unknown message type
596  error = ERROR_INVALID_TYPE;
597  }
598  }
599  else
600 #endif
601  //Invalid operation mode?
602  {
603  //Report an error
604  error = ERROR_INVALID_TYPE;
605  }
606 
607  //Return status code
608  return error;
609 }
610 
611 
612 /**
613  * @brief Select ECDH domain parameters
614  * @param[in] connection Pointer to the SSH connection
615  * @return Error code
616  **/
617 
619 {
620  error_t error;
621  const EcCurve *curve;
622 
623 #if (SSH_NISTP256_SUPPORT == ENABLED)
624  //NIST P-256 elliptic curve?
625  if(sshCompareAlgo(connection->kexAlgo, "ecdh-sha2-nistp256"))
626  {
627  curve = SECP256R1_CURVE;
628  }
629  else
630 #endif
631 #if (SSH_NISTP384_SUPPORT == ENABLED)
632  //NIST P-384 elliptic curve?
633  if(sshCompareAlgo(connection->kexAlgo, "ecdh-sha2-nistp384"))
634  {
635  curve = SECP384R1_CURVE;
636  }
637  else
638 #endif
639 #if (SSH_NISTP521_SUPPORT == ENABLED)
640  //NIST P-521 elliptic curve?
641  if(sshCompareAlgo(connection->kexAlgo, "ecdh-sha2-nistp521"))
642  {
643  curve = SECP521R1_CURVE;
644  }
645  else
646 #endif
647 #if (SSH_CURVE25519_SUPPORT == ENABLED)
648  //Curve25519 elliptic curve?
649  if(sshCompareAlgo(connection->kexAlgo, "curve25519-sha256") ||
650  sshCompareAlgo(connection->kexAlgo, "curve25519-sha256@libssh.org"))
651  {
652  curve = X25519_CURVE;
653  }
654  else
655 #endif
656 #if (SSH_CURVE448_SUPPORT == ENABLED)
657  //Curve448 elliptic curve?
658  if(sshCompareAlgo(connection->kexAlgo, "curve448-sha512"))
659  {
660  curve = X448_CURVE;
661  }
662  else
663 #endif
664  //Unknown elliptic curve?
665  {
666  curve = NULL;
667  }
668 
669  //Make sure the specified elliptic curve is supported
670  if(curve != NULL)
671  {
672  //Save ECDH domain parameters
673  error = ecdhSetCurve(&connection->ecdhContext, curve);
674  }
675  else
676  {
677  //Report an error
679  }
680 
681  //Return status code
682  return error;
683 }
684 
685 
686 /**
687  * @brief ECDH key pair generation
688  * @param[in] connection Pointer to the SSH connection
689  * @return Error code
690  **/
691 
693 {
694  error_t error;
695  SshContext *context;
696 
697  //Point to the SSH context
698  context = connection->context;
699 
700 #if (SSH_ECDH_CALLBACK_SUPPORT == ENABLED)
701  //Valid ECDH key pair generation callback function?
702  if(context->ecdhKeyPairGenCallback != NULL)
703  {
704  //Invoke user-defined callback
705  error = context->ecdhKeyPairGenCallback(connection, connection->kexAlgo,
706  &connection->ecdhContext.da.q);
707  }
708  else
709 #endif
710  {
711  //No callback function registered
713  }
714 
715  //Check status code
717  {
718  //Generate an ephemeral key pair
719  error = ecdhGenerateKeyPair(&connection->ecdhContext, context->prngAlgo,
720  context->prngContext);
721  }
722 
723  //Return status code
724  return error;
725 }
726 
727 
728 /**
729  * @brief ECDH shared secret calculation
730  * @param[in] connection Pointer to the SSH connection
731  * @return Error code
732  **/
733 
735 {
736  error_t error;
737 
738 #if (SSH_ECDH_CALLBACK_SUPPORT == ENABLED)
739  //Valid ECDH shared secret calculation callback function?
740  if(connection->context->ecdhSharedSecretCalcCallback != NULL)
741  {
742  //Invoke user-defined callback
743  error = connection->context->ecdhSharedSecretCalcCallback(connection,
744  connection->kexAlgo, &connection->ecdhContext.qb, connection->k,
745  &connection->kLen);
746  }
747  else
748 #endif
749  {
750  //No callback function registered
752  }
753 
754  //Check status code
756  {
757  //Compute the shared secret K
758  error = ecdhComputeSharedSecret(&connection->ecdhContext, connection->k,
760  }
761 
762  //Check status code
763  if(!error)
764  {
765  //Log shared secret (for debugging purpose only)
766  sshDumpKey(connection, "SHARED_SECRET", connection->k, connection->kLen);
767 
768  //Convert the shared secret K to mpint representation
769  error = sshConvertArrayToMpint(connection->k, connection->kLen,
770  connection->k, &connection->kLen);
771  }
772 
773  //Return status code
774  return error;
775 }
776 
777 
778 /**
779  * @brief Update exchange hash with client's ephemeral public key
780  * @param[in] connection Pointer to the SSH connection
781  * @return Error code
782  **/
783 
785 {
786  error_t error;
787  size_t n;
788  uint8_t *buffer;
789 
790  //Allocate a temporary buffer
791  buffer = sshAllocMem(SSH_BUFFER_SIZE);
792 
793  //Successful memory allocation?
794  if(buffer != NULL)
795  {
796  //Format client's ephemeral public key
797  error = ecdhExportPublicKey(&connection->ecdhContext, buffer, &n,
799 
800  //Check status code
801  if(!error)
802  {
803  //Update exchange hash H with Q_C (client's ephemeral public key
804  //octet string)
805  error = sshUpdateExchangeHash(connection, buffer, n);
806  }
807 
808  //Release previously allocated memory
809  sshFreeMem(buffer);
810  }
811  else
812  {
813  //Failed to allocate memory
814  error = ERROR_OUT_OF_MEMORY;
815  }
816 
817  //Return status code
818  return error;
819 }
820 
821 #endif
error_t sshGenerateExchangeHashSignature(SshConnection *connection, uint8_t *p, size_t *written)
Compute the signature on the exchange hash.
#define SECP521R1_CURVE
Definition: ec_curves.h:53
SSH host key verification.
Binary string.
Definition: ssh_types.h:67
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
@ ERROR_UNEXPECTED_MESSAGE
Definition: error.h:195
void sshDumpKey(SshConnection *connection, const char_t *label, const uint8_t *key, size_t keyLen)
Dump secret key (for debugging purpose only)
ECDH key exchange.
#define SECP384R1_CURVE
Definition: ec_curves.h:52
uint8_t p
Definition: ndp.h:300
uint8_t message[]
Definition: chap.h:154
#define SECP256R1_CURVE
Definition: ec_curves.h:51
error_t sshVerifyServerHostKey(SshConnection *connection, const SshString *publicKeyAlgo, const SshBinaryString *hostKey)
Verify server's host key.
void ecdhFree(EcdhContext *context)
Release ECDH context.
Definition: ecdh.c:65
error_t sshVerifyExchangeHashSignature(SshConnection *connection, const SshBinaryString *serverHostKey, const SshBinaryString *signature)
Verify the signature on the exchange hash.
error_t sshParseKexEcdhReply(SshConnection *connection, const uint8_t *message, size_t length)
Parse SSH_MSG_KEX_ECDH_REPLY message.
Definition: ssh_kex_ecdh.c:397
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
@ EC_PUBLIC_KEY_FORMAT_X963
Definition: ec.h:386
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:168
#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
error_t sshGenerateEcdhKeyPair(SshConnection *connection)
ECDH key pair generation.
Definition: ssh_kex_ecdh.c:692
size_t length
Definition: ssh_types.h:69
Key material generation.
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:1625
error_t sshSendKexEcdhInit(SshConnection *connection)
Send SSH_MSG_KEX_ECDH_INIT message.
Definition: ssh_kex_ecdh.c:58
#define SshContext
Definition: ssh.h:870
error_t sshDigestClientEcdhPublicKey(SshConnection *connection)
Update exchange hash with client's ephemeral public key.
Definition: ssh_kex_ecdh.c:784
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
bool_t sshCompareAlgo(const char_t *name1, const char_t *name2)
Compare algorithm names.
Definition: ssh_misc.c:1747
@ SSH_OPERATION_MODE_SERVER
Definition: ssh.h:893
@ SSH_OPERATION_MODE_CLIENT
Definition: ssh.h:892
@ SSH_CONN_STATE_KEX_ECDH_INIT
Definition: ssh.h:1047
error_t sshVerifyServerCertificate(SshConnection *connection, const SshString *publicKeyAlgo, const SshBinaryString *hostKey)
Verify server's certificate.
@ SSH_CONN_STATE_KEX_ECDH_REPLY
Definition: ssh.h:1048
@ ERROR_INVALID_TYPE
Definition: error.h:115
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
@ 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 ecdhComputeSharedSecret(EcdhContext *context, uint8_t *output, size_t outputSize, size_t *outputLen)
Compute ECDH shared secret.
Definition: ecdh.c:415
@ ERROR_UNSUPPORTED_KEY_EXCH_ALGO
Definition: error.h:131
error_t ecdhImportPeerPublicKey(EcdhContext *context, const uint8_t *input, size_t length, EcPublicKeyFormat format)
Import peer's public key.
Definition: ecdh.c:274
error_t sshFormatKexEcdhInit(SshConnection *connection, uint8_t *p, size_t *length)
Format SSH_MSG_KEX_ECDH_INIT message.
Definition: ssh_kex_ecdh.c:173
void ecdhInit(EcdhContext *context)
Initialize ECDH context.
Definition: ecdh.c:49
#define sshFreeMem(p)
Definition: ssh.h:729
uint8_t n
Exchange hash calculation.
#define SshConnection
Definition: ssh.h:874
error_t sshComputeEcdhSharedSecret(SshConnection *connection)
ECDH shared secret calculation.
Definition: ssh_kex_ecdh.c:734
@ SSH_MSG_KEX_ECDH_INIT
Definition: ssh.h:957
error_t sshFormatKexEcdhReply(SshConnection *connection, uint8_t *p, size_t *length)
Format SSH_MSG_KEX_ECDH_REPLY message.
Definition: ssh_kex_ecdh.c:220
SSH helper functions.
error_t sshFormatHostKey(SshConnection *connection, uint8_t *p, size_t *written)
Format host key structure.
Definition: ssh_misc.c:864
#define X448_CURVE
Definition: ec_curves.h:71
error_t sshParseKexEcdhInit(SshConnection *connection, const uint8_t *message, size_t length)
Parse SSH_MSG_KEX_ECDH_INIT message.
Definition: ssh_kex_ecdh.c:318
error_t ecdhSetCurve(EcdhContext *context, const EcCurve *curve)
Specify the elliptic curve to use.
Definition: ecdh.c:83
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:1204
#define EcCurve
Definition: ec.h:346
#define sshAllocMem(size)
Definition: ssh.h:724
error_t sshSendKexEcdhReply(SshConnection *connection)
Send SSH_MSG_KEX_ECDH_REPLY message.
Definition: ssh_kex_ecdh.c:118
error_t sshParseKexEcdhMessage(SshConnection *connection, uint8_t type, const uint8_t *message, size_t length)
Parse ECDH specific messages.
Definition: ssh_kex_ecdh.c:560
#define PRIuSIZE
@ SSH_MSG_KEX_ECDH_REPLY
Definition: ssh.h:958
Secure Shell (SSH)
SSH algorithm negotiation.
error_t ecdhExportPublicKey(EcdhContext *context, uint8_t *output, size_t *written, EcPublicKeyFormat format)
Export our own public key.
Definition: ecdh.c:257
error_t sshSelectEcdhCurve(SshConnection *connection)
Select ECDH domain parameters.
Definition: ssh_kex_ecdh.c:618
#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 ecdhGenerateKeyPair(EcdhContext *context, const PrngAlgo *prngAlgo, void *prngContext)
ECDH key pair generation.
Definition: ecdh.c:115
#define X25519_CURVE
Definition: ec_curves.h:70
#define TRACE_VERBOSE_ARRAY(p, a, n)
Definition: debug.h:140