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