tls13_client_extensions.c
Go to the documentation of this file.
1 /**
2  * @file tls13_client_extensions.c
3  * @brief Formatting and parsing of extensions (TLS 1.3 client)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneSSL 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.2
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL TLS_TRACE_LEVEL
33 
34 //Dependencies
35 #include "tls/tls.h"
36 #include "tls/tls_misc.h"
38 #include "tls13/tls13_ticket.h"
39 #include "debug.h"
40 
41 //Check TLS library configuration
42 #if (TLS_SUPPORT == ENABLED && TLS_CLIENT_SUPPORT == ENABLED && \
43  TLS_MAX_VERSION >= TLS_VERSION_1_3)
44 
45 
46 /**
47  * @brief Format Cookie extension
48  * @param[in] context Pointer to the TLS context
49  * @param[in] p Output stream where to write the Cookie extension
50  * @param[out] written Total number of bytes that have been written
51  * @return Error code
52  **/
53 
55  size_t *written)
56 {
57  size_t n;
58  TlsExtension *extension;
60 
61  //Initialize length field
62  n = 0;
63 
64  //When sending a HelloRetryRequest, the server may provide a Cookie
65  //extension to the client
66  if(context->cookieLen > 0)
67  {
68  //Add the Cookie extension
69  extension = (TlsExtension *) p;
70  //Type of the extension
71  extension->type = HTONS(TLS_EXT_COOKIE);
72 
73  //Point to the extension data field
74  cookie = (Tls13Cookie *) extension->value;
75 
76  //When sending the new ClientHello, the client must copy the contents
77  //of the Cookie extension received in the HelloRetryRequest
78  osMemcpy(cookie->value, context->cookie, context->cookieLen);
79 
80  //Set the length of the cookie
81  cookie->length = ntohs(context->cookieLen);
82 
83  //Consider the 2-byte length field that precedes the cookie
84  n = sizeof(Tls13Cookie) + context->cookieLen;
85  //Fix the length of the extension
86  extension->length = htons(n);
87 
88  //Compute the length, in bytes, of the Cookie extension
89  n += sizeof(TlsExtension);
90  }
91 
92  //Total number of bytes that have been written
93  *written = n;
94 
95  //Successful processing
96  return NO_ERROR;
97 }
98 
99 
100 /**
101  * @brief Format KeyShare extension (ClientHello message)
102  * @param[in] context Pointer to the TLS context
103  * @param[in] p Output stream where to write the KeyShare extension
104  * @param[out] written Total number of bytes that have been written
105  * @return Error code
106  **/
107 
109  uint8_t *p, size_t *written)
110 {
111  size_t n = 0;
112 
113 #if (TLS13_DHE_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
114  TLS13_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || \
115  TLS13_MLKEM_KE_SUPPORT == ENABLED || TLS13_PSK_MLKEM_KE_SUPPORT == ENABLED || \
116  TLS13_HYBRID_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
117  error_t error;
118  TlsExtension *extension;
119  Tls13KeyShareList *keyShareList;
120  Tls13KeyShareEntry *keyShareEntry;
121 
122  //Add the KeyShare extension
123  extension = (TlsExtension *) p;
124  //Type of the extension
125  extension->type = HTONS(TLS_EXT_KEY_SHARE);
126 
127  //The extension contains a list of offered KeyShareEntry values in
128  //descending order of client preference
129  keyShareList = (Tls13KeyShareList *) extension->value;
130 
131  //Point to the KeyShareEntry
132  keyShareEntry = (Tls13KeyShareEntry *) keyShareList->value;
133 
134 #if (TLS13_DHE_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED)
135  //Finite field group?
136  if(tls13IsFfdheGroupSupported(context, context->namedGroup))
137  {
138  //Specify the named group for the key being exchanged
139  keyShareEntry->group = htons(context->namedGroup);
140 
141  //Diffie-Hellman parameters are encoded in the opaque key_exchange field
142  //of the KeyShareEntry. The opaque value contains the Diffie-Hellman
143  //public value for the specified group encoded as a big-endian integer
144  //and padded to the left with zeros to the size of p in bytes
145  error = dhExportPublicKey(&context->dhContext,
146  keyShareEntry->keyExchange, &n, MPI_FORMAT_BIG_ENDIAN);
147  //Any error to report?
148  if(error)
149  return error;
150 
151  //Set the length of the key_exchange field
152  keyShareEntry->length = htons(n);
153 
154  //Compute the length of the KeyShareEntry
155  n += sizeof(Tls13KeyShareEntry);
156  }
157  else
158 #endif
159 #if (TLS13_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED)
160  //Elliptic curve group?
161  if(tls13IsEcdheGroupSupported(context, context->namedGroup))
162  {
163  //Specify the named group for the key being exchanged
164  keyShareEntry->group = htons(context->namedGroup);
165 
166  //ECDHE parameters are encoded in the opaque key_exchange field of
167  //the KeyShareEntry
168  error = ecdhExportPublicKey(&context->ecdhContext,
169  keyShareEntry->keyExchange, &n, EC_PUBLIC_KEY_FORMAT_X963);
170  //Any error to report?
171  if(error)
172  return error;
173 
174  //Set the length of the key_exchange field
175  keyShareEntry->length = htons(n);
176 
177  //Compute the length of the KeyShareEntry
178  n += sizeof(Tls13KeyShareEntry);
179  }
180  else
181 #endif
182 #if (TLS13_MLKEM_KE_SUPPORT == ENABLED || TLS13_PSK_MLKEM_KE_SUPPORT == ENABLED)
183  //ML-KEM key exchange method?
184  if(tls13IsMlkemGroupSupported(context, context->namedGroup))
185  {
186  const KemAlgo *kemAlgo;
187 
188  //Point to the KEM algorithm
189  kemAlgo = context->kemContext.kemAlgo;
190 
191  //Specify the named group for the key being exchanged
192  keyShareEntry->group = htons(context->namedGroup);
193 
194  //For the client's share, the key_exchange value contains the pk output
195  //of the corresponding KEM's KeyGen algorithm
196  osMemcpy(keyShareEntry->keyExchange, context->kemContext.pk,
197  kemAlgo->publicKeySize);
198 
199  //The length of the public key is fixed
200  n = kemAlgo->publicKeySize;
201 
202  //Set the length of the key_exchange field
203  keyShareEntry->length = htons(n);
204 
205  //Compute the length of the KeyShareEntry
206  n += sizeof(Tls13KeyShareEntry);
207  }
208  else
209 #endif
210 #if (TLS13_HYBRID_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
211  //Hybrid key exchange method?
212  if(tls13IsHybridGroupSupported(context, context->namedGroup))
213  {
214  size_t offset;
215  const KemAlgo *kemAlgo;
216 
217  //Point to the KEM algorithm
218  kemAlgo = context->kemContext.kemAlgo;
219 
220  //Specify the named group for the key being exchanged
221  keyShareEntry->group = htons(context->namedGroup);
222 
223  //NIST's special publication 800-56C approves the usage of HKDF with two
224  //distinct shared secrets, with the condition that the first one is
225  //computed by a FIPS-approved key-establishment scheme
226  if(context->namedGroup == TLS_GROUP_X25519_MLKEM768)
227  {
228  offset = kemAlgo->publicKeySize;
229  }
230  else
231  {
232  offset = 0;
233  }
234 
235  //The ECDHE share is the serialized value of the uncompressed ECDH point
236  //representation
237  error = ecdhExportPublicKey(&context->ecdhContext,
238  keyShareEntry->keyExchange + offset, &n, EC_PUBLIC_KEY_FORMAT_X963);
239  //Any error to report?
240  if(error)
241  return error;
242 
243  //X25519MLKEM768 group?
244  if(context->namedGroup == TLS_GROUP_X25519_MLKEM768)
245  {
246  offset = 0;
247  }
248  else
249  {
250  offset = n;
251  }
252 
253  //The ML-KEM's ephemeral share is the public key of the KeyGen step
254  //represented as an octet string
255  osMemcpy(keyShareEntry->keyExchange + offset, context->kemContext.pk,
256  kemAlgo->publicKeySize);
257 
258  //The client's share is a fixed-size concatenation of the ECDHE share
259  //and ML-KEM's public key
260  n += kemAlgo->publicKeySize;
261 
262  //Set the length of the key_exchange field
263  keyShareEntry->length = htons(n);
264 
265  //Compute the length of the KeyShareEntry
266  n += sizeof(Tls13KeyShareEntry);
267  }
268  else
269 #endif
270  //Unknown group?
271  {
272  //Clients may send an empty client_shares vector in order to request group
273  //selection from the server, at the cost of an additional round trip
274  }
275 
276  //Fix the length of the list of offered key shares
277  keyShareList->length = htons(n);
278 
279  //Consider the 2-byte length field that precedes the list
280  n += sizeof(Tls13KeyShareList);
281  //Fix the length of the extension
282  extension->length = htons(n);
283 
284  //Compute the length, in bytes, of the KeyShare extension
285  n += sizeof(TlsExtension);
286 #endif
287 
288  //Total number of bytes that have been written
289  *written = n;
290 
291  //Successful processing
292  return NO_ERROR;
293 }
294 
295 
296 /**
297  * @brief Format PskKeyExchangeModes extension
298  * @param[in] context Pointer to the TLS context
299  * @param[in] p Output stream where to write the PskKeyExchangeModes extension
300  * @param[out] written Total number of bytes that have been written
301  * @return Error code
302  **/
303 
305  uint8_t *p, size_t *written)
306 {
307  size_t n = 0;
308 
309 #if (TLS13_PSK_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
310  TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
311  TlsExtension *extension;
312  Tls13PskKeModeList *pskKeModeList;
313 
314  //Add the PskKeyExchangeModes extension
315  extension = (TlsExtension *) p;
316  //Type of the extension
317  extension->type = HTONS(TLS_EXT_PSK_KEY_EXCHANGE_MODES);
318 
319  //Point to the extension data field
320  pskKeModeList = (Tls13PskKeModeList *) extension->value;
321  //The extension contains a list of supported PSK key exchange modes
322  n = 0;
323 
326  //PSK with (EC)DHE key establishment
327  pskKeModeList->value[n++] = TLS_PSK_KEY_EXCH_MODE_PSK_DHE_KE;
328 #endif
329 #if (TLS13_PSK_KE_SUPPORT == ENABLED)
330  //PSK-only key establishment
331  pskKeModeList->value[n++] = TLS_PSK_KEY_EXCH_MODE_PSK_KE;
332 #endif
333 
334  //Fix the length of the list
335  pskKeModeList->length = (uint8_t) n;
336 
337  //Consider the length field that precedes the list
338  n += sizeof(Tls13PskKeModeList);
339  //Fix the length of the extension
340  extension->length = htons(n);
341 
342  //Compute the length, in bytes, of the PskKeyExchangeModes extension
343  n += sizeof(TlsExtension);
344 #endif
345 
346  //Total number of bytes that have been written
347  *written = n;
348 
349  //Successful processing
350  return NO_ERROR;
351 }
352 
353 
354 /**
355  * @brief Format PreSharedKey extension
356  * @param[in] context Pointer to the TLS context
357  * @param[in] p Output stream where to write the PreSharedKey extension
358  * @param[out] written Total number of bytes that have been written
359  * @param[out] identityList Pointer to the list of the identities that the
360  * client is willing to negotiate with the server
361  * @param[out] binderList Pointer to the list of HMAC values, one for each PSK
362  * offered in the PreSharedKey extension
363  * @return Error code
364  **/
365 
367  uint8_t *p, size_t *written, Tls13PskIdentityList **identityList,
368  Tls13PskBinderList **binderList)
369 {
370  size_t n = 0;
371 
372 #if (TLS13_PSK_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
373  TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
374  //Check whether the client is attempting a PSK key establishment
375  if(tls13IsPskValid(context) || tls13IsTicketValid(context))
376  {
377  error_t error;
378  size_t m;
379  uint16_t cipherSuite;
380  uint32_t ticketAge;
381  TlsExtension *extension;
382  TlsPskIdentity *pskIdentity;
383  Tls13PskBinder *pskBinder;
384  const HashAlgo *hashAlgo;
385 
386  //Add the PreSharedKey extension
387  extension = (TlsExtension *) p;
388  //Type of the extension
389  extension->type = HTONS(TLS_EXT_PRE_SHARED_KEY);
390 
391  //Point to the extension data field
392  *identityList = (Tls13PskIdentityList *) extension->value;
393  //Point to the first PskIdentity entry of the list
394  pskIdentity = (TlsPskIdentity *) (*identityList)->value;
395 
396  //Although PSKs can be established out of band, PSKs can also be
397  //established in a previous connection
398  if(tls13IsPskValid(context))
399  {
400  //Retrieve the length of the PSK identity
401  n = osStrlen(context->pskIdentity);
402  //Copy PSK identity
403  osMemcpy(pskIdentity->value, context->pskIdentity, n);
404 
405  //For externally established PSKs, the hash algorithm must be set when
406  //the PSK is established or default to SHA-256 if no such algorithm is
407  //defined
408  hashAlgo = tlsGetHashAlgo(context->pskHashAlgo);
409 
410  //Retrieve the cipher suite associated with the PSK, if any
411  cipherSuite = context->pskCipherSuite;
412 
413  //For PSK identities established externally, an obfuscated_ticket_age
414  //of 0 should be used (refer to RFC 8446, section 4.2.11)
415  ticketAge = 0;
416  }
417  else if(tls13IsTicketValid(context))
418  {
419  //Retrieve the length of the session ticket
420  n = context->ticketLen;
421  //Copy session ticket
422  osMemcpy(pskIdentity->value, context->ticket, n);
423 
424  //Each PSK is associated with a single hash algorithm. For PSKs
425  //established via the ticket mechanism, this is the KDF hash algorithm
426  //on the connection where the ticket was established
427  hashAlgo = tlsGetHashAlgo(context->ticketHashAlgo);
428 
429  //Retrieve the cipher suite associated with the ticket
430  cipherSuite = context->ticketCipherSuite;
431 
432  //The client's view of the age of a ticket is the time since the
433  //receipt of the NewSessionTicket message
434  ticketAge = context->clientHelloTimestamp - context->ticketTimestamp;
435 
436  //The obfuscated_ticket_age field contains an obfuscated version of
437  //the ticket age formed by taking the age in milliseconds and adding
438  //the ticket_age_add value that was included with the ticket
439  ticketAge += context->ticketAgeAdd;
440  }
441  else
442  {
443  //Just for sanity
444  return ERROR_FAILURE;
445  }
446 
447  //Valid cipher suite provisioned?
448  if(cipherSuite != 0)
449  {
450  //Restore the cipher suite associated with the PSK
451  error = tlsSelectCipherSuite(context, cipherSuite);
452  //Any error to report?
453  if(error)
454  return error;
455  }
456  else
457  {
458  //Make sure the hash algorithm is valid
459  if(hashAlgo == NULL)
460  return ERROR_FAILURE;
461 
462  //Restore the hash algorithm associated with the PSK
463  context->cipherSuite.prfHashAlgo = hashAlgo;
464  }
465 
466  //Fix the length of the PSK identity
467  pskIdentity->length = htons(n);
468  //Consider the length field that precedes the PSK identity
469  n += sizeof(TlsPskIdentity);
470 
471  //The obfuscated_ticket_age field is a 32-bit unsigned integer
472  STORE32BE(ticketAge, (uint8_t *) pskIdentity + n);
473  //Compute the length of the PskIdentity entry
474  n += sizeof(uint32_t);
475 
476  //Fix the length of the list of PSK identities
477  (*identityList)->length = htons(n);
478  //Consider the 2-byte length field that precedes the list
479  n += sizeof(Tls13PskIdentityList);
480 
481  //Point to the list of PSK binders
482  *binderList = (Tls13PskBinderList *) ((uint8_t *) *identityList + n);
483  //Point to the first PskBinderEntry of the list
484  pskBinder = (Tls13PskBinder *) (*binderList)->value;
485 
486  //The PSK binder consists of Hash.length bytes
487  m = hashAlgo->digestSize;
488  //The value of the PSK binder will be calculated in a second step
489  osMemset(pskBinder->value, 0, m);
490 
491  //Fix the length of the PSK binder
492  pskBinder->length = (uint8_t) m;
493  //Consider the length field that precedes the PSK binder
494  m += sizeof(Tls13PskBinder);
495 
496  //Fix the length of the list of PSK binders
497  (*binderList)->length = htons(m);
498  //Consider the 2-byte length field that precedes the list
499  n += sizeof(Tls13PskBinderList) + m;
500 
501  //Fix the length of the extension
502  extension->length = htons(n);
503  //Compute the length, in bytes, of the PreSharedKey extension
504  n += sizeof(TlsExtension);
505  }
506  else
507 #endif
508  {
509  //PSK key establishment is not used
510  *identityList = NULL;
511  *binderList = NULL;
512  }
513 
514  //Total number of bytes that have been written
515  *written = n;
516 
517  //Successful processing
518  return NO_ERROR;
519 }
520 
521 
522 /**
523  * @brief Format EarlyData extension
524  * @param[in] context Pointer to the TLS context
525  * @param[in] p Output stream where to write the EarlyData extension
526  * @param[out] written Total number of bytes that have been written
527  * @return Error code
528  **/
529 
531  uint8_t *p, size_t *written)
532 {
533  size_t n = 0;
534 
535 #if (TLS13_EARLY_DATA_SUPPORT == ENABLED)
536  //If the client opts to send application data in its first flight of
537  //messages, it must supply both the PreSharedKey and EarlyData extensions
538  if(context->earlyDataEnabled && !context->earlyDataRejected)
539  {
540  TlsExtension *extension;
541 
542  //Add the EarlyData extension
543  extension = (TlsExtension *) p;
544  //Type of the extension
545  extension->type = HTONS(TLS_EXT_EARLY_DATA);
546 
547  //The extension data field of this extension is empty
548  extension->length = HTONS(0);
549 
550  //Compute the length, in bytes, of the EarlyData extension
551  n = sizeof(TlsExtension);
552  }
553 #endif
554 
555  //Total number of bytes that have been written
556  *written = n;
557 
558  //Successful processing
559  return NO_ERROR;
560 }
561 
562 
563 /**
564  * @brief Parse SupportedVersions extension
565  * @param[in] context Pointer to the TLS context
566  * @param[in] selectedVersion Pointer to the SupportedVersions extension
567  * @return Error code
568  **/
569 
571  const TlsExtension *selectedVersion)
572 {
573  error_t error;
574  uint16_t version;
575 
576  //The extension contains the selected version value
577  version = LOAD16BE(selectedVersion->value);
578 
579  //Debug message
580  TRACE_INFO(" selectedVersion = 0x%04" PRIX16 " (%s)\r\n",
582 
583 #if (DTLS_SUPPORT == ENABLED)
584  //DTLS protocol?
585  if(context->transportProtocol == TLS_TRANSPORT_PROTOCOL_DATAGRAM)
586  {
587  //Version of DTLS prior to DTLS 1.3?
589  {
590  //The client must abort the handshake with an illegal_parameter alert
591  error = ERROR_ILLEGAL_PARAMETER;
592  }
593  else
594  {
595  //Set the DTLS version to be used
596  error = dtlsSelectVersion(context, version);
597  }
598  }
599  else
600 #endif
601  //TLS protocol?
602  {
603  //Version of TLS prior to TLS 1.3?
605  {
606  //The client must abort the handshake with an illegal_parameter alert
607  error = ERROR_ILLEGAL_PARAMETER;
608  }
609  else
610  {
611  //Set the TLS version to be used
612  error = tlsSelectVersion(context, version);
613  }
614  }
615 
616  //Return status code
617  return error;
618 }
619 
620 
621 /**
622  * @brief Parse Cookie extension
623  * @param[in] context Pointer to the TLS context
624  * @param[in] cookie Pointer to the Cookie extension
625  * @return Error code
626  **/
627 
629  const Tls13Cookie *cookie)
630 {
631  //Cookie extension found?
632  if(cookie != NULL)
633  {
634  size_t n;
635 
636  //Retrieve the length of the cookie
637  n = ntohs(cookie->length);
638 
639  //Clients must abort the handshake with an illegal_parameter alert if the
640  //HelloRetryRequest would not result in any change in the ClientHello
641  if(n == 0)
643 
644  //Check the length of the cookie
647 
648  //Release cookie
649  if(context->cookie != NULL)
650  {
651  tlsFreeMem(context->cookie);
652  context->cookie = NULL;
653  context->cookieLen = 0;
654  }
655 
656  //Allocate a memory block to store the cookie
657  context->cookie = tlsAllocMem(n);
658  //Failed to allocate memory?
659  if(context->cookie == NULL)
660  return ERROR_OUT_OF_MEMORY;
661 
662  //Save cookie
663  osMemcpy(context->cookie, cookie->value, n);
664  context->cookieLen = n;
665  }
666 
667  //Successful processing
668  return NO_ERROR;
669 }
670 
671 
672 /**
673  * @brief Parse KeyShare extension (HelloRetryRequest message)
674  * @param[in] context Pointer to the TLS context
675  * @param[in] selectedGroup Pointer to the KeyShare extension
676  * @return Error code
677  **/
678 
680  const TlsExtension *selectedGroup)
681 {
682  error_t error;
683 
684  //Initialize status code
685  error = NO_ERROR;
686 
687 #if (TLS13_DHE_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
688  TLS13_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || \
689  TLS13_MLKEM_KE_SUPPORT == ENABLED || TLS13_PSK_MLKEM_KE_SUPPORT == ENABLED || \
690  TLS13_HYBRID_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
691  //KeyShare extension found?
692  if(selectedGroup != NULL)
693  {
694  uint16_t namedGroup;
695 
696  //The KeyShare extension contains the mutually supported group the server
697  //intends to negotiate
698  namedGroup = LOAD16BE(selectedGroup->value);
699 
700  //Check whether the server has selected a different ECDHE or FFDHE group
701  if(namedGroup != context->namedGroup)
702  {
703  //Generate an ephemeral key pair
704  error = tls13GenerateKeyShare(context, namedGroup);
705  }
706  }
707 #else
708  //KeyShare extension found?
709  if(selectedGroup != NULL)
710  {
711  //If a client receives an extension type that it did not request in the
712  //ClientHello, it must abort the handshake with an unsupported_extension
713  //fatal alert
715  }
716 #endif
717 
718  //Return status code
719  return error;
720 }
721 
722 
723 /**
724  * @brief Parse KeyShare extension (ServerHello message)
725  * @param[in] context Pointer to the TLS context
726  * @param[in] serverShare Pointer to the KeyShare extension
727  * @return Error code
728  **/
729 
731  const Tls13KeyShareEntry *serverShare)
732 {
733  error_t error;
734 
735  //Initialize status code
736  error = NO_ERROR;
737 
738 #if (TLS13_DHE_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
739  TLS13_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || \
740  TLS13_MLKEM_KE_SUPPORT == ENABLED || TLS13_PSK_MLKEM_KE_SUPPORT == ENABLED || \
741  TLS13_HYBRID_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
742  //If using (EC)DHE key establishment, servers offer exactly one KeyShareEntry
743  //in the ServerHello
744  if(serverShare != NULL)
745  {
746  uint16_t namedGroup;
747 
748  //Convert the selected NamedGroup to host byte order
749  namedGroup = ntohs(serverShare->group);
750 
751  //The client must verify that the selected NamedGroup in the ServerHello
752  //is the same as that in the HelloRetryRequest
753  if(namedGroup == context->namedGroup)
754  {
755  //Finite field group?
756  if(tls13IsFfdheGroupSupported(context, namedGroup))
757  {
758  //DHE key exchange mechanism provides forward secrecy
759  context->keyExchMethod = TLS13_KEY_EXCH_DHE;
760 
761  //Compute DHE shared secret
762  error = tls13GenerateSharedSecret(context, serverShare->keyExchange,
763  ntohs(serverShare->length));
764  }
765  //Elliptic curve group?
766  else if(tls13IsEcdheGroupSupported(context, namedGroup))
767  {
768  //ECDHE key exchange mechanism provides forward secrecy
769  context->keyExchMethod = TLS13_KEY_EXCH_ECDHE;
770 
771  //Compute ECDHE shared secret
772  error = tls13GenerateSharedSecret(context, serverShare->keyExchange,
773  ntohs(serverShare->length));
774  }
775  //ML-KEM key exchange method?
776  else if(tls13IsMlkemGroupSupported(context, namedGroup))
777  {
778  //ML-KEM-512, ML-KEM-768, and ML-KEM-1024 can be used as a
779  //standalone algorithm to achieve post-quantum key agreement
780  context->keyExchMethod = TLS13_KEY_EXCH_MLKEM;
781 
782  //Decapsulation algorithm
783  error = tls13Decapsulate(context, serverShare->keyExchange,
784  ntohs(serverShare->length));
785  }
786  //Hybrid key exchange method?
787  else if(tls13IsHybridGroupSupported(context, namedGroup))
788  {
789  //Hybrid key exchange makes use of two key exchange algorithms
790  //based on different cryptographic assumptions
791  context->keyExchMethod = TLS13_KEY_EXCH_HYBRID;
792 
793  //Decapsulation algorithm
794  error = tls13Decapsulate(context, serverShare->keyExchange,
795  ntohs(serverShare->length));
796  }
797  //Unknown group?
798  else
799  {
800  //Servers must not send a KeyShareEntry for any group not indicated
801  //in the client's SupportedGroups extension
802  error = ERROR_ILLEGAL_PARAMETER;
803  }
804  }
805  else
806  {
807  //If this check fails, the client must abort the handshake with an
808  //illegal_parameter alert
809  error = ERROR_ILLEGAL_PARAMETER;
810  }
811  }
812  else
813  {
814  //PSKs can be used alone, at the cost of losing forward secrecy for the
815  //application data
816  context->keyExchMethod = TLS_KEY_EXCH_NONE;
817  }
818 #else
819  //KeyShareEntry extension found?
820  if(serverShare != NULL)
821  {
822  //If a client receives an extension type that it did not request in the
823  //ClientHello, it must abort the handshake with an unsupported_extension
824  //fatal alert
826  }
827  else
828  {
829  //Perform a PSK handshake if possible
830  context->keyExchMethod = TLS_KEY_EXCH_NONE;
831  }
832 #endif
833 
834  //Return status code
835  return error;
836 }
837 
838 
839 /**
840  * @brief Parse PreSharedKey extension
841  * @param[in] context Pointer to the TLS context
842  * @param[in] selectedIdentity Pointer to the PreSharedKey extension
843  * @return Error code
844  **/
845 
847  const TlsExtension *selectedIdentity)
848 {
849  //Reset the server's selected_identity to its default value
850  context->selectedIdentity = -1;
851 
852 #if (TLS13_PSK_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
853  TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
854  //PreSharedKey extension found?
855  if(selectedIdentity != NULL)
856  {
857  const HashAlgo *hashAlgo;
858 
859  //If a client receives an extension type that it did not request in the
860  //ClientHello, it must abort the handshake with an unsupported_extension
861  //fatal alert
862  if(!tls13IsPskValid(context) && !tls13IsTicketValid(context))
864 
865  //In order to accept PSK key establishment, the server sends a
866  //PreSharedKey extension indicating the selected identity
867  context->selectedIdentity = LOAD16BE(selectedIdentity->value);
868 
869  //Clients must verify that the server's selected_identity is within the
870  //range supplied by the client (refer to RFC 8446, section 4.2.11)
871  if(context->selectedIdentity != 0)
873 
874  //Point to the cipher suite hash algorithm
875  hashAlgo = context->cipherSuite.prfHashAlgo;
876  //Make sure the hash algorithm is valid
877  if(hashAlgo == NULL)
878  return ERROR_FAILURE;
879 
880  //Clients must also verify that the server has selected a cipher suite
881  //indicating a hash algorithm associated with the PSK
882  if(tls13IsPskValid(context))
883  {
884  //PSK incompatible with the selected cipher suite?
885  if(tlsGetHashAlgo(context->pskHashAlgo) != hashAlgo)
887  }
888  else if(tls13IsTicketValid(context))
889  {
890  //PSK incompatible with the selected cipher suite?
891  if(tlsGetHashAlgo(context->ticketHashAlgo) != hashAlgo)
893  }
894  else
895  {
896  //Just for sanity
897  }
898 
899  //PSKs can be used with (EC)DHE key exchange in order to provide forward
900  //secrecy in combination with shared keys, or can be used alone, at the
901  //cost of losing forward secrecy for the application data
902 #if (TLS13_PSK_KE_SUPPORT == ENABLED)
903  if(context->keyExchMethod == TLS_KEY_EXCH_NONE)
904  {
905  context->keyExchMethod = TLS13_KEY_EXCH_PSK;
906  }
907 #endif
908 #if (TLS13_PSK_DHE_KE_SUPPORT == ENABLED)
909  if(context->keyExchMethod == TLS13_KEY_EXCH_DHE)
910  {
911  context->keyExchMethod = TLS13_KEY_EXCH_PSK_DHE;
912  }
913 #endif
914 #if (TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED)
915  if(context->keyExchMethod == TLS13_KEY_EXCH_ECDHE)
916  {
917  context->keyExchMethod = TLS13_KEY_EXCH_PSK_ECDHE;
918  }
919 #endif
920 #if (TLS13_PSK_MLKEM_KE_SUPPORT == ENABLED)
921  if(context->keyExchMethod == TLS13_KEY_EXCH_MLKEM)
922  {
923  context->keyExchMethod = TLS13_KEY_EXCH_PSK_MLKEM;
924  }
925 #endif
926 #if (TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
927  if(context->keyExchMethod == TLS13_KEY_EXCH_HYBRID)
928  {
929  context->keyExchMethod = TLS13_KEY_EXCH_PSK_HYBRID;
930  }
931 #endif
932  }
933 #else
934  //PreSharedKey extension found?
935  if(selectedIdentity != NULL)
936  {
937  //If a client receives an extension type that it did not request in the
938  //ClientHello, it must abort the handshake with an unsupported_extension
939  //fatal alert
941  }
942 #endif
943 
944  //Successful processing
945  return NO_ERROR;
946 }
947 
948 
949 /**
950  * @brief Parse EarlyData extension
951  * @param[in] msgType Handshake message type
952  * @param[in] context Pointer to the TLS context
953  * @param[in] earlyDataIndication Pointer to the EarlyData extension
954  * @return Error code
955  **/
956 
958  TlsMessageType msgType, const TlsExtension *earlyDataIndication)
959 {
960 #if (TLS13_EARLY_DATA_SUPPORT == ENABLED)
961  //The extension may appear in EncryptedExtensions and NewSessionTicket
962  //messages
964  {
965  //EarlyData extension found?
966  if(earlyDataIndication != NULL)
967  {
968  //If a client receives an extension type that it did not request in the
969  //ClientHello, it must abort the handshake with an unsupported_extension
970  //fatal alert
971  if(!context->earlyDataEnabled || context->earlyDataRejected)
973 
974  //If the server has supplied an EarlyData extension, the client must
975  //verify that the server's selected_identity is 0. If any other value
976  //is returned, it must abort the handshake with an illegal_parameter
977  //fatal alert
978  if(context->selectedIdentity != 0)
980 
981  //A valid EarlyData extension has been received
982  context->earlyDataExtReceived = TRUE;
983  }
984  else
985  {
986  //The EncryptedExtensions message does not contain any EarlyData
987  //extension
988  context->earlyDataExtReceived = FALSE;
989  }
990  }
992  {
993  //The extension contains the maximum amount of 0-RTT data that the client
994  //is allowed to send
995  if(earlyDataIndication != NULL)
996  {
997  context->maxEarlyDataSize = LOAD32BE(earlyDataIndication->value);
998  }
999  else
1000  {
1001  context->maxEarlyDataSize = 0;
1002  }
1003  }
1004  else
1005  {
1006  //Just for sanity
1007  }
1008 #else
1009  //Check message type
1011  {
1012  //EarlyData extension found?
1013  if(earlyDataIndication != NULL)
1014  {
1015  //If a client receives an extension type that it did not request in the
1016  //ClientHello, it must abort the handshake with an unsupported_extension
1017  //fatal alert
1019  }
1020  }
1022  {
1023  //Early data is not implemented
1024  context->maxEarlyDataSize = 0;
1025  }
1026  else
1027  {
1028  //Just for sanity
1029  }
1030 #endif
1031 
1032  //Successful processing
1033  return NO_ERROR;
1034 }
1035 
1036 #endif
@ TLS_GROUP_X25519_MLKEM768
Definition: tls.h:1520
@ TLS13_KEY_EXCH_PSK
Definition: tls.h:1224
@ TLS_EXT_PSK_KEY_EXCHANGE_MODES
Definition: tls.h:1406
#define tlsAllocMem(size)
Definition: tls.h:889
#define htons(value)
Definition: cpu_endian.h:413
TLS helper functions.
#define TLS13_PSK_DHE_KE_SUPPORT
Definition: tls13_misc.h:71
Tls13PskBinderList
Definition: tls13_misc.h:275
uint16_t cipherSuite
Cipher suite identifier.
Definition: tls.h:2026
error_t dtlsSelectVersion(TlsContext *context, uint16_t version)
Set the DTLS version to be used.
Definition: dtls_misc.c:53
const HashAlgo * tlsGetHashAlgo(TlsHashAlgo hashAlgoId)
Get the hash algorithm that matches the specified identifier.
Definition: tls_misc.c:1431
@ TLS13_KEY_EXCH_MLKEM
Definition: tls.h:1222
@ TLS13_KEY_EXCH_PSK_DHE
Definition: tls.h:1225
Tls13Cookie
Definition: tls13_misc.h:197
#define LOAD32BE(p)
Definition: cpu_endian.h:210
@ ERROR_ILLEGAL_PARAMETER
Definition: error.h:244
uint8_t p
Definition: ndp.h:300
error_t tlsSelectVersion(TlsContext *context, uint16_t version)
Set the TLS version to be used.
Definition: tls_misc.c:305
#define TRUE
Definition: os_port.h:50
size_t digestSize
Definition: crypto.h:1157
#define TLS13_MAX_COOKIE_SIZE
Definition: tls13_misc.h:113
error_t tls13ParseServerKeyShareExtension(TlsContext *context, const Tls13KeyShareEntry *serverShare)
Parse KeyShare extension (ServerHello message)
TLS 1.3 session tickets.
@ TLS_TRANSPORT_PROTOCOL_DATAGRAM
Definition: tls.h:1017
TlsPskIdentity
Definition: tls.h:1838
TlsMessageType
Handshake message type.
Definition: tls.h:1100
@ TLS13_KEY_EXCH_PSK_MLKEM
Definition: tls.h:1227
bool_t tls13IsMlkemGroupSupported(TlsContext *context, uint16_t namedGroup)
Check whether a given ML-KEM exchange method is supported.
Definition: tls13_misc.c:1086
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
@ TLS13_KEY_EXCH_ECDHE
Definition: tls.h:1221
@ EC_PUBLIC_KEY_FORMAT_X963
Definition: ec.h:386
size_t publicKeySize
Definition: crypto.h:1212
#define osStrlen(s)
Definition: os_port.h:168
uint8_t version
Definition: coap_common.h:177
Tls13KeyShareEntry
Definition: tls13_misc.h:209
TlsExtension
Definition: tls.h:1716
@ TLS_EXT_EARLY_DATA
Definition: tls.h:1403
@ TLS13_KEY_EXCH_PSK_HYBRID
Definition: tls.h:1228
error_t tls13FormatClientEarlyDataExtension(TlsContext *context, uint8_t *p, size_t *written)
Format EarlyData extension.
@ TLS_PSK_KEY_EXCH_MODE_PSK_KE
Definition: tls13_misc.h:165
error_t tls13ParseSelectedGroupExtension(TlsContext *context, const TlsExtension *selectedGroup)
Parse KeyShare extension (HelloRetryRequest message)
@ TLS_PSK_KEY_EXCH_MODE_PSK_DHE_KE
Definition: tls13_misc.h:166
#define FALSE
Definition: os_port.h:46
error_t tls13ParseServerCookieExtension(TlsContext *context, const Tls13Cookie *cookie)
Parse Cookie extension.
error_t tls13ParseServerSupportedVersionsExtension(TlsContext *context, const TlsExtension *selectedVersion)
Parse SupportedVersions extension.
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
@ ERROR_UNSUPPORTED_EXTENSION
Definition: error.h:246
#define TlsContext
Definition: tls.h:36
error_t
Error codes.
Definition: error.h:43
bool_t tls13IsEcdheGroupSupported(TlsContext *context, uint16_t namedGroup)
Check whether a given ECDHE group is supported.
Definition: tls13_misc.c:1028
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
@ TLS13_KEY_EXCH_DHE
Definition: tls.h:1220
error_t tlsSelectCipherSuite(TlsContext *context, uint16_t identifier)
Set cipher suite.
Definition: tls_misc.c:333
error_t tls13Decapsulate(TlsContext *context, const uint8_t *keyShare, size_t length)
Decapsulation algorithm.
Definition: tls13_misc.c:660
@ TLS_EXT_KEY_SHARE
Definition: tls.h:1411
error_t tls13FormatClientKeyShareExtension(TlsContext *context, uint8_t *p, size_t *written)
Format KeyShare extension (ClientHello message)
#define TLS_VERSION_1_3
Definition: tls.h:98
error_t tls13FormatClientCookieExtension(TlsContext *context, uint8_t *p, size_t *written)
Format Cookie extension.
@ TLS_TYPE_ENCRYPTED_EXTENSIONS
Definition: tls.h:1108
bool_t tls13IsTicketValid(TlsContext *context)
Check whether a session ticket is valid.
Definition: tls13_ticket.c:51
@ TLS_EXT_COOKIE
Definition: tls.h:1405
bool_t tls13IsFfdheGroupSupported(TlsContext *context, uint16_t namedGroup)
Check whether a given FFDHE group is supported.
Definition: tls13_misc.c:988
Tls13PskBinder
Definition: tls13_misc.h:264
bool_t tls13IsHybridGroupSupported(TlsContext *context, uint16_t namedGroup)
Check whether a given hybrid key exchange method is supported.
Definition: tls13_misc.c:1127
error_t tls13FormatClientPreSharedKeyExtension(TlsContext *context, uint8_t *p, size_t *written, Tls13PskIdentityList **identityList, Tls13PskBinderList **binderList)
Format PreSharedKey extension.
#define TRACE_INFO(...)
Definition: debug.h:105
error_t dhExportPublicKey(DhContext *context, uint8_t *output, size_t *written, MpiFormat format)
Export our own public key.
Definition: dh.c:185
#define ENABLED
Definition: os_port.h:37
Tls13KeyShareList
Definition: tls13_misc.h:220
#define ntohs(value)
Definition: cpu_endian.h:421
#define TLS13_PSK_HYBRID_KE_SUPPORT
Definition: tls13_misc.h:92
@ TLS_KEY_EXCH_NONE
Definition: tls.h:1201
@ TLS13_KEY_EXCH_PSK_ECDHE
Definition: tls.h:1226
uint8_t msgType
error_t tls13GenerateSharedSecret(TlsContext *context, const uint8_t *keyShare, size_t length)
(EC)DHE shared secret generation
Definition: tls13_misc.c:407
bool_t tls13IsPskValid(TlsContext *context)
Check whether an externally established PSK is valid.
Definition: tls13_misc.c:909
error_t tls13GenerateKeyShare(TlsContext *context, uint16_t namedGroup)
Key share generation.
Definition: tls13_misc.c:234
uint8_t m
Definition: ndp.h:304
#define HTONS(value)
Definition: cpu_endian.h:410
uint8_t n
error_t tls13ParseServerPreSharedKeyExtension(TlsContext *context, const TlsExtension *selectedIdentity)
Parse PreSharedKey extension.
#define DTLS_VERSION_1_3
Definition: dtls_misc.h:37
@ TLS13_KEY_EXCH_HYBRID
Definition: tls.h:1223
error_t tls13FormatPskKeModesExtension(TlsContext *context, uint8_t *p, size_t *written)
Format PskKeyExchangeModes extension.
Common interface for key encapsulation mechanisms (KEM)
Definition: crypto.h:1210
Tls13PskKeModeList
Definition: tls13_misc.h:231
Formatting and parsing of extensions (TLS 1.3 client)
@ TLS_EXT_PRE_SHARED_KEY
Definition: tls.h:1402
@ MPI_FORMAT_BIG_ENDIAN
Definition: mpi.h:93
TLS (Transport Layer Security)
uint8_t cookie[]
Definition: dtls_misc.h:211
Common interface for hash algorithms.
Definition: crypto.h:1151
const char_t * tlsGetVersionName(uint16_t version)
Convert TLS version to string representation.
Definition: tls_misc.c:1370
@ TLS_TYPE_NEW_SESSION_TICKET
Definition: tls.h:1105
Tls13PskIdentityList
Definition: tls13_misc.h:253
#define LOAD16BE(p)
Definition: cpu_endian.h:186
#define osMemset(p, value, length)
Definition: os_port.h:138
#define TLS13_PSK_ECDHE_KE_SUPPORT
Definition: tls13_misc.h:78
#define tlsFreeMem(p)
Definition: tls.h:894
error_t ecdhExportPublicKey(EcdhContext *context, uint8_t *output, size_t *written, EcPublicKeyFormat format)
Export our own public key.
Definition: ecdh.c:257
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
error_t tls13ParseServerEarlyDataExtension(TlsContext *context, TlsMessageType msgType, const TlsExtension *earlyDataIndication)
Parse EarlyData extension.