tls13_key_material.c
Go to the documentation of this file.
1 /**
2  * @file tls13_key_material.c
3  * @brief TLS 1.3 key schedule
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_key_material.h"
37 #include "tls_transcript_hash.h"
38 #include "tls_misc.h"
39 #include "tls13_key_material.h"
40 #include "tls13_ticket.h"
41 #include "kdf/hkdf.h"
42 #include "debug.h"
43 
44 //Check TLS library configuration
45 #if (TLS_SUPPORT == ENABLED && TLS_MAX_VERSION >= TLS_VERSION_1_3)
46 
47 
48 /**
49  * @brief HKDF-Expand-Label function
50  * @param[in] transportProtocol Transport protocol (TLS or DTLS)
51  * @param[in] hash Hash function used by HKDF
52  * @param[in] secret Pointer to the secret
53  * @param[in] secretLen Length of the secret
54  * @param[in] label Identifying label (NULL-terminated string)
55  * @param[in] context Pointer to the upper-layer context
56  * @param[in] contextLen Length of the upper-layer context
57  * @param[out] output Pointer to the output
58  * @param[in] outputLen Desired output length
59  * @return Error code
60  **/
61 
63  const HashAlgo *hash, const uint8_t *secret, size_t secretLen,
64  const char_t *label, const uint8_t *context, size_t contextLen,
65  uint8_t *output, size_t outputLen)
66 {
67  error_t error;
68  size_t n;
69  size_t labelLen;
70  uint8_t *hkdfLabel;
71  const char_t *prefix;
72 
73  //Check parameters
74  if(label == NULL)
76  if(context == NULL && contextLen != 0)
78 
79  //Retrieve the length of the label
80  labelLen = osStrlen(label);
81 
82  //Check parameters
83  if(labelLen > (255 - 6) || contextLen > 255)
84  return ERROR_INVALID_LENGTH;
85 
86  //Compute the length of the HkdfLabel structure
87  n = labelLen + contextLen + 10;
88  //Allocate a memory buffer to hold the HkdfLabel structure
89  hkdfLabel = tlsAllocMem(n);
90 
91  //Successful memory allocation?
92  if(hkdfLabel != NULL)
93  {
94 #if (DTLS_SUPPORT == ENABLED)
95  //DTLS protocol?
96  if(transportProtocol == TLS_TRANSPORT_PROTOCOL_DATAGRAM)
97  {
98  //For DTLS 1.3, the label prefix shall be "dtls13". This ensures key
99  //separation between DTLS 1.3 and TLS 1.3. Note that there is no
100  //trailing space (refer to RFC 9147, section 5.9)
101  prefix = "dtls13";
102  }
103  else
104 #endif
105  //TLS protocol?
106  {
107  //For TLS 1.3, the label prefix shall be "tls13 " (refer to RFC 8446,
108  //section 7.1)
109  prefix = "tls13 ";
110  }
111 
112  //Format the HkdfLabel structure
113  hkdfLabel[0] = MSB(outputLen);
114  hkdfLabel[1] = LSB(outputLen);
115  hkdfLabel[2] = (uint8_t) (labelLen + 6);
116  osMemcpy(hkdfLabel + 3, prefix, 6);
117  osMemcpy(hkdfLabel + 9, label, labelLen);
118  hkdfLabel[labelLen + 9] = (uint8_t) contextLen;
119  osMemcpy(hkdfLabel + labelLen + 10, context, contextLen);
120 
121  //Debug message
122  TRACE_DEBUG("HkdfLabel (%" PRIuSIZE " bytes):\r\n", n);
123  TRACE_DEBUG_ARRAY(" ", hkdfLabel, n);
124 
125  //Compute HKDF-Expand(Secret, HkdfLabel, Length)
126  error = hkdfExpand(hash, secret, secretLen, hkdfLabel, n, output,
127  outputLen);
128 
129  //Release previously allocated memory
130  tlsFreeMem(hkdfLabel);
131  }
132  else
133  {
134  //Failed to allocate memory
135  error = ERROR_OUT_OF_MEMORY;
136  }
137 
138  //Return status code
139  return error;
140 }
141 
142 
143 /**
144  * @brief Derive-Secret function
145  * @param[in] context Pointer to the TLS context
146  * @param[in] secret Pointer to the secret
147  * @param[in] secretLen Length of the secret
148  * @param[in] label Identifying label (NULL-terminated string)
149  * @param[in] message Concatenation of the indicated handshake messages
150  * @param[in] messageLen Length of the indicated handshake messages
151  * @param[out] output Pointer to the output
152  * @param[in] outputLen Desired output length
153  * @return Error code
154  **/
155 
156 error_t tls13DeriveSecret(TlsContext *context, const uint8_t *secret,
157  size_t secretLen, const char_t *label, const char_t *message,
158  size_t messageLen, uint8_t *output, size_t outputLen)
159 {
160  error_t error;
161  const HashAlgo *hash;
162  uint8_t digest[TLS_MAX_HKDF_DIGEST_SIZE];
163 
164  //The hash function used by HKDF is the cipher suite hash algorithm
165  hash = context->cipherSuite.prfHashAlgo;
166 
167  //Make sure the hash algorithm is valid
168  if(hash != NULL)
169  {
170  //Any handshake messages specified?
171  if(message != NULL)
172  {
173  //Compute Transcript-Hash(Messages);
174  error = hash->compute(message, messageLen, digest);
175  }
176  else
177  {
178  //Implementations can implement the transcript by keeping a running
179  //transcript hash value based on the negotiated hash
180  error = tlsFinalizeTranscriptHash(context, hash,
181  context->transcriptHashContext, "", digest);
182  }
183 
184  //Debug message
185  TRACE_DEBUG("Transcript hash (%" PRIuSIZE " bytes):\r\n", hash->digestSize);
186  TRACE_DEBUG_ARRAY(" ", digest, hash->digestSize);
187 
188  //Check status code
189  if(!error)
190  {
191  //Compute HKDF-Expand-Label(Secret, Label, Transcript-Hash, Hash.length)
192  error = tls13HkdfExpandLabel(context->transportProtocol, hash, secret,
193  secretLen, label, digest, hash->digestSize, output, outputLen);
194  }
195  }
196  else
197  {
198  //Invalid HKDF hash algorithm
199  error = ERROR_FAILURE;
200  }
201 
202  //Return status code
203  return error;
204 }
205 
206 
207 /**
208  * @brief Compute early traffic keys
209  * @param[in] context Pointer to the TLS context
210  * @return Error code
211  **/
212 
214 {
215  error_t error;
216  size_t ikmLen;
217  const uint8_t *ikm;
218  const HashAlgo *hash;
219 
220  //The hash function used by HKDF is the cipher suite hash algorithm
221  hash = context->cipherSuite.prfHashAlgo;
222  //Make sure the hash algorithm is valid
223  if(hash == NULL)
224  return ERROR_FAILURE;
225 
226  //Although PSKs can be established out of band, PSKs can also be established
227  //in a previous connection
228  if(tls13IsPskValid(context))
229  {
230  //IKM is a pre-shared key established externally
231  ikm = context->psk;
232  ikmLen = context->pskLen;
233  }
234  else if(tls13IsTicketValid(context))
235  {
236  //IKM is a pre-shared key derived from the resumption master secret from
237  //a previous connection
238  ikm = context->ticketPsk;
239  ikmLen = context->ticketPskLen;
240  }
241  else
242  {
243  //The pre-shared key is not valid
244  return ERROR_FAILURE;
245  }
246 
247  //Calculate early secret
248  error = hkdfExtract(hash, ikm, ikmLen, NULL, 0, context->secret);
249  //Any error to report?
250  if(error)
251  return error;
252 
253  //Debug message
254  TRACE_DEBUG("Early secret:\r\n");
255  TRACE_DEBUG_ARRAY(" ", context->secret, hash->digestSize);
256 
257  //Calculate client early traffic secret
258  error = tls13DeriveSecret(context, context->secret, hash->digestSize,
259  "c e traffic", NULL, 0, context->clientEarlyTrafficSecret,
260  hash->digestSize);
261  //Any error to report?
262  if(error)
263  return error;
264 
265  //Debug message
266  TRACE_DEBUG("Client early secret:\r\n");
267  TRACE_DEBUG_ARRAY(" ", context->clientEarlyTrafficSecret, hash->digestSize);
268 
269  //The traffic keying material is generated from the traffic secret value
270  if(context->entity == TLS_CONNECTION_END_CLIENT)
271  {
272  //Calculate client early traffic keys
273  error = tlsInitEncryptionEngine(context, &context->encryptionEngine,
274  TLS_CONNECTION_END_CLIENT, context->clientEarlyTrafficSecret);
275  }
276  else
277  {
278  //The implementation must verify that its receive buffer is empty
279  if(context->rxBufferLen == 0)
280  {
281  //Calculate client early traffic keys
282  error = tlsInitEncryptionEngine(context, &context->decryptionEngine,
283  TLS_CONNECTION_END_CLIENT, context->clientEarlyTrafficSecret);
284  }
285  else
286  {
287  //The receive buffer is not empty
288  error = ERROR_UNEXPECTED_MESSAGE;
289  }
290  }
291 
292  //Failed to generate traffic keying material?
293  if(error)
294  return error;
295 
296  //Calculate early exporter master secret
297  error = tls13DeriveSecret(context, context->secret, hash->digestSize,
298  "e exp master", NULL, 0, context->exporterMasterSecret, hash->digestSize);
299  //Any error to report?
300  if(error)
301  return error;
302 
303  //Debug message
304  TRACE_DEBUG("Early exporter master secret:\r\n");
305  TRACE_DEBUG_ARRAY(" ", context->exporterMasterSecret, hash->digestSize);
306 
307 #if (TLS_KEY_LOG_SUPPORT == ENABLED)
308  //Log client early traffic secret
309  tlsDumpSecret(context, "CLIENT_EARLY_TRAFFIC_SECRET",
310  context->clientEarlyTrafficSecret, hash->digestSize);
311 
312  //Log early exporter master secret
313  tlsDumpSecret(context, "EARLY_EXPORTER_SECRET",
314  context->exporterMasterSecret, hash->digestSize);
315 #endif
316 
317  //When a PSK is used and early data is allowed for that PSK, the client can
318  //send application data in its first flight of messages
320 
321  //Successful processing
322  return NO_ERROR;
323 }
324 
325 
326 /**
327  * @brief Compute handshake traffic keys
328  * @param[in] context Pointer to the TLS context
329  * @return Error code
330  **/
331 
333 {
334  error_t error;
335  size_t ikmLen;
336  const uint8_t *ikm;
337  const HashAlgo *hash;
338 
339  //The hash function used by HKDF is the cipher suite hash algorithm
340  hash = context->cipherSuite.prfHashAlgo;
341  //Make sure the hash algorithm is valid
342  if(hash == NULL)
343  return ERROR_FAILURE;
344 
345 #if (TLS13_DHE_KE_SUPPORT == ENABLED || TLS13_ECDHE_KE_SUPPORT == ENABLED || \
346  TLS13_MLKEM_KE_SUPPORT == ENABLED || TLS13_HYBRID_KE_SUPPORT == ENABLED)
347  //(EC)DHE key exchange method?
348  if(context->keyExchMethod == TLS13_KEY_EXCH_DHE ||
349  context->keyExchMethod == TLS13_KEY_EXCH_ECDHE ||
350  context->keyExchMethod == TLS13_KEY_EXCH_MLKEM ||
351  context->keyExchMethod == TLS13_KEY_EXCH_HYBRID)
352  {
353  //If PSK is not in use, IKM is a string of Hash-lengths bytes set to 0
354  osMemset(context->secret, 0, hash->digestSize);
355 
356  //Point to the IKM argument
357  ikm = context->secret;
358  ikmLen = hash->digestSize;
359  }
360  else
361 #endif
362 #if (TLS13_PSK_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
363  TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_MLKEM_KE_SUPPORT == ENABLED || \
364  TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
365  //PSK-only or PSK with (EC)DHE key exchange method?
366  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK ||
367  context->keyExchMethod == TLS13_KEY_EXCH_PSK_DHE ||
368  context->keyExchMethod == TLS13_KEY_EXCH_PSK_ECDHE ||
369  context->keyExchMethod == TLS13_KEY_EXCH_PSK_MLKEM ||
370  context->keyExchMethod == TLS13_KEY_EXCH_PSK_HYBRID)
371  {
372  //Although PSKs can be established out of band, PSKs can also be
373  //established in a previous connection
374  if(tls13IsPskValid(context))
375  {
376  //IKM is a pre-shared key established externally
377  ikm = context->psk;
378  ikmLen = context->pskLen;
379  }
380  else if(tls13IsTicketValid(context))
381  {
382  //IKM is a pre-shared key derived from the resumption master secret
383  //from a previous connection
384  ikm = context->ticketPsk;
385  ikmLen = context->ticketPskLen;
386  }
387  else
388  {
389  //The pre-shared key is not valid
390  return ERROR_FAILURE;
391  }
392  }
393  else
394 #endif
395  //Invalid key exchange method?
396  {
397  //Report an error
398  return ERROR_FAILURE;
399  }
400 
401  //Calculate early secret
402  error = hkdfExtract(hash, ikm, ikmLen, NULL, 0, context->secret);
403  //Any error to report?
404  if(error)
405  return error;
406 
407  //Debug message
408  TRACE_DEBUG("Early secret:\r\n");
409  TRACE_DEBUG_ARRAY(" ", context->secret, hash->digestSize);
410 
411  //Derive early secret
412  error = tls13DeriveSecret(context, context->secret, hash->digestSize,
413  "derived", "", 0, context->secret, hash->digestSize);
414  //Any error to report?
415  if(error)
416  return error;
417 
418  //Debug message
419  TRACE_DEBUG("Derived secret:\r\n");
420  TRACE_DEBUG_ARRAY(" ", context->secret, hash->digestSize);
421 
422  //PSK-only key exchange method?
423  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK)
424  {
425  //If the (EC)DHE shared secret is not available, then the 0-value
426  //consisting of a string of Hash.length bytes set to zeros is used
427  osMemset(context->premasterSecret, 0, hash->digestSize);
428  context->premasterSecretLen = hash->digestSize;
429  }
430 
431  //Calculate handshake secret
432  error = hkdfExtract(hash, context->premasterSecret,
433  context->premasterSecretLen, context->secret, hash->digestSize,
434  context->secret);
435  //Any error to report?
436  if(error)
437  return error;
438 
439  //Debug message
440  TRACE_DEBUG("Handshake secret:\r\n");
441  TRACE_DEBUG_ARRAY(" ", context->secret, hash->digestSize);
442 
443  //Calculate client handshake traffic secret
444  error = tls13DeriveSecret(context, context->secret, hash->digestSize,
445  "c hs traffic", NULL, 0, context->clientHsTrafficSecret,
446  hash->digestSize);
447  //Any error to report?
448  if(error)
449  return error;
450 
451  //Debug message
452  TRACE_DEBUG("Client handshake secret:\r\n");
453  TRACE_DEBUG_ARRAY(" ", context->clientHsTrafficSecret, hash->digestSize);
454 
455  //Calculate server handshake traffic secret
456  error = tls13DeriveSecret(context, context->secret, hash->digestSize,
457  "s hs traffic", NULL, 0, context->serverHsTrafficSecret,
458  hash->digestSize);
459  //Any error to report?
460  if(error)
461  return error;
462 
463  //Debug message
464  TRACE_DEBUG("Server handshake secret:\r\n");
465  TRACE_DEBUG_ARRAY(" ", context->serverHsTrafficSecret, hash->digestSize);
466 
467  //The implementation must verify that its receive buffer is empty before
468  //switching to encrypted handshake
469  if(context->rxBufferLen != 0)
470  return ERROR_HANDSHAKE_FAILED;
471 
472  //The traffic keying material is generated from the traffic secret value
473  if(context->entity == TLS_CONNECTION_END_CLIENT)
474  {
475  //Release encryption engine
476  tlsFreeEncryptionEngine(&context->encryptionEngine);
477 
478  //Calculate client handshake traffic keys
479  error = tlsInitEncryptionEngine(context, &context->encryptionEngine,
480  TLS_CONNECTION_END_CLIENT, context->clientHsTrafficSecret);
481 
482  //Check status code
483  if(!error)
484  {
485  //Calculate server handshake traffic keys
486  error = tlsInitEncryptionEngine(context, &context->decryptionEngine,
487  TLS_CONNECTION_END_SERVER, context->serverHsTrafficSecret);
488  }
489  }
490  else
491  {
492  //Release decryption engine
493  tlsFreeEncryptionEngine(&context->decryptionEngine);
494 
495  //Calculate client handshake traffic keys
496  error = tlsInitEncryptionEngine(context, &context->decryptionEngine,
497  TLS_CONNECTION_END_CLIENT, context->clientHsTrafficSecret);
498 
499  //Check status code
500  if(!error)
501  {
502  //Calculate server handshake traffic keys
503  error = tlsInitEncryptionEngine(context, &context->encryptionEngine,
504  TLS_CONNECTION_END_SERVER, context->serverHsTrafficSecret);
505  }
506  }
507 
508  //Failed to generate traffic keying material?
509  if(error)
510  return error;
511 
512 #if (TLS_KEY_LOG_SUPPORT == ENABLED)
513  //Log client handshake traffic secret
514  tlsDumpSecret(context, "CLIENT_HANDSHAKE_TRAFFIC_SECRET",
515  context->clientHsTrafficSecret, hash->digestSize);
516 
517  //Log server handshake traffic secret
518  tlsDumpSecret(context, "SERVER_HANDSHAKE_TRAFFIC_SECRET",
519  context->serverHsTrafficSecret, hash->digestSize);
520 #endif
521 
522 #if (DTLS_SUPPORT == ENABLED)
523  //DTLS protocol?
524  if(context->transportProtocol == TLS_TRANSPORT_PROTOCOL_DATAGRAM)
525  {
526  //Because each epoch resets the sequence number space, a separate sliding
527  //window is needed for each epoch (refer to RFC 9147, section 4.5.1)
528  dtlsInitReplayWindow(context);
529  }
530 #endif
531 
532  //In all handshakes, the server must send the EncryptedExtensions message
533  //immediately after the ServerHello message
535 
536  //Successful processing
537  return NO_ERROR;
538 }
539 
540 
541 /**
542  * @brief Compute server application traffic keys
543  * @param[in] context Pointer to the TLS context
544  * @return Error code
545  **/
546 
548 {
549  error_t error;
550  const HashAlgo *hash;
551  uint8_t ikm[TLS_MAX_HKDF_DIGEST_SIZE];
552 
553  //The hash function used by HKDF is the cipher suite hash algorithm
554  hash = context->cipherSuite.prfHashAlgo;
555  //Make sure the hash algorithm is valid
556  if(hash == NULL)
557  return ERROR_FAILURE;
558 
559  //Derive handshake secret
560  error = tls13DeriveSecret(context, context->secret, hash->digestSize,
561  "derived", "", 0, context->secret, hash->digestSize);
562  //Any error to report?
563  if(error)
564  return error;
565 
566  //Debug message
567  TRACE_DEBUG("Derived secret:\r\n");
568  TRACE_DEBUG_ARRAY(" ", context->secret, hash->digestSize);
569 
570  //IKM is a string of Hash-lengths bytes set to 0
571  osMemset(ikm, 0, hash->digestSize);
572 
573  //Calculate master secret
574  error = hkdfExtract(hash, ikm, hash->digestSize, context->secret,
575  hash->digestSize, context->secret);
576  //Any error to report?
577  if(error)
578  return error;
579 
580  //Debug message
581  TRACE_DEBUG("Master secret:\r\n");
582  TRACE_DEBUG_ARRAY(" ", context->secret, hash->digestSize);
583 
584  //Calculate client application traffic secret
585  error = tls13DeriveSecret(context, context->secret, hash->digestSize,
586  "c ap traffic", NULL, 0, context->clientAppTrafficSecret,
587  hash->digestSize);
588  //Any error to report?
589  if(error)
590  return error;
591 
592  //Debug message
593  TRACE_DEBUG("Client application secret:\r\n");
594  TRACE_DEBUG_ARRAY(" ", context->clientAppTrafficSecret, hash->digestSize);
595 
596  //Calculate server application traffic secret
597  error = tls13DeriveSecret(context, context->secret, hash->digestSize,
598  "s ap traffic", NULL, 0, context->serverAppTrafficSecret,
599  hash->digestSize);
600  //Any error to report?
601  if(error)
602  return error;
603 
604  //Debug message
605  TRACE_DEBUG("Server application secret:\r\n");
606  TRACE_DEBUG_ARRAY(" ", context->serverAppTrafficSecret, hash->digestSize);
607 
608  //All the traffic keying material is recomputed when changing from the
609  //handshake to application data keys
610  if(context->entity == TLS_CONNECTION_END_CLIENT)
611  {
612  //The implementation must verify that its receive buffer is empty before
613  //rekeying
614  if(context->rxBufferLen == 0)
615  {
616  //Release decryption engine
617  tlsFreeEncryptionEngine(&context->decryptionEngine);
618 
619  //Inform the record layer that subsequent records will be protected
620  //under the new traffic keys
621  error = tlsInitEncryptionEngine(context, &context->decryptionEngine,
622  TLS_CONNECTION_END_SERVER, context->serverAppTrafficSecret);
623  }
624  else
625  {
626  //The receive buffer is not empty
627  error = ERROR_UNEXPECTED_MESSAGE;
628  }
629  }
630  else
631  {
632  //Release encryption engine
633  tlsFreeEncryptionEngine(&context->encryptionEngine);
634 
635  //Inform the record layer that subsequent records will be protected
636  //under the new traffic keys
637  error = tlsInitEncryptionEngine(context, &context->encryptionEngine,
638  TLS_CONNECTION_END_SERVER, context->serverAppTrafficSecret);
639  }
640 
641  //Failed to generate traffic keying material?
642  if(error)
643  return error;
644 
645  //Calculate exporter master secret
646  error = tls13DeriveSecret(context, context->secret, hash->digestSize,
647  "exp master", NULL, 0, context->exporterMasterSecret, hash->digestSize);
648  //Any error to report?
649  if(error)
650  return error;
651 
652  //Debug message
653  TRACE_DEBUG("Exporter master secret:\r\n");
654  TRACE_DEBUG_ARRAY(" ", context->exporterMasterSecret, hash->digestSize);
655 
656 #if (TLS_KEY_LOG_SUPPORT == ENABLED)
657  //Log client application traffic secret
658  tlsDumpSecret(context, "CLIENT_TRAFFIC_SECRET_0",
659  context->clientAppTrafficSecret, hash->digestSize);
660 
661  //Log server application traffic secret
662  tlsDumpSecret(context, "SERVER_TRAFFIC_SECRET_0",
663  context->serverAppTrafficSecret, hash->digestSize);
664 
665  //Log exporter master secret
666  tlsDumpSecret(context, "EXPORTER_SECRET",
667  context->exporterMasterSecret, hash->digestSize);
668 #endif
669 
670 #if (DTLS_SUPPORT == ENABLED)
671  //DTLS protocol?
672  if(context->transportProtocol == TLS_TRANSPORT_PROTOCOL_DATAGRAM &&
673  context->entity == TLS_CONNECTION_END_CLIENT)
674  {
675  //Because each epoch resets the sequence number space, a separate sliding
676  //window is needed for each epoch (refer to RFC 9147, section 4.5.1)
677  dtlsInitReplayWindow(context);
678  }
679 #endif
680 
681  //Check whether TLS operates as a client or a server
682  if(context->entity == TLS_CONNECTION_END_CLIENT)
683  {
684  //In DTLS 1.3, the EndOfEarlyData message is omitted both from the wire
685  //and the handshake transcript. Because DTLS records have epochs,
686  //EndOfEarlyData is not necessary to determine when the early data is
687  //complete (refer to RFC 9147, section 5.6)
688  if(context->transportProtocol == TLS_TRANSPORT_PROTOCOL_STREAM &&
689  context->earlyDataEnabled && context->earlyDataExtReceived)
690  {
691  //If the server sent an EarlyData extension, the client must send an
692  //EndOfEarlyData message after receiving the server Finished
694  }
695  else
696  {
697  //PSK key exchange method?
698  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK ||
699  context->keyExchMethod == TLS13_KEY_EXCH_PSK_DHE ||
700  context->keyExchMethod == TLS13_KEY_EXCH_PSK_ECDHE ||
701  context->keyExchMethod == TLS13_KEY_EXCH_PSK_HYBRID)
702  {
703  //Send a Finished message to the server
705  }
706  else
707  {
708  //Send a Certificate message if the server requests it
710  }
711  }
712  }
713  else
714  {
715  //PSK key exchange method?
716  if(context->keyExchMethod == TLS13_KEY_EXCH_PSK ||
717  context->keyExchMethod == TLS13_KEY_EXCH_PSK_DHE ||
718  context->keyExchMethod == TLS13_KEY_EXCH_PSK_ECDHE ||
719  context->keyExchMethod == TLS13_KEY_EXCH_PSK_HYBRID)
720  {
721  //Wait for a Finished message from the client
723  }
724  else
725  {
726  //The client must send a Certificate message if the server requests it
727  if(context->clientAuthMode != TLS_CLIENT_AUTH_NONE)
728  {
730  }
731  else
732  {
734  }
735  }
736  }
737 
738  //Successful processing
739  return NO_ERROR;
740 }
741 
742 
743 /**
744  * @brief Compute client application traffic keys
745  * @param[in] context Pointer to the TLS context
746  * @return Error code
747  **/
748 
750 {
751  error_t error;
752  const HashAlgo *hash;
753 
754  //The hash function used by HKDF is the cipher suite hash algorithm
755  hash = context->cipherSuite.prfHashAlgo;
756  //Make sure the hash algorithm is valid
757  if(hash == NULL)
758  return ERROR_FAILURE;
759 
760  //At this point, the handshake is complete, and the client and server
761  //derive the keying material required by the record layer to exchange
762  //application-layer data protected through authenticated encryption
763  if(context->entity == TLS_CONNECTION_END_CLIENT)
764  {
765  //Release encryption engine
766  tlsFreeEncryptionEngine(&context->encryptionEngine);
767 
768  //Inform the record layer that subsequent records will be protected
769  //under the new traffic keys
770  error = tlsInitEncryptionEngine(context, &context->encryptionEngine,
771  TLS_CONNECTION_END_CLIENT, context->clientAppTrafficSecret);
772  }
773  else
774  {
775  //The implementation must verify that its receive buffer is empty before
776  //rekeying
777  if(context->rxBufferLen == 0)
778  {
779  //Release decryption engine
780  tlsFreeEncryptionEngine(&context->decryptionEngine);
781 
782  //Inform the record layer that subsequent records will be protected
783  //under the new traffic keys
784  error = tlsInitEncryptionEngine(context, &context->decryptionEngine,
785  TLS_CONNECTION_END_CLIENT, context->clientAppTrafficSecret);
786  }
787  else
788  {
789  //The receive buffer is not empty
790  error = ERROR_UNEXPECTED_MESSAGE;
791  }
792  }
793 
794  //Failed to generate traffic keying material?
795  if(error)
796  return error;
797 
798  //Calculate resumption master secret
799  error = tls13DeriveSecret(context, context->secret, hash->digestSize,
800  "res master", NULL, 0, context->resumptionMasterSecret, hash->digestSize);
801  //Any error to report?
802  if(error)
803  return error;
804 
805  //Debug message
806  TRACE_DEBUG("Resumption master secret:\r\n");
807  TRACE_DEBUG_ARRAY(" ", context->resumptionMasterSecret, hash->digestSize);
808 
809  //Once all the values which are to be derived from a given secret have been
810  //computed, that secret should be erased
811  osMemset(context->secret, 0, TLS13_MAX_HKDF_DIGEST_SIZE);
812  osMemset(context->clientEarlyTrafficSecret, 0, TLS13_MAX_HKDF_DIGEST_SIZE);
813  osMemset(context->clientHsTrafficSecret, 0, TLS13_MAX_HKDF_DIGEST_SIZE);
814  osMemset(context->serverHsTrafficSecret, 0, TLS13_MAX_HKDF_DIGEST_SIZE);
815 
816 #if (DTLS_SUPPORT == ENABLED)
817  //DTLS protocol?
818  if(context->transportProtocol == TLS_TRANSPORT_PROTOCOL_DATAGRAM &&
819  context->entity == TLS_CONNECTION_END_SERVER)
820  {
821  //Because each epoch resets the sequence number space, a separate sliding
822  //window is needed for each epoch (refer to RFC 9147, section 4.5.1)
823  dtlsInitReplayWindow(context);
824  }
825 #endif
826 
827 #if (TLS_TICKET_SUPPORT == ENABLED)
828  //Check whether session ticket mechanism is enabled
829  if(context->entity == TLS_CONNECTION_END_SERVER &&
830  context->ticketEncryptCallback != NULL &&
831  context->pskKeModeSupported)
832  {
833  //At any time after the server has received the client Finished message,
834  //it may send a NewSessionTicket message
836  }
837  else
838 #endif
839  {
840  //At this point, the handshake is complete, and the client and server
841  //can exchange application-layer data
843  }
844 
845  //Successful processing
846  return NO_ERROR;
847 }
848 
849 #endif
@ TLS13_KEY_EXCH_PSK
Definition: tls.h:1184
#define tlsAllocMem(size)
Definition: tls.h:867
error_t tls13GenerateEarlyTrafficKeys(TlsContext *context)
Compute early traffic keys.
TLS helper functions.
#define TLS13_MAX_HKDF_DIGEST_SIZE
Definition: tls13_misc.h:148
void dtlsInitReplayWindow(TlsContext *context)
Initialize sliding window.
Definition: dtls_misc.c:452
error_t tls13DeriveSecret(TlsContext *context, const uint8_t *secret, size_t secretLen, const char_t *label, const char_t *message, size_t messageLen, uint8_t *output, size_t outputLen)
Derive-Secret function.
@ TLS13_KEY_EXCH_MLKEM
Definition: tls.h:1182
error_t tls13GenerateHandshakeTrafficKeys(TlsContext *context)
Compute handshake traffic keys.
@ TLS13_KEY_EXCH_PSK_DHE
Definition: tls.h:1185
Key material generation.
error_t tlsFinalizeTranscriptHash(TlsContext *context, const HashAlgo *hash, const void *hashContext, const char_t *label, uint8_t *output)
Finalize hash calculation from previous handshake messages.
@ ERROR_UNEXPECTED_MESSAGE
Definition: error.h:195
uint8_t message[]
Definition: chap.h:154
size_t digestSize
Definition: crypto.h:1088
TLS 1.3 session tickets.
@ TLS_TRANSPORT_PROTOCOL_DATAGRAM
Definition: tls.h:979
void tlsDumpSecret(TlsContext *context, const char_t *label, const uint8_t *secret, size_t secretLen)
Dump secret key (for debugging purpose only)
@ TLS13_KEY_EXCH_PSK_MLKEM
Definition: tls.h:1187
@ TLS_STATE_APPLICATION_DATA
Definition: tls.h:1523
@ ERROR_HANDSHAKE_FAILED
Definition: error.h:234
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
@ TLS13_KEY_EXCH_ECDHE
Definition: tls.h:1181
#define osStrlen(s)
Definition: os_port.h:168
Ipv6Addr prefix
error_t tls13GenerateClientAppTrafficKeys(TlsContext *context)
Compute client application traffic keys.
@ TLS13_KEY_EXCH_PSK_HYBRID
Definition: tls.h:1188
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
#define TlsContext
Definition: tls.h:36
error_t
Error codes.
Definition: error.h:43
HashAlgoCompute compute
Definition: crypto.h:1091
@ TLS_CONNECTION_END_SERVER
Definition: tls.h:991
void tlsFreeEncryptionEngine(TlsEncryptionEngine *encryptionEngine)
Release encryption engine.
Definition: tls_misc.c:919
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
@ TLS13_KEY_EXCH_DHE
Definition: tls.h:1180
@ TLS_STATE_EARLY_DATA
Definition: tls.h:1496
@ ERROR_INVALID_LENGTH
Definition: error.h:111
bool_t tls13IsTicketValid(TlsContext *context)
Check whether a session ticket is valid.
Definition: tls13_ticket.c:51
error_t tls13GenerateServerAppTrafficKeys(TlsContext *context)
Compute server application traffic keys.
#define MSB(x)
Definition: os_port.h:59
@ TLS_STATE_END_OF_EARLY_DATA
Definition: tls.h:1519
#define LSB(x)
Definition: os_port.h:55
error_t hkdfExpand(const HashAlgo *hash, const uint8_t *prk, size_t prkLen, const uint8_t *info, size_t infoLen, uint8_t *okm, size_t okmLen)
HKDF expand step.
Definition: hkdf.c:158
@ TLS_CLIENT_AUTH_NONE
Definition: tls.h:1001
@ TLS_STATE_NEW_SESSION_TICKET
Definition: tls.h:1521
Transcript hash calculation.
uint8_t secret[TLS_MASTER_SECRET_SIZE]
Master secret.
Definition: tls.h:1922
#define TRACE_DEBUG(...)
Definition: debug.h:119
char char_t
Definition: compiler_port.h:55
@ TLS13_KEY_EXCH_PSK_ECDHE
Definition: tls.h:1186
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:120
bool_t tls13IsPskValid(TlsContext *context)
Check whether an externally established PSK is valid.
Definition: tls13_misc.c:933
uint8_t n
TlsTransportProtocol
TLS transport protocols.
Definition: tls.h:977
HKDF (HMAC-based Key Derivation Function)
@ TLS_STATE_CLIENT_CERTIFICATE
Definition: tls.h:1509
@ TLS13_KEY_EXCH_HYBRID
Definition: tls.h:1183
@ TLS_STATE_ENCRYPTED_EXTENSIONS
Definition: tls.h:1503
#define TLS_MAX_HKDF_DIGEST_SIZE
Definition: tls.h:943
@ TLS_CONNECTION_END_CLIENT
Definition: tls.h:990
TLS (Transport Layer Security)
@ TLS_TRANSPORT_PROTOCOL_STREAM
Definition: tls.h:978
TLS 1.3 key schedule.
Common interface for hash algorithms.
Definition: crypto.h:1082
__weak_func error_t tlsInitEncryptionEngine(TlsContext *context, TlsEncryptionEngine *encryptionEngine, TlsConnectionEnd entity, const uint8_t *secret)
Initialize encryption engine.
Definition: tls_misc.c:672
error_t hkdfExtract(const HashAlgo *hash, const uint8_t *ikm, size_t ikmLen, const uint8_t *salt, size_t saltLen, uint8_t *prk)
HKDF extract step.
Definition: hkdf.c:97
error_t tls13HkdfExpandLabel(TlsTransportProtocol transportProtocol, const HashAlgo *hash, const uint8_t *secret, size_t secretLen, const char_t *label, const uint8_t *context, size_t contextLen, uint8_t *output, size_t outputLen)
HKDF-Expand-Label function.
void tlsChangeState(TlsContext *context, TlsState newState)
Update TLS state.
Definition: tls_misc.c:54
#define PRIuSIZE
#define osMemset(p, value, length)
Definition: os_port.h:138
#define tlsFreeMem(p)
Definition: tls.h:872
@ TLS_STATE_CLIENT_FINISHED
Definition: tls.h:1514
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.