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.0
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 = ecExportPublicKey(&connection->ecdhContext.da.q,
192  p + sizeof(uint32_t), &n, EC_PUBLIC_KEY_FORMAT_X963);
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 = ecExportPublicKey(&connection->ecdhContext.da.q,
252  p + sizeof(uint32_t), &n, EC_PUBLIC_KEY_FORMAT_X963);
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 = ecImportPublicKey(&connection->ecdhContext.qb,
375  connection->ecdhContext.curve, publicKey.value, publicKey.length,
377  //Any error to report?
378  if(error)
379  return error;
380 
381  //Ensure the public key is acceptable
382  error = ecdhCheckPublicKey(&connection->ecdhContext,
383  &connection->ecdhContext.qb);
384  //Any error to report?
385  if(error)
386  return error;
387 
388  //The server responds with an SSH_MSG_KEX_ECDH_REPLY message
389  return sshSendKexEcdhReply(connection);
390 #else
391  //Server operation mode is not implemented
393 #endif
394 }
395 
396 
397 /**
398  * @brief Parse SSH_MSG_KEX_ECDH_REPLY message
399  * @param[in] connection Pointer to the SSH connection
400  * @param[in] message Pointer to message
401  * @param[in] length Length of the message, in bytes
402  * @return Error code
403  **/
404 
405 error_t sshParseKexEcdhReply(SshConnection *connection, const uint8_t *message,
406  size_t length)
407 {
408 #if (SSH_CLIENT_SUPPORT == ENABLED)
409  error_t error;
410  const uint8_t *p;
411  SshString hostKeyAlgo;
412  SshBinaryString hostKey;
413  SshBinaryString publicKey;
414  SshBinaryString signature;
415  SshContext *context;
416 
417  //Point to the SSH context
418  context = connection->context;
419 
420  //Debug message
421  TRACE_INFO("SSH_MSG_KEX_ECDH_REPLY message received (%" PRIuSIZE " bytes)...\r\n", length);
423 
424  //Check operation mode
425  if(context->mode != SSH_OPERATION_MODE_CLIENT)
427 
428  //Check connection state
429  if(connection->state != SSH_CONN_STATE_KEX_ECDH_REPLY)
431 
432  //Sanity check
433  if(length < sizeof(uint8_t))
434  return ERROR_INVALID_MESSAGE;
435 
436  //Point to the first field of the message
437  p = message + sizeof(uint8_t);
438  //Remaining bytes to process
439  length -= sizeof(uint8_t);
440 
441  //Decode server's public host key (K_S)
442  error = sshParseBinaryString(p, length, &hostKey);
443  //Any error to report?
444  if(error)
445  return error;
446 
447  //Point to the next field
448  p += sizeof(uint32_t) + hostKey.length;
449  length -= sizeof(uint32_t) + hostKey.length;
450 
451  //Decode server's ephemeral public key (Q_S)
452  error = sshParseBinaryString(p, length, &publicKey);
453  //Any error to report?
454  if(error)
455  return error;
456 
457  //Point to the next field
458  p += sizeof(uint32_t) + publicKey.length;
459  length -= sizeof(uint32_t) + publicKey.length;
460 
461  //Decode the signature field
462  error = sshParseBinaryString(p, length, &signature);
463  //Any error to report?
464  if(error)
465  return error;
466 
467  //Point to the next field
468  p += sizeof(uint32_t) + signature.length;
469  length -= sizeof(uint32_t) + signature.length;
470 
471  //Malformed message?
472  if(length != 0)
473  return ERROR_INVALID_MESSAGE;
474 
475  //Get the selected server's host key algorithm
476  hostKeyAlgo.value = connection->serverHostKeyAlgo;
477  hostKeyAlgo.length = osStrlen(connection->serverHostKeyAlgo);
478 
479 #if (SSH_CERT_SUPPORT == ENABLED)
480  //Certificate-based authentication?
481  if(sshIsCertPublicKeyAlgo(&hostKeyAlgo))
482  {
483  //Verify server's certificate
484  error = sshVerifyServerCertificate(connection, &hostKeyAlgo, &hostKey);
485  }
486  else
487 #endif
488  {
489  //Verify server's host key
490  error = sshVerifyServerHostKey(connection, &hostKeyAlgo, &hostKey);
491  }
492 
493  //If the client fails to verify the server's host key, it should disconnect
494  //from the server by sending an SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE message
495  if(error)
496  return ERROR_INVALID_KEY;
497 
498  //Update exchange hash H with K_S (server's public host key)
499  error = sshUpdateExchangeHash(connection, hostKey.value, hostKey.length);
500  //Any error to report?
501  if(error)
502  return error;
503 
504  //Update exchange hash H with Q_C (client's ephemeral public key octet
505  //string)
506  error = sshDigestClientEcdhPublicKey(connection);
507  //Any error to report?
508  if(error)
509  return error;
510 
511  //Update exchange hash H with Q_S (server's ephemeral public key octet
512  //string)
513  error = sshUpdateExchangeHash(connection, publicKey.value,
514  publicKey.length);
515  //Any error to report?
516  if(error)
517  return error;
518 
519  //Load server's ephemeral public key
520  error = ecImportPublicKey(&connection->ecdhContext.qb,
521  connection->ecdhContext.curve, publicKey.value, publicKey.length,
523  //Any error to report?
524  if(error)
525  return error;
526 
527  //Ensure the public key is acceptable
528  error = ecdhCheckPublicKey(&connection->ecdhContext,
529  &connection->ecdhContext.qb);
530  //Any error to report?
531  if(error)
532  return error;
533 
534  //Compute the shared secret K
535  error = sshComputeEcdhSharedSecret(connection);
536  //Any error to report?
537  if(error)
538  return error;
539 
540  //Update exchange hash H with K (shared secret)
541  error = sshUpdateExchangeHashRaw(connection, connection->k,
542  connection->kLen);
543  //Any error to report?
544  if(error)
545  return error;
546 
547  //Verify the signature on the exchange hash
548  error = sshVerifyExchangeHashSignature(connection, &hostKey, &signature);
549  //Any error to report?
550  if(error)
551  return error;
552 
553  //The ephemeral private key shall be destroyed as soon as possible (refer
554  //to RFC 9212, section 6)
555  ecdhFree(&connection->ecdhContext);
556  ecdhInit(&connection->ecdhContext);
557 
558  //Key exchange ends by each side sending an SSH_MSG_NEWKEYS message
559  return sshSendNewKeys(connection);
560 #else
561  //Client operation mode is not implemented
563 #endif
564 }
565 
566 
567 /**
568  * @brief Parse ECDH specific messages
569  * @param[in] connection Pointer to the SSH connection
570  * @param[in] type SSH message type
571  * @param[in] message Pointer to message
572  * @param[in] length Length of the message, in bytes
573  * @return Error code
574  **/
575 
577  const uint8_t *message, size_t length)
578 {
579  error_t error;
580 
581 #if (SSH_CLIENT_SUPPORT == ENABLED)
582  //Client operation mode?
583  if(connection->context->mode == SSH_OPERATION_MODE_CLIENT)
584  {
585  //Check message type
587  {
588  //Parse SSH_MSG_KEX_ECDH_REPLY message
589  error = sshParseKexEcdhReply(connection, message, length);
590  }
591  else
592  {
593  //Unknown message type
594  error = ERROR_INVALID_TYPE;
595  }
596  }
597  else
598 #endif
599 #if (SSH_SERVER_SUPPORT == ENABLED)
600  //Server operation mode?
601  if(connection->context->mode == SSH_OPERATION_MODE_SERVER)
602  {
603  //Check message type
605  {
606  //Parse SSH_MSG_KEX_ECDH_INIT message
607  error = sshParseKexEcdhInit(connection, message, length);
608  }
609  else
610  {
611  //Unknown message type
612  error = ERROR_INVALID_TYPE;
613  }
614  }
615  else
616 #endif
617  //Invalid operation mode?
618  {
619  //Report an error
620  error = ERROR_INVALID_TYPE;
621  }
622 
623  //Return status code
624  return error;
625 }
626 
627 
628 /**
629  * @brief Select ECDH domain parameters
630  * @param[in] connection Pointer to the SSH connection
631  * @return Error code
632  **/
633 
635 {
636  error_t error;
637  const EcCurve *curve;
638 
639  //Initialize status code
640  error = NO_ERROR;
641 
642 #if (SSH_NISTP256_SUPPORT == ENABLED)
643  //NIST P-256 elliptic curve?
644  if(sshCompareAlgo(connection->kexAlgo, "ecdh-sha2-nistp256"))
645  {
646  curve = SECP256R1_CURVE;
647  }
648  else
649 #endif
650 #if (SSH_NISTP384_SUPPORT == ENABLED)
651  //NIST P-384 elliptic curve?
652  if(sshCompareAlgo(connection->kexAlgo, "ecdh-sha2-nistp384"))
653  {
654  curve = SECP384R1_CURVE;
655  }
656  else
657 #endif
658 #if (SSH_NISTP521_SUPPORT == ENABLED)
659  //NIST P-521 elliptic curve?
660  if(sshCompareAlgo(connection->kexAlgo, "ecdh-sha2-nistp521"))
661  {
662  curve = SECP521R1_CURVE;
663  }
664  else
665 #endif
666 #if (SSH_CURVE25519_SUPPORT == ENABLED)
667  //Curve25519 elliptic curve?
668  if(sshCompareAlgo(connection->kexAlgo, "curve25519-sha256") ||
669  sshCompareAlgo(connection->kexAlgo, "curve25519-sha256@libssh.org"))
670  {
671  curve = X25519_CURVE;
672  }
673  else
674 #endif
675 #if (SSH_CURVE448_SUPPORT == ENABLED)
676  //Curve448 elliptic curve?
677  if(sshCompareAlgo(connection->kexAlgo, "curve448-sha512"))
678  {
679  curve = X448_CURVE;
680  }
681  else
682 #endif
683  //Unknown elliptic curve?
684  {
685  curve = NULL;
686  }
687 
688  //Make sure the specified elliptic curve is supported
689  if(curve != NULL)
690  {
691  //Save ECDH domain parameters
692  connection->ecdhContext.curve = curve;
693  }
694  else
695  {
696  //Report an error
698  }
699 
700  //Return status code
701  return error;
702 }
703 
704 
705 /**
706  * @brief ECDH key pair generation
707  * @param[in] connection Pointer to the SSH connection
708  * @return Error code
709  **/
710 
712 {
713  error_t error;
714  SshContext *context;
715 
716  //Point to the SSH context
717  context = connection->context;
718 
719 #if (SSH_ECDH_CALLBACK_SUPPORT == ENABLED)
720  //Valid ECDH key pair generation callback function?
721  if(context->ecdhKeyPairGenCallback != NULL)
722  {
723  //Invoke user-defined callback
724  error = context->ecdhKeyPairGenCallback(connection, connection->kexAlgo,
725  &connection->ecdhContext.da.q);
726  }
727  else
728 #endif
729  {
730  //No callback function registered
732  }
733 
734  //Check status code
736  {
737  //Generate an ephemeral key pair
738  error = ecdhGenerateKeyPair(&connection->ecdhContext, context->prngAlgo,
739  context->prngContext);
740  }
741 
742  //Return status code
743  return error;
744 }
745 
746 
747 /**
748  * @brief ECDH shared secret calculation
749  * @param[in] connection Pointer to the SSH connection
750  * @return Error code
751  **/
752 
754 {
755  error_t error;
756 
757 #if (SSH_ECDH_CALLBACK_SUPPORT == ENABLED)
758  //Valid ECDH shared secret calculation callback function?
759  if(connection->context->ecdhSharedSecretCalcCallback != NULL)
760  {
761  //Invoke user-defined callback
762  error = connection->context->ecdhSharedSecretCalcCallback(connection,
763  connection->kexAlgo, &connection->ecdhContext.qb, connection->k,
764  &connection->kLen);
765  }
766  else
767 #endif
768  {
769  //No callback function registered
771  }
772 
773  //Check status code
775  {
776  //Compute the shared secret K
777  error = ecdhComputeSharedSecret(&connection->ecdhContext, connection->k,
779  }
780 
781  //Check status code
782  if(!error)
783  {
784  //Log shared secret (for debugging purpose only)
785  sshDumpKey(connection, "SHARED_SECRET", connection->k, connection->kLen);
786 
787  //Convert the shared secret K to mpint representation
788  error = sshConvertArrayToMpint(connection->k, connection->kLen,
789  connection->k, &connection->kLen);
790  }
791 
792  //Return status code
793  return error;
794 }
795 
796 
797 /**
798  * @brief Update exchange hash with client's ephemeral public key
799  * @param[in] connection Pointer to the SSH connection
800  * @return Error code
801  **/
802 
804 {
805  error_t error;
806  size_t n;
807  uint8_t *buffer;
808 
809  //Allocate a temporary buffer
810  buffer = sshAllocMem(SSH_BUFFER_SIZE);
811 
812  //Successful memory allocation?
813  if(buffer != NULL)
814  {
815  //Format client's ephemeral public key
816  error = ecExportPublicKey(&connection->ecdhContext.da.q, buffer, &n,
818 
819  //Check status code
820  if(!error)
821  {
822  //Update exchange hash H with Q_C (client's ephemeral public key
823  //octet string)
824  error = sshUpdateExchangeHash(connection, buffer, n);
825  }
826 
827  //Release previously allocated memory
828  sshFreeMem(buffer);
829  }
830  else
831  {
832  //Failed to allocate memory
833  error = ERROR_OUT_OF_MEMORY;
834  }
835 
836  //Return status code
837  return error;
838 }
839 
840 #endif
error_t sshGenerateExchangeHashSignature(SshConnection *connection, uint8_t *p, size_t *written)
Compute the signature on the exchange hash.
error_t ecImportPublicKey(EcPublicKey *key, const EcCurve *curve, const uint8_t *data, size_t length, EcPublicKeyFormat format)
Import an EC public key.
Definition: ec.c:263
#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:405
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:711
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:1571
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:803
error_t ecdhCheckPublicKey(EcdhContext *context, const EcPublicKey *publicKey)
Check ECDH public key.
Definition: ecdh.c:224
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:1693
@ 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.
error_t ecExportPublicKey(const EcPublicKey *key, uint8_t *data, size_t *length, EcPublicKeyFormat format)
Export an EC public key.
Definition: ec.c:378
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:338
@ ERROR_UNSUPPORTED_KEY_EXCH_ALGO
Definition: error.h:131
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:753
@ 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
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:1185
#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:576
#define PRIuSIZE
@ SSH_MSG_KEX_ECDH_REPLY
Definition: ssh.h:958
Secure Shell (SSH)
SSH algorithm negotiation.
error_t sshSelectEcdhCurve(SshConnection *connection)
Select ECDH domain parameters.
Definition: ssh_kex_ecdh.c:634
#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:84
#define X25519_CURVE
Definition: ec_curves.h:70
#define TRACE_VERBOSE_ARRAY(p, a, n)
Definition: debug.h:140