ssh_kex_kem.c
Go to the documentation of this file.
1 /**
2  * @file ssh_kex_kem.c
3  * @brief Pure post-quantum key exchange
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2019-2026 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.6.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_kem.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_KEM_KEX_SUPPORT == ENABLED)
50 
51 
52 /**
53  * @brief Send SSH_MSG_KEX_KEM_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  SshContext *context;
65 
66  //Point to the SSH context
67  context = connection->context;
68 
69  //Point to the buffer where to format the message
70  message = connection->buffer + SSH_PACKET_HEADER_SIZE;
71 
72  //Key exchange algorithms are formulated as key encapsulation mechanisms
73  error = sshSelectKemAlgo(connection);
74 
75  //Check status code
76  if(!error)
77  {
78  //Generate a post-quantum KEM key pair
79  error = kemGenerateKeyPair(&connection->kemContext, context->prngAlgo,
80  context->prngContext);
81  }
82 
83  //Check status code
84  if(!error)
85  {
86  //Format SSH_MSG_KEX_KEM_INIT message
87  error = sshFormatKexKemInit(connection, message, &length);
88  }
89 
90  //Check status code
91  if(!error)
92  {
93  //Debug message
94  TRACE_INFO("Sending SSH_MSG_KEX_KEM_INIT message (%" PRIuSIZE " bytes)...\r\n", length);
96 
97  //Send message
98  error = sshSendPacket(connection, message, length);
99  }
100 
101  //Check status code
102  if(!error)
103  {
104  //The server responds with an SSH_MSG_KEX_KEM_REPLY message
105  connection->state = SSH_CONN_STATE_KEX_KEM_REPLY;
106  }
107 
108  //Return status code
109  return error;
110 #else
111  //Client operation mode is not implemented
112  return ERROR_NOT_IMPLEMENTED;
113 #endif
114 }
115 
116 
117 /**
118  * @brief Send SSH_MSG_KEX_KEM_REPLY message
119  * @param[in] connection Pointer to the SSH connection
120  * @return Error code
121  **/
122 
124 {
125 #if (SSH_SERVER_SUPPORT == ENABLED)
126  error_t error;
127  size_t length;
128  uint8_t *message;
129 
130  //Point to the buffer where to format the message
131  message = connection->buffer + SSH_PACKET_HEADER_SIZE;
132 
133  //Format SSH_MSG_KEX_KEM_REPLY message
134  error = sshFormatKexKemReply(connection, message, &length);
135 
136  //Check status code
137  if(!error)
138  {
139  //Debug message
140  TRACE_INFO("Sending SSH_MSG_KEX_KEM_REPLY message (%" PRIuSIZE " bytes)...\r\n", length);
142 
143  //Send message
144  error = sshSendPacket(connection, message, length);
145  }
146 
147  //Check status code
148  if(!error)
149  {
150  //Key exchange ends by each side sending an SSH_MSG_NEWKEYS message
151  connection->state = SSH_CONN_STATE_SERVER_NEW_KEYS;
152  }
153 
154  //Return status code
155  return error;
156 #else
157  //Server operation mode is not implemented
158  return ERROR_NOT_IMPLEMENTED;
159 #endif
160 }
161 
162 
163 /**
164  * @brief Format SSH_MSG_KEX_KEM_INIT message
165  * @param[in] connection Pointer to the SSH connection
166  * @param[out] p Buffer where to format the message
167  * @param[out] length Length of the resulting message, in bytes
168  * @return Error code
169  **/
170 
172  size_t *length)
173 {
174 #if (SSH_CLIENT_SUPPORT == ENABLED)
175  size_t n;
176 
177  //Total length of the message
178  *length = 0;
179 
180  //Set message type
181  p[0] = SSH_MSG_KEX_KEM_INIT;
182 
183  //Point to the first field of the message
184  p += sizeof(uint8_t);
185  *length += sizeof(uint8_t);
186 
187  //Get the length of the public key
188  n = connection->kemContext.kemAlgo->publicKeySize;
189 
190  //C_INIT is the ephemeral client ML-KEM public key (C_PK)
191  osMemcpy(p + sizeof(uint32_t), connection->kemContext.pk, n);
192  //The octet string value is preceded by a uint32 containing its length
193  STORE32BE(n, p);
194 
195  //Total length of the message
196  *length += sizeof(uint32_t) + n;
197 
198  //Successful processing
199  return NO_ERROR;
200 #else
201  //Client operation mode is not implemented
202  return ERROR_NOT_IMPLEMENTED;
203 #endif
204 }
205 
206 
207 /**
208  * @brief Format SSH_MSG_KEX_KEM_REPLY message
209  * @param[in] connection Pointer to the SSH connection
210  * @param[out] p Buffer where to format the message
211  * @param[out] length Length of the resulting message, in bytes
212  * @return Error code
213  **/
214 
216  size_t *length)
217 {
218 #if (SSH_SERVER_SUPPORT == ENABLED)
219  error_t error;
220  size_t n;
221  SshContext *context;
222 
223  //Point to the SSH context
224  context = connection->context;
225 
226  //Total length of the message
227  *length = 0;
228 
229  //Set message type
231 
232  //Point to the first field of the message
233  p += sizeof(uint8_t);
234  *length += sizeof(uint8_t);
235 
236  //Format server's public host key (K_S)
237  error = sshFormatHostKey(connection, p + sizeof(uint32_t), &n);
238  //Any error to report?
239  if(error)
240  return error;
241 
242  //The octet string value is preceded by a uint32 containing its length
243  STORE32BE(n, p);
244 
245  //Point to the next field
246  p += sizeof(uint32_t) + n;
247  *length += sizeof(uint32_t) + n;
248 
249  //Perform KEM encapsulation
250  error = kemEncapsulate(&connection->kemContext, context->prngAlgo,
251  context->prngContext, p + sizeof(uint32_t), connection->k +
252  sizeof(uint32_t));
253  //Any error to report?
254  if(error)
255  return error;
256 
257  //Get the length of the KEM ciphertext
258  n = connection->kemContext.kemAlgo->ciphertextSize;
259 
260  //Update exchange hash H with S_REPLY
261  error = sshUpdateExchangeHash(connection, p + sizeof(uint32_t), n);
262  //Any error to report?
263  if(error)
264  return error;
265 
266  //The octet string value is preceded by a uint32 containing its length
267  STORE32BE(n, p);
268 
269  //Point to the next field
270  p += sizeof(uint32_t) + n;
271  *length += sizeof(uint32_t) + n;
272 
273  //Get the length of the KEM shared secret
274  n = connection->kemContext.kemAlgo->sharedSecretSize;
275 
276  //Log shared secret (for debugging purpose only)
277  sshDumpKey(connection, "SHARED_SECRET", connection->k + sizeof(uint32_t), n);
278 
279  //Convert K_PQ to string representation
280  STORE32BE(n, connection->k);
281  connection->kLen = sizeof(uint32_t) + n;
282 
283  //Update exchange hash H with K_PQ (shared secret)
284  error = sshUpdateExchangeHashRaw(connection, connection->k,
285  connection->kLen);
286  //Any error to report?
287  if(error)
288  return error;
289 
290  //Compute the signature on the exchange hash
291  error = sshGenerateExchangeHashSignature(connection, p + sizeof(uint32_t),
292  &n);
293  //Any error to report?
294  if(error)
295  return error;
296 
297  //The octet string value is preceded by a uint32 containing its length
298  STORE32BE(n, p);
299 
300  //Total length of the message
301  *length += sizeof(uint32_t) + n;
302 
303  //Destroy post-quantum private key
304  kemFree(&connection->kemContext);
305  kemInit(&connection->kemContext, NULL);
306 
307  //Successful processing
308  return NO_ERROR;
309 #else
310  //Server operation mode is not implemented
311  return ERROR_NOT_IMPLEMENTED;
312 #endif
313 }
314 
315 
316 /**
317  * @brief Parse SSH_MSG_KEX_KEM_INIT message
318  * @param[in] connection Pointer to the SSH connection
319  * @param[in] message Pointer to message
320  * @param[in] length Length of the message, in bytes
321  * @return Error code
322  **/
323 
325  const uint8_t *message, size_t length)
326 {
327 #if (SSH_SERVER_SUPPORT == ENABLED)
328  error_t error;
329  const uint8_t *p;
330  SshBinaryString clientInit;
331 
332  //Debug message
333  TRACE_INFO("SSH_MSG_KEX_KEM_INIT message received (%" PRIuSIZE " bytes)...\r\n", length);
335 
336  //Check operation mode
337  if(connection->context->mode != SSH_OPERATION_MODE_SERVER)
339 
340  //Check connection state
341  if(connection->state != SSH_CONN_STATE_KEX_KEM_INIT)
343 
344  //Sanity check
345  if(length < sizeof(uint8_t))
346  return ERROR_INVALID_MESSAGE;
347 
348  //Point to the first field of the message
349  p = message + sizeof(uint8_t);
350  //Remaining bytes to process
351  length -= sizeof(uint8_t);
352 
353  //C_INIT is the ephemeral client ML-KEM public key (C_PK)
354  error = sshParseBinaryString(p, length, &clientInit);
355  //Any error to report?
356  if(error)
357  return error;
358 
359  //Point to the next field
360  p += sizeof(uint32_t) + clientInit.length;
361  length -= sizeof(uint32_t) + clientInit.length;
362 
363  //Malformed message?
364  if(length != 0)
365  return ERROR_INVALID_MESSAGE;
366 
367  //Update exchange hash H with C_INIT
368  error = sshUpdateExchangeHash(connection, clientInit.value,
369  clientInit.length);
370  //Any error to report?
371  if(error)
372  return error;
373 
374  //Key exchange algorithms are formulated as key encapsulation mechanisms
375  error = sshSelectKemAlgo(connection);
376  //Any error to report?
377  if(error)
378  return error;
379 
380  //Check the length of the C_INIT field
381  if(clientInit.length != connection->kemContext.kemAlgo->publicKeySize)
382  {
383  //Abort using a disconnect message (SSH_MSG_DISCONNECT) with a
384  //SSH_DISCONNECT_KEY_EXCHANGE_FAILED as the reason
385  return ERROR_KEY_EXCH_FAILED;
386  }
387 
388  //Load ephemeral client ML-KEM public key (C_PK)
389  error = kemLoadPublicKey(&connection->kemContext, clientInit.value);
390  //Any error to report?
391  if(error)
392  return error;
393 
394  //The server responds with an SSH_MSG_KEX_KEM_REPLY message
395  return sshSendKexKemReply(connection);
396 #else
397  //Server operation mode is not implemented
399 #endif
400 }
401 
402 
403 /**
404  * @brief Parse SSH_MSG_KEX_KEM_REPLY message
405  * @param[in] connection Pointer to the SSH connection
406  * @param[in] message Pointer to message
407  * @param[in] length Length of the message, in bytes
408  * @return Error code
409  **/
410 
412  const uint8_t *message, size_t length)
413 {
414 #if (SSH_CLIENT_SUPPORT == ENABLED)
415  error_t error;
416  size_t n;
417  const uint8_t *p;
418  SshString hostKeyAlgo;
419  SshBinaryString hostKey;
420  SshBinaryString serverReply;
421  SshBinaryString signature;
422  SshContext *context;
423 
424  //Point to the SSH context
425  context = connection->context;
426 
427  //Debug message
428  TRACE_INFO("SSH_MSG_KEX_KEM_REPLY message received (%" PRIuSIZE " bytes)...\r\n", length);
430 
431  //Check operation mode
432  if(context->mode != SSH_OPERATION_MODE_CLIENT)
434 
435  //Check connection state
436  if(connection->state != SSH_CONN_STATE_KEX_KEM_REPLY)
438 
439  //Sanity check
440  if(length < sizeof(uint8_t))
441  return ERROR_INVALID_MESSAGE;
442 
443  //Point to the first field of the message
444  p = message + sizeof(uint8_t);
445  //Remaining bytes to process
446  length -= sizeof(uint8_t);
447 
448  //Decode server's public host key (K_S)
449  error = sshParseBinaryString(p, length, &hostKey);
450  //Any error to report?
451  if(error)
452  return error;
453 
454  //Point to the next field
455  p += sizeof(uint32_t) + hostKey.length;
456  length -= sizeof(uint32_t) + hostKey.length;
457 
458  //Decode S_REPLY
459  error = sshParseBinaryString(p, length, &serverReply);
460  //Any error to report?
461  if(error)
462  return error;
463 
464  //Point to the next field
465  p += sizeof(uint32_t) + serverReply.length;
466  length -= sizeof(uint32_t) + serverReply.length;
467 
468  //Decode the signature field
469  error = sshParseBinaryString(p, length, &signature);
470  //Any error to report?
471  if(error)
472  return error;
473 
474  //Point to the next field
475  p += sizeof(uint32_t) + signature.length;
476  length -= sizeof(uint32_t) + signature.length;
477 
478  //Malformed message?
479  if(length != 0)
480  return ERROR_INVALID_MESSAGE;
481 
482  //Get the selected server's host key algorithm
483  hostKeyAlgo.value = connection->serverHostKeyAlgo;
484  hostKeyAlgo.length = osStrlen(connection->serverHostKeyAlgo);
485 
486 #if (SSH_CERT_SUPPORT == ENABLED)
487  //Certificate-based authentication?
488  if(sshIsCertPublicKeyAlgo(&hostKeyAlgo))
489  {
490  //Verify server's certificate
491  error = sshVerifyServerCertificate(connection, &hostKeyAlgo, &hostKey);
492  }
493  else
494 #endif
495  {
496  //Verify server's host key
497  error = sshVerifyServerHostKey(connection, &hostKeyAlgo, &hostKey);
498  }
499 
500  //If the client fails to verify the server's host key, it should disconnect
501  //from the server by sending an SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE message
502  if(error)
503  return ERROR_INVALID_KEY;
504 
505  //Update exchange hash H with K_S (server's public host key)
506  error = sshUpdateExchangeHash(connection, hostKey.value, hostKey.length);
507  //Any error to report?
508  if(error)
509  return error;
510 
511  //Update exchange hash H with C_INIT
512  error = sshUpdateExchangeHash(connection, connection->kemContext.pk,
513  connection->kemContext.kemAlgo->publicKeySize);
514  //Any error to report?
515  if(error)
516  return error;
517 
518  //Update exchange hash H with S_REPLY
519  error = sshUpdateExchangeHash(connection, serverReply.value,
520  serverReply.length);
521  //Any error to report?
522  if(error)
523  return error;
524 
525  //Before decapsulating, the client must check if the ciphertext S_CT length
526  //matches the selected ML-KEM variant
527  if(serverReply.length != connection->kemContext.kemAlgo->ciphertextSize)
528  {
529  //The client must abort using a disconnect message (SSH_MSG_DISCONNECT)
530  //with a SSH_DISCONNECT_KEY_EXCHANGE_FAILED as the reason if the S_CT
531  //length does not match the ML-KEM variant
532  return ERROR_KEY_EXCH_FAILED;
533  }
534 
535  //K_PQ is the post-quantum shared secret decapsulated from S_CT
536  error = kemDecapsulate(&connection->kemContext, serverReply.value,
537  connection->k + sizeof(uint32_t));
538  //Any error to report?
539  if(error)
540  return error;
541 
542  //Get the length of the KEM shared secret
543  n = connection->kemContext.kemAlgo->sharedSecretSize;
544 
545  //Log shared secret (for debugging purpose only)
546  sshDumpKey(connection, "SHARED_SECRET", connection->k + sizeof(uint32_t), n);
547 
548  //Convert K_PQ to string representation
549  STORE32BE(n, connection->k);
550  connection->kLen = sizeof(uint32_t) + n;
551 
552  //Update exchange hash H with K_PQ (shared secret)
553  error = sshUpdateExchangeHashRaw(connection, connection->k,
554  connection->kLen);
555  //Any error to report?
556  if(error)
557  return error;
558 
559  //Verify the signature on the exchange hash
560  error = sshVerifyExchangeHashSignature(connection, &hostKey, &signature);
561  //Any error to report?
562  if(error)
563  return error;
564 
565  //Destroy post-quantum private key
566  kemFree(&connection->kemContext);
567  kemInit(&connection->kemContext, NULL);
568 
569  //Key exchange ends by each side sending an SSH_MSG_NEWKEYS message
570  return sshSendNewKeys(connection);
571 #else
572  //Client operation mode is not implemented
574 #endif
575 }
576 
577 
578 /**
579  * @brief Parse ML-KEM specific messages
580  * @param[in] connection Pointer to the SSH connection
581  * @param[in] type SSH message type
582  * @param[in] message Pointer to message
583  * @param[in] length Length of the message, in bytes
584  * @return Error code
585  **/
586 
588  const uint8_t *message, size_t length)
589 {
590  error_t error;
591 
592 #if (SSH_CLIENT_SUPPORT == ENABLED)
593  //Client operation mode?
594  if(connection->context->mode == SSH_OPERATION_MODE_CLIENT)
595  {
596  //Check message type
598  {
599  //Parse SSH_MSG_KEX_KEM_REPLY message
600  error = sshParseKexKemReply(connection, message, length);
601  }
602  else
603  {
604  //Unknown message type
605  error = ERROR_INVALID_TYPE;
606  }
607  }
608  else
609 #endif
610 #if (SSH_SERVER_SUPPORT == ENABLED)
611  //Server operation mode?
612  if(connection->context->mode == SSH_OPERATION_MODE_SERVER)
613  {
614  //Check message type
616  {
617  //Parse SSH_MSG_KEX_KEM_INIT message
618  error = sshParseKexKemInit(connection, message, length);
619  }
620  else
621  {
622  //Unknown message type
623  error = ERROR_INVALID_TYPE;
624  }
625  }
626  else
627 #endif
628  //Invalid operation mode?
629  {
630  //Report an error
631  error = ERROR_INVALID_TYPE;
632  }
633 
634  //Return status code
635  return error;
636 }
637 
638 
639 /**
640  * @brief Select key encapsulation mechanism
641  * @param[in] connection Pointer to the SSH connection
642  * @return Error code
643  **/
644 
646 {
647  error_t error;
648 
649  //Release KEM context
650  kemFree(&connection->kemContext);
651 
652 #if (SSH_MLKEM512_SUPPORT == ENABLED)
653  //ML-KEM-512 key encapsulation mechanism?
654  if(sshCompareAlgo(connection->kexAlgo, "mlkem512-sha256"))
655  {
656  //Initialize KEM context
657  kemInit(&connection->kemContext, MLKEM512_KEM_ALGO);
658  //Successful processing
659  error = NO_ERROR;
660  }
661  else
662 #endif
663 #if (SSH_MLKEM768_SUPPORT == ENABLED)
664  //ML-KEM-768 key encapsulation mechanism?
665  if(sshCompareAlgo(connection->kexAlgo, "mlkem768-sha256"))
666  {
667  //Initialize KEM context
668  kemInit(&connection->kemContext, MLKEM768_KEM_ALGO);
669  //Successful processing
670  error = NO_ERROR;
671  }
672  else
673 #endif
674 #if (SSH_MLKEM1024_SUPPORT == ENABLED)
675  //ML-KEM-1024 key encapsulation mechanism?
676  if(sshCompareAlgo(connection->kexAlgo, "mlkem1024-sha384"))
677  {
678  //Initialize KEM context
679  kemInit(&connection->kemContext, MLKEM1024_KEM_ALGO);
680  //Successful processing
681  error = NO_ERROR;
682  }
683  else
684 #endif
685  //Unknown key encapsulation mechanism?
686  {
687  //Report an error
689  }
690 
691  //Return status code
692  return error;
693 }
694 
695 #endif
error_t sshGenerateExchangeHashSignature(SshConnection *connection, uint8_t *p, size_t *written)
Compute the signature on the exchange hash.
@ SSH_CONN_STATE_KEX_KEM_REPLY
Definition: ssh.h:1074
error_t sshParseKexKemMessage(SshConnection *connection, uint8_t type, const uint8_t *message, size_t length)
Parse ML-KEM specific messages.
Definition: ssh_kex_kem.c:587
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)
uint8_t p
Definition: ndp.h:300
uint8_t message[]
Definition: chap.h:154
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.
void kemInit(KemContext *context, const KemAlgo *kemAlgo)
Initialize KEM context.
Definition: kem.c:48
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.
size_t length
Definition: ssh_types.h:58
@ ERROR_INVALID_MESSAGE
Definition: error.h:105
#define osStrlen(s)
Definition: os_port.h:168
Pure post-quantum key exchange.
@ SSH_MSG_KEX_KEM_INIT
Definition: ssh.h:981
void kemFree(KemContext *context)
Release KEM context.
Definition: kem.c:62
#define SSH_PACKET_HEADER_SIZE
Definition: ssh_packet.h:38
error_t kemEncapsulate(KemContext *context, const PrngAlgo *prngAlgo, void *prngContext, uint8_t *ct, uint8_t *ss)
Encapsulation algorithm.
Definition: kem.c:209
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:204
size_t length
Definition: ssh_types.h:69
error_t sshSelectKemAlgo(SshConnection *connection)
Select key encapsulation mechanism.
Definition: ssh_kex_kem.c:645
Key material generation.
#define SshContext
Definition: ssh.h:892
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
const char_t * value
Definition: ssh_types.h:57
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:1758
@ SSH_OPERATION_MODE_SERVER
Definition: ssh.h:915
@ SSH_CONN_STATE_KEX_KEM_INIT
Definition: ssh.h:1073
@ SSH_OPERATION_MODE_CLIENT
Definition: ssh.h:914
error_t sshVerifyServerCertificate(SshConnection *connection, const SshString *publicKeyAlgo, const SshBinaryString *hostKey)
Verify server's certificate.
#define MLKEM512_KEM_ALGO
Definition: mlkem512.h:47
error_t sshParseKexKemReply(SshConnection *connection, const uint8_t *message, size_t length)
Parse SSH_MSG_KEX_KEM_REPLY message.
Definition: ssh_kex_kem.c:411
@ 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:1078
String.
Definition: ssh_types.h:56
SSH key exchange.
const uint8_t * value
Definition: ssh_types.h:68
@ ERROR_UNSUPPORTED_KEY_EXCH_ALGO
Definition: error.h:131
error_t sshParseKexKemInit(SshConnection *connection, const uint8_t *message, size_t length)
Parse SSH_MSG_KEX_KEM_INIT message.
Definition: ssh_kex_kem.c:324
error_t sshFormatKexKemInit(SshConnection *connection, uint8_t *p, size_t *length)
Format SSH_MSG_KEX_KEM_INIT message.
Definition: ssh_kex_kem.c:171
uint8_t n
Exchange hash calculation.
#define SshConnection
Definition: ssh.h:896
error_t kemGenerateKeyPair(KemContext *context, const PrngAlgo *prngAlgo, void *prngContext)
Key pair generation.
Definition: kem.c:100
error_t kemLoadPublicKey(KemContext *context, const uint8_t *pk)
Load public key.
Definition: kem.c:160
error_t kemDecapsulate(KemContext *context, const uint8_t *ct, uint8_t *ss)
Decapsulation algorithm.
Definition: kem.c:240
SSH helper functions.
error_t sshFormatHostKey(SshConnection *connection, uint8_t *p, size_t *written)
Format host key structure.
Definition: ssh_misc.c:875
error_t sshSendKexKemReply(SshConnection *connection)
Send SSH_MSG_KEX_KEM_REPLY message.
Definition: ssh_kex_kem.c:123
#define MLKEM1024_KEM_ALGO
Definition: mlkem1024.h:47
SSH packet encryption/decryption.
error_t sshUpdateExchangeHash(SshConnection *connection, const void *data, size_t length)
Update exchange hash calculation.
@ ERROR_KEY_EXCH_FAILED
Definition: error.h:313
error_t sshParseBinaryString(const uint8_t *p, size_t length, SshBinaryString *string)
Parse a binary string.
Definition: ssh_misc.c:1215
@ SSH_MSG_KEX_KEM_REPLY
Definition: ssh.h:982
#define PRIuSIZE
error_t sshSendKexKemInit(SshConnection *connection)
Send SSH_MSG_KEX_KEM_INIT message.
Definition: ssh_kex_kem.c:58
Secure Shell (SSH)
SSH algorithm negotiation.
error_t sshFormatKexKemReply(SshConnection *connection, uint8_t *p, size_t *length)
Format SSH_MSG_KEX_KEM_REPLY message.
Definition: ssh_kex_kem.c:215
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
#define MLKEM768_KEM_ALGO
Definition: mlkem768.h:47
@ ERROR_INVALID_KEY
Definition: error.h:106
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
#define TRACE_VERBOSE_ARRAY(p, a, n)
Definition: debug.h:140