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-2025 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.5.2
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL TLS_TRACE_LEVEL
33 
34 //Dependencies
35 #include "tls.h"
36 #include "tls_misc.h"
38 #include "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  //If the SupportedVersions extension contains a version prior to TLS 1.3,
580  //the client must abort the handshake with an illegal_parameter alert
583 
584  //Debug message
585  TRACE_INFO(" selectedVersion = 0x%04" PRIX16 " (%s)\r\n",
587 
588  //Set the TLS version to be used
589  error = tlsSelectVersion(context, version);
590  //Specified TLS/DTLS version not supported?
591  if(error)
592  return error;
593 
594  //Successful processing
595  return NO_ERROR;
596 }
597 
598 
599 /**
600  * @brief Parse Cookie extension
601  * @param[in] context Pointer to the TLS context
602  * @param[in] cookie Pointer to the Cookie extension
603  * @return Error code
604  **/
605 
607  const Tls13Cookie *cookie)
608 {
609  //Cookie extension found?
610  if(cookie != NULL)
611  {
612  size_t n;
613 
614  //Retrieve the length of the cookie
615  n = ntohs(cookie->length);
616 
617  //Clients must abort the handshake with an illegal_parameter alert if the
618  //HelloRetryRequest would not result in any change in the ClientHello
619  if(n == 0)
621 
622  //Check the length of the cookie
625 
626  //Sanity check
627  if(context->cookie != NULL)
628  {
629  //Release memory
630  tlsFreeMem(context->cookie);
631  context->cookie = NULL;
632  context->cookieLen = 0;
633  }
634 
635  //Allocate a memory block to store the cookie
636  context->cookie = tlsAllocMem(n);
637  //Failed to allocate memory?
638  if(context->cookie == NULL)
639  return ERROR_OUT_OF_MEMORY;
640 
641  //Save cookie
642  osMemcpy(context->cookie, cookie->value, n);
643  context->cookieLen = n;
644  }
645 
646  //Successful processing
647  return NO_ERROR;
648 }
649 
650 
651 /**
652  * @brief Parse KeyShare extension (HelloRetryRequest message)
653  * @param[in] context Pointer to the TLS context
654  * @param[in] selectedGroup Pointer to the KeyShare extension
655  * @return Error code
656  **/
657 
659  const TlsExtension *selectedGroup)
660 {
661  error_t error;
662 
663  //Initialize status code
664  error = NO_ERROR;
665 
666 #if (TLS13_DHE_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
667  TLS13_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || \
668  TLS13_MLKEM_KE_SUPPORT == ENABLED || TLS13_PSK_MLKEM_KE_SUPPORT == ENABLED || \
669  TLS13_HYBRID_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
670  //KeyShare extension found?
671  if(selectedGroup != NULL)
672  {
673  uint16_t namedGroup;
674 
675  //The KeyShare extension contains the mutually supported group the server
676  //intends to negotiate
677  namedGroup = LOAD16BE(selectedGroup->value);
678 
679  //Check whether the server has selected a different ECDHE or FFDHE group
680  if(namedGroup != context->namedGroup)
681  {
682  //Generate an ephemeral key pair
683  error = tls13GenerateKeyShare(context, namedGroup);
684  }
685  }
686 #else
687  //KeyShare extension found?
688  if(selectedGroup != NULL)
689  {
690  //If a client receives an extension type that it did not request in the
691  //ClientHello, it must abort the handshake with an unsupported_extension
692  //fatal alert
694  }
695 #endif
696 
697  //Return status code
698  return error;
699 }
700 
701 
702 /**
703  * @brief Parse KeyShare extension (ServerHello message)
704  * @param[in] context Pointer to the TLS context
705  * @param[in] serverShare Pointer to the KeyShare extension
706  * @return Error code
707  **/
708 
710  const Tls13KeyShareEntry *serverShare)
711 {
712  error_t error;
713 
714  //Initialize status code
715  error = NO_ERROR;
716 
717 #if (TLS13_DHE_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
718  TLS13_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || \
719  TLS13_MLKEM_KE_SUPPORT == ENABLED || TLS13_PSK_MLKEM_KE_SUPPORT == ENABLED || \
720  TLS13_HYBRID_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
721  //If using (EC)DHE key establishment, servers offer exactly one KeyShareEntry
722  //in the ServerHello
723  if(serverShare != NULL)
724  {
725  uint16_t namedGroup;
726 
727  //Convert the selected NamedGroup to host byte order
728  namedGroup = ntohs(serverShare->group);
729 
730  //The client must verify that the selected NamedGroup in the ServerHello
731  //is the same as that in the HelloRetryRequest
732  if(namedGroup == context->namedGroup)
733  {
734  //Finite field group?
735  if(tls13IsFfdheGroupSupported(context, namedGroup))
736  {
737  //DHE key exchange mechanism provides forward secrecy
738  context->keyExchMethod = TLS13_KEY_EXCH_DHE;
739 
740  //Compute DHE shared secret
741  error = tls13GenerateSharedSecret(context, serverShare->keyExchange,
742  ntohs(serverShare->length));
743  }
744  //Elliptic curve group?
745  else if(tls13IsEcdheGroupSupported(context, namedGroup))
746  {
747  //ECDHE key exchange mechanism provides forward secrecy
748  context->keyExchMethod = TLS13_KEY_EXCH_ECDHE;
749 
750  //Compute ECDHE shared secret
751  error = tls13GenerateSharedSecret(context, serverShare->keyExchange,
752  ntohs(serverShare->length));
753  }
754  //ML-KEM key exchange method?
755  else if(tls13IsMlkemGroupSupported(context, namedGroup))
756  {
757  //ML-KEM-512, ML-KEM-768, and ML-KEM-1024 can be used as a
758  //standalone algorithm to achieve post-quantum key agreement
759  context->keyExchMethod = TLS13_KEY_EXCH_MLKEM;
760 
761  //Decapsulation algorithm
762  error = tls13Decapsulate(context, serverShare->keyExchange,
763  ntohs(serverShare->length));
764  }
765  //Hybrid key exchange method?
766  else if(tls13IsHybridGroupSupported(context, namedGroup))
767  {
768  //Hybrid key exchange makes use of two key exchange algorithms
769  //based on different cryptographic assumptions
770  context->keyExchMethod = TLS13_KEY_EXCH_HYBRID;
771 
772  //Decapsulation algorithm
773  error = tls13Decapsulate(context, serverShare->keyExchange,
774  ntohs(serverShare->length));
775  }
776  //Unknown group?
777  else
778  {
779  //Servers must not send a KeyShareEntry for any group not indicated
780  //in the client's SupportedGroups extension
781  error = ERROR_ILLEGAL_PARAMETER;
782  }
783  }
784  else
785  {
786  //If this check fails, the client must abort the handshake with an
787  //illegal_parameter alert
788  error = ERROR_ILLEGAL_PARAMETER;
789  }
790  }
791  else
792  {
793  //PSKs can be used alone, at the cost of losing forward secrecy for the
794  //application data
795  context->keyExchMethod = TLS_KEY_EXCH_NONE;
796  }
797 #else
798  //KeyShareEntry extension found?
799  if(serverShare != NULL)
800  {
801  //If a client receives an extension type that it did not request in the
802  //ClientHello, it must abort the handshake with an unsupported_extension
803  //fatal alert
805  }
806  else
807  {
808  //Perform a PSK handshake if possible
809  context->keyExchMethod = TLS_KEY_EXCH_NONE;
810  }
811 #endif
812 
813  //Return status code
814  return error;
815 }
816 
817 
818 /**
819  * @brief Parse PreSharedKey extension
820  * @param[in] context Pointer to the TLS context
821  * @param[in] selectedIdentity Pointer to the PreSharedKey extension
822  * @return Error code
823  **/
824 
826  const TlsExtension *selectedIdentity)
827 {
828  //Reset the server's selected_identity to its default value
829  context->selectedIdentity = -1;
830 
831 #if (TLS13_PSK_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
832  TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
833  //PreSharedKey extension found?
834  if(selectedIdentity != NULL)
835  {
836  const HashAlgo *hashAlgo;
837 
838  //If a client receives an extension type that it did not request in the
839  //ClientHello, it must abort the handshake with an unsupported_extension
840  //fatal alert
841  if(!tls13IsPskValid(context) && !tls13IsTicketValid(context))
843 
844  //In order to accept PSK key establishment, the server sends a
845  //PreSharedKey extension indicating the selected identity
846  context->selectedIdentity = LOAD16BE(selectedIdentity->value);
847 
848  //Clients must verify that the server's selected_identity is within the
849  //range supplied by the client (refer to RFC 8446, section 4.2.11)
850  if(context->selectedIdentity != 0)
852 
853  //Point to the cipher suite hash algorithm
854  hashAlgo = context->cipherSuite.prfHashAlgo;
855  //Make sure the hash algorithm is valid
856  if(hashAlgo == NULL)
857  return ERROR_FAILURE;
858 
859  //Clients must also verify that the server has selected a cipher suite
860  //indicating a hash algorithm associated with the PSK
861  if(tls13IsPskValid(context))
862  {
863  //PSK incompatible with the selected cipher suite?
864  if(tlsGetHashAlgo(context->pskHashAlgo) != hashAlgo)
866  }
867  else if(tls13IsTicketValid(context))
868  {
869  //PSK incompatible with the selected cipher suite?
870  if(tlsGetHashAlgo(context->ticketHashAlgo) != hashAlgo)
872  }
873  else
874  {
875  //Just for sanity
876  }
877 
878  //PSKs can be used with (EC)DHE key exchange in order to provide forward
879  //secrecy in combination with shared keys, or can be used alone, at the
880  //cost of losing forward secrecy for the application data
881 #if (TLS13_PSK_KE_SUPPORT == ENABLED)
882  if(context->keyExchMethod == TLS_KEY_EXCH_NONE)
883  {
884  context->keyExchMethod = TLS13_KEY_EXCH_PSK;
885  }
886 #endif
887 #if (TLS13_PSK_DHE_KE_SUPPORT == ENABLED)
888  if(context->keyExchMethod == TLS13_KEY_EXCH_DHE)
889  {
890  context->keyExchMethod = TLS13_KEY_EXCH_PSK_DHE;
891  }
892 #endif
893 #if (TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED)
894  if(context->keyExchMethod == TLS13_KEY_EXCH_ECDHE)
895  {
896  context->keyExchMethod = TLS13_KEY_EXCH_PSK_ECDHE;
897  }
898 #endif
899 #if (TLS13_PSK_MLKEM_KE_SUPPORT == ENABLED)
900  if(context->keyExchMethod == TLS13_KEY_EXCH_MLKEM)
901  {
902  context->keyExchMethod = TLS13_KEY_EXCH_PSK_MLKEM;
903  }
904 #endif
905 #if (TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
906  if(context->keyExchMethod == TLS13_KEY_EXCH_HYBRID)
907  {
908  context->keyExchMethod = TLS13_KEY_EXCH_PSK_HYBRID;
909  }
910 #endif
911  }
912 #else
913  //PreSharedKey extension found?
914  if(selectedIdentity != NULL)
915  {
916  //If a client receives an extension type that it did not request in the
917  //ClientHello, it must abort the handshake with an unsupported_extension
918  //fatal alert
920  }
921 #endif
922 
923  //Successful processing
924  return NO_ERROR;
925 }
926 
927 
928 /**
929  * @brief Parse EarlyData extension
930  * @param[in] msgType Handshake message type
931  * @param[in] context Pointer to the TLS context
932  * @param[in] earlyDataIndication Pointer to the EarlyData extension
933  * @return Error code
934  **/
935 
937  TlsMessageType msgType, const TlsExtension *earlyDataIndication)
938 {
939 #if (TLS13_EARLY_DATA_SUPPORT == ENABLED)
940  //The extension may appear in EncryptedExtensions and NewSessionTicket
941  //messages
943  {
944  //EarlyData extension found?
945  if(earlyDataIndication != NULL)
946  {
947  //If a client receives an extension type that it did not request in the
948  //ClientHello, it must abort the handshake with an unsupported_extension
949  //fatal alert
950  if(!context->earlyDataEnabled || context->earlyDataRejected)
952 
953  //If the server has supplied an EarlyData extension, the client must
954  //verify that the server's selected_identity is 0. If any other value
955  //is returned, it must abort the handshake with an illegal_parameter
956  //fatal alert
957  if(context->selectedIdentity != 0)
959 
960  //A valid EarlyData extension has been received
961  context->earlyDataExtReceived = TRUE;
962  }
963  else
964  {
965  //The EncryptedExtensions message does not contain any EarlyData
966  //extension
967  context->earlyDataExtReceived = FALSE;
968  }
969  }
971  {
972  //The extension contains the maximum amount of 0-RTT data that the client
973  //is allowed to send
974  if(earlyDataIndication != NULL)
975  {
976  context->maxEarlyDataSize = LOAD32BE(earlyDataIndication->value);
977  }
978  else
979  {
980  context->maxEarlyDataSize = 0;
981  }
982  }
983  else
984  {
985  //Just for sanity
986  }
987 #else
988  //Check message type
990  {
991  //EarlyData extension found?
992  if(earlyDataIndication != NULL)
993  {
994  //If a client receives an extension type that it did not request in the
995  //ClientHello, it must abort the handshake with an unsupported_extension
996  //fatal alert
998  }
999  }
1001  {
1002  //Early data is not implemented
1003  context->maxEarlyDataSize = 0;
1004  }
1005  else
1006  {
1007  //Just for sanity
1008  }
1009 #endif
1010 
1011  //Successful processing
1012  return NO_ERROR;
1013 }
1014 
1015 #endif
@ TLS_GROUP_X25519_MLKEM768
Definition: tls.h:1473
@ TLS13_KEY_EXCH_PSK
Definition: tls.h:1193
@ TLS_EXT_PSK_KEY_EXCHANGE_MODES
Definition: tls.h:1375
#define tlsAllocMem(size)
Definition: tls.h:874
#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:1939
const HashAlgo * tlsGetHashAlgo(TlsHashAlgo hashAlgoId)
Get the hash algorithm that matches the specified identifier.
Definition: tls_misc.c:1186
@ TLS13_KEY_EXCH_MLKEM
Definition: tls.h:1191
@ TLS13_KEY_EXCH_PSK_DHE
Definition: tls.h:1194
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:307
#define TRUE
Definition: os_port.h:50
size_t digestSize
Definition: crypto.h:1095
#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.
TlsPskIdentity
Definition: tls.h:1751
TlsMessageType
Handshake message type.
Definition: tls.h:1069
@ TLS13_KEY_EXCH_PSK_MLKEM
Definition: tls.h:1196
bool_t tls13IsMlkemGroupSupported(TlsContext *context, uint16_t namedGroup)
Check whether a given ML-KEM exchange method is supported.
Definition: tls13_misc.c:1092
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
@ TLS13_KEY_EXCH_ECDHE
Definition: tls.h:1190
@ EC_PUBLIC_KEY_FORMAT_X963
Definition: ec.h:386
error_t tls13FormatCookieExtension(TlsContext *context, uint8_t *p, size_t *written)
Format Cookie extension.
size_t publicKeySize
Definition: crypto.h:1132
#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:1629
@ TLS_EXT_EARLY_DATA
Definition: tls.h:1372
@ TLS13_KEY_EXCH_PSK_HYBRID
Definition: tls.h:1197
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 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:1034
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
@ TLS13_KEY_EXCH_DHE
Definition: tls.h:1189
error_t tlsSelectCipherSuite(TlsContext *context, uint16_t identifier)
Set cipher suite.
Definition: tls_misc.c:335
error_t tls13Decapsulate(TlsContext *context, const uint8_t *keyShare, size_t length)
Decapsulation algorithm.
Definition: tls13_misc.c:686
@ TLS_EXT_KEY_SHARE
Definition: tls.h:1380
error_t tls13FormatClientKeyShareExtension(TlsContext *context, uint8_t *p, size_t *written)
Format KeyShare extension (ClientHello message)
#define TLS_VERSION_1_3
Definition: tls.h:97
@ TLS_TYPE_ENCRYPTED_EXTENSIONS
Definition: tls.h:1077
bool_t tls13IsTicketValid(TlsContext *context)
Check whether a session ticket is valid.
Definition: tls13_ticket.c:51
@ TLS_EXT_COOKIE
Definition: tls.h:1374
bool_t tls13IsFfdheGroupSupported(TlsContext *context, uint16_t namedGroup)
Check whether a given FFDHE group is supported.
Definition: tls13_misc.c:994
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:1133
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
error_t tls13ParseCookieExtension(TlsContext *context, const Tls13Cookie *cookie)
Parse Cookie extension.
#define TLS13_PSK_HYBRID_KE_SUPPORT
Definition: tls13_misc.h:92
@ TLS_KEY_EXCH_NONE
Definition: tls.h:1170
@ TLS13_KEY_EXCH_PSK_ECDHE
Definition: tls.h:1195
uint8_t msgType
error_t tls13GenerateSharedSecret(TlsContext *context, const uint8_t *keyShare, size_t length)
(EC)DHE shared secret generation
Definition: tls13_misc.c:433
bool_t tls13IsPskValid(TlsContext *context)
Check whether an externally established PSK is valid.
Definition: tls13_misc.c:915
error_t tls13GenerateKeyShare(TlsContext *context, uint16_t namedGroup)
Key share generation.
Definition: tls13_misc.c:260
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.
@ TLS13_KEY_EXCH_HYBRID
Definition: tls.h:1192
error_t tls13FormatPskKeModesExtension(TlsContext *context, uint8_t *p, size_t *written)
Format PskKeyExchangeModes extension.
Common interface for key encapsulation mechanisms (KEM)
Definition: crypto.h:1130
Tls13PskKeModeList
Definition: tls13_misc.h:231
Formatting and parsing of extensions (TLS 1.3 client)
@ TLS_EXT_PRE_SHARED_KEY
Definition: tls.h:1371
@ MPI_FORMAT_BIG_ENDIAN
Definition: mpi.h:93
TLS (Transport Layer Security)
uint8_t cookie[]
Definition: dtls_misc.h:206
Common interface for hash algorithms.
Definition: crypto.h:1089
const char_t * tlsGetVersionName(uint16_t version)
Convert TLS version to string representation.
Definition: tls_misc.c:1125
@ TLS_TYPE_NEW_SESSION_TICKET
Definition: tls.h:1074
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:879
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.