tls13_server_extensions.c
Go to the documentation of this file.
1 /**
2  * @file tls13_server_extensions.c
3  * @brief Formatting and parsing of extensions (TLS 1.3 server)
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.6
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"
39 #include "tls13/tls13_ticket.h"
40 #include "debug.h"
41 
42 //Check TLS library configuration
43 #if (TLS_SUPPORT == ENABLED && TLS_SERVER_SUPPORT == ENABLED && \
44  TLS_MAX_VERSION >= TLS_VERSION_1_3)
45 
46 
47 /**
48  * @brief Format SupportedVersions extension
49  * @param[in] context Pointer to the TLS context
50  * @param[in] p Output stream where to write the SupportedVersions extension
51  * @param[out] written Total number of bytes that have been written
52  * @return Error code
53  **/
54 
56  uint8_t *p, size_t *written)
57 {
58  size_t n;
59  uint16_t version;
60  TlsExtension *extension;
61 
62  //Add the SupportedVersions extension
63  extension = (TlsExtension *) p;
64  //Type of the extension
65  extension->type = HTONS(TLS_EXT_SUPPORTED_VERSIONS);
66 
67 #if (DTLS_SUPPORT == ENABLED)
68  //DTLS protocol?
69  if(context->transportProtocol == TLS_TRANSPORT_PROTOCOL_DATAGRAM)
70  {
71  //Retrieve the selected DTLS version
72  version = dtlsTranslateVersion(context->version);
73  }
74  else
75 #endif
76  {
77  //Retrieve the selected TLS version
78  version = context->version;
79  }
80 
81  //The extension contains the selected version value
82  STORE16BE(version, extension->value);
83 
84  //The extension data field contains a 16-bit unsigned integer
85  n = sizeof(uint16_t);
86  //Fix the length of the extension
87  extension->length = htons(n);
88 
89  //Compute the length, in bytes, of the SupportedVersions extension
90  n += sizeof(TlsExtension);
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 (HelloRetryRequest 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  //Check whether the selected ECDHE or FFDHE group is valid
118  if(context->namedGroup != TLS_GROUP_NONE)
119  {
120  TlsExtension *extension;
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 the mutually supported group the server intends
128  //to negotiate
129  STORE16BE(context->namedGroup, extension->value);
130 
131  //The extension data field contains a 16-bit unsigned integer
132  n = sizeof(uint16_t);
133  //Fix the length of the extension
134  extension->length = htons(n);
135 
136  //Compute the length, in bytes, of the KeyShare extension
137  n += sizeof(TlsExtension);
138  }
139 #endif
140 
141  //Total number of bytes that have been written
142  *written = n;
143 
144  //Successful processing
145  return NO_ERROR;
146 }
147 
148 
149 /**
150  * @brief Format KeyShare extension (ServerHello message)
151  * @param[in] context Pointer to the TLS context
152  * @param[in] p Output stream where to write the KeyShare extension
153  * @param[out] written Total number of bytes that have been written
154  * @return Error code
155  **/
156 
158  uint8_t *p, size_t *written)
159 {
160  size_t n = 0;
161 
162 #if (TLS13_DHE_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
163  TLS13_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || \
164  TLS13_MLKEM_KE_SUPPORT == ENABLED || TLS13_PSK_MLKEM_KE_SUPPORT == ENABLED || \
165  TLS13_HYBRID_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
166  //If using (EC)DHE key establishment, servers offer exactly one
167  //KeyShareEntry in the ServerHello
168  if(context->keyExchMethod == TLS13_KEY_EXCH_DHE ||
169  context->keyExchMethod == TLS13_KEY_EXCH_ECDHE ||
170  context->keyExchMethod == TLS13_KEY_EXCH_MLKEM ||
171  context->keyExchMethod == TLS13_KEY_EXCH_HYBRID ||
172  context->keyExchMethod == TLS13_KEY_EXCH_PSK_DHE ||
173  context->keyExchMethod == TLS13_KEY_EXCH_PSK_ECDHE ||
174  context->keyExchMethod == TLS13_KEY_EXCH_PSK_MLKEM ||
175  context->keyExchMethod == TLS13_KEY_EXCH_PSK_HYBRID)
176  {
177  error_t error;
178  TlsExtension *extension;
179  Tls13KeyShareEntry *keyShareEntry;
180 
181  //Add the KeyShare extension
182  extension = (TlsExtension *) p;
183  //Type of the extension
184  extension->type = HTONS(TLS_EXT_KEY_SHARE);
185 
186  //If using (EC)DHE key establishment, servers offer exactly one
187  //KeyShareEntry in the ServerHello
188  keyShareEntry = (Tls13KeyShareEntry *) extension->value;
189 
190  //The key share value must be in the same group as the KeyShareEntry
191  //value offered by the client that the server has selected for the
192  //negotiated key exchange
193  keyShareEntry->group = htons(context->namedGroup);
194 
195 #if (TLS13_DHE_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED)
196  //DHE key exchange method?
197  if(context->keyExchMethod == TLS13_KEY_EXCH_DHE ||
198  context->keyExchMethod == TLS13_KEY_EXCH_PSK_DHE)
199  {
200  //Diffie-Hellman parameters are encoded in the opaque key_exchange field
201  //of the KeyShareEntry. The opaque value contains the Diffie-Hellman
202  //public value for the specified group encoded as a big-endian integer
203  //and padded to the left with zeros to the size of p in bytes
204  error = dhExportPublicKey(&context->dhContext,
205  keyShareEntry->keyExchange, &n, MPI_FORMAT_BIG_ENDIAN);
206  //Any error to report?
207  if(error)
208  return error;
209  }
210  else
211 #endif
212 #if (TLS13_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED)
213  //ECDHE key exchange method?
214  if(context->keyExchMethod == TLS13_KEY_EXCH_ECDHE ||
215  context->keyExchMethod == TLS13_KEY_EXCH_PSK_ECDHE)
216  {
217  //ECDHE parameters are encoded in the opaque key_exchange field of
218  //the KeyShareEntry
219  error = ecdhExportPublicKey(&context->ecdhContext,
220  keyShareEntry->keyExchange, &n, EC_PUBLIC_KEY_FORMAT_X963);
221  //Any error to report?
222  if(error)
223  return error;
224  }
225  else
226 #endif
227 #if (TLS13_MLKEM_KE_SUPPORT == ENABLED || TLS13_PSK_MLKEM_KE_SUPPORT == ENABLED)
228  //ML-KEM key exchange method?
229  if(context->keyExchMethod == TLS13_KEY_EXCH_MLKEM ||
230  context->keyExchMethod == TLS13_KEY_EXCH_PSK_MLKEM)
231  {
232  const KemAlgo *kemAlgo;
233 
234  //Point to the KEM algorithm
235  kemAlgo = context->kemContext.kemAlgo;
236 
237  //For the server's share, the key_exchange value contains the ct output
238  //of the corresponding KEM's Encaps algorithm
239  error = kemEncapsulate(&context->kemContext, context->prngAlgo,
240  context->prngContext, keyShareEntry->keyExchange,
241  context->premasterSecret);
242  //Any error to report?
243  if(error)
244  return error;
245 
246  //The length of the ciphertext is fixed
247  n = kemAlgo->ciphertextSize;
248 
249  //The shared secret output from the ML-KEM Encaps is inserted into the
250  //TLS 1.3 key schedule in place of the (EC)DHE shared secret
251  context->premasterSecretLen = kemAlgo->sharedSecretSize;
252  }
253  else
254 #endif
255 #if (TLS13_HYBRID_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
256  //Hybrid key exchange method?
257  if(context->keyExchMethod == TLS13_KEY_EXCH_HYBRID ||
258  context->keyExchMethod == TLS13_KEY_EXCH_PSK_HYBRID)
259  {
260  size_t keyShareOffset;
261  size_t sharedSecretOffset;
262  const KemAlgo *kemAlgo;
263 
264  //Point to the KEM algorithm
265  kemAlgo = context->kemContext.kemAlgo;
266 
267  //The group name X25519MLKEM768 does not adhere to the naming
268  //convention outlined in Section 3.2 of RFC 9954. Specifically, the
269  //order of shares in the concatenation has been reversed. This is due
270  //to historical reasons (refer to RFC 10024, section 4.1)
271  if(context->namedGroup == TLS_GROUP_X25519_MLKEM768)
272  {
273  keyShareOffset = kemAlgo->ciphertextSize;
274  }
275  else
276  {
277  keyShareOffset = 0;
278  }
279 
280  //The server ECDHE share is the serialized value of the uncompressed
281  //ECDH point representation
282  error = ecdhExportPublicKey(&context->ecdhContext,
283  keyShareEntry->keyExchange + keyShareOffset, &n,
285  //Any error to report?
286  if(error)
287  return error;
288 
289  //X25519MLKEM768 group?
290  if(context->namedGroup == TLS_GROUP_X25519_MLKEM768)
291  {
292  keyShareOffset = 0;
293  sharedSecretOffset = 0;
294  }
295  else
296  {
297  keyShareOffset = n;
298  sharedSecretOffset = context->premasterSecretLen;
299  }
300 
301  //The server share is the ML-KEM's ciphertext returned from the
302  //Encapsulate step represented as an octet string
303  error = kemEncapsulate(&context->kemContext, context->prngAlgo,
304  context->prngContext, keyShareEntry->keyExchange + keyShareOffset,
305  context->premasterSecret + sharedSecretOffset);
306  //Any error to report?
307  if(error)
308  return error;
309 
310  //The server's share is a fixed-size concatenation of ECDHE share and
311  //Kyber's ciphertext returned from encapsulation
312  n += kemAlgo->ciphertextSize;
313 
314  //Finally, the shared secret is a concatenation of the ECDHE and the
315  //Kyber shared secrets
316  context->premasterSecretLen += kemAlgo->sharedSecretSize;
317  }
318  else
319 #endif
320  //Unknown key exchange method?
321  {
322  //Report an error
323  return ERROR_FAILURE;
324  }
325 
326  //Set the length of the key_exchange field
327  keyShareEntry->length = htons(n);
328 
329  //Compute the length, in bytes, of the KeyShareEntry
330  n += sizeof(Tls13KeyShareEntry);
331  //Fix the length of the extension
332  extension->length = htons(n);
333 
334  //Compute the length, in bytes, of the KeyShare extension
335  n += sizeof(TlsExtension);
336  }
337 #endif
338 
339  //Total number of bytes that have been written
340  *written = n;
341 
342  //Successful processing
343  return NO_ERROR;
344 }
345 
346 
347 /**
348  * @brief Format PreSharedKey extension
349  * @param[in] context Pointer to the TLS context
350  * @param[in] p Output stream where to write the PreSharedKey extension
351  * @param[out] written Total number of bytes that have been written
352  * @return Error code
353  **/
354 
356  uint8_t *p, size_t *written)
357 {
358  size_t n = 0;
359 
360 #if (TLS13_PSK_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
361  TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
362  //PSK key exchange method?
363  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK ||
364  context->keyExchMethod == TLS13_KEY_EXCH_PSK_DHE ||
365  context->keyExchMethod == TLS13_KEY_EXCH_PSK_ECDHE ||
366  context->keyExchMethod == TLS13_KEY_EXCH_PSK_HYBRID)
367  {
368  TlsExtension *extension;
369 
370  //Add the PreSharedKey extension
371  extension = (TlsExtension *) p;
372  //Type of the extension
373  extension->type = HTONS(TLS_EXT_PRE_SHARED_KEY);
374 
375  //The extension contains the selected identity
376  STORE16BE(context->selectedIdentity, extension->value);
377 
378  //The extension data field contains a 16-bit unsigned integer
379  n = sizeof(uint16_t);
380  //Fix the length of the extension
381  extension->length = htons(n);
382 
383  //Compute the length, in bytes, of the PreSharedKey extension
384  n += sizeof(TlsExtension);
385  }
386 #endif
387 
388  //Total number of bytes that have been written
389  *written = n;
390 
391  //Successful processing
392  return NO_ERROR;
393 }
394 
395 
396 /**
397  * @brief Format EarlyData extension
398  * @param[in] context Pointer to the TLS context
399  * @param[in] msgType Handshake message type
400  * @param[in] p Output stream where to write the EarlyData extension
401  * @param[out] written Total number of bytes that have been written
402  * @return Error code
403  **/
404 
406  TlsMessageType msgType, uint8_t *p, size_t *written)
407 {
408  size_t n = 0;
409 
410 #if (TLS13_EARLY_DATA_SUPPORT == ENABLED)
411  //The extension may appear in EncryptedExtensions and NewSessionTicket
412  //messages
414  {
415  //If the server intends to process the early data, then it returns its
416  //own EarlyData extension in EncryptedExtensions
417  if(context->earlyDataExtReceived && !context->earlyDataRejected)
418  {
419  TlsExtension *extension;
420 
421  //Add the EarlyData extension
422  extension = (TlsExtension *) p;
423  //Type of the extension
424  extension->type = HTONS(TLS_EXT_EARLY_DATA);
425 
426  //The extension data field of this extension is empty
427  extension->length = HTONS(0);
428 
429  //Compute the length, in bytes, of the EarlyData extension
430  n = sizeof(TlsExtension);
431  }
432  }
434  {
435  TlsExtension *extension;
436 
437  //Add the EarlyData extension
438  extension = (TlsExtension *) p;
439  //Type of the extension
440  extension->type = HTONS(TLS_EXT_EARLY_DATA);
441 
442  //The extension contains the maximum amount of 0-RTT data that the
443  //client is allowed to send when using this ticket, in bytes
444  STORE32BE(context->maxEarlyDataSize, extension->value);
445 
446  //The extension data field contains a 32-bit unsigned integer
447  n = sizeof(uint32_t);
448  //Fix the length of the extension
449  extension->length = htons(n);
450 
451  //Compute the length, in bytes, of the EarlyData extension
452  n += sizeof(TlsExtension);
453  }
454  else
455  {
456  //Just for sanity
457  }
458 #endif
459 
460  //Total number of bytes that have been written
461  *written = n;
462 
463  //Successful processing
464  return NO_ERROR;
465 }
466 
467 
468 /**
469  * @brief Parse KeyShare extension
470  * @param[in] context Pointer to the TLS context
471  * @param[in] keyShareList Pointer to the KeyShare extension
472  * @param[in] groupList Pointer to the SupportedGroups extension
473  * @return Error code
474  **/
475 
477  const Tls13KeyShareList *keyShareList,
478  const TlsSupportedGroupList *groupList)
479 {
480 #if (TLS13_DHE_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
481  TLS13_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || \
482  TLS13_MLKEM_KE_SUPPORT == ENABLED || TLS13_PSK_MLKEM_KE_SUPPORT == ENABLED || \
483  TLS13_HYBRID_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
484  //KeyShare extension found?
485  if(keyShareList != NULL)
486  {
487  error_t error;
488  bool_t acceptable;
489  uint16_t namedGroup;
490  size_t n;
491  size_t length;
492  const uint8_t *p;
493  const Tls13KeyShareEntry *keyShareEntry;
494 
495  //Initialize variables
496  acceptable = FALSE;
497  keyShareEntry = NULL;
498 
499  //Point to the first KeyShareEntry of the list
500  p = keyShareList->value;
501  //Retrieve the length of the list
502  length = ntohs(keyShareList->length);
503 
504  //The extension contains a list of KeyShareEntry values offered by the
505  //client. The values are indicated in descending order of preference
506  while(length > 0 && !acceptable)
507  {
508  //Malformed extension?
509  if(length < sizeof(Tls13KeyShareEntry))
510  return ERROR_DECODING_FAILED;
511 
512  //Point to the current key share entry
513  keyShareEntry = (Tls13KeyShareEntry *) p;
514  //Retrieve the length of the key_exchange field
515  n = ntohs(keyShareEntry->length);
516 
517  //Malformed extension?
518  if(length < (sizeof(Tls13KeyShareEntry) + n))
519  return ERROR_DECODING_FAILED;
520 
521  //Each KeyShareEntry value must correspond to a group offered in the
522  //SupportedGroups extension (refer to RFC 8446, section 4.2.8)
523  if(!tls13IsGroupOffered(ntohs(keyShareEntry->group), groupList))
525 
526  //Initial or updated ClientHello?
527  if(context->state == TLS_STATE_CLIENT_HELLO)
528  {
529  //Check whether the ECDHE or FFDHE group is supported
530  acceptable = tls13IsGroupSupported(context,
531  ntohs(keyShareEntry->group));
532  }
533  else
534  {
535  //If the server has sent a HelloRetryRequest, the client needs
536  //to restart the handshake with an appropriate group
537  if(ntohs(keyShareEntry->group) == context->namedGroup)
538  {
539  //Check whether the ECDHE or FFDHE group is supported
540  acceptable = tls13IsGroupSupported(context,
541  ntohs(keyShareEntry->group));
542  }
543  }
544 
545  //Point to the next entry
546  p += sizeof(Tls13KeyShareEntry) + n;
547  //Remaining bytes to process
548  length -= sizeof(Tls13KeyShareEntry) + n;
549  }
550 
551  //Acceptable ECDHE or FFDHE group found?
552  if(acceptable)
553  {
554  //Convert the named group to host byte order
555  namedGroup = ntohs(keyShareEntry->group);
556 
557  //Finite field group?
558  if(tls13IsFfdheGroupSupported(context, namedGroup))
559  {
560  //Generate an ephemeral key pair
561  error = tls13GenerateKeyShare(context, namedGroup);
562  //Any error to report?
563  if(error)
564  return error;
565 
566  //Compute DHE shared secret
567  error = tls13GenerateSharedSecret(context,
568  keyShareEntry->keyExchange, ntohs(keyShareEntry->length));
569  //Any error to report?
570  if(error)
571  return error;
572 
573  //DHE key exchange mechanism provides forward secrecy
574  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK)
575  {
576  context->keyExchMethod = TLS13_KEY_EXCH_PSK_DHE;
577  }
578  else
579  {
580  context->keyExchMethod = TLS13_KEY_EXCH_DHE;
581  }
582  }
583  //Elliptic curve group?
584  else if(tls13IsEcdheGroupSupported(context, namedGroup))
585  {
586  //Generate an ephemeral key pair
587  error = tls13GenerateKeyShare(context, namedGroup);
588  //Any error to report?
589  if(error)
590  return error;
591 
592  //Compute ECDHE shared secret
593  error = tls13GenerateSharedSecret(context,
594  keyShareEntry->keyExchange, ntohs(keyShareEntry->length));
595  //Any error to report?
596  if(error)
597  return error;
598 
599  //ECDHE key exchange mechanism provides forward secrecy
600  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK)
601  {
602  context->keyExchMethod = TLS13_KEY_EXCH_PSK_ECDHE;
603  }
604  else
605  {
606  context->keyExchMethod = TLS13_KEY_EXCH_ECDHE;
607  }
608  }
609  //ML-KEM key exchange method?
610  else if(tls13IsMlkemGroupSupported(context, namedGroup))
611  {
612  //Encapsulation algorithm
613  error = tls13Encapsulate(context, namedGroup,
614  keyShareEntry->keyExchange, ntohs(keyShareEntry->length));
615  //Any error to report?
616  if(error)
617  return error;
618 
619  //ML-KEM-512, ML-KEM-768, and ML-KEM-1024 can be used as a
620  //standalone algorithm to achieve post-quantum key agreement
621  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK)
622  {
623  context->keyExchMethod = TLS13_KEY_EXCH_PSK_MLKEM;
624  }
625  else
626  {
627  context->keyExchMethod = TLS13_KEY_EXCH_MLKEM;
628  }
629  }
630  //Hybrid key exchange method?
631  else if(tls13IsHybridGroupSupported(context, namedGroup))
632  {
633  //Encapsulation algorithm
634  error = tls13Encapsulate(context, namedGroup,
635  keyShareEntry->keyExchange, ntohs(keyShareEntry->length));
636  //Any error to report?
637  if(error)
638  return error;
639 
640  //Hybrid key exchange makes use of two key exchange algorithms
641  //based on different cryptographic assumptions
642  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK)
643  {
644  context->keyExchMethod = TLS13_KEY_EXCH_PSK_HYBRID;
645  }
646  else
647  {
648  context->keyExchMethod = TLS13_KEY_EXCH_HYBRID;
649  }
650  }
651  //Unknown group?
652  else
653  {
654  //Just for sanity
655  return ERROR_FAILURE;
656  }
657  }
658  else
659  {
660  //If no common cryptographic parameters can be negotiated, the server
661  //must abort the handshake with an appropriate alert
662  if(context->state == TLS_STATE_CLIENT_HELLO_2)
663  return ERROR_HANDSHAKE_FAILED;
664  }
665  }
666 #endif
667 
668  //Successful processing
669  return NO_ERROR;
670 }
671 
672 
673 /**
674  * @brief Parse PskKeyExchangeModes extension
675  * @param[in] context Pointer to the TLS context
676  * @param[in] pskKeModeList Pointer to the PskKeyExchangeModes extension
677  * @return Error code
678  **/
679 
681  const Tls13PskKeModeList *pskKeModeList)
682 {
683  error_t error;
684  uint_t i;
685 
686  //PskKeyExchangeModes extension found?
687  if(pskKeModeList != NULL)
688  {
689  //Check whether the client supports session resumption with a PSK
690  for(i = 0; i < pskKeModeList->length; i++)
691  {
692  //PSK key establishment supported?
693  if(pskKeModeList->value[i] == TLS_PSK_KEY_EXCH_MODE_PSK_KE ||
694  pskKeModeList->value[i] == TLS_PSK_KEY_EXCH_MODE_PSK_DHE_KE)
695  {
696  context->pskKeModeSupported = TRUE;
697  }
698  }
699  }
700 
701  //PSK key exchange method?
702  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK ||
703  context->keyExchMethod == TLS13_KEY_EXCH_PSK_DHE ||
704  context->keyExchMethod == TLS13_KEY_EXCH_PSK_ECDHE ||
705  context->keyExchMethod == TLS13_KEY_EXCH_PSK_HYBRID)
706  {
707  //PskKeyExchangeModes extension found?
708  if(pskKeModeList != NULL)
709  {
710  //Initialize status code
711  error = ERROR_HANDSHAKE_FAILED;
712 
713  //The extension contains a list of supported PSK key exchange modes
714  for(i = 0; i < pskKeModeList->length && error; i++)
715  {
716 #if (TLS13_PSK_KE_SUPPORT == ENABLED)
717  //PSK-only key establishment?
718  if(pskKeModeList->value[i] == TLS_PSK_KEY_EXCH_MODE_PSK_KE)
719  {
720  //Servers must not select a key exchange mode that is not listed
721  //by the client
722  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK)
723  {
724  error = NO_ERROR;
725  }
726  }
727  else
728 #endif
729 #if (TLS13_PSK_DHE_KE_SUPPORT == ENABLED || TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || \
730  TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
731  //PSK with (EC)DHE key establishment?
732  if(pskKeModeList->value[i] == TLS_PSK_KEY_EXCH_MODE_PSK_DHE_KE)
733  {
734  //Servers must not select a key exchange mode that is not listed
735  //by the client
736  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK_DHE ||
737  context->keyExchMethod == TLS13_KEY_EXCH_PSK_ECDHE ||
738  context->keyExchMethod == TLS13_KEY_EXCH_PSK_HYBRID)
739  {
740  error = NO_ERROR;
741  }
742  }
743  else
744 #endif
745  //Unknown key exchange method?
746  {
747  //Just for sanity
748  }
749  }
750  }
751  else
752  {
753  //A client must provide a PskKeyExchangeModes extension if it offers a
754  //PreSharedKey extension
755  error = ERROR_MISSING_EXTENSION;
756  }
757  }
758  else
759  {
760  //If no acceptable PSKs are found, the server should perform a non-PSK
761  //handshake if possible
762  error = NO_ERROR;
763  }
764 
765  //Return status code
766  return error;
767 }
768 
769 
770 /**
771  * @brief Parse PreSharedKey extension
772  * @param[in] context Pointer to the TLS context
773  * @param[in] clientHello Pointer to the ClientHello message
774  * @param[in] clientHelloLen Length of the ClientHello message
775  * @param[in] identityList List of the identities that the client is willing
776  * to negotiate with the server
777  * @param[in] binderList List of HMAC values, one for each PSK offered in the
778  * PreSharedKey extension
779  * @return Error code
780  **/
781 
783  const TlsClientHello *clientHello, size_t clientHelloLen,
784  const Tls13PskIdentityList *identityList, const Tls13PskBinderList *binderList)
785 {
786 #if (TLS13_PSK_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
787  TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
788  //PreSharedKey extension found?
789  if(identityList != NULL && binderList != NULL)
790  {
791  error_t error;
792  int_t i;
793  size_t n;
794  size_t m;
795  uint32_t obfuscatedTicketAge;
796  const uint8_t *p;
797  const uint8_t *q;
798  const Tls13PskIdentity *identity;
799  const Tls13PskBinder *binder;
800  const HashAlgo *hashAlgo;
801 
802  //Initialize variables
803  identity = NULL;
804  binder = NULL;
805 
806  //Reset the server's chosen identity to its default value
807  context->selectedIdentity = -1;
808 
809  //Debug message
810  TRACE_DEBUG("PSK identity list:\r\n");
811  TRACE_DEBUG_ARRAY(" ", identityList, ntohs(identityList->length) + 2);
812  TRACE_DEBUG("PSK binder list:\r\n");
813  TRACE_DEBUG_ARRAY(" ", binderList, ntohs(binderList->length) + 2);
814 
815  //Point to the list of the identities that the client is willing to
816  //negotiate with the server
817  p = identityList->value;
818  n = ntohs(identityList->length);
819 
820  //Point to the list of HMAC values, one for each PSK offered in the
821  //PreSharedKey extension
822  q = binderList->value;
823  m = ntohs(binderList->length);
824 
825  //Loop through the list of PSK identities
826  for(i = 0; n > 0; i++)
827  {
828  //Point to the current PskIdentity entry
829  identity = (Tls13PskIdentity *) p;
830 
831  //Malformed PreSharedKey extension?
832  if(n < sizeof(TlsPskIdentity))
833  return ERROR_DECODING_FAILED;
834  if(n < (sizeof(TlsPskIdentity) + ntohs(identity->length)))
835  return ERROR_DECODING_FAILED;
836 
837  //Debug message
838  TRACE_DEBUG("PSK identity #%u:\r\n", i);
839  TRACE_DEBUG_ARRAY(" ", identity->value, ntohs(identity->length));
840 
841  //Point to the obfuscated_ticket_age field
842  p += sizeof(TlsPskIdentity) + ntohs(identity->length);
843  n -= sizeof(TlsPskIdentity) + ntohs(identity->length);
844 
845  //Malformed PreSharedKey extension?
846  if(n < sizeof(uint32_t))
847  return ERROR_DECODING_FAILED;
848 
849  //The obfuscated_ticket_age field is a 32-bit unsigned integer
850  obfuscatedTicketAge = LOAD32BE(p);
851 
852  //Point to the next PskIdentity entry
853  p += sizeof(uint32_t);
854  n -= sizeof(uint32_t);
855 
856  //Point to the PskBinderEntry
857  binder = (Tls13PskBinder *) q;
858 
859  //If the binder is not present, the server must abort the handshake
860  if(context->selectedIdentity >= 0 && m == 0)
862 
863  //Malformed PreSharedKey extension?
864  if(m < sizeof(Tls13PskBinder))
865  return ERROR_DECODING_FAILED;
866  if(m < (sizeof(Tls13PskBinder) + binder->length))
867  return ERROR_DECODING_FAILED;
868 
869  //Debug message
870  TRACE_DEBUG("PSK binder #%u:\r\n", i);
871  TRACE_DEBUG_ARRAY(" ", binder->value, binder->length);
872 
873  //Point to the next PskBinderEntry
874  q += sizeof(Tls13PskBinder) + binder->length;
875  m -= sizeof(Tls13PskBinder) + binder->length;
876 
877  //The server should select a single PSK
878  if(context->selectedIdentity < 0)
879  {
880  //Any registered callback?
881  if(context->pskCallback != NULL)
882  {
883  //Check whether the PSK identity provided by the client matches
884  //any externally established PSK
885  error = context->pskCallback(context, identity->value,
886  ntohs(identity->length));
887 
888  //Valid PSK?
889  if(!error && tls13IsPskValid(context))
890  {
891  //For externally established PSKs, the hash algorithm must be
892  //set when the PSK is established
893  hashAlgo = tlsGetHashAlgo(context->pskHashAlgo);
894 
895  //Make sure the hash algorithm is valid
896  if(hashAlgo != NULL)
897  {
898  //Save the hash algorithm associated with the PSK
899  context->cipherSuite.prfHashAlgo = hashAlgo;
900 
901  //The server's chosen identity is expressed as a 0-based
902  //index into the identities in the client's list
903  context->selectedIdentity = i;
904  }
905  }
906  }
907  }
908 
909  //The server should select a single PSK
910  if(context->selectedIdentity < 0)
911  {
912  //Decrypt the received ticket and verify the ticket's validity
913  error = tls13VerifyTicket(context, identity->value,
914  htons(identity->length), obfuscatedTicketAge);
915 
916  //Valid ticket?
917  if(!error)
918  {
919  //The server's chosen identity is expressed as a 0-based index
920  //into the identities in the client's list
921  context->selectedIdentity = i;
922  }
923  }
924  }
925 
926  //Extra binders found?
927  if(m != 0)
928  {
930  }
931  }
932  else
933 #endif
934  {
935  //Initial or updated ClientHello?
936  if(context->state == TLS_STATE_CLIENT_HELLO_2)
937  {
938  //When responding to a HelloRetryRequest, the client must send the
939  //same ClientHello without modification
940  if(context->selectedIdentity >= 0)
941  {
943  }
944  }
945 
946  //The ClientHello message does not contain any PreSharedKey extension
947  context->selectedIdentity = -1;
948  }
949 
950  //Successful processing
951  return NO_ERROR;
952 }
953 
954 
955 /**
956  * @brief Parse EarlyData extension
957  * @param[in] context Pointer to the TLS context
958  * @param[in] earlyDataIndication Pointer to the EarlyData extension
959  * @return Error code
960  **/
961 
963  const TlsExtension *earlyDataIndication)
964 {
965  //EarlyData extension found?
966  if(earlyDataIndication != NULL)
967  {
968  //Early data is not permitted after a HelloRetryRequest (refer to
969  //RFC 8446, section 4.1.2)
970  if(context->state == TLS_STATE_CLIENT_HELLO_2)
971  {
972  context->earlyDataRejected = TRUE;
973  }
974 
975  //In order to accept early data, the server must have accepted a PSK
976  //cipher suite and selected the first key offered in the client's
977  //PreSharedKey extension (refer to RFC 8446, section 4.2.10)
978  if(context->selectedIdentity != 0)
979  {
980  context->earlyDataRejected = TRUE;
981  }
982 
983  //A valid EarlyData extension has been received
984  context->earlyDataExtReceived = TRUE;
985  }
986  else
987  {
988  //The ClientHello message does not contain any EarlyData extension
989  context->earlyDataExtReceived = FALSE;
990  }
991 
992  //Successful processing
993  return NO_ERROR;
994 }
995 
996 #endif
@ TLS_GROUP_X25519_MLKEM768
Definition: tls.h:1546
@ TLS13_KEY_EXCH_PSK
Definition: tls.h:1247
#define htons(value)
Definition: cpu_endian.h:413
TLS helper functions.
Tls13PskBinderList
Definition: tls13_misc.h:275
int bool_t
Definition: compiler_port.h:63
error_t tls13ParsePskKeModesExtension(TlsContext *context, const Tls13PskKeModeList *pskKeModeList)
Parse PskKeyExchangeModes extension.
error_t tls13VerifyTicket(TlsContext *context, const uint8_t *ticket, size_t length, uint32_t obfuscatedTicketAge)
Session ticket verification.
Definition: tls13_ticket.c:377
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:1245
@ TLS13_KEY_EXCH_PSK_DHE
Definition: tls.h:1248
signed int int_t
Definition: compiler_port.h:56
#define LOAD32BE(p)
Definition: cpu_endian.h:210
@ ERROR_ILLEGAL_PARAMETER
Definition: error.h:244
@ TLS_EXT_SUPPORTED_VERSIONS
Definition: tls.h:1430
uint8_t p
Definition: ndp.h:300
#define TRUE
Definition: os_port.h:50
TLS 1.3 session tickets.
@ TLS_TRANSPORT_PROTOCOL_DATAGRAM
Definition: tls.h:1039
TlsPskIdentity
Definition: tls.h:1864
TlsMessageType
Handshake message type.
Definition: tls.h:1122
@ TLS13_KEY_EXCH_PSK_MLKEM
Definition: tls.h:1250
bool_t tls13IsMlkemGroupSupported(TlsContext *context, uint16_t namedGroup)
Check whether a given ML-KEM exchange method is supported.
Definition: tls13_misc.c:1088
@ ERROR_HANDSHAKE_FAILED
Definition: error.h:234
@ TLS13_KEY_EXCH_ECDHE
Definition: tls.h:1244
@ EC_PUBLIC_KEY_FORMAT_X963
Definition: ec.h:386
uint8_t version
Definition: coap_common.h:177
Tls13KeyShareEntry
Definition: tls13_misc.h:209
TlsExtension
Definition: tls.h:1742
@ TLS_EXT_EARLY_DATA
Definition: tls.h:1429
@ TLS13_KEY_EXCH_PSK_HYBRID
Definition: tls.h:1251
error_t kemEncapsulate(KemContext *context, const PrngAlgo *prngAlgo, void *prngContext, uint8_t *ct, uint8_t *ss)
Encapsulation algorithm.
Definition: kem.c:209
@ TLS_STATE_CLIENT_HELLO
Definition: tls.h:1585
@ TLS_PSK_KEY_EXCH_MODE_PSK_KE
Definition: tls13_misc.h:165
@ TLS_PSK_KEY_EXCH_MODE_PSK_DHE_KE
Definition: tls13_misc.h:166
#define FALSE
Definition: os_port.h:46
#define TlsContext
Definition: tls.h:36
error_t
Error codes.
Definition: error.h:43
bool_t tls13IsGroupSupported(TlsContext *context, uint16_t namedGroup)
Check whether a given named group is supported.
Definition: tls13_misc.c:949
size_t sharedSecretSize
Definition: crypto.h:1309
@ TLS_GROUP_NONE
Definition: tls.h:1494
Formatting and parsing of extensions (TLS 1.3 server)
bool_t tls13IsEcdheGroupSupported(TlsContext *context, uint16_t namedGroup)
Check whether a given ECDHE group is supported.
Definition: tls13_misc.c:1030
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
@ TLS13_KEY_EXCH_DHE
Definition: tls.h:1243
#define STORE16BE(a, p)
Definition: cpu_endian.h:262
@ TLS_EXT_KEY_SHARE
Definition: tls.h:1437
error_t tls13FormatServerPreSharedKeyExtension(TlsContext *context, uint8_t *p, size_t *written)
Format PreSharedKey extension.
@ ERROR_MISSING_EXTENSION
Definition: error.h:245
@ TLS_TYPE_ENCRYPTED_EXTENSIONS
Definition: tls.h:1130
bool_t tls13IsFfdheGroupSupported(TlsContext *context, uint16_t namedGroup)
Check whether a given FFDHE group is supported.
Definition: tls13_misc.c:990
error_t tls13ParseClientEarlyDataExtension(TlsContext *context, const TlsExtension *earlyDataIndication)
Parse EarlyData extension.
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:1129
uint8_t length
Definition: tcp.h:375
error_t tls13FormatSelectedGroupExtension(TlsContext *context, uint8_t *p, size_t *written)
Format KeyShare extension (HelloRetryRequest message)
error_t dhExportPublicKey(DhContext *context, uint8_t *output, size_t *written, MpiFormat format)
Export our own public key.
Definition: dh.c:185
uint16_t dtlsTranslateVersion(uint16_t version)
Translate TLS version into DTLS version.
Definition: dtls_misc.c:124
error_t tls13FormatServerSupportedVersionsExtension(TlsContext *context, uint8_t *p, size_t *written)
Format SupportedVersions extension.
Helper functions for TLS 1.3 server.
Tls13KeyShareList
Definition: tls13_misc.h:220
#define ntohs(value)
Definition: cpu_endian.h:421
#define TRACE_DEBUG(...)
Definition: debug.h:119
@ TLS13_KEY_EXCH_PSK_ECDHE
Definition: tls.h:1249
@ TLS_STATE_CLIENT_HELLO_2
Definition: tls.h:1586
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:120
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:911
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 tls13ParseClientKeyShareExtension(TlsContext *context, const Tls13KeyShareList *keyShareList, const TlsSupportedGroupList *groupList)
Parse KeyShare extension.
@ TLS13_KEY_EXCH_HYBRID
Definition: tls.h:1246
TlsClientHello
Definition: tls.h:1943
Common interface for key encapsulation mechanisms (KEM)
Definition: crypto.h:1304
Tls13PskKeModeList
Definition: tls13_misc.h:231
error_t tls13FormatServerEarlyDataExtension(TlsContext *context, TlsMessageType msgType, uint8_t *p, size_t *written)
Format EarlyData extension.
size_t ciphertextSize
Definition: crypto.h:1308
@ TLS_EXT_PRE_SHARED_KEY
Definition: tls.h:1428
@ MPI_FORMAT_BIG_ENDIAN
Definition: mpi.h:93
TLS (Transport Layer Security)
Common interface for hash algorithms.
Definition: crypto.h:1243
error_t tls13FormatServerKeyShareExtension(TlsContext *context, uint8_t *p, size_t *written)
Format KeyShare extension (ServerHello message)
bool_t tls13IsGroupOffered(uint16_t namedGroup, const TlsSupportedGroupList *groupList)
Check whether a group is offered in the SupportedGroups extension.
error_t tls13Encapsulate(TlsContext *context, uint16_t namedGroup, const uint8_t *keyShare, size_t length)
Encapsulation algorithm.
Definition: tls13_misc.c:488
@ TLS_TYPE_NEW_SESSION_TICKET
Definition: tls.h:1127
Tls13PskIdentity
Definition: tls13_misc.h:242
@ ERROR_DECODING_FAILED
Definition: error.h:242
Tls13PskIdentityList
Definition: tls13_misc.h:253
unsigned int uint_t
Definition: compiler_port.h:57
TlsSupportedGroupList
Definition: tls.h:1820
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
error_t tls13ParseClientPreSharedKeyExtension(TlsContext *context, const TlsClientHello *clientHello, size_t clientHelloLen, const Tls13PskIdentityList *identityList, const Tls13PskBinderList *binderList)
Parse PreSharedKey extension.
Debugging facilities.