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