tls_key_material.c
Go to the documentation of this file.
1 /**
2  * @file tls_key_material.c
3  * @brief Key material generation
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 "debug.h"
39 
40 //Check TLS library configuration
41 #if (TLS_SUPPORT == ENABLED)
42 
43 
44 /**
45  * @brief Generate session keys
46  * @param[in] context Pointer to the TLS context
47  * @return Error code
48  **/
49 
51 {
52 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
53  error_t error;
54  size_t keyBlockLen;
56 
57  //Point to the negotiated cipher suite
58  cipherSuite = &context->cipherSuite;
59 
60  //Length of necessary key material
61  keyBlockLen = 2 * (cipherSuite->macKeyLen + cipherSuite->encKeyLen +
62  cipherSuite->fixedIvLen);
63 
64  //Make sure that the key block is large enough
65  if(keyBlockLen > sizeof(context->keyBlock))
66  return ERROR_FAILURE;
67 
68  //Debug message
69  TRACE_DEBUG("Generating session keys...\r\n");
70  TRACE_DEBUG(" Client random bytes:\r\n");
71  TRACE_DEBUG_ARRAY(" ", context->clientRandom, 32);
72  TRACE_DEBUG(" Server random bytes:\r\n");
73  TRACE_DEBUG_ARRAY(" ", context->serverRandom, 32);
74 
75  //If a full handshake is being performed, the premaster secret shall be
76  //first converted to the master secret
77  if(!context->resume)
78  {
79  //Debug message
80  TRACE_DEBUG(" Premaster secret:\r\n");
81  TRACE_DEBUG_ARRAY(" ", context->premasterSecret, context->premasterSecretLen);
82 
83 #if (TLS_EXT_MASTER_SECRET_SUPPORT == ENABLED)
84  //If both the ClientHello and ServerHello contain the ExtendedMasterSecret
85  //extension, the new session uses the extended master secret computation
86  if(context->emsExtReceived)
87  {
88  //Extended master secret computation
89  error = tlsGenerateExtendedMasterSecret(context);
90  }
91  else
92 #endif
93  {
94  //Legacy master secret computation
95  error = tlsGenerateMasterSecret(context);
96  }
97 
98  //Failed to generate master secret?
99  if(error)
100  return error;
101 
102  //The premaster secret should be deleted from memory once the master
103  //secret has been computed
104  osMemset(context->premasterSecret, 0, TLS_PREMASTER_SECRET_SIZE);
105  }
106 
107  //Debug message
108  TRACE_DEBUG(" Master secret:\r\n");
109  TRACE_DEBUG_ARRAY(" ", context->masterSecret, TLS_MASTER_SECRET_SIZE);
110 
111 #if (TLS_KEY_LOG_SUPPORT == ENABLED)
112  //Log master secret
113  tlsDumpSecret(context, "CLIENT_RANDOM", context->masterSecret,
115 #endif
116 
117  //The master secret is used as an entropy source to generate the key material
118  error = tlsGenerateKeyBlock(context, keyBlockLen);
119  //Any error to report?
120  if(error)
121  return error;
122 
123  //Debug message
124  TRACE_DEBUG(" Key block:\r\n");
125  TRACE_DEBUG_ARRAY(" ", context->keyBlock, keyBlockLen);
126 
127  //Successful processing
128  return NO_ERROR;
129 #else
130  //Not implemented
131  return ERROR_NOT_IMPLEMENTED;
132 #endif
133 }
134 
135 
136 /**
137  * @brief Master secret computation
138  * @param[in] context Pointer to the TLS context
139  * @return Error code
140  **/
141 
143 {
144  error_t error;
145  uint8_t random[2 * TLS_RANDOM_SIZE];
146 
147  //Concatenate client_random and server_random values
148  osMemcpy(random, context->clientRandom, TLS_RANDOM_SIZE);
149  osMemcpy(random + 32, context->serverRandom, TLS_RANDOM_SIZE);
150 
151 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_1)
152  //TLS 1.0 or TLS 1.1 currently selected?
153  if(context->version == TLS_VERSION_1_0 || context->version == TLS_VERSION_1_1)
154  {
155  //TLS 1.0 and 1.1 use a PRF that combines MD5 and SHA-1
156  error = tlsPrf(context->premasterSecret, context->premasterSecretLen,
157  "master secret", random, sizeof(random), context->masterSecret,
159  }
160  else
161 #endif
162 #if (TLS_MAX_VERSION >= TLS_VERSION_1_2 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
163  //TLS 1.2 currently selected?
164  if(context->version == TLS_VERSION_1_2)
165  {
166  //TLS 1.2 PRF uses SHA-256 or a stronger hash algorithm as the core
167  //function in its construction
168  error = tls12Prf(context->cipherSuite.prfHashAlgo,
169  context->premasterSecret, context->premasterSecretLen,
170  "master secret", random, sizeof(random), context->masterSecret,
172  }
173  else
174 #endif
175  //Invalid TLS version?
176  {
177  //Report an error
178  error = ERROR_INVALID_VERSION;
179  }
180 
181  //Return status code
182  return error;
183 }
184 
185 
186 /**
187  * @brief Extended master secret computation
188  * @param[in] context Pointer to the TLS context
189  * @return Error code
190  **/
191 
193 {
194 #if (TLS_EXT_MASTER_SECRET_SUPPORT == ENABLED)
195  error_t error;
196 
197 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_1)
198  //TLS 1.0 or TLS 1.1 currently selected?
199  if(context->version == TLS_VERSION_1_0 || context->version == TLS_VERSION_1_1)
200  {
201  //A temporary buffer is needed to concatenate MD5 and SHA-1 hash
202  //values before computing the extended master secret
203  uint8_t sessionHash[MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE];
204 
205  //Finalize MD5 hash computation
206  error = tlsFinalizeTranscriptHash(context, MD5_HASH_ALGO,
207  context->transcriptMd5Context, "", sessionHash);
208 
209  //Check status code
210  if(!error)
211  {
212  //Finalize SHA-1 hash computation
213  error = tlsFinalizeTranscriptHash(context, SHA1_HASH_ALGO,
214  context->transcriptSha1Context, "", sessionHash + MD5_DIGEST_SIZE);
215  }
216 
217  //Check status code
218  if(!error)
219  {
220  //Compute the extended master secret (refer to RFC 7627, section 4)
221  error = tlsPrf(context->premasterSecret, context->premasterSecretLen,
222  "extended master secret", sessionHash, sizeof(sessionHash),
223  context->masterSecret, TLS_MASTER_SECRET_SIZE);
224  }
225  }
226  else
227 #endif
228 #if (TLS_MAX_VERSION >= TLS_VERSION_1_2 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
229  //TLS 1.2 currently selected?
230  if(context->version == TLS_VERSION_1_2)
231  {
232  const HashAlgo *hashAlgo;
233  HashContext *hashContext;
234  uint8_t digest[MAX_HASH_DIGEST_SIZE];
235 
236  //Point to the hash algorithm to be used
237  hashAlgo = context->cipherSuite.prfHashAlgo;
238 
239  //Allocate hash algorithm context
240  hashContext = tlsAllocMem(hashAlgo->contextSize);
241 
242  //Successful memory allocation?
243  if(hashContext != NULL)
244  {
245  //The original hash context must be preserved
246  osMemcpy(hashContext, context->transcriptHashContext,
247  hashAlgo->contextSize);
248 
249  //Finalize hash computation
250  hashAlgo->final(hashContext, digest);
251 
252  //Compute the extended master secret (refer to RFC 7627, section 4)
253  error = tls12Prf(hashAlgo, context->premasterSecret,
254  context->premasterSecretLen, "extended master secret",
255  digest, hashAlgo->digestSize, context->masterSecret,
257 
258  //Release previously allocated memory
259  tlsFreeMem(hashContext);
260  }
261  else
262  {
263  //Failed to allocate memory
264  error = ERROR_OUT_OF_MEMORY;
265  }
266  }
267  else
268 #endif
269  //Invalid TLS version?
270  {
271  //Report an error
272  error = ERROR_INVALID_VERSION;
273  }
274 
275  //Return status code
276  return error;
277 #else
278  //Extended master secret computation is not implemented
279  return ERROR_NOT_IMPLEMENTED;
280 #endif
281 }
282 
283 
284 /**
285  * @brief Premaster secret generation (for PSK cipher suites)
286  * @param[in] context Pointer to the TLS context
287  * @return Error code
288  **/
289 
291 {
292  error_t error;
293 
294 #if (TLS_PSK_KE_SUPPORT == ENABLED)
295  //PSK key exchange method?
296  if(context->keyExchMethod == TLS_KEY_EXCH_PSK)
297  {
298  size_t n;
299 
300  //Let N be the length of pre-shared key
301  n = context->pskLen;
302 
303  //Check whether the output buffer is large enough to hold the premaster
304  //secret
305  if((n * 2 + 4) <= TLS_PREMASTER_SECRET_SIZE)
306  {
307  //The premaster secret is formed as follows: if the PSK is N octets
308  //long, concatenate a uint16 with the value N, N zero octets, a second
309  //uint16 with the value N, and the PSK itself
310  STORE16BE(n, context->premasterSecret);
311  osMemset(context->premasterSecret + 2, 0, n);
312  STORE16BE(n, context->premasterSecret + n + 2);
313  osMemcpy(context->premasterSecret + n + 4, context->psk, n);
314 
315  //Save the length of the premaster secret
316  context->premasterSecretLen = n * 2 + 4;
317 
318  //Premaster secret successfully generated
319  error = NO_ERROR;
320  }
321  else
322  {
323  //Report an error
324  error = ERROR_BUFFER_OVERFLOW;
325  }
326  }
327  else
328 #endif
329 #if (TLS_RSA_PSK_KE_SUPPORT == ENABLED || TLS_DHE_PSK_KE_SUPPORT == ENABLED || \
330  TLS_ECDHE_PSK_KE_SUPPORT == ENABLED)
331  //RSA_PSK, DHE_PSK or ECDHE_PSK key exchange method?
332  if(context->keyExchMethod == TLS_KEY_EXCH_RSA_PSK ||
333  context->keyExchMethod == TLS_KEY_EXCH_DHE_PSK ||
334  context->keyExchMethod == TLS_KEY_EXCH_ECDHE_PSK)
335  {
336  size_t n;
337 
338  //Let N be the length of pre-shared key
339  n = context->pskLen;
340 
341  //Check whether the output buffer is large enough to hold the premaster
342  //secret
343  if((context->premasterSecretLen + n + 4) <= TLS_PREMASTER_SECRET_SIZE)
344  {
345  //The "other_secret" field comes from the Diffie-Hellman, ECDH or
346  //RSA exchange (DHE_PSK, ECDH_PSK and RSA_PSK, respectively)
347  osMemmove(context->premasterSecret + 2, context->premasterSecret,
348  context->premasterSecretLen);
349 
350  //The "other_secret" field is preceded by a 2-byte length field
351  STORE16BE(context->premasterSecretLen, context->premasterSecret);
352 
353  //if the PSK is N octets long, concatenate a uint16 with the value N
354  STORE16BE(n, context->premasterSecret + context->premasterSecretLen + 2);
355 
356  //Concatenate the PSK itself
357  osMemcpy(context->premasterSecret + context->premasterSecretLen + 4,
358  context->psk, n);
359 
360  //Adjust the length of the premaster secret
361  context->premasterSecretLen += n + 4;
362 
363  //Premaster secret successfully generated
364  error = NO_ERROR;
365  }
366  else
367  {
368  //Report an error
369  error = ERROR_BUFFER_OVERFLOW;
370  }
371  }
372  else
373 #endif
374  //Invalid key exchange method?
375  {
376  //The specified key exchange method is not supported
378  }
379 
380  //Return status code
381  return error;
382 }
383 
384 
385 /**
386  * @brief Key expansion function
387  * @param[in] context Pointer to the TLS context
388  * @param[in] keyBlockLen Desired length for the resulting key block
389  * @return Error code
390  **/
391 
392 __weak_func error_t tlsGenerateKeyBlock(TlsContext *context, size_t keyBlockLen)
393 {
394  error_t error;
395  uint8_t random[2 * TLS_RANDOM_SIZE];
396 
397  //Concatenate server_random and client_random values
398  osMemcpy(random, context->serverRandom, TLS_RANDOM_SIZE);
399  osMemcpy(random + 32, context->clientRandom, TLS_RANDOM_SIZE);
400 
401 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_1)
402  //TLS 1.0 or TLS 1.1 currently selected?
403  if(context->version == TLS_VERSION_1_0 || context->version == TLS_VERSION_1_1)
404  {
405  //TLS 1.0 and 1.1 use a PRF that combines MD5 and SHA-1
406  error = tlsPrf(context->masterSecret, TLS_MASTER_SECRET_SIZE,
407  "key expansion", random, sizeof(random), context->keyBlock,
408  keyBlockLen);
409  }
410  else
411 #endif
412 #if (TLS_MAX_VERSION >= TLS_VERSION_1_2 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
413  //TLS 1.2 currently selected?
414  if(context->version == TLS_VERSION_1_2)
415  {
416  //TLS 1.2 PRF uses SHA-256 or a stronger hash algorithm as the core
417  //function in its construction
418  error = tls12Prf(context->cipherSuite.prfHashAlgo,
419  context->masterSecret, TLS_MASTER_SECRET_SIZE, "key expansion",
420  random, sizeof(random), context->keyBlock, keyBlockLen);
421  }
422  else
423 #endif
424  //Invalid TLS version?
425  {
426  //Report an error
427  error = ERROR_INVALID_VERSION;
428  }
429 
430  //Return status code
431  return error;
432 }
433 
434 
435 /**
436  * @brief Pseudorandom function (TLS 1.0 and 1.1)
437  *
438  * The pseudorandom function (PRF) takes as input a secret, a seed, and
439  * an identifying label and produces an output of arbitrary length. This
440  * function is used to expand secrets into blocks of data for the purpose
441  * of key generation
442  *
443  * @param[in] secret Pointer to the secret
444  * @param[in] secretLen Length of the secret
445  * @param[in] label Identifying label (NULL-terminated string)
446  * @param[in] seed Pointer to the seed
447  * @param[in] seedLen Length of the seed
448  * @param[out] output Pointer to the output
449  * @param[in] outputLen Desired output length
450  * @return Error code
451  **/
452 
453 error_t tlsPrf(const uint8_t *secret, size_t secretLen, const char_t *label,
454  const uint8_t *seed, size_t seedLen, uint8_t *output, size_t outputLen)
455 {
456 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_1)
457  error_t error;
458  uint_t i;
459  uint_t j;
460  size_t labelLen;
461  size_t sLen;
462  const uint8_t *s1;
463  const uint8_t *s2;
464  HmacContext *hmacContext;
465  uint8_t a[SHA1_DIGEST_SIZE];
466 
467  //Allocate a memory buffer to hold the HMAC context
468  hmacContext = tlsAllocMem(sizeof(HmacContext));
469 
470  //Successful memory allocation?
471  if(hmacContext != NULL)
472  {
473  //Retrieve the length of the label
474  labelLen = osStrlen(label);
475 
476  //The secret is partitioned into two halves S1 and S2
477  //with the possibility of one shared byte
478  sLen = (secretLen + 1) / 2;
479  //S1 is taken from the first half of the secret
480  s1 = secret;
481  //S2 is taken from the second half
482  s2 = secret + secretLen - sLen;
483 
484  //First compute A(1) = HMAC_MD5(S1, label + seed)
485  hmacInit(hmacContext, MD5_HASH_ALGO, s1, sLen);
486  hmacUpdate(hmacContext, label, labelLen);
487  hmacUpdate(hmacContext, seed, seedLen);
488  hmacFinal(hmacContext, a);
489 
490  //Apply the data expansion function P_MD5
491  for(i = 0; i < outputLen; )
492  {
493  //Compute HMAC_MD5(S1, A(i) + label + seed)
494  hmacInit(hmacContext, MD5_HASH_ALGO, s1, sLen);
495  hmacUpdate(hmacContext, a, MD5_DIGEST_SIZE);
496  hmacUpdate(hmacContext, label, labelLen);
497  hmacUpdate(hmacContext, seed, seedLen);
498  hmacFinal(hmacContext, NULL);
499 
500  //Copy the resulting digest
501  for(j = 0; i < outputLen && j < MD5_DIGEST_SIZE; i++, j++)
502  {
503  output[i] = hmacContext->digest[j];
504  }
505 
506  //Compute A(i + 1) = HMAC_MD5(S1, A(i))
507  hmacInit(hmacContext, MD5_HASH_ALGO, s1, sLen);
508  hmacUpdate(hmacContext, a, MD5_DIGEST_SIZE);
509  hmacFinal(hmacContext, a);
510  }
511 
512  //First compute A(1) = HMAC_SHA1(S2, label + seed)
513  hmacInit(hmacContext, SHA1_HASH_ALGO, s2, sLen);
514  hmacUpdate(hmacContext, label, labelLen);
515  hmacUpdate(hmacContext, seed, seedLen);
516  hmacFinal(hmacContext, a);
517 
518  //Apply the data expansion function P_SHA1
519  for(i = 0; i < outputLen; )
520  {
521  //Compute HMAC_SHA1(S2, A(i) + label + seed)
522  hmacInit(hmacContext, SHA1_HASH_ALGO, s2, sLen);
523  hmacUpdate(hmacContext, a, SHA1_DIGEST_SIZE);
524  hmacUpdate(hmacContext, label, labelLen);
525  hmacUpdate(hmacContext, seed, seedLen);
526  hmacFinal(hmacContext, NULL);
527 
528  //Copy the resulting digest
529  for(j = 0; i < outputLen && j < SHA1_DIGEST_SIZE; i++, j++)
530  {
531  output[i] ^= hmacContext->digest[j];
532  }
533 
534  //Compute A(i + 1) = HMAC_SHA1(S2, A(i))
535  hmacInit(hmacContext, SHA1_HASH_ALGO, s2, sLen);
536  hmacUpdate(hmacContext, a, SHA1_DIGEST_SIZE);
537  hmacFinal(hmacContext, a);
538  }
539 
540  //Free previously allocated memory
541  tlsFreeMem(hmacContext);
542 
543  //Successful processing
544  error = NO_ERROR;
545  }
546  else
547  {
548  //Failed to allocate memory
549  error = ERROR_OUT_OF_MEMORY;
550  }
551 
552  //Return status code
553  return error;
554 #else
555  //Not implemented
556  return ERROR_NOT_IMPLEMENTED;
557 #endif
558 }
559 
560 
561 /**
562  * @brief Pseudorandom function (TLS 1.2)
563  *
564  * The pseudorandom function (PRF) takes as input a secret, a seed, and
565  * an identifying label and produces an output of arbitrary length. This
566  * function is used to expand secrets into blocks of data for the purpose
567  * of key generation
568  *
569  * @param[in] hash Hash function used to compute PRF
570  * @param[in] secret Pointer to the secret
571  * @param[in] secretLen Length of the secret
572  * @param[in] label Identifying label (NULL-terminated string)
573  * @param[in] seed Pointer to the seed
574  * @param[in] seedLen Length of the seed
575  * @param[out] output Pointer to the output
576  * @param[in] outputLen Desired output length
577  * @return Error code
578  **/
579 
580 error_t tls12Prf(const HashAlgo *hash, const uint8_t *secret, size_t secretLen,
581  const char_t *label, const uint8_t *seed, size_t seedLen, uint8_t *output,
582  size_t outputLen)
583 {
584 #if (TLS_MAX_VERSION >= TLS_VERSION_1_2 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
585  error_t error;
586  size_t n;
587  size_t labelLen;
588  HmacContext *hmacContext;
589  uint8_t a[MAX_HASH_DIGEST_SIZE];
590 
591  //Allocate a memory buffer to hold the HMAC context
592  hmacContext = tlsAllocMem(sizeof(HmacContext));
593 
594  //Successful memory allocation?
595  if(hmacContext != NULL)
596  {
597  //Retrieve the length of the label
598  labelLen = osStrlen(label);
599 
600  //First compute A(1) = HMAC_hash(secret, label + seed)
601  hmacInit(hmacContext, hash, secret, secretLen);
602  hmacUpdate(hmacContext, label, labelLen);
603  hmacUpdate(hmacContext, seed, seedLen);
604  hmacFinal(hmacContext, a);
605 
606  //Apply the data expansion function P_hash
607  while(outputLen > 0)
608  {
609  //Compute HMAC_hash(secret, A(i) + label + seed)
610  hmacInit(hmacContext, hash, secret, secretLen);
611  hmacUpdate(hmacContext, a, hash->digestSize);
612  hmacUpdate(hmacContext, label, labelLen);
613  hmacUpdate(hmacContext, seed, seedLen);
614  hmacFinal(hmacContext, NULL);
615 
616  //Calculate the number of bytes to copy
617  n = MIN(outputLen, hash->digestSize);
618  //Copy the resulting digest
619  osMemcpy(output, hmacContext->digest, n);
620 
621  //Compute A(i + 1) = HMAC_hash(secret, A(i))
622  hmacInit(hmacContext, hash, secret, secretLen);
623  hmacUpdate(hmacContext, a, hash->digestSize);
624  hmacFinal(hmacContext, a);
625 
626  //Advance data pointer
627  output += n;
628  //Decrement byte counter
629  outputLen -= n;
630  }
631 
632  //Free previously allocated memory
633  tlsFreeMem(hmacContext);
634 
635  //Successful processing
636  error = NO_ERROR;
637  }
638  else
639  {
640  //Failed to allocate memory
641  error = ERROR_OUT_OF_MEMORY;
642  }
643 
644  //Return status code
645  return error;
646 #else
647  //Not implemented
648  return ERROR_NOT_IMPLEMENTED;
649 #endif
650 }
651 
652 
653 /**
654  * @brief Dump secret key (for debugging purpose only)
655  * @param[in] context Pointer to the TLS context
656  * @param[in] label Identifying label (NULL-terminated string)
657  * @param[in] secret Pointer to the secret key
658  * @param[in] secretLen Length of the secret key, in bytes
659  **/
660 
661 void tlsDumpSecret(TlsContext *context, const char_t *label,
662  const uint8_t *secret, size_t secretLen)
663 {
664 #if (TLS_KEY_LOG_SUPPORT == ENABLED)
665  //Any registered callback?
666  if(context->keyLogCallback != NULL)
667  {
668  size_t i;
669  size_t n;
670  char_t buffer[194];
671 
672  //Retrieve the length of the label
673  n = osStrlen(label);
674 
675  //Sanity check
676  if((n + 2 * secretLen + 67) <= sizeof(buffer))
677  {
678  //Copy the identifying label
679  osStrncpy(buffer, label, n);
680 
681  //Append a space character
682  buffer[n++] = ' ';
683 
684  //Convert the client random value to a hex string
685  for(i = 0; i < 32; i++)
686  {
687  //Format current byte
688  n += osSprintf(buffer + n, "%02" PRIX8, context->clientRandom[i]);
689  }
690 
691  //Append a space character
692  buffer[n++] = ' ';
693 
694  //Convert the secret key to a hex string
695  for(i = 0; i < secretLen; i++)
696  {
697  //Format current byte
698  n += osSprintf(buffer + n, "%02" PRIX8, secret[i]);
699  }
700 
701  //Properly terminate the string with a NULL character
702  buffer[n] = '\0';
703 
704  //Invoke user callback function
705  context->keyLogCallback(context, buffer);
706  }
707  }
708 #endif
709 }
710 
711 #endif
#define tlsAllocMem(size)
Definition: tls.h:867
Generic hash algorithm context.
HMAC algorithm context.
Definition: hmac.h:59
uint16_t cipherSuite
Cipher suite identifier.
Definition: tls.h:1921
#define SHA1_HASH_ALGO
Definition: sha1.h:49
uint8_t a
Definition: ndp.h:411
Key material generation.
error_t tlsGeneratePskPremasterSecret(TlsContext *context)
Premaster secret generation (for PSK cipher suites)
@ ERROR_BUFFER_OVERFLOW
Definition: error.h:143
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
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_t tlsPrf(const uint8_t *secret, size_t secretLen, const char_t *label, const uint8_t *seed, size_t seedLen, uint8_t *output, size_t outputLen)
Pseudorandom function (TLS 1.0 and 1.1)
__weak_func error_t tlsGenerateMasterSecret(TlsContext *context)
Master secret computation.
size_t digestSize
Definition: crypto.h:1088
void tlsDumpSecret(TlsContext *context, const char_t *label, const uint8_t *secret, size_t secretLen)
Dump secret key (for debugging purpose only)
Structure describing a cipher suite.
Definition: tls.h:2054
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
#define osStrlen(s)
Definition: os_port.h:168
@ ERROR_INVALID_VERSION
Definition: error.h:118
#define TLS_RANDOM_SIZE
Definition: tls.h:960
size_t contextSize
Definition: crypto.h:1086
__weak_func error_t tlsGenerateKeyBlock(TlsContext *context, size_t keyBlockLen)
Key expansion function.
#define MAX_HASH_DIGEST_SIZE
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
#define TlsContext
Definition: tls.h:36
error_t
Error codes.
Definition: error.h:43
#define osSprintf(dest,...)
Definition: os_port.h:234
#define TLS_VERSION_1_2
Definition: tls.h:96
#define TLS_PREMASTER_SECRET_SIZE
Definition: tls.h:822
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define STORE16BE(a, p)
Definition: cpu_endian.h:262
#define MD5_HASH_ALGO
Definition: md5.h:49
#define MIN(a, b)
Definition: os_port.h:63
@ TLS_KEY_EXCH_DHE_PSK
Definition: tls.h:1175
#define MD5_DIGEST_SIZE
Definition: md5.h:45
error_t tls12Prf(const HashAlgo *hash, const uint8_t *secret, size_t secretLen, const char_t *label, const uint8_t *seed, size_t seedLen, uint8_t *output, size_t outputLen)
Pseudorandom function (TLS 1.2)
#define TLS_MASTER_SECRET_SIZE
Definition: tls.h:815
Transcript hash calculation.
uint8_t secret[TLS_MASTER_SECRET_SIZE]
Master secret.
Definition: tls.h:1922
@ ERROR_UNSUPPORTED_KEY_EXCH_ALGO
Definition: error.h:131
uint8_t random[32]
Definition: tls.h:1809
@ TLS_KEY_EXCH_RSA_PSK
Definition: tls.h:1174
HashAlgoFinal final
Definition: crypto.h:1094
__weak_func void hmacUpdate(HmacContext *context, const void *data, size_t length)
Update the HMAC context with a portion of the message being hashed.
Definition: hmac.c:201
#define TRACE_DEBUG(...)
Definition: debug.h:119
char char_t
Definition: compiler_port.h:55
#define TLS_VERSION_1_1
Definition: tls.h:95
uint8_t digest[MAX_HASH_DIGEST_SIZE]
Definition: hmac.h:63
#define SHA1_DIGEST_SIZE
Definition: sha1.h:45
error_t tlsGenerateExtendedMasterSecret(TlsContext *context)
Extended master secret computation.
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:120
uint8_t n
__weak_func void hmacFinal(HmacContext *context, uint8_t *digest)
Finish the HMAC calculation.
Definition: hmac.c:218
#define TLS_VERSION_1_0
Definition: tls.h:94
@ TLS_KEY_EXCH_PSK
Definition: tls.h:1173
@ TLS_KEY_EXCH_ECDHE_PSK
Definition: tls.h:1176
#define osStrncpy(s1, s2, length)
Definition: os_port.h:216
TLS (Transport Layer Security)
Common interface for hash algorithms.
Definition: crypto.h:1082
error_t tlsGenerateSessionKeys(TlsContext *context)
Generate session keys.
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
#define tlsFreeMem(p)
Definition: tls.h:872
__weak_func error_t hmacInit(HmacContext *context, const HashAlgo *hash, const void *key, size_t keyLen)
Initialize HMAC calculation.
Definition: hmac.c:140
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
#define osMemmove(dest, src, length)
Definition: os_port.h:150