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