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-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_server_misc.h"
39 #include "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  //NIST's special publication 800-56C approves the usage of HKDF with two
268  //distinct shared secrets, with the condition that the first one is
269  //computed by a FIPS-approved key-establishment scheme
270  if(context->namedGroup == TLS_GROUP_X25519_MLKEM768)
271  {
272  keyShareOffset = kemAlgo->ciphertextSize;
273  }
274  else
275  {
276  keyShareOffset = 0;
277  }
278 
279  //The server ECDHE share is the serialized value of the uncompressed
280  //ECDH point representation
281  error = ecdhExportPublicKey(&context->ecdhContext,
282  keyShareEntry->keyExchange + keyShareOffset, &n,
284  //Any error to report?
285  if(error)
286  return error;
287 
288  //X25519MLKEM768 group?
289  if(context->namedGroup == TLS_GROUP_X25519_MLKEM768)
290  {
291  keyShareOffset = 0;
292  sharedSecretOffset = 0;
293  }
294  else
295  {
296  keyShareOffset = n;
297  sharedSecretOffset = context->premasterSecretLen;
298  }
299 
300  //The server share is the ML-KEM's ciphertext returned from the
301  //Encapsulate step represented as an octet string
302  error = kemEncapsulate(&context->kemContext, context->prngAlgo,
303  context->prngContext, keyShareEntry->keyExchange + keyShareOffset,
304  context->premasterSecret + sharedSecretOffset);
305  //Any error to report?
306  if(error)
307  return error;
308 
309  //The server's share is a fixed-size concatenation of ECDHE share and
310  //Kyber's ciphertext returned from encapsulation
311  n += kemAlgo->ciphertextSize;
312 
313  //Finally, the shared secret is a concatenation of the ECDHE and the
314  //Kyber shared secrets
315  context->premasterSecretLen += kemAlgo->sharedSecretSize;
316  }
317  else
318 #endif
319  //Unknown key exchange method?
320  {
321  //Report an error
322  return ERROR_FAILURE;
323  }
324 
325  //Set the length of the key_exchange field
326  keyShareEntry->length = htons(n);
327 
328  //Compute the length, in bytes, of the KeyShareEntry
329  n += sizeof(Tls13KeyShareEntry);
330  //Fix the length of the extension
331  extension->length = htons(n);
332 
333  //Compute the length, in bytes, of the KeyShare extension
334  n += sizeof(TlsExtension);
335  }
336 #endif
337 
338  //Total number of bytes that have been written
339  *written = n;
340 
341  //Successful processing
342  return NO_ERROR;
343 }
344 
345 
346 /**
347  * @brief Format PreSharedKey extension
348  * @param[in] context Pointer to the TLS context
349  * @param[in] p Output stream where to write the PreSharedKey extension
350  * @param[out] written Total number of bytes that have been written
351  * @return Error code
352  **/
353 
355  uint8_t *p, size_t *written)
356 {
357  size_t n = 0;
358 
359 #if (TLS13_PSK_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
360  TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
361  //PSK key exchange method?
362  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK ||
363  context->keyExchMethod == TLS13_KEY_EXCH_PSK_DHE ||
364  context->keyExchMethod == TLS13_KEY_EXCH_PSK_ECDHE ||
365  context->keyExchMethod == TLS13_KEY_EXCH_PSK_HYBRID)
366  {
367  TlsExtension *extension;
368 
369  //Add the PreSharedKey extension
370  extension = (TlsExtension *) p;
371  //Type of the extension
372  extension->type = HTONS(TLS_EXT_PRE_SHARED_KEY);
373 
374  //The extension contains the selected identity
375  STORE16BE(context->selectedIdentity, extension->value);
376 
377  //The extension data field contains a 16-bit unsigned integer
378  n = sizeof(uint16_t);
379  //Fix the length of the extension
380  extension->length = htons(n);
381 
382  //Compute the length, in bytes, of the PreSharedKey extension
383  n += sizeof(TlsExtension);
384  }
385 #endif
386 
387  //Total number of bytes that have been written
388  *written = n;
389 
390  //Successful processing
391  return NO_ERROR;
392 }
393 
394 
395 /**
396  * @brief Format EarlyData extension
397  * @param[in] context Pointer to the TLS context
398  * @param[in] msgType Handshake message type
399  * @param[in] p Output stream where to write the EarlyData extension
400  * @param[out] written Total number of bytes that have been written
401  * @return Error code
402  **/
403 
405  TlsMessageType msgType, uint8_t *p, size_t *written)
406 {
407  size_t n = 0;
408 
409 #if (TLS13_EARLY_DATA_SUPPORT == ENABLED)
410  //The extension may appear in EncryptedExtensions and NewSessionTicket
411  //messages
413  {
414  //If the server intends to process the early data, then it returns its
415  //own EarlyData extension in EncryptedExtensions
416  if(context->earlyDataExtReceived && !context->earlyDataRejected)
417  {
418  TlsExtension *extension;
419 
420  //Add the EarlyData extension
421  extension = (TlsExtension *) p;
422  //Type of the extension
423  extension->type = HTONS(TLS_EXT_EARLY_DATA);
424 
425  //The extension data field of this extension is empty
426  extension->length = HTONS(0);
427 
428  //Compute the length, in bytes, of the EarlyData extension
429  n = sizeof(TlsExtension);
430  }
431  }
433  {
434  TlsExtension *extension;
435 
436  //Add the EarlyData extension
437  extension = (TlsExtension *) p;
438  //Type of the extension
439  extension->type = HTONS(TLS_EXT_EARLY_DATA);
440 
441  //The extension contains the maximum amount of 0-RTT data that the
442  //client is allowed to send when using this ticket, in bytes
443  STORE32BE(context->maxEarlyDataSize, extension->value);
444 
445  //The extension data field contains a 32-bit unsigned integer
446  n = sizeof(uint32_t);
447  //Fix the length of the extension
448  extension->length = htons(n);
449 
450  //Compute the length, in bytes, of the EarlyData extension
451  n += sizeof(TlsExtension);
452  }
453  else
454  {
455  //Just for sanity
456  }
457 #endif
458 
459  //Total number of bytes that have been written
460  *written = n;
461 
462  //Successful processing
463  return NO_ERROR;
464 }
465 
466 
467 /**
468  * @brief Parse KeyShare extension
469  * @param[in] context Pointer to the TLS context
470  * @param[in] keyShareList Pointer to the KeyShare extension
471  * @param[in] groupList Pointer to the SupportedGroups extension
472  * @return Error code
473  **/
474 
476  const Tls13KeyShareList *keyShareList,
477  const TlsSupportedGroupList *groupList)
478 {
479 #if (TLS13_DHE_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
480  TLS13_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || \
481  TLS13_MLKEM_KE_SUPPORT == ENABLED || TLS13_PSK_MLKEM_KE_SUPPORT == ENABLED || \
482  TLS13_HYBRID_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
483  //KeyShare extension found?
484  if(keyShareList != NULL)
485  {
486  error_t error;
487  bool_t acceptable;
488  uint16_t namedGroup;
489  size_t n;
490  size_t length;
491  const uint8_t *p;
492  const Tls13KeyShareEntry *keyShareEntry;
493 
494  //Initialize variables
495  acceptable = FALSE;
496  keyShareEntry = NULL;
497 
498  //Point to the first KeyShareEntry of the list
499  p = keyShareList->value;
500  //Retrieve the length of the list
501  length = ntohs(keyShareList->length);
502 
503  //The extension contains a list of KeyShareEntry values offered by the
504  //client. The values are indicated in descending order of preference
505  while(length > 0 && !acceptable)
506  {
507  //Malformed extension?
508  if(length < sizeof(Tls13KeyShareEntry))
509  return ERROR_DECODING_FAILED;
510 
511  //Point to the current key share entry
512  keyShareEntry = (Tls13KeyShareEntry *) p;
513  //Retrieve the length of the key_exchange field
514  n = ntohs(keyShareEntry->length);
515 
516  //Malformed extension?
517  if(length < (sizeof(Tls13KeyShareEntry) + n))
518  return ERROR_DECODING_FAILED;
519 
520  //Each KeyShareEntry value must correspond to a group offered in the
521  //SupportedGroups extension (refer to RFC 8446, section 4.2.8)
522  if(!tls13IsGroupOffered(ntohs(keyShareEntry->group), groupList))
524 
525  //Initial or updated ClientHello?
526  if(context->state == TLS_STATE_CLIENT_HELLO)
527  {
528  //Check whether the ECDHE or FFDHE group is supported
529  acceptable = tls13IsGroupSupported(context,
530  ntohs(keyShareEntry->group));
531  }
532  else
533  {
534  //If the server has sent a HelloRetryRequest, the client needs
535  //to restart the handshake with an appropriate group
536  if(ntohs(keyShareEntry->group) == context->namedGroup)
537  {
538  //Check whether the ECDHE or FFDHE group is supported
539  acceptable = tls13IsGroupSupported(context,
540  ntohs(keyShareEntry->group));
541  }
542  }
543 
544  //Point to the next entry
545  p += sizeof(Tls13KeyShareEntry) + n;
546  //Remaining bytes to process
547  length -= sizeof(Tls13KeyShareEntry) + n;
548  }
549 
550  //Acceptable ECDHE or FFDHE group found?
551  if(acceptable)
552  {
553  //Convert the named group to host byte order
554  namedGroup = ntohs(keyShareEntry->group);
555 
556  //Finite field group?
557  if(tls13IsFfdheGroupSupported(context, namedGroup))
558  {
559  //Generate an ephemeral key pair
560  error = tls13GenerateKeyShare(context, namedGroup);
561  //Any error to report?
562  if(error)
563  return error;
564 
565  //Compute DHE shared secret
566  error = tls13GenerateSharedSecret(context,
567  keyShareEntry->keyExchange, ntohs(keyShareEntry->length));
568  //Any error to report?
569  if(error)
570  return error;
571 
572  //DHE key exchange mechanism provides forward secrecy
573  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK)
574  {
575  context->keyExchMethod = TLS13_KEY_EXCH_PSK_DHE;
576  }
577  else
578  {
579  context->keyExchMethod = TLS13_KEY_EXCH_DHE;
580  }
581  }
582  //Elliptic curve group?
583  else if(tls13IsEcdheGroupSupported(context, namedGroup))
584  {
585  //Generate an ephemeral key pair
586  error = tls13GenerateKeyShare(context, namedGroup);
587  //Any error to report?
588  if(error)
589  return error;
590 
591  //Compute ECDHE shared secret
592  error = tls13GenerateSharedSecret(context,
593  keyShareEntry->keyExchange, ntohs(keyShareEntry->length));
594  //Any error to report?
595  if(error)
596  return error;
597 
598  //ECDHE key exchange mechanism provides forward secrecy
599  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK)
600  {
601  context->keyExchMethod = TLS13_KEY_EXCH_PSK_ECDHE;
602  }
603  else
604  {
605  context->keyExchMethod = TLS13_KEY_EXCH_ECDHE;
606  }
607  }
608  //ML-KEM key exchange method?
609  else if(tls13IsMlkemGroupSupported(context, namedGroup))
610  {
611  //Encapsulation algorithm
612  error = tls13Encapsulate(context, namedGroup,
613  keyShareEntry->keyExchange, ntohs(keyShareEntry->length));
614  //Any error to report?
615  if(error)
616  return error;
617 
618  //ML-KEM-512, ML-KEM-768, and ML-KEM-1024 can be used as a
619  //standalone algorithm to achieve post-quantum key agreement
620  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK)
621  {
622  context->keyExchMethod = TLS13_KEY_EXCH_PSK_MLKEM;
623  }
624  else
625  {
626  context->keyExchMethod = TLS13_KEY_EXCH_MLKEM;
627  }
628  }
629  //Hybrid key exchange method?
630  else if(tls13IsHybridGroupSupported(context, namedGroup))
631  {
632  //Encapsulation algorithm
633  error = tls13Encapsulate(context, namedGroup,
634  keyShareEntry->keyExchange, ntohs(keyShareEntry->length));
635  //Any error to report?
636  if(error)
637  return error;
638 
639  //Hybrid key exchange makes use of two key exchange algorithms
640  //based on different cryptographic assumptions
641  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK)
642  {
643  context->keyExchMethod = TLS13_KEY_EXCH_PSK_HYBRID;
644  }
645  else
646  {
647  context->keyExchMethod = TLS13_KEY_EXCH_HYBRID;
648  }
649  }
650  //Unknown group?
651  else
652  {
653  //Just for sanity
654  return ERROR_FAILURE;
655  }
656  }
657  else
658  {
659  //If no common cryptographic parameters can be negotiated, the server
660  //must abort the handshake with an appropriate alert
661  if(context->state == TLS_STATE_CLIENT_HELLO_2)
662  return ERROR_HANDSHAKE_FAILED;
663  }
664  }
665 #endif
666 
667  //Successful processing
668  return NO_ERROR;
669 }
670 
671 
672 /**
673  * @brief Parse PskKeyExchangeModes extension
674  * @param[in] context Pointer to the TLS context
675  * @param[in] pskKeModeList Pointer to the PskKeyExchangeModes extension
676  * @return Error code
677  **/
678 
680  const Tls13PskKeModeList *pskKeModeList)
681 {
682  error_t error;
683  uint_t i;
684 
685  //PskKeyExchangeModes extension found?
686  if(pskKeModeList != NULL)
687  {
688  //Check whether the client supports session resumption with a PSK
689  for(i = 0; i < pskKeModeList->length; i++)
690  {
691  //PSK key establishment supported?
692  if(pskKeModeList->value[i] == TLS_PSK_KEY_EXCH_MODE_PSK_KE ||
693  pskKeModeList->value[i] == TLS_PSK_KEY_EXCH_MODE_PSK_DHE_KE)
694  {
695  context->pskKeModeSupported = TRUE;
696  }
697  }
698  }
699 
700  //PSK key exchange method?
701  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK ||
702  context->keyExchMethod == TLS13_KEY_EXCH_PSK_DHE ||
703  context->keyExchMethod == TLS13_KEY_EXCH_PSK_ECDHE ||
704  context->keyExchMethod == TLS13_KEY_EXCH_PSK_HYBRID)
705  {
706  //PskKeyExchangeModes extension found?
707  if(pskKeModeList != NULL)
708  {
709  //Initialize status code
710  error = ERROR_HANDSHAKE_FAILED;
711 
712  //The extension contains a list of supported PSK key exchange modes
713  for(i = 0; i < pskKeModeList->length && error; i++)
714  {
715 #if (TLS13_PSK_KE_SUPPORT == ENABLED)
716  //PSK-only key establishment?
717  if(pskKeModeList->value[i] == TLS_PSK_KEY_EXCH_MODE_PSK_KE)
718  {
719  //Servers must not select a key exchange mode that is not listed
720  //by the client
721  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK)
722  {
723  error = NO_ERROR;
724  }
725  }
726  else
727 #endif
728 #if (TLS13_PSK_DHE_KE_SUPPORT == ENABLED || TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || \
729  TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
730  //PSK with (EC)DHE key establishment?
731  if(pskKeModeList->value[i] == TLS_PSK_KEY_EXCH_MODE_PSK_DHE_KE)
732  {
733  //Servers must not select a key exchange mode that is not listed
734  //by the client
735  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK_DHE ||
736  context->keyExchMethod == TLS13_KEY_EXCH_PSK_ECDHE ||
737  context->keyExchMethod == TLS13_KEY_EXCH_PSK_HYBRID)
738  {
739  error = NO_ERROR;
740  }
741  }
742  else
743 #endif
744  //Unknown key exchange method?
745  {
746  //Just for sanity
747  }
748  }
749  }
750  else
751  {
752  //A client must provide a PskKeyExchangeModes extension if it offers a
753  //PreSharedKey extension
754  error = ERROR_MISSING_EXTENSION;
755  }
756  }
757  else
758  {
759  //If no acceptable PSKs are found, the server should perform a non-PSK
760  //handshake if possible
761  error = NO_ERROR;
762  }
763 
764  //Return status code
765  return error;
766 }
767 
768 
769 /**
770  * @brief Parse PreSharedKey extension
771  * @param[in] context Pointer to the TLS context
772  * @param[in] clientHello Pointer to the ClientHello message
773  * @param[in] clientHelloLen Length of the ClientHello message
774  * @param[in] identityList List of the identities that the client is willing
775  * to negotiate with the server
776  * @param[in] binderList List of HMAC values, one for each PSK offered in the
777  * PreSharedKey extension
778  * @return Error code
779  **/
780 
782  const TlsClientHello *clientHello, size_t clientHelloLen,
783  const Tls13PskIdentityList *identityList, const Tls13PskBinderList *binderList)
784 {
785  #if (TLS13_PSK_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
786  TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
787  //PreSharedKey extension found?
788  if(identityList != NULL && binderList != NULL)
789  {
790  error_t error;
791  int_t i;
792  size_t n;
793  size_t m;
794  uint32_t obfuscatedTicketAge;
795  const uint8_t *p;
796  const uint8_t *q;
797  const Tls13PskIdentity *identity;
798  const Tls13PskBinder *binder;
799  const HashAlgo *hashAlgo;
800 
801  //Initialize variables
802  identity = NULL;
803  binder = NULL;
804 
805  //Reset the server's chosen identity to its default value
806  context->selectedIdentity = -1;
807 
808  //Debug message
809  TRACE_DEBUG("PSK identity list:\r\n");
810  TRACE_DEBUG_ARRAY(" ", identityList, ntohs(identityList->length) + 2);
811  TRACE_DEBUG("PSK binder list:\r\n");
812  TRACE_DEBUG_ARRAY(" ", binderList, ntohs(binderList->length) + 2);
813 
814  //Point to the list of the identities that the client is willing to
815  //negotiate with the server
816  p = identityList->value;
817  n = ntohs(identityList->length);
818 
819  //Point to the list of HMAC values, one for each PSK offered in the
820  //PreSharedKey extension
821  q = binderList->value;
822  m = ntohs(binderList->length);
823 
824  //Loop through the list of PSK identities
825  for(i = 0; n > 0; i++)
826  {
827  //Point to the current PskIdentity entry
828  identity = (Tls13PskIdentity *) p;
829 
830  //Malformed PreSharedKey extension?
831  if(n < sizeof(TlsPskIdentity))
832  return ERROR_DECODING_FAILED;
833  if(n < (sizeof(TlsPskIdentity) + ntohs(identity->length)))
834  return ERROR_DECODING_FAILED;
835 
836  //Debug message
837  TRACE_DEBUG("PSK identity #%u:\r\n", i);
838  TRACE_DEBUG_ARRAY(" ", identity->value, ntohs(identity->length));
839 
840  //Point to the obfuscated_ticket_age field
841  p += sizeof(TlsPskIdentity) + ntohs(identity->length);
842  n -= sizeof(TlsPskIdentity) + ntohs(identity->length);
843 
844  //Malformed PreSharedKey extension?
845  if(n < sizeof(uint32_t))
846  return ERROR_DECODING_FAILED;
847 
848  //The obfuscated_ticket_age field is a 32-bit unsigned integer
849  obfuscatedTicketAge = LOAD32BE(p);
850 
851  //Point to the next PskIdentity entry
852  p += sizeof(uint32_t);
853  n -= sizeof(uint32_t);
854 
855  //Point to the PskBinderEntry
856  binder = (Tls13PskBinder *) q;
857 
858  //If the binder is not present, the server must abort the handshake
859  if(context->selectedIdentity >= 0 && m == 0)
861 
862  //Malformed PreSharedKey extension?
863  if(m < sizeof(Tls13PskBinder))
864  return ERROR_DECODING_FAILED;
865  if(m < (sizeof(Tls13PskBinder) + binder->length))
866  return ERROR_DECODING_FAILED;
867 
868  //Debug message
869  TRACE_DEBUG("PSK binder #%u:\r\n", i);
870  TRACE_DEBUG_ARRAY(" ", binder->value, binder->length);
871 
872  //Point to the next PskBinderEntry
873  q += sizeof(Tls13PskBinder) + binder->length;
874  m -= sizeof(Tls13PskBinder) + binder->length;
875 
876  //The server should select a single PSK
877  if(context->selectedIdentity < 0)
878  {
879  //Any registered callback?
880  if(context->pskCallback != NULL)
881  {
882  //Check whether the PSK identity provided by the client matches
883  //any externally established PSK
884  error = context->pskCallback(context, identity->value,
885  ntohs(identity->length));
886 
887  //Valid PSK?
888  if(!error && tls13IsPskValid(context))
889  {
890  //For externally established PSKs, the hash algorithm must be
891  //set when the PSK is established
892  hashAlgo = tlsGetHashAlgo(context->pskHashAlgo);
893 
894  //Make sure the hash algorithm is valid
895  if(hashAlgo != NULL)
896  {
897  //Save the hash algorithm associated with the PSK
898  context->cipherSuite.prfHashAlgo = hashAlgo;
899 
900  //The server's chosen identity is expressed as a 0-based
901  //index into the identities in the client's list
902  context->selectedIdentity = i;
903  }
904  }
905  }
906  }
907 
908  //The server should select a single PSK
909  if(context->selectedIdentity < 0)
910  {
911  //Decrypt the received ticket and verify the ticket's validity
912  error = tls13VerifyTicket(context, identity->value,
913  htons(identity->length), obfuscatedTicketAge);
914 
915  //Valid ticket?
916  if(!error)
917  {
918  //The server's chosen identity is expressed as a 0-based index
919  //into the identities in the client's list
920  context->selectedIdentity = i;
921  }
922  }
923  }
924 
925  //Extra binders found?
926  if(m != 0)
927  {
929  }
930  }
931  else
932 #endif
933  {
934  //Initial or updated ClientHello?
935  if(context->state == TLS_STATE_CLIENT_HELLO_2)
936  {
937  //When responding to a HelloRetryRequest, the client must send the
938  //same ClientHello without modification
939  if(context->selectedIdentity >= 0)
940  {
942  }
943  }
944 
945  //The ClientHello message does not contain any PreSharedKey extension
946  context->selectedIdentity = -1;
947  }
948 
949  //Successful processing
950  return NO_ERROR;
951 }
952 
953 
954 /**
955  * @brief Parse EarlyData extension
956  * @param[in] context Pointer to the TLS context
957  * @param[in] earlyDataIndication Pointer to the EarlyData extension
958  * @return Error code
959  **/
960 
962  const TlsExtension *earlyDataIndication)
963 {
964  //EarlyData extension found?
965  if(earlyDataIndication != NULL)
966  {
967  //Early data is not permitted after a HelloRetryRequest (refer to
968  //RFC 8446, section 4.1.2)
969  if(context->state == TLS_STATE_CLIENT_HELLO_2)
970  {
971  context->earlyDataRejected = TRUE;
972  }
973 
974  //In order to accept early data, the server must have accepted a PSK
975  //cipher suite and selected the first key offered in the client's
976  //PreSharedKey extension (refer to RFC 8446, section 4.2.10)
977  if(context->selectedIdentity != 0)
978  {
979  context->earlyDataRejected = TRUE;
980  }
981 
982  //A valid EarlyData extension has been received
983  context->earlyDataExtReceived = TRUE;
984  }
985  else
986  {
987  //The ClientHello message does not contain any EarlyData extension
988  context->earlyDataExtReceived = FALSE;
989  }
990 
991  //Successful processing
992  return NO_ERROR;
993 }
994 
995 #endif
@ TLS_GROUP_X25519_MLKEM768
Definition: tls.h:1473
@ TLS13_KEY_EXCH_PSK
Definition: tls.h:1193
#define htons(value)
Definition: cpu_endian.h:413
TLS helper functions.
Tls13PskBinderList
Definition: tls13_misc.h:275
int bool_t
Definition: compiler_port.h:61
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:1186
@ TLS13_KEY_EXCH_MLKEM
Definition: tls.h:1191
@ TLS13_KEY_EXCH_PSK_DHE
Definition: tls.h:1194
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:1373
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:986
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_HANDSHAKE_FAILED
Definition: error.h:234
@ TLS13_KEY_EXCH_ECDHE
Definition: tls.h:1190
@ 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:1629
@ TLS_EXT_EARLY_DATA
Definition: tls.h:1372
@ TLS13_KEY_EXCH_PSK_HYBRID
Definition: tls.h:1197
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:1512
@ 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:953
size_t sharedSecretSize
Definition: crypto.h:1135
@ TLS_GROUP_NONE
Definition: tls.h:1421
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:1034
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
@ TLS13_KEY_EXCH_DHE
Definition: tls.h:1189
#define STORE16BE(a, p)
Definition: cpu_endian.h:262
@ TLS_EXT_KEY_SHARE
Definition: tls.h:1380
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:1077
bool_t tls13IsFfdheGroupSupported(TlsContext *context, uint16_t namedGroup)
Check whether a given FFDHE group is supported.
Definition: tls13_misc.c:994
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:1133
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:112
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:1195
@ TLS_STATE_CLIENT_HELLO_2
Definition: tls.h:1513
#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: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 tls13ParseClientKeyShareExtension(TlsContext *context, const Tls13KeyShareList *keyShareList, const TlsSupportedGroupList *groupList)
Parse KeyShare extension.
@ TLS13_KEY_EXCH_HYBRID
Definition: tls.h:1192
TlsClientHello
Definition: tls.h:1830
Common interface for key encapsulation mechanisms (KEM)
Definition: crypto.h:1130
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:1134
@ TLS_EXT_PRE_SHARED_KEY
Definition: tls.h:1371
@ MPI_FORMAT_BIG_ENDIAN
Definition: mpi.h:93
TLS (Transport Layer Security)
Common interface for hash algorithms.
Definition: crypto.h:1089
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:514
@ TLS_TYPE_NEW_SESSION_TICKET
Definition: tls.h:1074
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:1707
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.