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