1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** NetX Secure Component                                                 */
17 /**                                                                       */
18 /**    Transport Layer Security (TLS) - Generate Session Keys             */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 #define NX_SECURE_SOURCE_CODE
24 
25 #include "nx_secure_tls.h"
26 #ifdef NX_SECURE_ENABLE_DTLS
27 #include "nx_secure_dtls.h"
28 #endif /* NX_SECURE_ENABLE_DTLS */
29 
30 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
31 
32 /* Some secret generation requires a string of zeroes with a length
33    equivalent to the key/hash size. This array is used for that with a memset. */
34 static UCHAR _nx_secure_tls_zeroes[NX_SECURE_TLS_MAX_KEY_SIZE];
35 
36 static UINT _nx_secure_tls_1_3_generate_handshake_secrets(NX_SECURE_TLS_SESSION *tls_session);
37 
38 static UINT _nx_secure_tls_1_3_generate_session_secrets(NX_SECURE_TLS_SESSION *tls_session);
39 
40 
41 static UINT _nx_secure_tls_hkdf_expand_label(NX_SECURE_TLS_SESSION *tls_session, UCHAR *secret, UINT secret_len,
42             UCHAR *label, UINT label_len, UCHAR *context, UINT context_len, UINT length,
43             UCHAR *output, UINT output_length, const NX_CRYPTO_METHOD *hash_method);
44 
45 static UINT _nx_secure_tls_derive_secret(NX_SECURE_TLS_SESSION *tls_session, UCHAR *secret, UINT secret_len,
46                                   UCHAR *label, UINT label_len,
47                                   UCHAR *message_hash, UINT message_hash_len,
48                                   UCHAR *output, UINT output_length, const NX_CRYPTO_METHOD *hash_method);
49 
50 static UINT _nx_secure_tls_hkdf_extract(NX_SECURE_TLS_SESSION *tls_session, UCHAR *salt, UINT salt_len,
51                                       UCHAR *ikm, UINT ikm_len, UCHAR *output, UINT output_length, const NX_CRYPTO_METHOD *hash_method);
52 #endif
53 
54 
55 
56 /**************************************************************************/
57 /*                                                                        */
58 /*  FUNCTION                                               RELEASE        */
59 /*                                                                        */
60 /*    _nx_secure_tls_1_3_generate_psk_secrets             PORTABLE C      */
61 /*                                                           6.1          */
62 /*  AUTHOR                                                                */
63 /*                                                                        */
64 /*    Timothy Stapko, Microsoft Corporation                               */
65 /*                                                                        */
66 /*  DESCRIPTION                                                           */
67 /*                                                                        */
68 /*    This function is used by TLS 1.3 to generate the secrets and keys   */
69 /*    needed for PSK binder generation. Since each "external" PSK needs   */
70 /*    a binder generated from the early secret (which is generated using  */
71 /*    that PSK), each PSK gets a separate "early secret" and "binder key".*/
72 /*    Therefore, this function will be called for *every* PSK provided by */
73 /*    the application, each time with a different PSK and hash method.    */
74 /*                                                                        */
75 /*  INPUT                                                                 */
76 /*                                                                        */
77 /*    tls_session                           TLS control block             */
78 /*                                                                        */
79 /*  OUTPUT                                                                */
80 /*                                                                        */
81 /*    status                                Completion status             */
82 /*                                                                        */
83 /*  CALLS                                                                 */
84 /*                                                                        */
85 /*                                                                        */
86 /*  CALLED BY                                                             */
87 /*                                                                        */
88 /*                                                                        */
89 /*  RELEASE HISTORY                                                       */
90 /*                                                                        */
91 /*    DATE              NAME                      DESCRIPTION             */
92 /*                                                                        */
93 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
94 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
95 /*                                            resulting in version 6.1    */
96 /*                                                                        */
97 /**************************************************************************/
98 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
99 
_nx_secure_tls_1_3_generate_psk_secret(NX_SECURE_TLS_SESSION * tls_session,NX_SECURE_TLS_PSK_STORE * psk_entry,const NX_CRYPTO_METHOD * hash_method)100 UINT _nx_secure_tls_1_3_generate_psk_secret(NX_SECURE_TLS_SESSION *tls_session, NX_SECURE_TLS_PSK_STORE *psk_entry, const NX_CRYPTO_METHOD *hash_method)
101 {
102 UINT status;
103 UINT hash_length;
104 UCHAR *psk_secret;
105 UINT   psk_secret_length;
106 UCHAR *label;
107 UINT label_length;
108 UINT is_resumption_psk = NX_FALSE;
109 
110 
111     /* Get the hash length so we know how much data we are generating. */
112     hash_length = (hash_method->nx_crypto_ICV_size_in_bits >> 3);
113 
114     /* The PSK is the input to the early secret. */
115     psk_secret = (UCHAR *)psk_entry->nx_secure_tls_psk_data;
116     psk_secret_length = psk_entry->nx_secure_tls_psk_data_size;
117 
118     NX_SECURE_MEMSET(_nx_secure_tls_zeroes, 0, sizeof(_nx_secure_tls_zeroes));
119 
120     /* Perform an HKDF-Extract to get the "early secret". */
121     /* Salt: 0 string, IKM: PSK secret. */
122 
123 
124     status = _nx_secure_tls_hkdf_extract(tls_session, _nx_secure_tls_zeroes, hash_length, psk_secret, psk_secret_length,
125                                          psk_entry->nx_secure_tls_psk_early_secret, hash_length, hash_method);
126 
127     if(status != NX_SUCCESS)
128     {
129         return(status);
130     }
131 
132     psk_entry->nx_secure_tls_psk_early_secret_size = hash_length;
133 
134     /*----- Binder key value. -----*/
135 
136     /* Get the appropriate label for our secret derivation. */
137     label = (UCHAR *)((is_resumption_psk)? "res binder" : "ext binder" );
138     label_length = 10;
139 
140     /* Ext/Res binder key has an empty messages context. */
141     status = _nx_secure_tls_derive_secret(tls_session, psk_entry->nx_secure_tls_psk_early_secret, psk_entry->nx_secure_tls_psk_early_secret_size,
142                                           label, label_length,
143                                           (UCHAR *)"", 0,
144                                           psk_entry->nx_secure_tls_psk_binder_key, hash_length, hash_method);
145 
146     if(status != NX_SUCCESS)
147     {
148         return(status);
149     }
150 
151     psk_entry->nx_secure_tls_psk_binder_key_size = hash_length;
152 
153     /* Generate Finished Key. According to RFC 8446 Section 4.2.11.2, we generate the PSK binder in the same
154      * fashion as the Finished message, but using the binder key as input to the HKDF expansion. Thus, generate a "finished"
155      * key for this specific PSK entry to use in the binder generation. */
156     status = _nx_secure_tls_hkdf_expand_label(tls_session, psk_entry->nx_secure_tls_psk_binder_key, psk_entry->nx_secure_tls_psk_binder_key_size,
157                                           (UCHAR *)"finished", 8, (UCHAR *)"", 0, hash_length,
158                                           psk_entry->nx_secure_tls_psk_finished_key, hash_length, hash_method);
159 
160     psk_entry->nx_secure_tls_psk_finished_key_size = hash_length;
161 
162     return(status);
163 }
164 #endif
165 
166 
167 /**************************************************************************/
168 /*                                                                        */
169 /*  FUNCTION                                               RELEASE        */
170 /*                                                                        */
171 /*    _nx_secure_tls_1_3_generate_handshake_keys          PORTABLE C      */
172 /*                                                           6.1.8        */
173 /*  AUTHOR                                                                */
174 /*                                                                        */
175 /*    Timothy Stapko, Microsoft Corporation                               */
176 /*                                                                        */
177 /*  DESCRIPTION                                                           */
178 /*                                                                        */
179 /*    This function is used by TLS 1.3 to generate the symmetric          */
180 /*    encryption keys used to protect TLS handshake messages.             */
181 /*                                                                        */
182 /*  INPUT                                                                 */
183 /*                                                                        */
184 /*    tls_session                           TLS control block             */
185 /*                                                                        */
186 /*  OUTPUT                                                                */
187 /*                                                                        */
188 /*    status                                Completion status             */
189 /*                                                                        */
190 /*  CALLS                                                                 */
191 /*                                                                        */
192 /*                                                                        */
193 /*  CALLED BY                                                             */
194 /*                                                                        */
195 /*                                                                        */
196 /*  RELEASE HISTORY                                                       */
197 /*                                                                        */
198 /*    DATE              NAME                      DESCRIPTION             */
199 /*                                                                        */
200 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
201 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
202 /*                                            resulting in version 6.1    */
203 /*  08-02-2021     Timothy Stapko           Modified comment(s), added    */
204 /*                                            cleanup for session cipher, */
205 /*                                            resulting in version 6.1.8  */
206 /*                                                                        */
207 /**************************************************************************/
208 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
209 
_nx_secure_tls_1_3_generate_handshake_keys(NX_SECURE_TLS_SESSION * tls_session)210 UINT _nx_secure_tls_1_3_generate_handshake_keys(NX_SECURE_TLS_SESSION *tls_session)
211 {
212 UINT status;
213 UCHAR                                *key_block;
214 ULONG                                 key_block_size;
215 NX_SECURE_TLS_KEY_SECRETS *secrets;
216 const NX_CRYPTO_METHOD                     *session_cipher_method = NX_NULL;
217 const NX_CRYPTO_METHOD                     *hash_method = NX_NULL;
218 UINT                                  key_size;
219 UINT                                  iv_size;
220 UINT                                  key_offset;
221 UINT                                  hash_size;
222 
223     /* From RFC 8446, Section 7.3:
224     The traffic keying material is generated from an input traffic secret
225     value using:
226 
227     [sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length)
228     [sender]_write_iv  = HKDF-Expand-Label(Secret, "iv", "", iv_length)
229 
230     [sender] denotes the sending side.  The value of Secret for each
231     record type is shown in the table below.
232 
233         +-------------------+---------------------------------------+
234         | Record Type       | Secret                                |
235         +-------------------+---------------------------------------+
236         | 0-RTT Application | client_early_traffic_secret           |
237         |                   |                                       |
238         | Handshake         | [sender]_handshake_traffic_secret     |
239         |                   |                                       |
240         | Application Data  | [sender]_application_traffic_secret_N |
241         +-------------------+---------------------------------------+
242     */
243 
244     /* Generate handshake secrets. */
245     status = _nx_secure_tls_1_3_generate_handshake_secrets(tls_session);
246 
247     /* Get our generated secrets. */
248     secrets = &tls_session->nx_secure_tls_key_material.nx_secure_tls_key_secrets;
249 
250     if(status != NX_SUCCESS)
251     {
252         return(status);
253     }
254 
255     if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL)
256     {
257         /* Likely internal error since at this point ciphersuite negotiation was theoretically completed. */
258         return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE);
259     }
260 
261     /* Get our session cipher method so we can get key sizes. */
262     session_cipher_method = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_session_cipher;
263 
264     hash_method = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_hash;
265 
266     /* Lookup ciphersuite data for key size. We need 2 keys for each session. */
267     key_size = session_cipher_method -> nx_crypto_key_size_in_bits >> 3;
268 
269     /* Lookup initialization vector size.  */
270     /* IV size for AES-128-GCM is 12 bytes! */
271     iv_size = 12; // session_cipher_method -> nx_crypto_IV_size_in_bits >> 3;
272 
273     /* Working pointers into our key material blocks - we need a place to store generated keys. */
274     key_block = tls_session -> nx_secure_tls_key_material.nx_secure_tls_key_material_data;
275     key_block_size = sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_key_material_data);
276 
277 
278     /* Assign MAC secrets to TLS Session. */
279     tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_write_mac_secret = secrets->tls_client_handshake_traffic_secret;
280     tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_write_mac_secret = secrets->tls_server_handshake_traffic_secret;
281 
282     /* To generate handshake keys, we need the [sender]_handshake_traffic_secret. */
283 
284     /* Generate client traffic key. */
285     key_offset = 0;
286     status = _nx_secure_tls_hkdf_expand_label(tls_session, secrets->tls_client_handshake_traffic_secret, secrets->tls_client_handshake_traffic_secret_len,
287                                           (UCHAR *)"key", 3, (UCHAR *)"", 0, key_size,
288                                           &key_block[key_offset], (key_block_size - key_offset), hash_method);
289 
290     if(status != NX_SUCCESS)
291     {
292         return(status);
293     }
294 
295     tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_write_key = &key_block[key_offset];
296 
297     key_offset += key_size;
298 
299     /* Generate client traffic IV. */
300     status = _nx_secure_tls_hkdf_expand_label(tls_session, secrets->tls_client_handshake_traffic_secret, secrets->tls_client_handshake_traffic_secret_len,
301                                           (UCHAR *)"iv", 2, (UCHAR *)"", 0, iv_size,
302                                           &key_block[key_offset], (key_block_size - key_offset), hash_method);
303 
304     if(status != NX_SUCCESS)
305     {
306         return(status);
307     }
308 
309     tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_iv = &key_block[key_offset];
310 
311     key_offset += iv_size;
312 
313     /* Generate server-side key. */
314     status = _nx_secure_tls_hkdf_expand_label(tls_session, secrets->tls_server_handshake_traffic_secret, secrets->tls_server_handshake_traffic_secret_len,
315                                           (UCHAR *)"key", 3, (UCHAR *)"", 0, key_size,
316                                           &key_block[key_offset], (key_block_size - key_offset), hash_method);
317 
318     if(status != NX_SUCCESS)
319     {
320         return(status);
321     }
322 
323     tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_write_key = &key_block[key_offset];
324 
325     key_offset += key_size;
326 
327     /* Generate server-side IV. */
328     status = _nx_secure_tls_hkdf_expand_label(tls_session, secrets->tls_server_handshake_traffic_secret, secrets->tls_server_handshake_traffic_secret_len,
329                                           (UCHAR *)"iv", 2, (UCHAR *)"", 0, iv_size,
330                                           &key_block[key_offset], (key_block_size - key_offset), hash_method);
331 
332     if(status != NX_SUCCESS)
333     {
334         return(status);
335     }
336 
337     tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_iv = &key_block[key_offset];
338 
339     key_offset += iv_size;
340 
341     /* We now have the session keys so we can generate the Finished keys for both client and server. */
342     /*  From RFC 8446 (TLS 1.3):
343         finished_key =
344               HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)
345     */
346 
347     /* Get hash size for this ciphersuite. */
348     hash_size = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_hash_size;
349 
350     /* Generate server-side Finished Key. */
351     status = _nx_secure_tls_hkdf_expand_label(tls_session, secrets->tls_server_handshake_traffic_secret, secrets->tls_server_handshake_traffic_secret_len,
352                                           (UCHAR *)"finished", 8, (UCHAR *)"", 0, hash_size,
353                                           &secrets->tls_server_finished_key[0], (key_block_size - key_offset), hash_method);
354 
355     if(status != NX_SUCCESS)
356     {
357         return(status);
358     }
359 
360     secrets->tls_server_finished_key_len = hash_size;
361 
362     /* Generate client-side Finished Key. */
363     status = _nx_secure_tls_hkdf_expand_label(tls_session, secrets->tls_client_handshake_traffic_secret, secrets->tls_client_handshake_traffic_secret_len,
364                                           (UCHAR *)"finished", 8, (UCHAR *)"", 0, hash_size,
365                                           &secrets->tls_client_finished_key[0], (key_block_size - key_offset), hash_method);
366 
367     secrets->tls_client_finished_key_len = hash_size;
368 
369     if(status != NX_SUCCESS)
370     {
371         return(status);
372     }
373 
374 
375     /* Now, we can initialize our crypto routines and turn on encryption. */
376     /* Initialize the crypto method used in the session cipher. */
377     if (session_cipher_method -> nx_crypto_init != NULL)
378     {
379         if (tls_session -> nx_secure_tls_session_cipher_client_initialized && session_cipher_method -> nx_crypto_cleanup)
380         {
381             status = session_cipher_method -> nx_crypto_cleanup(tls_session -> nx_secure_session_cipher_metadata_area_client);
382             if (status != NX_CRYPTO_SUCCESS)
383             {
384                 return(status);
385             }
386 
387             tls_session -> nx_secure_tls_session_cipher_client_initialized = 0;
388         }
389 
390         /* Set client write key. */
391         status = session_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_cipher_method,
392                                                          tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_write_key,
393                                                          session_cipher_method -> nx_crypto_key_size_in_bits,
394                                                          &tls_session -> nx_secure_session_cipher_handler_client,
395                                                          tls_session -> nx_secure_session_cipher_metadata_area_client,
396                                                          tls_session -> nx_secure_session_cipher_metadata_size);
397 
398         if (status != NX_CRYPTO_SUCCESS)
399         {
400             return(status);
401         }
402 
403         tls_session -> nx_secure_tls_session_cipher_client_initialized = 1;
404 
405         if (tls_session -> nx_secure_tls_session_cipher_server_initialized && session_cipher_method -> nx_crypto_cleanup)
406         {
407             status = session_cipher_method -> nx_crypto_cleanup(tls_session -> nx_secure_session_cipher_metadata_area_server);
408             if (status != NX_CRYPTO_SUCCESS)
409             {
410                 return(status);
411             }
412 
413             tls_session -> nx_secure_tls_session_cipher_server_initialized = 0;
414         }
415 
416         /* Set server write key. */
417         status = session_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_cipher_method,
418                                                          tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_write_key,
419                                                          session_cipher_method -> nx_crypto_key_size_in_bits,
420                                                          &tls_session -> nx_secure_session_cipher_handler_server,
421                                                          tls_session -> nx_secure_session_cipher_metadata_area_server,
422                                                          tls_session -> nx_secure_session_cipher_metadata_size);
423 
424         if (status != NX_CRYPTO_SUCCESS)
425         {
426             return(status);
427         }
428 
429         tls_session -> nx_secure_tls_session_cipher_server_initialized = 1;
430     }
431 
432     return(NX_SUCCESS);
433 }
434 
435 #endif
436 
437 /**************************************************************************/
438 /*                                                                        */
439 /*  FUNCTION                                               RELEASE        */
440 /*                                                                        */
441 /*    _nx_secure_tls_1_3_generate_session_keys            PORTABLE C      */
442 /*                                                           6.1          */
443 /*  AUTHOR                                                                */
444 /*                                                                        */
445 /*    Timothy Stapko, Microsoft Corporation                               */
446 /*                                                                        */
447 /*  DESCRIPTION                                                           */
448 /*                                                                        */
449 /*    This function is used by TLS 1.3 to generate the symmetric          */
450 /*    encryption keys used to protect application data.                   */
451 /*                                                                        */
452 /*  INPUT                                                                 */
453 /*                                                                        */
454 /*    tls_session                           TLS control block             */
455 /*                                                                        */
456 /*  OUTPUT                                                                */
457 /*                                                                        */
458 /*    status                                Completion status             */
459 /*                                                                        */
460 /*  CALLS                                                                 */
461 /*                                                                        */
462 /*                                                                        */
463 /*  CALLED BY                                                             */
464 /*                                                                        */
465 /*                                                                        */
466 /*  RELEASE HISTORY                                                       */
467 /*                                                                        */
468 /*    DATE              NAME                      DESCRIPTION             */
469 /*                                                                        */
470 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
471 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
472 /*                                            resulting in version 6.1    */
473 /*                                                                        */
474 /**************************************************************************/
475 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
476 
_nx_secure_tls_1_3_generate_session_keys(NX_SECURE_TLS_SESSION * tls_session)477 UINT _nx_secure_tls_1_3_generate_session_keys(NX_SECURE_TLS_SESSION *tls_session)
478 {
479 UINT status;
480 UCHAR                                *key_block;
481 ULONG                                 key_block_size;
482 NX_SECURE_TLS_KEY_SECRETS *secrets;
483 const NX_CRYPTO_METHOD                     *session_cipher_method = NX_NULL;
484 const NX_CRYPTO_METHOD                     *hash_method = NX_NULL;
485 UINT                                  key_size;
486 UINT                                  iv_size;
487 UINT                                  key_offset;
488 
489     /* From RFC 8446, Section 7.3:
490     The traffic keying material is generated from an input traffic secret
491     value using:
492 
493     [sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length)
494     [sender]_write_iv  = HKDF-Expand-Label(Secret, "iv", "", iv_length)
495 
496     [sender] denotes the sending side.  The value of Secret for each
497     record type is shown in the table below.
498 
499         +-------------------+---------------------------------------+
500         | Record Type       | Secret                                |
501         +-------------------+---------------------------------------+
502         | 0-RTT Application | client_early_traffic_secret           |
503         |                   |                                       |
504         | Handshake         | [sender]_handshake_traffic_secret     |
505         |                   |                                       |
506         | Application Data  | [sender]_application_traffic_secret_N |
507         +-------------------+---------------------------------------+
508     */
509 
510     /* Generate handshake secrets. */
511     status = _nx_secure_tls_1_3_generate_session_secrets(tls_session);
512 
513     /* Get our generated secrets. */
514     secrets = &tls_session->nx_secure_tls_key_material.nx_secure_tls_key_secrets;
515 
516     if(status != NX_SUCCESS)
517     {
518         return(status);
519     }
520 
521     if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL)
522     {
523         /* Likely internal error since at this point ciphersuite negotiation was theoretically completed. */
524         return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE);
525     }
526 
527     /* Get our session cipher method so we can get key sizes. */
528     session_cipher_method = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_session_cipher;
529 
530     hash_method = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_hash;
531 
532     /* Lookup ciphersuite data for key size. We need 2 keys for each session. */
533     key_size = session_cipher_method -> nx_crypto_key_size_in_bits >> 3;
534 
535     /* Lookup initialization vector size.  */
536 //    iv_size = session_cipher_method -> nx_crypto_IV_size_in_bits >> 3;
537 
538     /* IV size for AES-128-GCM is 12 bytes. */
539     iv_size = 12; // session_cipher_method -> nx_crypto_IV_size_in_bits >> 3;
540 
541     /* Working pointers into our key material blocks - we need a place to store generated keys.
542      * Whenever we generate session keys in TLS 1.3 we are coming from an existing encrypted
543      * context so save the keys to the "on-deck" space to be enabled later. */
544     key_block = tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data;
545     key_block_size = sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_key_material_data);
546 
547 
548     /* Assign MAC secrets to TLS Session. */
549     tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_write_mac_secret = secrets->tls_client_application_traffic_secret_0;
550     tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_write_mac_secret = secrets->tls_server_application_traffic_secret_0;
551 
552     /* To generate handshake keys, we need the [sender]_handshake_traffic_secret. */
553 
554     /* Generate client traffic key. */
555     key_offset = 0;
556     status = _nx_secure_tls_hkdf_expand_label(tls_session, secrets->tls_client_application_traffic_secret_0, secrets->tls_client_application_traffic_secret_0_len,
557                                           (UCHAR *)"key", 3, (UCHAR *)"", 0, key_size,
558                                           &key_block[key_offset], (key_block_size - key_offset), hash_method);
559 
560     if(status != NX_SUCCESS)
561     {
562         return(status);
563     }
564 
565     /* Save the generated keys to the on-deck space (don't initialize yet). */
566     tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_next_write_key = &key_block[key_offset];
567 
568     key_offset += key_size;
569 
570     /* Generate client traffic IV. */
571     status = _nx_secure_tls_hkdf_expand_label(tls_session, secrets->tls_client_application_traffic_secret_0, secrets->tls_client_application_traffic_secret_0_len,
572                                           (UCHAR *)"iv", 2, (UCHAR *)"", 0, iv_size,
573                                           &key_block[key_offset], (key_block_size - key_offset), hash_method);
574 
575     if(status != NX_SUCCESS)
576     {
577         return(status);
578     }
579 
580     tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_next_iv = &key_block[key_offset];
581 
582     key_offset += iv_size;
583 
584     /* Generate server-side key. */
585     status = _nx_secure_tls_hkdf_expand_label(tls_session, secrets->tls_server_application_traffic_secret_0, secrets->tls_server_application_traffic_secret_0_len,
586                                           (UCHAR *)"key", 3, (UCHAR *)"", 0, key_size,
587                                           &key_block[key_offset], (key_block_size - key_offset), hash_method);
588 
589     if(status != NX_SUCCESS)
590     {
591         return(status);
592     }
593 
594     tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_next_write_key = &key_block[key_offset];
595 
596     key_offset += key_size;
597 
598     /* Generate server-side IV. */
599     status = _nx_secure_tls_hkdf_expand_label(tls_session, secrets->tls_server_application_traffic_secret_0, secrets->tls_server_application_traffic_secret_0_len,
600                                           (UCHAR *)"iv", 2, (UCHAR *)"", 0, iv_size,
601                                           &key_block[key_offset], (key_block_size - key_offset), hash_method);
602 
603     if(status != NX_SUCCESS)
604     {
605         return(status);
606     }
607 
608     tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_next_iv = &key_block[key_offset];
609 
610     key_offset += iv_size;
611 
612     if(status != NX_SUCCESS)
613     {
614         return(status);
615     }
616 
617     return(NX_SUCCESS);
618 
619 }
620 
621 #endif
622 
623 /**************************************************************************/
624 /*                                                                        */
625 /*  FUNCTION                                               RELEASE        */
626 /*                                                                        */
627 /*    _nx_secure_tls_generate_session_psk                 PORTABLE C      */
628 /*                                                           6.1          */
629 /*  AUTHOR                                                                */
630 /*                                                                        */
631 /*    Timothy Stapko, Microsoft Corporation                               */
632 /*                                                                        */
633 /*  DESCRIPTION                                                           */
634 /*                                                                        */
635 /*    This function is used by TLS 1.3 to generate a PSK for use in       */
636 /*    session resumptions, using the nonce provided in the                */
637 /*    NewSessionTicket message.                                           */
638 /*                                                                        */
639 /*  INPUT                                                                 */
640 /*                                                                        */
641 /*    tls_session                           TLS control block             */
642 /*    ticket_psk                            PSK control block for output  */
643 /*    nonce                                 Pointer to session nonce      */
644 /*    nonce_len                             Length of nonce               */
645 /*                                                                        */
646 /*  OUTPUT                                                                */
647 /*                                                                        */
648 /*    status                                Completion status             */
649 /*                                                                        */
650 /*  CALLS                                                                 */
651 /*                                                                        */
652 /*                                                                        */
653 /*  CALLED BY                                                             */
654 /*                                                                        */
655 /*                                                                        */
656 /*  RELEASE HISTORY                                                       */
657 /*                                                                        */
658 /*    DATE              NAME                      DESCRIPTION             */
659 /*                                                                        */
660 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
661 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
662 /*                                            resulting in version 6.1    */
663 /*                                                                        */
664 /**************************************************************************/
665 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
666 
_nx_secure_tls_1_3_session_psk_generate(NX_SECURE_TLS_SESSION * tls_session,NX_SECURE_TLS_PSK_STORE * ticket_psk,UCHAR * nonce,UINT nonce_len)667 UINT _nx_secure_tls_1_3_session_psk_generate(NX_SECURE_TLS_SESSION *tls_session, NX_SECURE_TLS_PSK_STORE *ticket_psk, UCHAR *nonce, UINT nonce_len)
668 {
669 NX_SECURE_TLS_KEY_SECRETS *secrets;
670 UINT status;
671 UINT hash_length;
672 const NX_CRYPTO_METHOD *hash_method;
673 
674     /* Session PSK is generated as follows (From RFC 8446):
675      *      HKDF-Expand-Label(resumption_master_secret,
676      *                        "resumption", ticket_nonce, Hash.length)
677      *
678      */
679 
680     /* Get a pointer to our key secrets for this session. */
681     secrets = &tls_session->nx_secure_tls_key_material.nx_secure_tls_key_secrets;
682 
683     if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL)
684     {
685         /* Likely internal error since at this point ciphersuite negotiation was theoretically completed. */
686         return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE);
687     }
688 
689     /* Get the hash method so we know how much data we are generating. */
690     hash_method = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_hash;
691     hash_length = (hash_method->nx_crypto_ICV_size_in_bits >> 3);
692 
693     /* Generate the PSK by running HKDF-Expand-Label with the resumption secret and the passed-in nonce. */
694     status = _nx_secure_tls_hkdf_expand_label(tls_session, secrets->tls_resumption_master_secret, secrets->tls_resumption_master_secret_len,
695                                           (UCHAR *)"resumption", 10, nonce, nonce_len, hash_length,
696                                           ticket_psk->nx_secure_tls_psk_data,
697                                           sizeof(ticket_psk->nx_secure_tls_psk_data), hash_method);
698 
699     /* Set the length of our PSK. */
700     ticket_psk->nx_secure_tls_psk_data_size = hash_length;
701 
702     return(status);
703 }
704 #endif
705 
706 /**************************************************************************/
707 /*                                                                        */
708 /*  FUNCTION                                               RELEASE        */
709 /*                                                                        */
710 /*    _nx_secure_tls_1_3_generate_handshake_secrets       PORTABLE C      */
711 /*                                                           6.1          */
712 /*  AUTHOR                                                                */
713 /*                                                                        */
714 /*    Timothy Stapko, Microsoft Corporation                               */
715 /*                                                                        */
716 /*  DESCRIPTION                                                           */
717 /*                                                                        */
718 /*    This function is used by TLS 1.3 in generating key material.        */
719 /*                                                                        */
720 /*  INPUT                                                                 */
721 /*                                                                        */
722 /*    tls_session                           TLS control block             */
723 /*                                                                        */
724 /*  OUTPUT                                                                */
725 /*                                                                        */
726 /*    status                                Completion status             */
727 /*                                                                        */
728 /*  CALLS                                                                 */
729 /*                                                                        */
730 /*                                                                        */
731 /*  CALLED BY                                                             */
732 /*                                                                        */
733 /*                                                                        */
734 /*  RELEASE HISTORY                                                       */
735 /*                                                                        */
736 /*    DATE              NAME                      DESCRIPTION             */
737 /*                                                                        */
738 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
739 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
740 /*                                            resulting in version 6.1    */
741 /*                                                                        */
742 /**************************************************************************/
743 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
744 
_nx_secure_tls_1_3_generate_handshake_secrets(NX_SECURE_TLS_SESSION * tls_session)745 static UINT _nx_secure_tls_1_3_generate_handshake_secrets(NX_SECURE_TLS_SESSION *tls_session)
746 {
747 UINT status;
748 NX_SECURE_TLS_KEY_SECRETS *secrets;
749 UINT hash_length;
750 const NX_CRYPTO_METHOD *hash_method;
751 UCHAR *psk_secret;
752 UINT   psk_secret_length;
753 UCHAR *label;
754 UINT label_length;
755 UINT is_resumption_psk = NX_FALSE;
756 
757     if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL)
758     {
759         /* Likely internal error since at this point ciphersuite negotiation was theoretically completed. */
760         return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE);
761     }
762 
763     /* Get the hash method so we know how much data we are generating. */
764     hash_method = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_hash;
765     hash_length = (hash_method->nx_crypto_ICV_size_in_bits >> 3);
766 
767     /* Get a pointer to our key secrets for this session. */
768     secrets = &tls_session->nx_secure_tls_key_material.nx_secure_tls_key_secrets;
769 
770     /* From RFC 8446, section 7.1:
771 
772        Keys are derived from two input secrets using the HKDF-Extract and
773        Derive-Secret functions.  The general pattern for adding a new secret
774        is to use HKDF-Extract with the Salt being the current secret state
775        and the Input Keying Material (IKM) being the new secret to be added.
776        In this version of TLS 1.3, the two input secrets are:
777 
778        -  PSK (a pre-shared key established externally or derived from the
779           resumption_master_secret value from a previous connection)
780 
781        -  (EC)DHE shared secret (Section 7.4)
782 
783        This produces a full key derivation schedule shown in the diagram
784        below.  In this diagram, the following formatting conventions apply:
785 
786        -  HKDF-Extract is drawn as taking the Salt argument from the top and
787           the IKM argument from the left, with its output to the bottom and
788           the name of the output on the right.
789 
790        -  Derive-Secret's Secret argument is indicated by the incoming
791           arrow.  For instance, the Early Secret is the Secret for
792           generating the client_early_traffic_secret.
793 
794        -  "0" indicates a string of Hash.length bytes set to zero.
795 
796                  0
797                  |
798                  v
799        PSK ->  HKDF-Extract = Early Secret
800                  |
801                  +-----> Derive-Secret(., "ext binder" | "res binder", "")
802                  |                     = binder_key
803                  |
804                  +-----> Derive-Secret(., "c e traffic", ClientHello)
805                  |                     = client_early_traffic_secret
806                  |
807                  +-----> Derive-Secret(., "e exp master", ClientHello)
808                  |                     = early_exporter_master_secret
809                  v
810            Derive-Secret(., "derived", "")
811                  |
812                  v
813        (EC)DHE -> HKDF-Extract = Handshake Secret
814                  |
815                  +-----> Derive-Secret(., "c hs traffic",
816                  |                     ClientHello...ServerHello)
817                  |                     = client_handshake_traffic_secret
818                  |
819                  +-----> Derive-Secret(., "s hs traffic",
820                  |                     ClientHello...ServerHello)
821                  |                     = server_handshake_traffic_secret
822                  v
823            Derive-Secret(., "derived", "")
824                  |
825                  v
826        0 -> HKDF-Extract = Master Secret
827                  |
828                  +-----> Derive-Secret(., "c ap traffic",
829                  |                     ClientHello...server Finished)
830                  |                     = client_application_traffic_secret_0
831                  |
832                  +-----> Derive-Secret(., "s ap traffic",
833                  |                     ClientHello...server Finished)
834                  |                     = server_application_traffic_secret_0
835                  |
836                  +-----> Derive-Secret(., "exp master",
837                  |                     ClientHello...server Finished)
838                  |                     = exporter_master_secret
839                  |
840                  +-----> Derive-Secret(., "res master",
841                                        ClientHello...client Finished)
842                                        = resumption_master_secret
843 
844        The general pattern here is that the secrets shown down the left side
845        of the diagram are just raw entropy without context, whereas the
846        secrets down the right side include Handshake Context and therefore
847        can be used to derive working keys without additional context.  Note
848        that the different calls to Derive-Secret may take different Messages
849        arguments, even with the same secret.  In a 0-RTT exchange,
850        Derive-Secret is called with four distinct transcripts; in a
851        1-RTT-only exchange, it is called with three distinct transcripts.
852 
853        If a given secret is not available, then the 0-value consisting of a
854        string of Hash.length bytes set to zeros is used.  Note that this
855        does not mean skipping rounds, so if PSK is not in use, Early Secret
856        will still be HKDF-Extract(0, 0).  For the computation of the
857        binder_key, the label is "ext binder" for external PSKs (those
858        provisioned outside of TLS) and "res binder" for resumption PSKs
859        (those provisioned as the resumption master secret of a previous
860        handshake).  The different labels prevent the substitution of one
861        type of PSK for the other.
862 
863        There are multiple potential Early Secret values, depending on which
864        PSK the server ultimately selects.  The client will need to compute
865        one for each potential PSK; if no PSK is selected, it will then need
866        to compute the Early Secret corresponding to the zero PSK.
867 
868        Once all the values which are to be derived from a given secret have
869        been computed, that secret SHOULD be erased.
870 
871 
872      */
873 
874     /* Go through all secrets, generate those that haven't been generated yet. */
875 
876     /* If available, the chosen PSK is fed into the key generation process. */
877     /* If PSK is not in use, Early Secret will still be HKDF-Extract(0, 0). So set PSK as "0". */
878     psk_secret = _nx_secure_tls_zeroes;
879     psk_secret_length = hash_length;
880 
881     if(tls_session->nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_data_size > 0)
882     {
883         psk_secret = tls_session->nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_data;
884         psk_secret_length = tls_session->nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_data_size;
885     }
886 
887     NX_SECURE_MEMSET(_nx_secure_tls_zeroes, 0, sizeof(_nx_secure_tls_zeroes));
888 
889     if(secrets->tls_early_secret_len == 0)
890     {
891         /* Perform an HKDF-Extract to get the "early secret". */
892         /* Salt: 0 string, IKM: PSK secret. */
893         status = _nx_secure_tls_hkdf_extract(tls_session, _nx_secure_tls_zeroes, hash_length, psk_secret, psk_secret_length,
894                                              secrets->tls_early_secret, hash_length, hash_method);
895 
896         if(status != NX_SUCCESS)
897         {
898             return(status);
899         }
900         secrets->tls_early_secret_len = hash_length;
901     }
902 
903     /* Generate keys and secrets based on the "early secret". */
904     if(secrets->tls_early_secret_len != 0)
905     {
906         /*----- Binder key value. -----*/
907 
908         /* Get the appropriate label for our secret derivation. */
909         label = (UCHAR *)((is_resumption_psk)? "res binder" : "ext binder");
910         label_length = 10;
911 
912         /* Ext/Res binder key has an empty messages context. */
913         status = _nx_secure_tls_derive_secret(tls_session, secrets->tls_early_secret, secrets->tls_early_secret_len, label, label_length,
914                                               (UCHAR *)"", 0,
915                                               secrets->tls_binder_key, hash_length, hash_method);
916 
917         if(status != NX_SUCCESS)
918         {
919             return(status);
920         }
921         secrets->tls_binder_key_len = hash_length;
922 
923         /*----- Early traffic secret. -----*/
924         label = (UCHAR *)"c e traffic";
925         label_length = 11;
926 
927         /* Context is hash of ClientHello. */
928         status = _nx_secure_tls_derive_secret(tls_session, secrets->tls_early_secret, secrets->tls_early_secret_len, label, label_length,
929                                               (UCHAR *)"FIXME", 5,
930                                               secrets->tls_client_early_traffic_secret, hash_length, hash_method);
931 
932         if(status != NX_SUCCESS)
933         {
934             return(status);
935         }
936         secrets->tls_client_early_traffic_secret_len = hash_length;
937 
938         /*----- Early exporter master secret. -----*/
939         label = (UCHAR *)"e exp master";
940         label_length = 12;
941 
942         /* Context is hash of ClientHello. */
943         status = _nx_secure_tls_derive_secret(tls_session, secrets->tls_early_secret, secrets->tls_early_secret_len, label, label_length,
944                                               (UCHAR *)"FIXME", 5,
945                                               secrets->tls_early_exporter_master_secret, hash_length, hash_method);
946 
947         if(status != NX_SUCCESS)
948         {
949             return(status);
950         }
951         secrets->tls_early_exporter_master_secret_len = hash_length;
952     }
953 
954     /* Handshake secret - special case! Needs a pre-master secret from the ECDHE exchange and the early secret from above. */
955     if(secrets->tls_handshake_secret_len == 0 && tls_session->nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size != 0)
956     {
957         /* Start by deriving the salt from the early secret. Context is empty! */
958         status = _nx_secure_tls_derive_secret(tls_session, secrets->tls_early_secret, secrets->tls_early_secret_len, (UCHAR *)"derived", 7,
959                                               (UCHAR *)"", 0,
960                                               secrets->tls_handshake_secret, hash_length, hash_method);
961 
962         if(status != NX_SUCCESS)
963         {
964             return(status);
965         }
966 
967         /* Now perform an HKDF-Extract to get the handshake secret.
968            Salt: derived secret from above, IKM: ECDHE pre-master secret */
969         status = _nx_secure_tls_hkdf_extract(tls_session, secrets->tls_handshake_secret, hash_length,
970                                              tls_session->nx_secure_tls_key_material.nx_secure_tls_pre_master_secret,
971                                              tls_session->nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size,
972                                              secrets->tls_handshake_secret, hash_length, hash_method);
973 
974         if(status != NX_SUCCESS)
975         {
976             return(status);
977         }
978         secrets->tls_handshake_secret_len = hash_length;
979     }
980 
981     /* Generate keys and secrets based on the "handshake secret". */
982     if(secrets->tls_handshake_secret_len != 0)
983     {
984         /*----- Client handshake traffic secret. -----*/
985         label = (UCHAR *)"c hs traffic";
986         label_length = 12;
987 
988         status = _nx_secure_tls_derive_secret(tls_session, secrets->tls_handshake_secret, secrets->tls_handshake_secret_len, label, label_length,
989                                               tls_session->nx_secure_tls_key_material.nx_secure_tls_transcript_hashes[NX_SECURE_TLS_TRANSCRIPT_IDX_SERVERHELLO], hash_length,
990                                               secrets->tls_client_handshake_traffic_secret, hash_length, hash_method);
991 
992         if(status != NX_SUCCESS)
993         {
994             return(status);
995         }
996         secrets->tls_client_handshake_traffic_secret_len = hash_length;
997 
998         /*----- Server handshake traffic secret. -----*/
999         label = (UCHAR *)"s hs traffic";
1000         label_length = 12;
1001 
1002         status = _nx_secure_tls_derive_secret(tls_session, secrets->tls_handshake_secret, secrets->tls_handshake_secret_len, label, label_length,
1003                                               tls_session->nx_secure_tls_key_material.nx_secure_tls_transcript_hashes[NX_SECURE_TLS_TRANSCRIPT_IDX_SERVERHELLO], hash_length,
1004                                               secrets->tls_server_handshake_traffic_secret, hash_length, hash_method);
1005 
1006         if(status != NX_SUCCESS)
1007         {
1008             return(status);
1009         }
1010         secrets->tls_server_handshake_traffic_secret_len = hash_length;
1011     }
1012 
1013     return(NX_SUCCESS);
1014 }
1015 #endif
1016 
1017 /**************************************************************************/
1018 /*                                                                        */
1019 /*  FUNCTION                                               RELEASE        */
1020 /*                                                                        */
1021 /*    _nx_secure_tls_1_3_generate_session_secrets         PORTABLE C      */
1022 /*                                                           6.1          */
1023 /*  AUTHOR                                                                */
1024 /*                                                                        */
1025 /*    Timothy Stapko, Microsoft Corporation                               */
1026 /*                                                                        */
1027 /*  DESCRIPTION                                                           */
1028 /*                                                                        */
1029 /*    This function is used by TLS 1.3 in generating key material.        */
1030 /*                                                                        */
1031 /*  INPUT                                                                 */
1032 /*                                                                        */
1033 /*    tls_session                           TLS control block             */
1034 /*                                                                        */
1035 /*  OUTPUT                                                                */
1036 /*                                                                        */
1037 /*    status                                Completion status             */
1038 /*                                                                        */
1039 /*  CALLS                                                                 */
1040 /*                                                                        */
1041 /*                                                                        */
1042 /*  CALLED BY                                                             */
1043 /*                                                                        */
1044 /*                                                                        */
1045 /*  RELEASE HISTORY                                                       */
1046 /*                                                                        */
1047 /*    DATE              NAME                      DESCRIPTION             */
1048 /*                                                                        */
1049 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
1050 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
1051 /*                                            resulting in version 6.1    */
1052 /*                                                                        */
1053 /**************************************************************************/
1054 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
1055 
_nx_secure_tls_1_3_generate_session_secrets(NX_SECURE_TLS_SESSION * tls_session)1056 static UINT _nx_secure_tls_1_3_generate_session_secrets(NX_SECURE_TLS_SESSION *tls_session)
1057 {
1058 UINT status;
1059 NX_SECURE_TLS_KEY_SECRETS *secrets;
1060 UINT hash_length;
1061 const NX_CRYPTO_METHOD *hash_method;
1062 UCHAR *label;
1063 UINT label_length;
1064 UCHAR (*transcript_hashes)[NX_SECURE_TLS_MAX_HASH_SIZE] = tls_session->nx_secure_tls_key_material.nx_secure_tls_transcript_hashes;
1065 
1066 
1067 
1068     if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL)
1069     {
1070         /* Likely internal error since at this point ciphersuite negotiation was theoretically completed. */
1071         return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE);
1072     }
1073 
1074     /* Get the hash method so we know how much data we are generating. */
1075     hash_method = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_hash;
1076     hash_length = (hash_method->nx_crypto_ICV_size_in_bits >> 3);
1077 
1078     /* Get a pointer to our key secrets for this session. */
1079     secrets = &tls_session->nx_secure_tls_key_material.nx_secure_tls_key_secrets;
1080 
1081     /* Make sure our zeroes string is initialized. */
1082     NX_SECURE_MEMSET(_nx_secure_tls_zeroes, 0, sizeof(_nx_secure_tls_zeroes));
1083 
1084     /* Application Master secret - special case! Needs a secret derived from the previous secret. */
1085     if(secrets->tls_master_secret_len == 0 && secrets->tls_handshake_secret_len != 0)
1086     {
1087         /* Start by deriving the salt from the handshake secret. Context is empty! */
1088         status = _nx_secure_tls_derive_secret(tls_session, secrets->tls_handshake_secret, secrets->tls_handshake_secret_len, (UCHAR *)"derived", 7,
1089                                               (UCHAR *)"", 0,
1090                                               secrets->tls_master_secret, hash_length, hash_method);
1091 
1092         if(status != NX_SUCCESS)
1093         {
1094             return(status);
1095         }
1096 
1097         /* Now perform an HKDF-Extract to get the application master secret.
1098            Salt: derived secret from above, IKM: 0 string  */
1099         status = _nx_secure_tls_hkdf_extract(tls_session, secrets->tls_master_secret, hash_length,
1100                                              _nx_secure_tls_zeroes, hash_length,
1101                                              secrets->tls_master_secret, hash_length, hash_method);
1102 
1103         if(status != NX_SUCCESS)
1104         {
1105             return(status);
1106         }
1107         secrets->tls_master_secret_len = hash_length;
1108     }
1109 
1110     /* Derive secrets based on the application master secret. */
1111     if(secrets->tls_master_secret_len != 0)
1112     {
1113         /*----- Client application traffic secret 0. -----*/
1114         label = (UCHAR *)"c ap traffic";
1115         label_length = 12;
1116 
1117         status = _nx_secure_tls_derive_secret(tls_session, secrets->tls_master_secret, secrets->tls_master_secret_len, label, label_length,
1118                                               transcript_hashes[NX_SECURE_TLS_TRANSCRIPT_IDX_SERVER_FINISHED], hash_length,
1119                                               secrets->tls_client_application_traffic_secret_0, hash_length, hash_method);
1120 
1121         if(status != NX_SUCCESS)
1122         {
1123             return(status);
1124         }
1125         secrets->tls_client_application_traffic_secret_0_len = hash_length;
1126 
1127         /*----- Server application traffic secret 0. -----*/
1128         label = (UCHAR *)"s ap traffic";
1129         label_length = 12;
1130 
1131         status = _nx_secure_tls_derive_secret(tls_session, secrets->tls_master_secret, secrets->tls_master_secret_len, label, label_length,
1132                                               transcript_hashes[NX_SECURE_TLS_TRANSCRIPT_IDX_SERVER_FINISHED], hash_length,
1133                                               secrets->tls_server_application_traffic_secret_0, hash_length, hash_method);
1134 
1135         if(status != NX_SUCCESS)
1136         {
1137             return(status);
1138         }
1139         secrets->tls_server_application_traffic_secret_0_len = hash_length;
1140 
1141         /*----- Exporter master secret. -----*/
1142         label = (UCHAR *)"exp master";
1143         label_length = 10;
1144 
1145         status = _nx_secure_tls_derive_secret(tls_session, secrets->tls_master_secret, secrets->tls_master_secret_len, label, label_length,
1146                                               transcript_hashes[NX_SECURE_TLS_TRANSCRIPT_IDX_SERVER_FINISHED], hash_length,
1147                                               secrets->tls_exporter_master_secret, hash_length, hash_method);
1148 
1149         if(status != NX_SUCCESS)
1150         {
1151             return(status);
1152         }
1153         secrets->tls_early_exporter_master_secret_len = hash_length;
1154 
1155         /*----- Resumption master secret. -----*/
1156         label = (UCHAR *)"res master";
1157         label_length = 10;
1158 
1159         status = _nx_secure_tls_derive_secret(tls_session, secrets->tls_master_secret, secrets->tls_master_secret_len, label, label_length,
1160                                               transcript_hashes[NX_SECURE_TLS_TRANSCRIPT_IDX_CLIENT_FINISHED], hash_length,
1161                                               secrets->tls_resumption_master_secret, hash_length, hash_method);
1162 
1163         if(status != NX_SUCCESS)
1164         {
1165             return(status);
1166         }
1167         secrets->tls_resumption_master_secret_len = hash_length;
1168 
1169 
1170     }
1171 
1172     return(NX_SUCCESS);
1173 }
1174 #endif
1175 
1176 /**************************************************************************/
1177 /*                                                                        */
1178 /*  FUNCTION                                               RELEASE        */
1179 /*                                                                        */
1180 /*    _nx_secure_tls_derive_secret                        PORTABLE C      */
1181 /*                                                           6.1          */
1182 /*  AUTHOR                                                                */
1183 /*                                                                        */
1184 /*    Timothy Stapko, Microsoft Corporation                               */
1185 /*                                                                        */
1186 /*  DESCRIPTION                                                           */
1187 /*                                                                        */
1188 /*    This function is used by TLS 1.3 in generating key material.        */
1189 /*                                                                        */
1190 /*  INPUT                                                                 */
1191 /*                                                                        */
1192 /*    tls_session                           TLS control block             */
1193 /*                                                                        */
1194 /*  OUTPUT                                                                */
1195 /*                                                                        */
1196 /*    status                                Completion status             */
1197 /*                                                                        */
1198 /*  CALLS                                                                 */
1199 /*                                                                        */
1200 /*                                                                        */
1201 /*  CALLED BY                                                             */
1202 /*                                                                        */
1203 /*                                                                        */
1204 /*  RELEASE HISTORY                                                       */
1205 /*                                                                        */
1206 /*    DATE              NAME                      DESCRIPTION             */
1207 /*                                                                        */
1208 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
1209 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
1210 /*                                            resulting in version 6.1    */
1211 /*                                                                        */
1212 /**************************************************************************/
1213 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
1214 
1215 static UCHAR _nx_secure_tls_temp_hash[100];
1216 
_nx_secure_tls_derive_secret(NX_SECURE_TLS_SESSION * tls_session,UCHAR * secret,UINT secret_len,UCHAR * label,UINT label_len,UCHAR * message_hash,UINT message_hash_len,UCHAR * output,UINT output_length,const NX_CRYPTO_METHOD * hash_method)1217 static UINT _nx_secure_tls_derive_secret(NX_SECURE_TLS_SESSION *tls_session, UCHAR *secret, UINT secret_len,
1218                                   UCHAR *label, UINT label_len,
1219                                   UCHAR *message_hash, UINT message_hash_len,
1220                                   UCHAR *output, UINT output_length, const NX_CRYPTO_METHOD *hash_method)
1221 {
1222 UINT status;
1223 UINT hash_length;
1224 
1225 /* From RFC 8446, section 7.1:
1226         Derive-Secret(Secret, Label, Messages) =
1227                  HKDF-Expand-Label(Secret, Label,
1228                                    Transcript-Hash(Messages), Hash.length)
1229 */
1230 
1231 
1232     /* Get session hash routine. */
1233     hash_length = (hash_method->nx_crypto_ICV_size_in_bits >> 3);
1234 
1235 
1236     /* Our "messages" parameter is actually the ongoing hash of handshake
1237        messages stored in the TLS session context. In some contexts, the message hash will be of 0 length! */
1238     if(message_hash_len == 0)
1239     {
1240         /* Point the message hash at our temporary buffer. */
1241         message_hash = &_nx_secure_tls_temp_hash[0];
1242         message_hash_len = hash_length;
1243 
1244         /* Context has 0 length, so generate a hash on the empty string to feed into expand label call below.
1245          * Utilize the temporary "hash scratch" data buffer to initialize and calculate the hash. */
1246         if (hash_method -> nx_crypto_init)
1247         {
1248             status = hash_method -> nx_crypto_init((NX_CRYPTO_METHOD*)hash_method,
1249                                                    NX_NULL,
1250                                                    0,
1251                                                    tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_handler,
1252                                                    tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
1253                                                    tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size);
1254 
1255             if (status != NX_CRYPTO_SUCCESS)
1256             {
1257                 return(status);
1258             }
1259         }
1260 
1261         if (hash_method -> nx_crypto_operation != NX_NULL)
1262         {
1263             status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE,
1264                                                         tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_handler,
1265                                                         (NX_CRYPTO_METHOD*)hash_method,
1266                                                         NX_NULL,
1267                                                         0,
1268                                                         NX_NULL,
1269                                                         0,
1270                                                         NX_NULL,
1271                                                         NX_NULL,
1272                                                         0,
1273                                                         tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
1274                                                         tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size,
1275                                                         NX_NULL,
1276                                                         NX_NULL);
1277 
1278             if (status != NX_CRYPTO_SUCCESS)
1279             {
1280                 return(status);
1281             }
1282         }
1283 
1284         if (hash_method -> nx_crypto_operation != NX_NULL)
1285         {
1286            status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
1287                                                       tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_handler,
1288                                                       (NX_CRYPTO_METHOD*)hash_method,
1289                                                       NX_NULL,
1290                                                       0,
1291                                                       (UCHAR *)"",
1292                                                       0,
1293                                                       NX_NULL,
1294                                                       NX_NULL,
1295                                                       0,
1296                                                       tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
1297                                                       tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size,
1298                                                       NX_NULL,
1299                                                       NX_NULL);
1300 
1301            if (status != NX_CRYPTO_SUCCESS)
1302            {
1303                return(status);
1304            }
1305         }
1306 
1307 
1308 
1309         /* Generate a hash using our temporary copy of the hash metadata, place it into the TLS Session transcript hash array. */
1310         if (hash_method -> nx_crypto_operation != NX_NULL)
1311         {
1312             status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE,
1313                                                         tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_handler,
1314                                                         (NX_CRYPTO_METHOD*)hash_method,
1315                                                         NX_NULL,
1316                                                         0,
1317                                                         NX_NULL,
1318                                                         0,
1319                                                         NX_NULL,
1320                                                         message_hash,
1321                                                         hash_length,
1322                                                         tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
1323                                                         tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size,
1324                                                         NX_NULL,
1325                                                         NX_NULL);
1326 
1327             if (status != NX_CRYPTO_SUCCESS)
1328             {
1329                 return(status);
1330             }
1331 
1332         }
1333     }
1334 
1335     /* Now derive the output by calling HKDF-Expand-Label. */
1336     status = _nx_secure_tls_hkdf_expand_label(tls_session, secret, secret_len,
1337             label, label_len, message_hash, message_hash_len, hash_length,
1338             output, output_length, hash_method);
1339 
1340     return(status);
1341 }
1342 
1343 #endif
1344 
1345 /**************************************************************************/
1346 /*                                                                        */
1347 /*  FUNCTION                                               RELEASE        */
1348 /*                                                                        */
1349 /*    _nx_secure_tls_hkdf_expand_label                    PORTABLE C      */
1350 /*                                                           6.1          */
1351 /*  AUTHOR                                                                */
1352 /*                                                                        */
1353 /*    Timothy Stapko, Microsoft Corporation                               */
1354 /*                                                                        */
1355 /*  DESCRIPTION                                                           */
1356 /*                                                                        */
1357 /*    This function is used by TLS 1.3 in generating key material.        */
1358 /*                                                                        */
1359 /*  INPUT                                                                 */
1360 /*                                                                        */
1361 /*    tls_session                           TLS control block             */
1362 /*                                                                        */
1363 /*  OUTPUT                                                                */
1364 /*                                                                        */
1365 /*    status                                Completion status             */
1366 /*                                                                        */
1367 /*  CALLS                                                                 */
1368 /*                                                                        */
1369 /*                                                                        */
1370 /*  CALLED BY                                                             */
1371 /*                                                                        */
1372 /*                                                                        */
1373 /*  RELEASE HISTORY                                                       */
1374 /*                                                                        */
1375 /*    DATE              NAME                      DESCRIPTION             */
1376 /*                                                                        */
1377 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
1378 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
1379 /*                                            verified memcpy use cases,  */
1380 /*                                            resulting in version 6.1    */
1381 /*                                                                        */
1382 /**************************************************************************/
1383 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
1384 
1385 /* Buffer for HKDF output. The HKDF temporary can technically be as big as
1386    514 bytes: 2 (length) + 1 (label length byte) + 255 (label) + 1 (context length byte) + 255 (context).
1387    However, 100 bytes is sufficient for the mandatory ciphersuite. */
1388 static UCHAR _nx_secure_tls_hkdf_temp_output[100];
_nx_secure_tls_hkdf_expand_label(NX_SECURE_TLS_SESSION * tls_session,UCHAR * secret,UINT secret_len,UCHAR * label,UINT label_len,UCHAR * context,UINT context_len,UINT length,UCHAR * output,UINT output_length,const NX_CRYPTO_METHOD * hash_method)1389 static UINT _nx_secure_tls_hkdf_expand_label(NX_SECURE_TLS_SESSION *tls_session, UCHAR *secret, UINT secret_len,
1390                                       UCHAR *label, UINT label_len, UCHAR *context, UINT context_len, UINT length,
1391                                       UCHAR *output, UINT output_length, const NX_CRYPTO_METHOD *hash_method)
1392 {
1393 UINT                                 status;
1394 UINT                                 data_len;
1395 const NX_CRYPTO_METHOD                     *session_hkdf_method = NX_NULL;
1396 const NX_CRYPTO_METHOD                     *session_hmac_method = NX_NULL;
1397 
1398 /*VOID                                 *handler = NX_NULL;*/
1399     /* From RFC 8446, section 7.1:
1400     HKDF-Expand-Label(Secret, Label, Context, Length) =
1401            HKDF-Expand(Secret, HkdfLabel, Length)
1402 
1403       Where HkdfLabel is specified as:
1404 
1405       struct {
1406           uint16 length = Length;
1407           opaque label<7..255> = "tls13 " + Label;
1408           opaque context<0..255> = Context;
1409       } HkdfLabel;
1410     */
1411 
1412     if (sizeof(_nx_secure_tls_hkdf_temp_output) < (10u + label_len + context_len))
1413     {
1414 
1415         /* Buffer too small. */
1416         return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
1417     }
1418 
1419     /* Get our HKDF method and hash routine. */
1420     /*session_hash_method = ciphersuite->nx_secure_tls_hash;*/
1421     session_hkdf_method = tls_session->nx_secure_tls_crypto_table->nx_secure_tls_hkdf_method;
1422     session_hmac_method = tls_session->nx_secure_tls_crypto_table->nx_secure_tls_hmac_method;
1423 
1424     /* Now build the HkdfLabel from our inputs. */
1425     _nx_secure_tls_hkdf_temp_output[0] = (UCHAR)((length & 0xFF00) >> 8);
1426     _nx_secure_tls_hkdf_temp_output[1] = (UCHAR)(length & 0x00FF);
1427     data_len = 2;
1428 
1429     /* Add the length of the label (single octet). */
1430     _nx_secure_tls_hkdf_temp_output[data_len] = (UCHAR)(6 + label_len);
1431     data_len = data_len + 1;
1432 
1433     /* Now copy in label with TLS 1.3 prefix. */
1434     NX_CRYPTO_MEMCPY(&_nx_secure_tls_hkdf_temp_output[data_len], "tls13 ", 6); /* Use case of memcpy is verified. */
1435     data_len += 6;
1436     NX_CRYPTO_MEMCPY(&_nx_secure_tls_hkdf_temp_output[data_len], label, label_len); /* Use case of memcpy is verified. */
1437     data_len += label_len;
1438 
1439     /* Add the length of the context (single octet). */
1440     _nx_secure_tls_hkdf_temp_output[data_len] = (UCHAR)(context_len);
1441     data_len = data_len + 1;
1442 
1443     /* Now copy in context. */
1444     NX_CRYPTO_MEMCPY(&_nx_secure_tls_hkdf_temp_output[data_len], context, context_len); /* Use case of memcpy is verified. */
1445     data_len += context_len;
1446 
1447 
1448     /* Initialize the HKDF context. */
1449     status = session_hkdf_method->nx_crypto_init((NX_CRYPTO_METHOD*)session_hkdf_method, NX_NULL, 0, NX_NULL,
1450                                         tls_session -> nx_secure_tls_prf_metadata_area,
1451                                         tls_session -> nx_secure_tls_prf_metadata_size);
1452 
1453     if(status != NX_CRYPTO_SUCCESS)
1454     {
1455         return(status);
1456     }
1457 
1458     /* Set the hash and HMAC routines for the HKDF. */
1459     status = session_hkdf_method->nx_crypto_operation(NX_CRYPTO_HKDF_SET_HMAC, NX_NULL, (NX_CRYPTO_METHOD*)session_hmac_method,
1460                                              NX_NULL, 0, NX_NULL, 0, NX_NULL, NX_NULL, 0,
1461                                              tls_session -> nx_secure_tls_prf_metadata_area,
1462                                              tls_session -> nx_secure_tls_prf_metadata_size,
1463                                              NX_NULL, NX_NULL);
1464 
1465     if(status != NX_CRYPTO_SUCCESS)
1466     {
1467         return(status);
1468     }
1469 
1470     status = session_hkdf_method->nx_crypto_operation(NX_CRYPTO_HKDF_SET_HASH, NX_NULL,
1471                                              (NX_CRYPTO_METHOD*)hash_method,
1472                                              NX_NULL, 0,NX_NULL, 0, NX_NULL, NX_NULL, 0,
1473                                              tls_session -> nx_secure_tls_prf_metadata_area,
1474                                              tls_session -> nx_secure_tls_prf_metadata_size,
1475                                              NX_NULL, NX_NULL);
1476 
1477     if(status != NX_CRYPTO_SUCCESS)
1478     {
1479         return(status);
1480     }
1481 
1482     /* Set the PRK for the HKDF-expand operation. */
1483     status = session_hkdf_method->nx_crypto_operation(NX_CRYPTO_HKDF_SET_PRK,
1484                                              NX_NULL,
1485                                              (NX_CRYPTO_METHOD*)session_hkdf_method,
1486                                              (UCHAR*)(secret),     /* Input HKDF label. */
1487                                              (secret_len << 3),
1488                                              NX_NULL,
1489                                              0,
1490                                              NX_NULL,
1491                                              NX_NULL,
1492                                              0,
1493                                              tls_session -> nx_secure_tls_prf_metadata_area,
1494                                              tls_session -> nx_secure_tls_prf_metadata_size,
1495                                              NX_NULL, NX_NULL);
1496 
1497     if(status != NX_CRYPTO_SUCCESS)
1498     {
1499         return(status);
1500     }
1501 
1502     /* Now perform the HKDF operation. */
1503     status = session_hkdf_method->nx_crypto_operation(NX_CRYPTO_HKDF_EXPAND,
1504                                              NX_NULL,
1505                                              (NX_CRYPTO_METHOD*)session_hkdf_method,
1506                                              (UCHAR*)(_nx_secure_tls_hkdf_temp_output), /* Input HKDF label. */
1507                                              (data_len << 3),
1508                                              NX_NULL,
1509                                              0,
1510                                              NX_NULL,
1511                                              (UCHAR *)output,
1512                                              output_length,
1513                                              tls_session -> nx_secure_tls_prf_metadata_area,
1514                                              tls_session -> nx_secure_tls_prf_metadata_size,
1515                                              NX_NULL, NX_NULL);
1516 
1517     return(status);
1518 }
1519 #endif
1520 
1521 
1522 /**************************************************************************/
1523 /*                                                                        */
1524 /*  FUNCTION                                               RELEASE        */
1525 /*                                                                        */
1526 /*    _nx_secure_tls_hkdf_extract                         PORTABLE C      */
1527 /*                                                           6.1          */
1528 /*  AUTHOR                                                                */
1529 /*                                                                        */
1530 /*    Timothy Stapko, Microsoft Corporation                               */
1531 /*                                                                        */
1532 /*  DESCRIPTION                                                           */
1533 /*                                                                        */
1534 /*    This function is used by TLS 1.3 in generating key material.        */
1535 /*                                                                        */
1536 /*  INPUT                                                                 */
1537 /*                                                                        */
1538 /*    tls_session                           TLS control block             */
1539 /*    salt                                  HKDF salt parameter           */
1540 /*    salt_len                              Length of salt                */
1541 /*    ikm                                   HKDF input key material       */
1542 /*    ikm_len                               Length of IKM                 */
1543 /*    output                                Output buffer                 */
1544 /*    output_length                         Desired output length         */
1545 /*    hash_method                           Hash routine for HMAC         */
1546 /*                                                                        */
1547 /*  OUTPUT                                                                */
1548 /*                                                                        */
1549 /*    status                                Completion status             */
1550 /*                                                                        */
1551 /*  CALLS                                                                 */
1552 /*                                                                        */
1553 /*                                                                        */
1554 /*  CALLED BY                                                             */
1555 /*                                                                        */
1556 /*                                                                        */
1557 /*  RELEASE HISTORY                                                       */
1558 /*                                                                        */
1559 /*    DATE              NAME                      DESCRIPTION             */
1560 /*                                                                        */
1561 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
1562 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
1563 /*                                            resulting in version 6.1    */
1564 /*                                                                        */
1565 /**************************************************************************/
1566 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
1567 
1568 /*static UCHAR _nx_secure_tls_hkdf_label[524];*/
1569 
_nx_secure_tls_hkdf_extract(NX_SECURE_TLS_SESSION * tls_session,UCHAR * salt,UINT salt_len,UCHAR * ikm,UINT ikm_len,UCHAR * output,UINT output_length,const NX_CRYPTO_METHOD * hash_method)1570 static UINT _nx_secure_tls_hkdf_extract(NX_SECURE_TLS_SESSION *tls_session, UCHAR *salt, UINT salt_len,
1571                                       UCHAR *ikm, UINT ikm_len, UCHAR *output, UINT output_length, const NX_CRYPTO_METHOD *hash_method)
1572 {
1573 UINT                                 status;
1574 const NX_CRYPTO_METHOD                     *session_hkdf_method = NX_NULL;
1575 const NX_CRYPTO_METHOD                     *session_hmac_method = NX_NULL;
1576 
1577 
1578     /* Get our HKDF method and hash routine. */
1579     session_hkdf_method = tls_session->nx_secure_tls_crypto_table->nx_secure_tls_hkdf_method;
1580     session_hmac_method = tls_session->nx_secure_tls_crypto_table->nx_secure_tls_hmac_method;
1581 
1582     /* Initialize the HKDF context with our IKM. */
1583     status = session_hkdf_method->nx_crypto_init((NX_CRYPTO_METHOD*)session_hkdf_method, ikm, ikm_len << 3, NX_NULL,
1584                                         tls_session -> nx_secure_tls_prf_metadata_area,
1585                                         tls_session -> nx_secure_tls_prf_metadata_size);
1586 
1587     if(status != NX_CRYPTO_SUCCESS)
1588     {
1589         return(status);
1590     }
1591 
1592     /* Set the hash and HMAC routines for the HKDF. */
1593     status = session_hkdf_method->nx_crypto_operation(NX_CRYPTO_HKDF_SET_HMAC, NX_NULL, (NX_CRYPTO_METHOD*)session_hmac_method,
1594                                              NX_NULL, 0, NX_NULL, 0, NX_NULL, NX_NULL, 0,
1595                                              tls_session -> nx_secure_tls_prf_metadata_area,
1596                                              tls_session -> nx_secure_tls_prf_metadata_size,
1597                                              NX_NULL, NX_NULL);
1598 
1599     if(status != NX_CRYPTO_SUCCESS)
1600     {
1601         return(status);
1602     }
1603 
1604     status = session_hkdf_method->nx_crypto_operation(NX_CRYPTO_HKDF_SET_HASH, NX_NULL,
1605                                              (NX_CRYPTO_METHOD*)hash_method,
1606                                              NX_NULL, 0,NX_NULL, 0, NX_NULL, NX_NULL, 0,
1607                                              tls_session -> nx_secure_tls_prf_metadata_area,
1608                                              tls_session -> nx_secure_tls_prf_metadata_size,
1609                                              NX_NULL, NX_NULL);
1610 
1611     if(status != NX_CRYPTO_SUCCESS)
1612     {
1613         return(status);
1614     }
1615 
1616     /* Now perform the HKDF operation. */
1617     status = session_hkdf_method->nx_crypto_operation(NX_CRYPTO_HKDF_EXTRACT,
1618                                              NX_NULL,
1619                                              (NX_CRYPTO_METHOD*)session_hkdf_method,
1620                                              salt,
1621                                              salt_len << 3,
1622                                              ikm,
1623                                              ikm_len,
1624                                              NX_NULL,
1625                                              (UCHAR *)output,
1626                                              output_length,
1627                                              tls_session -> nx_secure_tls_prf_metadata_area,
1628                                              tls_session -> nx_secure_tls_prf_metadata_size,
1629                                              NX_NULL, NX_NULL);
1630 
1631     return(status);
1632 }
1633 #endif
1634 
1635 
1636