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-2019 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 1.9.6
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL TLS_TRACE_LEVEL
33 
34 //Dependencies
35 #include <string.h>
36 #include "tls.h"
37 #include "tls_key_material.h"
38 #include "tls_transcript_hash.h"
39 #include "tls13_key_material.h"
40 #include "ssl_misc.h"
41 #include "debug.h"
42 
43 //Check TLS library configuration
44 #if (TLS_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief Generate session keys
49  * @param[in] context Pointer to the TLS context
50  * @return Error code
51  **/
52 
54 {
55 #if (TLS_MAX_VERSION >= SSL_VERSION_3_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
56  error_t error;
57  size_t keyBlockLen;
59 
60  //Point to the negotiated cipher suite
61  cipherSuite = &context->cipherSuite;
62 
63  //Length of necessary key material
64  keyBlockLen = 2 * (cipherSuite->macKeyLen + cipherSuite->encKeyLen +
65  cipherSuite->fixedIvLen);
66 
67  //Make sure that the key block is large enough
68  if(keyBlockLen > sizeof(context->keyBlock))
69  return ERROR_FAILURE;
70 
71  //Debug message
72  TRACE_DEBUG("Generating session keys...\r\n");
73  TRACE_DEBUG(" Client random bytes:\r\n");
74  TRACE_DEBUG_ARRAY(" ", context->clientRandom, 32);
75  TRACE_DEBUG(" Server random bytes:\r\n");
76  TRACE_DEBUG_ARRAY(" ", context->serverRandom, 32);
77 
78  //If a full handshake is being performed, the premaster secret shall be
79  //first converted to the master secret
80  if(!context->resume)
81  {
82  //Debug message
83  TRACE_DEBUG(" Premaster secret:\r\n");
84  TRACE_DEBUG_ARRAY(" ", context->premasterSecret, context->premasterSecretLen);
85 
86 #if (TLS_EXT_MASTER_SECRET_SUPPORT == ENABLED)
87  //If both the ClientHello and ServerHello contain the ExtendedMasterSecret
88  //extension, the new session uses the extended master secret computation
89  if(context->extendedMasterSecretExtReceived)
90  {
91  //Extended master secret computation
92  error = tlsGenerateExtendedMasterSecret(context);
93  }
94  else
95 #endif
96  {
97  //Legacy master secret computation
98  error = tlsGenerateMasterSecret(context);
99  }
100 
101  //Failed to generate master secret?
102  if(error)
103  return error;
104 
105  //The premaster secret should be deleted from memory once the master
106  //secret has been computed
107  memset(context->premasterSecret, 0, TLS_PREMASTER_SECRET_SIZE);
108  }
109 
110  //Debug message
111  TRACE_DEBUG(" Master secret:\r\n");
112  TRACE_DEBUG_ARRAY(" ", context->masterSecret, TLS_MASTER_SECRET_SIZE);
113 
114 #if (TLS_KEY_LOG_SUPPORT == ENABLED)
115  //Log master secret
116  tlsDumpSecret(context, "CLIENT_RANDOM", context->masterSecret,
118 #endif
119 
120  //The master secret is used as an entropy source to generate the key material
121  error = tlsGenerateKeyBlock(context, keyBlockLen);
122  //Any error to report?
123  if(error)
124  return error;
125 
126  //Debug message
127  TRACE_DEBUG(" Key block:\r\n");
128  TRACE_DEBUG_ARRAY(" ", context->keyBlock, keyBlockLen);
129 
130  //Successful processing
131  return NO_ERROR;
132 #else
133  //Not implemented
134  return ERROR_NOT_IMPLEMENTED;
135 #endif
136 }
137 
138 
139 /**
140  * @brief Master secret computation
141  * @param[in] context Pointer to the TLS context
142  * @return Error code
143  **/
144 
146 {
147  error_t error;
148  uint8_t random[2 * TLS_RANDOM_SIZE];
149 
150  //Concatenate client_random and server_random values
151  memcpy(random, context->clientRandom, TLS_RANDOM_SIZE);
152  memcpy(random + 32, context->serverRandom, TLS_RANDOM_SIZE);
153 
154 #if (TLS_MAX_VERSION >= SSL_VERSION_3_0 && TLS_MIN_VERSION <= SSL_VERSION_3_0)
155  //SSL 3.0 currently selected?
156  if(context->version == SSL_VERSION_3_0)
157  {
158  //SSL 3.0 does not use a PRF, instead makes use abundantly of MD5
159  error = sslExpandKey(context->premasterSecret,
160  context->premasterSecretLen, random, sizeof(random),
161  context->masterSecret, TLS_MASTER_SECRET_SIZE);
162  }
163  else
164 #endif
165 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_1)
166  //TLS 1.0 or TLS 1.1 currently selected?
167  if(context->version == TLS_VERSION_1_0 || context->version == TLS_VERSION_1_1)
168  {
169  //TLS 1.0 and 1.1 use a PRF that combines MD5 and SHA-1
170  error = tlsPrf(context->premasterSecret, context->premasterSecretLen,
171  "master secret", random, sizeof(random), context->masterSecret,
173  }
174  else
175 #endif
176 #if (TLS_MAX_VERSION >= TLS_VERSION_1_2 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
177  //TLS 1.2 currently selected?
178  if(context->version == TLS_VERSION_1_2)
179  {
180  //TLS 1.2 PRF uses SHA-256 or a stronger hash algorithm as the core
181  //function in its construction
182  error = tls12Prf(context->cipherSuite.prfHashAlgo,
183  context->premasterSecret, context->premasterSecretLen,
184  "master secret", random, sizeof(random), context->masterSecret,
186  }
187  else
188 #endif
189  //Invalid TLS version?
190  {
191  //Report an error
192  error = ERROR_INVALID_VERSION;
193  }
194 
195  //Return status code
196  return error;
197 }
198 
199 
200 /**
201  * @brief Extended master secret computation
202  * @param[in] context Pointer to the TLS context
203  * @return Error code
204  **/
205 
207 {
208 #if (TLS_EXT_MASTER_SECRET_SUPPORT == ENABLED)
209  error_t error;
210 
211 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_1)
212  //TLS 1.0 or TLS 1.1 currently selected?
213  if(context->version == TLS_VERSION_1_0 || context->version == TLS_VERSION_1_1)
214  {
215  //A temporary buffer is needed to concatenate MD5 and SHA-1 hash
216  //values before computing the extended master secret
217  uint8_t sessionHash[MD5_DIGEST_SIZE + SHA1_DIGEST_SIZE];
218 
219  //Finalize MD5 hash computation
220  error = tlsFinalizeTranscriptHash(context, MD5_HASH_ALGO,
221  context->transcriptMd5Context, "", sessionHash);
222 
223  //Check status code
224  if(!error)
225  {
226  //Finalize SHA-1 hash computation
227  error = tlsFinalizeTranscriptHash(context, SHA1_HASH_ALGO,
228  context->transcriptSha1Context, "", sessionHash + MD5_DIGEST_SIZE);
229  }
230 
231  //Check status code
232  if(!error)
233  {
234  //Compute the extended master secret (refer to RFC 7627, section 4)
235  error = tlsPrf(context->premasterSecret, context->premasterSecretLen,
236  "extended master secret", sessionHash, sizeof(sessionHash),
237  context->masterSecret, TLS_MASTER_SECRET_SIZE);
238  }
239  }
240  else
241 #endif
242 #if (TLS_MAX_VERSION >= TLS_VERSION_1_2 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
243  //TLS 1.2 currently selected?
244  if(context->version == TLS_VERSION_1_2)
245  {
246  const HashAlgo *hashAlgo;
247  HashContext *hashContext;
248 
249  //Point to the hash algorithm to be used
250  hashAlgo = context->cipherSuite.prfHashAlgo;
251 
252  //Allocate hash algorithm context
253  hashContext = tlsAllocMem(hashAlgo->contextSize);
254 
255  //Successful memory allocation?
256  if(hashContext != NULL)
257  {
258  //The original hash context must be preserved
259  memcpy(hashContext, context->transcriptHashContext,
260  hashAlgo->contextSize);
261 
262  //Finalize hash computation
263  hashAlgo->final(hashContext, NULL);
264 
265  //Compute the extended master secret (refer to RFC 7627, section 4)
266  error = tls12Prf(hashAlgo, context->premasterSecret,
267  context->premasterSecretLen, "extended master secret",
268  hashContext->digest, hashAlgo->digestSize,
269  context->masterSecret, TLS_MASTER_SECRET_SIZE);
270 
271  //Release previously allocated memory
272  tlsFreeMem(hashContext);
273  }
274  else
275  {
276  //Failed to allocate memory
277  error = ERROR_OUT_OF_MEMORY;
278  }
279  }
280  else
281 #endif
282  //Invalid TLS version?
283  {
284  //Report an error
285  error = ERROR_INVALID_VERSION;
286  }
287 
288  //Return status code
289  return error;
290 #else
291  //Extended master secret computation is not implemented
292  return ERROR_NOT_IMPLEMENTED;
293 #endif
294 }
295 
296 
297 /**
298  * @brief Premaster secret generation (for PSK cipher suites)
299  * @param[in] context Pointer to the TLS context
300  * @return Error code
301  **/
302 
304 {
305  error_t error;
306 
307 #if (TLS_PSK_KE_SUPPORT == ENABLED)
308  //PSK key exchange method?
309  if(context->keyExchMethod == TLS_KEY_EXCH_PSK)
310  {
311  size_t n;
312 
313  //Let N be the length of pre-shared key
314  n = context->pskLen;
315 
316  //Check whether the output buffer is large enough to hold the premaster
317  //secret
318  if((n * 2 + 4) <= TLS_PREMASTER_SECRET_SIZE)
319  {
320  //The premaster secret is formed as follows: if the PSK is N octets
321  //long, concatenate a uint16 with the value N, N zero octets, a second
322  //uint16 with the value N, and the PSK itself
323  STORE16BE(n, context->premasterSecret);
324  memset(context->premasterSecret + 2, 0, n);
325  STORE16BE(n, context->premasterSecret + n + 2);
326  memcpy(context->premasterSecret + n + 4, context->psk, n);
327 
328  //Save the length of the premaster secret
329  context->premasterSecretLen = n * 2 + 4;
330 
331  //Premaster secret successfully generated
332  error = NO_ERROR;
333  }
334  else
335  {
336  //Report an error
337  error = ERROR_BUFFER_OVERFLOW;
338  }
339  }
340  else
341 #endif
342 #if (TLS_RSA_PSK_KE_SUPPORT == ENABLED || TLS_DHE_PSK_KE_SUPPORT == ENABLED || \
343  TLS_ECDHE_PSK_KE_SUPPORT == ENABLED)
344  //RSA_PSK, DHE_PSK or ECDHE_PSK key exchange method?
345  if(context->keyExchMethod == TLS_KEY_EXCH_RSA_PSK ||
346  context->keyExchMethod == TLS_KEY_EXCH_DHE_PSK ||
347  context->keyExchMethod == TLS_KEY_EXCH_ECDHE_PSK)
348  {
349  size_t n;
350 
351  //Let N be the length of pre-shared key
352  n = context->pskLen;
353 
354  //Check whether the output buffer is large enough to hold the premaster
355  //secret
356  if((context->premasterSecretLen + n + 4) <= TLS_PREMASTER_SECRET_SIZE)
357  {
358  //The "other_secret" field comes from the Diffie-Hellman, ECDH or
359  //RSA exchange (DHE_PSK, ECDH_PSK and RSA_PSK, respectively)
360  memmove(context->premasterSecret + 2, context->premasterSecret,
361  context->premasterSecretLen);
362 
363  //The "other_secret" field is preceded by a 2-byte length field
364  STORE16BE(context->premasterSecretLen, context->premasterSecret);
365 
366  //if the PSK is N octets long, concatenate a uint16 with the value N
367  STORE16BE(n, context->premasterSecret + context->premasterSecretLen + 2);
368 
369  //Concatenate the PSK itself
370  memcpy(context->premasterSecret + context->premasterSecretLen + 4,
371  context->psk, n);
372 
373  //Adjust the length of the premaster secret
374  context->premasterSecretLen += n + 4;
375 
376  //Premaster secret successfully generated
377  error = NO_ERROR;
378  }
379  else
380  {
381  //Report an error
382  error = ERROR_BUFFER_OVERFLOW;
383  }
384  }
385  else
386 #endif
387  //Invalid key exchange method?
388  {
389  //The specified key exchange method is not supported
391  }
392 
393  //Return status code
394  return error;
395 }
396 
397 
398 /**
399  * @brief Key expansion function
400  * @param[in] context Pointer to the TLS context
401  * @param[in] keyBlockLen Desired length for the resulting key block
402  * @return Error code
403  **/
404 
405 error_t tlsGenerateKeyBlock(TlsContext *context, size_t keyBlockLen)
406 {
407  error_t error;
408  uint8_t random[2 * TLS_RANDOM_SIZE];
409 
410  //Concatenate server_random and client_random values
411  memcpy(random, context->serverRandom, TLS_RANDOM_SIZE);
412  memcpy(random + 32, context->clientRandom, TLS_RANDOM_SIZE);
413 
414 #if (TLS_MAX_VERSION >= SSL_VERSION_3_0 && TLS_MIN_VERSION <= SSL_VERSION_3_0)
415  //SSL 3.0 currently selected?
416  if(context->version == SSL_VERSION_3_0)
417  {
418  //SSL 3.0 does not use a PRF, instead makes use abundantly of MD5
419  error = sslExpandKey(context->masterSecret, TLS_MASTER_SECRET_SIZE,
420  random, sizeof(random), context->keyBlock, keyBlockLen);
421  }
422  else
423 #endif
424 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_1)
425  //TLS 1.0 or TLS 1.1 currently selected?
426  if(context->version == TLS_VERSION_1_0 || context->version == TLS_VERSION_1_1)
427  {
428  //TLS 1.0 and 1.1 use a PRF that combines MD5 and SHA-1
429  error = tlsPrf(context->masterSecret, TLS_MASTER_SECRET_SIZE,
430  "key expansion", random, sizeof(random), context->keyBlock,
431  keyBlockLen);
432  }
433  else
434 #endif
435 #if (TLS_MAX_VERSION >= TLS_VERSION_1_2 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
436  //TLS 1.2 currently selected?
437  if(context->version == TLS_VERSION_1_2)
438  {
439  //TLS 1.2 PRF uses SHA-256 or a stronger hash algorithm
440  //as the core function in its construction
441  error = tls12Prf(context->cipherSuite.prfHashAlgo,
442  context->masterSecret, TLS_MASTER_SECRET_SIZE, "key expansion",
443  random, sizeof(random), context->keyBlock, keyBlockLen);
444  }
445  else
446 #endif
447  //Invalid TLS version?
448  {
449  //Report an error
450  error = ERROR_INVALID_VERSION;
451  }
452 
453  //Return status code
454  return error;
455 }
456 
457 
458 /**
459  * @brief Export keying material per RFC 5705 standard
460  * @param[in] context Pointer to the TLS context
461  * @param[in] label Identifying label (NULL-terminated string)
462  * @param[in] useContextValue Specifies whether upper-layer context should
463  * be used when exporting keying material
464  * @param[in] contextValue Pointer to the upper-layer context
465  * @param[in] contextValueLen Length of the upper-layer context
466  * @param[out] output Pointer to the output
467  * @param[in] outputLen Desired output length
468  * @return Error code
469  **/
470 
472  bool_t useContextValue, const uint8_t *contextValue,
473  size_t contextValueLen, uint8_t *output, size_t outputLen)
474 {
475  error_t error;
476  size_t n;
477  uint8_t *seed;
478 
479  //Invalid TLS context?
480  if(context == NULL)
482 
483  //Check parameters
484  if(label == NULL || output == NULL)
486 
487  //Make sure the upper-layer context is valid
488  if(contextValue == NULL && contextValueLen != 0)
490 
491  //Calculate the length of the seed
492  n = 2 * TLS_RANDOM_SIZE;
493 
494  //Check whether a context is provided
495  if(useContextValue)
496  n += contextValueLen + 2;
497 
498  //Allocate a memory buffer to hold the seed
499  seed = tlsAllocMem(n);
500  //Failed to allocate memory?
501  if(seed == NULL)
502  return ERROR_OUT_OF_RESOURCES;
503 
504  //Concatenate client_random and server_random values
505  memcpy(seed, context->clientRandom, TLS_RANDOM_SIZE);
506  memcpy(seed + 32, context->serverRandom, TLS_RANDOM_SIZE);
507 
508  //Check whether a context is provided
509  if(useContextValue)
510  {
511  //The context_value_length is encoded as an unsigned, 16-bit quantity
512  //representing the length of the context value
513  STORE16BE(contextValueLen, seed + 64);
514 
515  //Copy the context value provided by the application using the exporter
516  memcpy(seed + 66, contextValue, contextValueLen);
517  }
518 
519 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_1)
520  //TLS 1.0 or TLS 1.1 currently selected?
521  if(context->version == TLS_VERSION_1_0 || context->version == TLS_VERSION_1_1)
522  {
523  //TLS 1.0 and 1.1 use a PRF that combines MD5 and SHA-1
524  error = tlsPrf(context->masterSecret, TLS_MASTER_SECRET_SIZE,
525  label, seed, n, output, outputLen);
526  }
527  else
528 #endif
529 #if (TLS_MAX_VERSION >= TLS_VERSION_1_2 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
530  //TLS 1.2 currently selected?
531  if(context->version == TLS_VERSION_1_2)
532  {
533  //Make sure the PRF hash algorithm is valid
534  if(context->cipherSuite.prfHashAlgo != NULL)
535  {
536  //TLS 1.2 PRF uses SHA-256 or a stronger hash algorithm as the core
537  //function in its construction
538  error = tls12Prf(context->cipherSuite.prfHashAlgo, context->masterSecret,
539  TLS_MASTER_SECRET_SIZE, label, seed, n, output, outputLen);
540  }
541  else
542  {
543  //Invalid PRF hash algorithm
544  error = ERROR_FAILURE;
545  }
546  }
547  else
548 #endif
549 #if (TLS_MAX_VERSION >= TLS_VERSION_1_3 && TLS_MIN_VERSION <= TLS_VERSION_1_3)
550  //TLS 1.3 currently selected?
551  if(context->version == TLS_VERSION_1_3)
552  {
553  const HashAlgo *hash;
554  uint8_t secret[TLS_MAX_HKDF_DIGEST_SIZE];
555  uint8_t digest[TLS_MAX_HKDF_DIGEST_SIZE];
556 
557  //The hash function used by HKDF is the cipher suite hash algorithm
558  hash = context->cipherSuite.prfHashAlgo;
559 
560  //Make sure the HKDF hash algorithm is valid
561  if(hash != NULL)
562  {
563  //Derive exporter master secret
564  error = tls13DeriveSecret(context, context->exporterMasterSecret,
565  hash->digestSize, label, "", 0, secret, hash->digestSize);
566 
567  //Check status code
568  if(!error)
569  {
570  //Hash context_value input
571  error = hash->compute(contextValue, contextValueLen, digest);
572  }
573 
574  //Check status code
575  if(!error)
576  {
577  //Export keying material
578  error = tls13HkdfExpandLabel(hash, secret, hash->digestSize,
579  "exporter", digest, hash->digestSize, output, outputLen);
580  }
581  }
582  else
583  {
584  //Invalid HKDF hash algorithm
585  error = ERROR_FAILURE;
586  }
587  }
588  else
589 #endif
590  //Invalid TLS version?
591  {
592  //Report an error
593  error = ERROR_INVALID_VERSION;
594  }
595 
596  //Release previously allocated memory
597  tlsFreeMem(seed);
598 
599  //Return status code
600  return error;
601 }
602 
603 
604 /**
605  * @brief Pseudorandom function (TLS 1.0 and 1.1)
606  *
607  * The pseudorandom function (PRF) takes as input a secret, a seed, and
608  * an identifying label and produces an output of arbitrary length. This
609  * function is used to expand secrets into blocks of data for the purpose
610  * of key generation
611  *
612  * @param[in] secret Pointer to the secret
613  * @param[in] secretLen Length of the secret
614  * @param[in] label Identifying label (NULL-terminated string)
615  * @param[in] seed Pointer to the seed
616  * @param[in] seedLen Length of the seed
617  * @param[out] output Pointer to the output
618  * @param[in] outputLen Desired output length
619  * @return Error code
620  **/
621 
622 error_t tlsPrf(const uint8_t *secret, size_t secretLen, const char_t *label,
623  const uint8_t *seed, size_t seedLen, uint8_t *output, size_t outputLen)
624 {
625 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_1)
626  error_t error;
627  uint_t i;
628  uint_t j;
629  size_t labelLen;
630  size_t sLen;
631  const uint8_t *s1;
632  const uint8_t *s2;
633  HmacContext *hmacContext;
634  uint8_t a[SHA1_DIGEST_SIZE];
635 
636  //Allocate a memory buffer to hold the HMAC context
637  hmacContext = tlsAllocMem(sizeof(HmacContext));
638 
639  //Successful memory allocation?
640  if(hmacContext != NULL)
641  {
642  //Retrieve the length of the label
643  labelLen = strlen(label);
644 
645  //The secret is partitioned into two halves S1 and S2
646  //with the possibility of one shared byte
647  sLen = (secretLen + 1) / 2;
648  //S1 is taken from the first half of the secret
649  s1 = secret;
650  //S2 is taken from the second half
651  s2 = secret + secretLen - sLen;
652 
653  //First compute A(1) = HMAC_MD5(S1, label + seed)
654  hmacInit(hmacContext, MD5_HASH_ALGO, s1, sLen);
655  hmacUpdate(hmacContext, label, labelLen);
656  hmacUpdate(hmacContext, seed, seedLen);
657  hmacFinal(hmacContext, a);
658 
659  //Apply the data expansion function P_MD5
660  for(i = 0; i < outputLen; )
661  {
662  //Compute HMAC_MD5(S1, A(i) + label + seed)
663  hmacInit(hmacContext, MD5_HASH_ALGO, s1, sLen);
664  hmacUpdate(hmacContext, a, MD5_DIGEST_SIZE);
665  hmacUpdate(hmacContext, label, labelLen);
666  hmacUpdate(hmacContext, seed, seedLen);
667  hmacFinal(hmacContext, NULL);
668 
669  //Copy the resulting digest
670  for(j = 0; i < outputLen && j < MD5_DIGEST_SIZE; i++, j++)
671  {
672  output[i] = hmacContext->digest[j];
673  }
674 
675  //Compute A(i + 1) = HMAC_MD5(S1, A(i))
676  hmacInit(hmacContext, MD5_HASH_ALGO, s1, sLen);
677  hmacUpdate(hmacContext, a, MD5_DIGEST_SIZE);
678  hmacFinal(hmacContext, a);
679  }
680 
681  //First compute A(1) = HMAC_SHA1(S2, label + seed)
682  hmacInit(hmacContext, SHA1_HASH_ALGO, s2, sLen);
683  hmacUpdate(hmacContext, label, labelLen);
684  hmacUpdate(hmacContext, seed, seedLen);
685  hmacFinal(hmacContext, a);
686 
687  //Apply the data expansion function P_SHA1
688  for(i = 0; i < outputLen; )
689  {
690  //Compute HMAC_SHA1(S2, A(i) + label + seed)
691  hmacInit(hmacContext, SHA1_HASH_ALGO, s2, sLen);
692  hmacUpdate(hmacContext, a, SHA1_DIGEST_SIZE);
693  hmacUpdate(hmacContext, label, labelLen);
694  hmacUpdate(hmacContext, seed, seedLen);
695  hmacFinal(hmacContext, NULL);
696 
697  //Copy the resulting digest
698  for(j = 0; i < outputLen && j < SHA1_DIGEST_SIZE; i++, j++)
699  {
700  output[i] ^= hmacContext->digest[j];
701  }
702 
703  //Compute A(i + 1) = HMAC_SHA1(S2, A(i))
704  hmacInit(hmacContext, SHA1_HASH_ALGO, s2, sLen);
705  hmacUpdate(hmacContext, a, SHA1_DIGEST_SIZE);
706  hmacFinal(hmacContext, a);
707  }
708 
709  //Free previously allocated memory
710  tlsFreeMem(hmacContext);
711 
712  //Successful processing
713  error = NO_ERROR;
714  }
715  else
716  {
717  //Failed to allocate memory
718  error = ERROR_OUT_OF_MEMORY;
719  }
720 
721  //Return status code
722  return error;
723 #else
724  //Not implemented
725  return ERROR_NOT_IMPLEMENTED;
726 #endif
727 }
728 
729 
730 /**
731  * @brief Pseudorandom function (TLS 1.2)
732  *
733  * The pseudorandom function (PRF) takes as input a secret, a seed, and
734  * an identifying label and produces an output of arbitrary length. This
735  * function is used to expand secrets into blocks of data for the purpose
736  * of key generation
737  *
738  * @param[in] hash Hash function used to compute PRF
739  * @param[in] secret Pointer to the secret
740  * @param[in] secretLen Length of the secret
741  * @param[in] label Identifying label (NULL-terminated string)
742  * @param[in] seed Pointer to the seed
743  * @param[in] seedLen Length of the seed
744  * @param[out] output Pointer to the output
745  * @param[in] outputLen Desired output length
746  * @return Error code
747  **/
748 
749 error_t tls12Prf(const HashAlgo *hash, const uint8_t *secret, size_t secretLen,
750  const char_t *label, const uint8_t *seed, size_t seedLen, uint8_t *output,
751  size_t outputLen)
752 {
753 #if (TLS_MAX_VERSION >= TLS_VERSION_1_2 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
754  error_t error;
755  size_t n;
756  size_t labelLen;
757  HmacContext *hmacContext;
758  uint8_t a[MAX_HASH_DIGEST_SIZE];
759 
760  //Allocate a memory buffer to hold the HMAC context
761  hmacContext = tlsAllocMem(sizeof(HmacContext));
762 
763  //Successful memory allocation?
764  if(hmacContext != NULL)
765  {
766  //Retrieve the length of the label
767  labelLen = strlen(label);
768 
769  //First compute A(1) = HMAC_hash(secret, label + seed)
770  hmacInit(hmacContext, hash, secret, secretLen);
771  hmacUpdate(hmacContext, label, labelLen);
772  hmacUpdate(hmacContext, seed, seedLen);
773  hmacFinal(hmacContext, a);
774 
775  //Apply the data expansion function P_hash
776  while(outputLen > 0)
777  {
778  //Compute HMAC_hash(secret, A(i) + label + seed)
779  hmacInit(hmacContext, hash, secret, secretLen);
780  hmacUpdate(hmacContext, a, hash->digestSize);
781  hmacUpdate(hmacContext, label, labelLen);
782  hmacUpdate(hmacContext, seed, seedLen);
783  hmacFinal(hmacContext, NULL);
784 
785  //Calculate the number of bytes to copy
786  n = MIN(outputLen, hash->digestSize);
787  //Copy the resulting digest
788  memcpy(output, hmacContext->digest, n);
789 
790  //Compute A(i + 1) = HMAC_hash(secret, A(i))
791  hmacInit(hmacContext, hash, secret, secretLen);
792  hmacUpdate(hmacContext, a, hash->digestSize);
793  hmacFinal(hmacContext, a);
794 
795  //Advance data pointer
796  output += n;
797  //Decrement byte counter
798  outputLen -= n;
799  }
800 
801  //Free previously allocated memory
802  tlsFreeMem(hmacContext);
803 
804  //Successful processing
805  error = NO_ERROR;
806  }
807  else
808  {
809  //Failed to allocate memory
810  error = ERROR_OUT_OF_MEMORY;
811  }
812 
813  //Return status code
814  return error;
815 #else
816  //Not implemented
817  return ERROR_NOT_IMPLEMENTED;
818 #endif
819 }
820 
821 
822 /**
823  * @brief Dump secret key (for debugging purpose only)
824  * @param[in] context Pointer to the TLS context
825  * @param[in] label Identifying label (NULL-terminated string)
826  * @param[in] secret Pointer to the secret key
827  * @param[in] secretLen Length of the secret key, in bytes
828  * @return Error code
829  **/
830 
831 void tlsDumpSecret(TlsContext *context, const char_t *label,
832  const uint8_t *secret, size_t secretLen)
833 {
834 #if (TLS_KEY_LOG_SUPPORT == ENABLED)
835  //Any registered callback?
836  if(context->keyLogCallback != NULL)
837  {
838  size_t i;
839  size_t n;
840  char_t buffer[194];
841 
842  //Retrieve the length of the label
843  n = strlen(label);
844 
845  //Sanity check
846  if((n + 2 * secretLen + 67) <= sizeof(buffer))
847  {
848  //Copy the identifying label
849  strncpy(buffer, label, n);
850 
851  //Append a space character
852  buffer[n++] = ' ';
853 
854  //Convert the client random value to a hex string
855  for(i = 0; i < 32; i++)
856  {
857  //Format current byte
858  n += sprintf(buffer + n, "%02" PRIX8, context->clientRandom[i]);
859  }
860 
861  //Append a space character
862  buffer[n++] = ' ';
863 
864  //Convert the secret key to a hex string
865  for(i = 0; i < secretLen; i++)
866  {
867  //Format current byte
868  n += sprintf(buffer + n, "%02" PRIX8, secret[i]);
869  }
870 
871  //Properly terminate the string with a NULL character
872  buffer[n] = '\0';
873 
874  //Invoke user callback function
875  context->keyLogCallback(context, buffer);
876  }
877  }
878 #endif
879 }
880 
881 #endif
#define tlsAllocMem(size)
Definition: tls.h:757
int bool_t
Definition: compiler_port.h:49
HMAC algorithm context.
Definition: hmac.h:182
#define SHA1_HASH_ALGO
Definition: sha1.h:46
uint8_t a
Definition: ndp.h:410
Key material generation.
error_t tlsGeneratePskPremasterSecret(TlsContext *context)
Premaster secret generation (for PSK cipher suites)
@ ERROR_BUFFER_OVERFLOW
Definition: error.h:140
@ 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)
size_t digestSize
Definition: crypto.h:1135
@ ERROR_OUT_OF_RESOURCES
Definition: error.h:64
error_t tlsExportKeyingMaterial(TlsContext *context, const char_t *label, bool_t useContextValue, const uint8_t *contextValue, size_t contextValueLen, uint8_t *output, size_t outputLen)
Export keying material per RFC 5705 standard.
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:1812
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
error_t tlsGenerateMasterSecret(TlsContext *context)
Master secret computation.
SSL 3.0 helper functions.
@ ERROR_INVALID_VERSION
Definition: error.h:116
#define TLS_RANDOM_SIZE
Definition: tls.h:834
size_t contextSize
Definition: crypto.h:1133
error_t sslExpandKey(const uint8_t *secret, size_t secretLen, const uint8_t *random, size_t randomLen, uint8_t *output, size_t outputLen)
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define TlsContext
Definition: tls.h:36
@ ERROR_UNSUPPORTED_KEY_EXCH_METHOD
Definition: error.h:129
error_t
Error codes.
Definition: error.h:42
#define TLS_VERSION_1_2
Definition: tls.h:94
#define TLS_PREMASTER_SECRET_SIZE
Definition: tls.h:722
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define STORE16BE(a, p)
Definition: cpu_endian.h:246
#define MD5_HASH_ALGO
Definition: md5.h:46
#define TLS_VERSION_1_3
Definition: tls.h:95
void hmacFinal(HmacContext *context, uint8_t *digest)
Finish the HMAC calculation.
Definition: hmac.c:185
#define SSL_VERSION_3_0
Definition: tls.h:91
#define MIN(a, b)
Definition: os_port.h:62
@ TLS_KEY_EXCH_DHE_PSK
Definition: tls.h:1040
#define MD5_DIGEST_SIZE
Definition: md5.h:40
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)
error_t tls13HkdfExpandLabel(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)
#define TLS_MASTER_SECRET_SIZE
Definition: tls.h:836
Transcript hash calculation.
@ TLS_KEY_EXCH_RSA_PSK
Definition: tls.h:1039
HashAlgoFinal final
Definition: crypto.h:1141
uint8_t hash
Definition: tls.h:1369
#define TRACE_DEBUG(...)
Definition: debug.h:106
char char_t
Definition: compiler_port.h:43
#define TLS_VERSION_1_1
Definition: tls.h:93
uint8_t digest[MAX_HASH_DIGEST_SIZE]
Definition: hmac.h:187
#define SHA1_DIGEST_SIZE
Definition: sha1.h:40
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)
error_t tlsGenerateExtendedMasterSecret(TlsContext *context)
Extended master secret computation.
void hmacInit(HmacContext *context, const HashAlgo *hash, const void *key, size_t keyLen)
Initialize HMAC calculation.
Definition: hmac.c:118
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:107
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:168
uint8_t digest[1]
Definition: crypto.h:1120
uint8_t n
uint16_t cipherSuite
Cipher suite identifier.
Definition: tls13_misc.h:372
#define TLS_VERSION_1_0
Definition: tls.h:92
@ TLS_KEY_EXCH_PSK
Definition: tls.h:1038
@ TLS_KEY_EXCH_ECDHE_PSK
Definition: tls.h:1041
#define TLS_MAX_HKDF_DIGEST_SIZE
Definition: tls.h:817
error_t tlsGenerateKeyBlock(TlsContext *context, size_t keyBlockLen)
Key expansion function.
TLS (Transport Layer Security)
uint8_t random[32]
Definition: tls.h:1614
TLS 1.3 key schedule.
Common interface for hash algorithms.
Definition: crypto.h:1128
#define MAX_HASH_DIGEST_SIZE
Definition: crypto.h:811
error_t tlsGenerateSessionKeys(TlsContext *context)
Generate session keys.
unsigned int uint_t
Definition: compiler_port.h:45
#define tlsFreeMem(p)
Definition: tls.h:762
Generic hash algorithm context.
Definition: crypto.h:1118
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.