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-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_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  //Load ECDH domain parameters
69  error = sshLoadKexEcdhParams(&connection->ecdhContext.params,
70  connection->kexAlgo);
71 
72  //Check status code
73  if(!error)
74  {
75  //Generate an ephemeral key pair
76  error = sshGenerateEcdhKeyPair(connection);
77  }
78 
79  //Check status code
80  if(!error)
81  {
82  //Format SSH_MSG_KEX_ECDH_INIT message
83  error = sshFormatKexEcdhInit(connection, message, &length);
84  }
85 
86  //Check status code
87  if(!error)
88  {
89  //Debug message
90  TRACE_INFO("Sending SSH_MSG_KEX_ECDH_INIT message (%" PRIuSIZE " bytes)...\r\n", length);
92 
93  //Send message
94  error = sshSendPacket(connection, message, length);
95  }
96 
97  //Check status code
98  if(!error)
99  {
100  //The server responds with an SSH_MSG_KEX_ECDH_REPLY message
101  connection->state = SSH_CONN_STATE_KEX_ECDH_REPLY;
102  }
103 
104  //Return status code
105  return error;
106 #else
107  //Client operation mode is not implemented
108  return ERROR_NOT_IMPLEMENTED;
109 #endif
110 }
111 
112 
113 /**
114  * @brief Send SSH_MSG_KEX_ECDH_REPLY message
115  * @param[in] connection Pointer to the SSH connection
116  * @return Error code
117  **/
118 
120 {
121 #if (SSH_SERVER_SUPPORT == ENABLED)
122  error_t error;
123  size_t length;
124  uint8_t *message;
125 
126  //Point to the buffer where to format the message
127  message = connection->buffer + SSH_PACKET_HEADER_SIZE;
128 
129  //Generate an ephemeral key pair
130  error = sshGenerateEcdhKeyPair(connection);
131 
132  //Check status code
133  if(!error)
134  {
135  //Format SSH_MSG_KEX_ECDH_REPLY message
136  error = sshFormatKexEcdhReply(connection, message, &length);
137  }
138 
139  //Check status code
140  if(!error)
141  {
142  //Debug message
143  TRACE_INFO("Sending SSH_MSG_KEX_ECDH_REPLY message (%" PRIuSIZE " bytes)...\r\n", length);
145 
146  //Send message
147  error = sshSendPacket(connection, message, length);
148  }
149 
150  //Check status code
151  if(!error)
152  {
153  //Key exchange ends by each side sending an SSH_MSG_NEWKEYS message
154  connection->state = SSH_CONN_STATE_SERVER_NEW_KEYS;
155  }
156 
157  //Return status code
158  return error;
159 #else
160  //Server operation mode is not implemented
161  return ERROR_NOT_IMPLEMENTED;
162 #endif
163 }
164 
165 
166 /**
167  * @brief Format SSH_MSG_KEX_ECDH_INIT message
168  * @param[in] connection Pointer to the SSH connection
169  * @param[out] p Buffer where to format the message
170  * @param[out] length Length of the resulting message, in bytes
171  * @return Error code
172  **/
173 
175  size_t *length)
176 {
177 #if (SSH_CLIENT_SUPPORT == ENABLED)
178  error_t error;
179  size_t n;
180 
181  //Total length of the message
182  *length = 0;
183 
184  //Set message type
186 
187  //Point to the first field of the message
188  p += sizeof(uint8_t);
189  *length += sizeof(uint8_t);
190 
191  //Format client's ephemeral public key (Q_C)
192  error = ecExport(&connection->ecdhContext.params,
193  &connection->ecdhContext.qa.q, p + sizeof(uint32_t), &n);
194  //Any error to report?
195  if(error)
196  return error;
197 
198  //The octet string value is preceded by a uint32 containing its length
199  STORE32BE(n, p);
200 
201  //Total length of the message
202  *length += sizeof(uint32_t) + n;
203 
204  //Successful processing
205  return NO_ERROR;
206 #else
207  //Client operation mode is not implemented
208  return ERROR_NOT_IMPLEMENTED;
209 #endif
210 }
211 
212 
213 /**
214  * @brief Format SSH_MSG_KEX_ECDH_REPLY message
215  * @param[in] connection Pointer to the SSH connection
216  * @param[out] p Buffer where to format the message
217  * @param[out] length Length of the resulting message, in bytes
218  * @return Error code
219  **/
220 
222  size_t *length)
223 {
224 #if (SSH_SERVER_SUPPORT == ENABLED)
225  error_t error;
226  size_t n;
227 
228  //Total length of the message
229  *length = 0;
230 
231  //Set message type
233 
234  //Point to the first field of the message
235  p += sizeof(uint8_t);
236  *length += sizeof(uint8_t);
237 
238  //Format server's public host key (K_S)
239  error = sshFormatHostKey(connection, p + sizeof(uint32_t), &n);
240  //Any error to report?
241  if(error)
242  return error;
243 
244  //The octet string value is preceded by a uint32 containing its length
245  STORE32BE(n, p);
246 
247  //Point to the next field
248  p += sizeof(uint32_t) + n;
249  *length += sizeof(uint32_t) + n;
250 
251  //Format server's ephemeral public key (Q_S)
252  error = ecExport(&connection->ecdhContext.params,
253  &connection->ecdhContext.qa.q, p + sizeof(uint32_t), &n);
254  //Any error to report?
255  if(error)
256  return error;
257 
258  //Update exchange hash H with Q_S (server's ephemeral public key octet string)
259  error = sshUpdateExchangeHash(connection, p + sizeof(uint32_t), n);
260  //Any error to report?
261  if(error)
262  return error;
263 
264  //The octet string value is preceded by a uint32 containing its length
265  STORE32BE(n, p);
266 
267  //Point to the next field
268  p += sizeof(uint32_t) + n;
269  *length += sizeof(uint32_t) + n;
270 
271  //Compute the shared secret K
272  error = sshComputeEcdhSharedSecret(connection);
273  //Any error to report?
274  if(error)
275  return error;
276 
277  //Update exchange hash H with K (shared secret)
278  error = sshUpdateExchangeHashRaw(connection, connection->k,
279  connection->kLen);
280  //Any error to report?
281  if(error)
282  return error;
283 
284  //Compute the signature on the exchange hash
285  error = sshGenerateExchangeHashSignature(connection, p + sizeof(uint32_t),
286  &n);
287  //Any error to report?
288  if(error)
289  return error;
290 
291  //The octet string value is preceded by a uint32 containing its length
292  STORE32BE(n, p);
293 
294  //Total length of the message
295  *length += sizeof(uint32_t) + n;
296 
297  //The ephemeral private key shall be destroyed as soon as possible (refer
298  //to RFC 9212, section 6)
299  ecdhFree(&connection->ecdhContext);
300  ecdhInit(&connection->ecdhContext);
301 
302  //Successful processing
303  return NO_ERROR;
304 #else
305  //Server operation mode is not implemented
306  return ERROR_NOT_IMPLEMENTED;
307 #endif
308 }
309 
310 
311 /**
312  * @brief Parse SSH_MSG_KEX_ECDH_INIT message
313  * @param[in] connection Pointer to the SSH connection
314  * @param[in] message Pointer to message
315  * @param[in] length Length of the message, in bytes
316  * @return Error code
317  **/
318 
319 error_t sshParseKexEcdhInit(SshConnection *connection, const uint8_t *message,
320  size_t length)
321 {
322 #if (SSH_SERVER_SUPPORT == ENABLED)
323  error_t error;
324  const uint8_t *p;
325  SshBinaryString publicKey;
326 
327  //Debug message
328  TRACE_INFO("SSH_MSG_KEX_ECDH_INIT message received (%" PRIuSIZE " bytes)...\r\n", length);
330 
331  //Check operation mode
332  if(connection->context->mode != SSH_OPERATION_MODE_SERVER)
334 
335  //Check connection state
336  if(connection->state != SSH_CONN_STATE_KEX_ECDH_INIT)
338 
339  //Sanity check
340  if(length < sizeof(uint8_t))
341  return ERROR_INVALID_MESSAGE;
342 
343  //Point to the first field of the message
344  p = message + sizeof(uint8_t);
345  //Remaining bytes to process
346  length -= sizeof(uint8_t);
347 
348  //Decode client's ephemeral public key (Q_C)
349  error = sshParseBinaryString(p, length, &publicKey);
350  //Any error to report?
351  if(error)
352  return error;
353 
354  //Point to the next field
355  p += sizeof(uint32_t) + publicKey.length;
356  length -= sizeof(uint32_t) + publicKey.length;
357 
358  //Malformed message?
359  if(length != 0)
360  return ERROR_INVALID_MESSAGE;
361 
362  //Update exchange hash H with Q_C (client's ephemeral public key octet string)
363  error = sshUpdateExchangeHash(connection, publicKey.value, publicKey.length);
364  //Any error to report?
365  if(error)
366  return error;
367 
368  //Load ECDH domain parameters
369  error = sshLoadKexEcdhParams(&connection->ecdhContext.params,
370  connection->kexAlgo);
371  //Any error to report?
372  if(error)
373  return error;
374 
375  //Load client's ephemeral public key
376  error = ecImport(&connection->ecdhContext.params, &connection->ecdhContext.qb.q,
377  publicKey.value, publicKey.length);
378  //Any error to report?
379  if(error)
380  return error;
381 
382  //Ensure the public key is acceptable
383  error = ecdhCheckPublicKey(&connection->ecdhContext.params,
384  &connection->ecdhContext.qb.q);
385  //Any error to report?
386  if(error)
387  return error;
388 
389  //The server responds with an SSH_MSG_KEX_ECDH_REPLY message
390  return sshSendKexEcdhReply(connection);
391 #else
392  //Server operation mode is not implemented
394 #endif
395 }
396 
397 
398 /**
399  * @brief Parse SSH_MSG_KEX_ECDH_REPLY message
400  * @param[in] connection Pointer to the SSH connection
401  * @param[in] message Pointer to message
402  * @param[in] length Length of the message, in bytes
403  * @return Error code
404  **/
405 
406 error_t sshParseKexEcdhReply(SshConnection *connection, const uint8_t *message,
407  size_t length)
408 {
409 #if (SSH_CLIENT_SUPPORT == ENABLED)
410  error_t error;
411  const uint8_t *p;
412  SshString hostKeyAlgo;
413  SshBinaryString hostKey;
414  SshBinaryString publicKey;
415  SshBinaryString signature;
416  SshContext *context;
417 
418  //Point to the SSH context
419  context = connection->context;
420 
421  //Debug message
422  TRACE_INFO("SSH_MSG_KEX_ECDH_REPLY message received (%" PRIuSIZE " bytes)...\r\n", length);
424 
425  //Check operation mode
426  if(context->mode != SSH_OPERATION_MODE_CLIENT)
428 
429  //Check connection state
430  if(connection->state != SSH_CONN_STATE_KEX_ECDH_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 (Q_S)
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 message
496  if(error)
497  return ERROR_INVALID_KEY;
498 
499  //Update exchange hash H with K_S (server's public host key)
500  error = sshUpdateExchangeHash(connection, hostKey.value, hostKey.length);
501  //Any error to report?
502  if(error)
503  return error;
504 
505  //Update exchange hash H with Q_C (client's ephemeral public key octet
506  //string)
507  error = sshDigestClientEcdhPublicKey(connection);
508  //Any error to report?
509  if(error)
510  return error;
511 
512  //Update exchange hash H with Q_S (server's ephemeral public key octet
513  //string)
514  error = sshUpdateExchangeHash(connection, publicKey.value,
515  publicKey.length);
516  //Any error to report?
517  if(error)
518  return error;
519 
520  //Load server's ephemeral public key
521  error = ecImport(&connection->ecdhContext.params,
522  &connection->ecdhContext.qb.q, 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.params,
529  &connection->ecdhContext.qb.q);
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 Load the EC parameters that match specified key exchange algorithm
630  * @param[in,out] params Elliptic curve domain parameters
631  * @param[in] kexAlgo Key exchange algorithm name
632  * @return Error code
633  **/
634 
636 {
637  error_t error;
638  const EcCurveInfo *curveInfo;
639 
640 #if (SSH_NISTP256_SUPPORT == ENABLED)
641  //NIST P-256 elliptic curve?
642  if(sshCompareAlgo(kexAlgo, "ecdh-sha2-nistp256"))
643  {
644  curveInfo = SECP256R1_CURVE;
645  }
646  else
647 #endif
648 #if (SSH_NISTP384_SUPPORT == ENABLED)
649  //NIST P-384 elliptic curve?
650  if(sshCompareAlgo(kexAlgo, "ecdh-sha2-nistp384"))
651  {
652  curveInfo = SECP384R1_CURVE;
653  }
654  else
655 #endif
656 #if (SSH_NISTP521_SUPPORT == ENABLED)
657  //NIST P-521 elliptic curve?
658  if(sshCompareAlgo(kexAlgo, "ecdh-sha2-nistp521"))
659  {
660  curveInfo = SECP521R1_CURVE;
661  }
662  else
663 #endif
664 #if (SSH_CURVE25519_SUPPORT == ENABLED)
665  //Curve25519 elliptic curve?
666  if(sshCompareAlgo(kexAlgo, "curve25519-sha256") ||
667  sshCompareAlgo(kexAlgo, "curve25519-sha256@libssh.org"))
668  {
669  curveInfo = X25519_CURVE;
670  }
671  else
672 #endif
673 #if (SSH_CURVE448_SUPPORT == ENABLED)
674  //Curve448 elliptic curve?
675  if(sshCompareAlgo(kexAlgo, "curve448-sha512"))
676  {
677  curveInfo = X448_CURVE;
678  }
679  else
680 #endif
681  //Unknown elliptic curve?
682  {
683  curveInfo = NULL;
684  }
685 
686  //Make sure the key exchange algorithm is acceptable
687  if(curveInfo != NULL)
688  {
689  //Load EC domain parameters
690  error = ecLoadDomainParameters(params, curveInfo);
691  }
692  else
693  {
694  //Report an error
696  }
697 
698  //Return status code
699  return error;
700 }
701 
702 
703 /**
704  * @brief ECDH key pair generation
705  * @param[in] connection Pointer to the SSH connection
706  * @return Error code
707  **/
708 
710 {
711  error_t error;
712  SshContext *context;
713 
714  //Point to the SSH context
715  context = connection->context;
716 
717 #if (SSH_ECDH_CALLBACK_SUPPORT == ENABLED)
718  //Valid ECDH key pair generation callback function?
719  if(context->ecdhKeyPairGenCallback != NULL)
720  {
721  //Invoke user-defined callback
722  error = context->ecdhKeyPairGenCallback(connection, connection->kexAlgo,
723  &connection->ecdhContext.qa);
724  }
725  else
726 #endif
727  {
728  //No callback function registered
730  }
731 
732  //Check status code
734  {
735  //Generate an ephemeral key pair
736  error = ecdhGenerateKeyPair(&connection->ecdhContext, context->prngAlgo,
737  context->prngContext);
738  }
739 
740  //Return status code
741  return error;
742 }
743 
744 
745 /**
746  * @brief ECDH shared secret calculation
747  * @param[in] connection Pointer to the SSH connection
748  * @return Error code
749  **/
750 
752 {
753  error_t error;
754 
755 #if (SSH_ECDH_CALLBACK_SUPPORT == ENABLED)
756  //Valid ECDH shared secret calculation callback function?
757  if(connection->context->ecdhSharedSecretCalcCallback != NULL)
758  {
759  //Invoke user-defined callback
760  error = connection->context->ecdhSharedSecretCalcCallback(connection,
761  connection->kexAlgo, &connection->ecdhContext.qb, connection->k,
762  &connection->kLen);
763  }
764  else
765 #endif
766  {
767  //No callback function registered
769  }
770 
771  //Check status code
773  {
774  //Compute the shared secret K
775  error = ecdhComputeSharedSecret(&connection->ecdhContext, connection->k,
777  }
778 
779  //Check status code
780  if(!error)
781  {
782  //Log shared secret (for debugging purpose only)
783  sshDumpKey(connection, "SHARED_SECRET", connection->k, connection->kLen);
784 
785  //Convert the shared secret K to mpint representation
786  error = sshConvertArrayToMpint(connection->k, connection->kLen,
787  connection->k, &connection->kLen);
788  }
789 
790  //Return status code
791  return error;
792 }
793 
794 
795 /**
796  * @brief Update exchange hash with client's ephemeral public key
797  * @param[in] connection Pointer to the SSH connection
798  * @return Error code
799  **/
800 
802 {
803  error_t error;
804  size_t n;
805  uint8_t *buffer;
806 
807  //Allocate a temporary buffer
808  buffer = sshAllocMem(SSH_BUFFER_SIZE);
809 
810  //Successful memory allocation?
811  if(buffer != NULL)
812  {
813  //Format client's ephemeral public key
814  error = ecExport(&connection->ecdhContext.params,
815  &connection->ecdhContext.qa.q, buffer, &n);
816 
817  //Check status code
818  if(!error)
819  {
820  //Update exchange hash H with Q_C (client's ephemeral public key
821  //octet string)
822  error = sshUpdateExchangeHash(connection, buffer, n);
823  }
824 
825  //Release previously allocated memory
826  sshFreeMem(buffer);
827  }
828  else
829  {
830  //Failed to allocate memory
831  error = ERROR_OUT_OF_MEMORY;
832  }
833 
834  //Return status code
835  return error;
836 }
837 
838 #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:249
SSH host key verification.
Binary string.
Definition: ssh_types.h:67
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
error_t ecImport(const EcDomainParameters *params, EcPoint *r, const uint8_t *data, size_t length)
Convert an octet string to an EC point.
Definition: ec.c:365
@ 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)
ECDH key exchange.
#define SECP384R1_CURVE
Definition: ec_curves.h:248
uint8_t p
Definition: ndp.h:300
uint8_t message[]
Definition: chap.h:154
#define SECP256R1_CURVE
Definition: ec_curves.h:247
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:406
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
EC domain parameters.
Definition: ec.h:76
#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:709
size_t length
Definition: ssh_types.h:69
error_t ecLoadDomainParameters(EcDomainParameters *params, const EcCurveInfo *curveInfo)
Load EC domain parameters.
Definition: ec.c:90
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:1531
Elliptic curve parameters.
Definition: ec_curves.h:302
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:801
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:1653
@ 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: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 ecdhComputeSharedSecret(EcdhContext *context, uint8_t *output, size_t outputSize, size_t *outputLen)
Compute ECDH shared secret.
Definition: ecdh.c:340
@ 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:174
void ecdhInit(EcdhContext *context)
Initialize ECDH context.
Definition: ecdh.c:48
char char_t
Definition: compiler_port.h:48
#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:751
@ 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:221
SSH helper functions.
error_t ecExport(const EcDomainParameters *params, const EcPoint *a, uint8_t *data, size_t *length)
Convert an EC point to an octet string.
Definition: ec.c:438
error_t sshFormatHostKey(SshConnection *connection, uint8_t *p, size_t *written)
Format host key structure.
Definition: ssh_misc.c:863
#define X448_CURVE
Definition: ec_curves.h:259
error_t sshParseKexEcdhInit(SshConnection *connection, const uint8_t *message, size_t length)
Parse SSH_MSG_KEX_ECDH_INIT message.
Definition: ssh_kex_ecdh.c:319
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
#define sshAllocMem(size)
Definition: ssh.h:724
error_t sshSendKexEcdhReply(SshConnection *connection)
Send SSH_MSG_KEX_ECDH_REPLY message.
Definition: ssh_kex_ecdh.c:119
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 ecdhCheckPublicKey(const EcDomainParameters *params, EcPoint *publicKey)
Check ECDH public key.
Definition: ecdh.c:227
#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 sshLoadKexEcdhParams(EcDomainParameters *params, const char_t *kexAlgo)
Load the EC parameters that match specified key exchange algorithm.
Definition: ssh_kex_ecdh.c:635
error_t ecdhGenerateKeyPair(EcdhContext *context, const PrngAlgo *prngAlgo, void *prngContext)
ECDH key pair generation.
Definition: ecdh.c:85
#define X25519_CURVE
Definition: ec_curves.h:258
#define TRACE_VERBOSE_ARRAY(p, a, n)
Definition: debug.h:125