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)                                     */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define NX_SECURE_SOURCE_CODE
23 
24 #include "nx_secure_tls.h"
25 
26 /**************************************************************************/
27 /*                                                                        */
28 /*  FUNCTION                                               RELEASE        */
29 /*                                                                        */
30 /*    _nx_secure_tls_session_create_ext                   PORTABLE C      */
31 /*                                                           6.2.1        */
32 /*  AUTHOR                                                                */
33 /*                                                                        */
34 /*    Timothy Stapko, Microsoft Corporation                               */
35 /*                                                                        */
36 /*  DESCRIPTION                                                           */
37 /*                                                                        */
38 /*    This function is the new-style API for creating a new TLS session.  */
39 /*    Like the original function, it initializes a TLS session control    */
40 /*    block for later use in establishing a secure TLS session over a TCP */
41 /*    socket or other lower-level networking protocol. The difference is  */
42 /*    that this function takes an un-ordered array of cryptographic       */
43 /*    methods and a mapping table from ciphersuites to algorithm          */
44 /*    identifiers so the mapping of crypto methods to ciphersuites can be */
45 /*    done automatically, rather than needing to link in all possible     */
46 /*    cipher routines in a single table.                                  */
47 /*                                                                        */
48 /*    To calculate the necessary metadata size, the API                   */
49 /*    nx_secure_tls_metadata_size_calculate may be used.                  */
50 /*                                                                        */
51 /*  INPUT                                                                 */
52 /*                                                                        */
53 /*    session_ptr                           TLS session control block     */
54 /*    crypto_array                          crypto methods to use         */
55 /*    cipher_map                            Mapping table for ciphersuites*/
56 /*    metadata_buffer                       Encryption metadata area      */
57 /*    metadata_size                         Encryption metadata size      */
58 /*                                                                        */
59 /*  OUTPUT                                                                */
60 /*                                                                        */
61 /*    status                                Completion status             */
62 /*                                                                        */
63 /*  CALLS                                                                 */
64 /*                                                                        */
65 /*    _nx_secure_tls_session_reset          Clear out the session         */
66 /*    tx_mutex_get                          Get protection mutex          */
67 /*    tx_mutex_put                          Put protection mutex          */
68 /*                                                                        */
69 /*  CALLED BY                                                             */
70 /*                                                                        */
71 /*    Application Code                                                    */
72 /*                                                                        */
73 /*  RELEASE HISTORY                                                       */
74 /*                                                                        */
75 /*    DATE              NAME                      DESCRIPTION             */
76 /*                                                                        */
77 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
78 /*  09-30-2020     Timothy Stapko           Modified comment(s), and      */
79 /*                                            fixed race condition for    */
80 /*                                            multithread transmission,   */
81 /*                                            added ECC initialization,   */
82 /*                                            fixed renegotiation bug,    */
83 /*                                            resulting in version 6.1    */
84 /*  01-31-2022     Timothy Stapko           Modified comment(s), and      */
85 /*                                            added null pointer checking,*/
86 /*                                            resulting in version 6.1.10 */
87 /*  04-25-2022     Yuxin Zhou               Modified comment(s), and      */
88 /*                                            added null pointer checking,*/
89 /*                                            removed unused code,        */
90 /*                                            resulting in version 6.1.11 */
91 /*  10-31-2022     Yanwu Cai                Modified comment(s), and added*/
92 /*                                            custom secret generation,   */
93 /*                                            resulting in version 6.2.0  */
94 /*  03-08-2023     Yanwu Cai                Modified comment(s),          */
95 /*                                            fixed compiler errors when  */
96 /*                                            x509 is disabled,           */
97 /*                                            resulting in version 6.2.1  */
98 /*                                                                        */
99 /**************************************************************************/
100 
_find_cipher(UINT cipher_id,UINT cipher_role_id,UINT key_size,const NX_CRYPTO_METHOD ** crypto_array,UINT array_size,const NX_CRYPTO_METHOD ** crypto_method)101 static UINT _find_cipher(UINT cipher_id, UINT cipher_role_id, UINT key_size, const NX_CRYPTO_METHOD **crypto_array, UINT array_size, const NX_CRYPTO_METHOD **crypto_method)
102 {
103 UINT i;
104 
105     for(i = 0; i < array_size; ++i)
106     {
107         if(crypto_array[i]->nx_crypto_algorithm == cipher_id)
108         {
109             if (cipher_role_id == NX_CRYPTO_ROLE_SYMMETRIC &&
110                 crypto_array[i] -> nx_crypto_key_size_in_bits != key_size << 3)
111             {
112                 continue;
113             }
114 
115             *crypto_method = crypto_array[i];
116             return(NX_SUCCESS);
117         }
118     }
119 
120     *crypto_method = NX_NULL;
121     return(NX_SECURE_TLS_UNSUPPORTED_CIPHER);
122 }
123 
124 
125 
_map_tls_ciphersuites(NX_SECURE_TLS_SESSION * tls_session,const NX_CRYPTO_METHOD ** crypto_array,UINT crypto_array_size,const NX_CRYPTO_CIPHERSUITE ** cipher_map,UINT cipher_map_size,UINT * metadata_size)126 static UINT _map_tls_ciphersuites(NX_SECURE_TLS_SESSION *tls_session,
127                                   const NX_CRYPTO_METHOD **crypto_array, UINT crypto_array_size,
128                                   const NX_CRYPTO_CIPHERSUITE **cipher_map, UINT cipher_map_size, UINT *metadata_size)
129 {
130 NX_CRYPTO_ROLE_ENTRY            current_cipher;
131 const NX_CRYPTO_METHOD          *cipher_method;
132 NX_SECURE_TLS_CIPHERSUITE_INFO  *cipher_entry;
133 NX_SECURE_TLS_CRYPTO *          crypto_table;
134 UINT                            cipher_id;
135 UINT                            suite;
136 UINT                            cipher_counter;
137 UINT                            remaining_size;
138 UCHAR                           crypto_found;
139 UINT                            status;
140 
141 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
142 UINT ecdhe_found;
143 UINT dhe_found;
144 UINT rsa_found;
145 UINT dsa_found;
146 UINT ecdsa_found;
147 #endif
148 
149 /* Bitmasks for marking found ciphers. */
150 const UCHAR sig_found =     0x1;
151 const UCHAR key_ex_found =  0x2;
152 const UCHAR symm_found =    0x4;
153 const UCHAR hash_found =    0x8;
154 const UCHAR prf_found =     0x10;
155 const UCHAR all_found =     sig_found | key_ex_found | symm_found | hash_found | prf_found;
156 
157     /* Pointer to our lookup table. */
158     crypto_table = tls_session->nx_secure_tls_crypto_table;
159 
160     /* Get a pointer to our entry. */
161     cipher_entry = crypto_table->nx_secure_tls_ciphersuite_lookup_table;
162 
163     /* For bookkeeping, keep track of remaining metadata space. */
164     remaining_size = *metadata_size;
165 
166     /* TLS version-specific cipher mapping. */
167 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
168     /* TLS 1.0, 1.1 both need SHA-1 AND MD5. If both are present, we support those versions, otherwise
169      * we don't support either. */
170 
171     /* Find MD5. If not found, cipher_method is set to NX_NULL so all good either way. */
172     status = _find_cipher(NX_CRYPTO_HASH_MD5, NX_CRYPTO_ROLE_RAW_HASH, 0, crypto_array, crypto_array_size, &cipher_method);
173     crypto_table->nx_secure_tls_handshake_hash_md5_method = cipher_method;
174     if(status != NX_SUCCESS)
175     {
176         /* TLS 1.0, 1.1 NOT supported! */
177         tls_session->nx_secure_tls_supported_versions = (tls_session->nx_secure_tls_supported_versions & (USHORT)(~(NX_SECURE_TLS_BITFIELD_VERSION_1_0)));
178         tls_session->nx_secure_tls_supported_versions = (tls_session->nx_secure_tls_supported_versions & (USHORT)(~(NX_SECURE_TLS_BITFIELD_VERSION_1_1)));
179     }
180 
181     /* Find SHA-1 and assign (if not found, pointer is set to NX_NULL). */
182     status = _find_cipher(NX_CRYPTO_HASH_SHA1, NX_CRYPTO_ROLE_RAW_HASH, 0, crypto_array, crypto_array_size, &cipher_method);
183     crypto_table->nx_secure_tls_handshake_hash_sha1_method = cipher_method;
184 
185     if(status != NX_SUCCESS)
186     {
187         /* TLS 1.0, 1.1 NOT supported! */
188         tls_session->nx_secure_tls_supported_versions = (tls_session->nx_secure_tls_supported_versions & (USHORT)(~(NX_SECURE_TLS_BITFIELD_VERSION_1_0)));
189         tls_session->nx_secure_tls_supported_versions = (tls_session->nx_secure_tls_supported_versions & (USHORT)(~(NX_SECURE_TLS_BITFIELD_VERSION_1_1)));
190     }
191 
192     /* Find TLS PRF (for TLS 1.0 and 1.1) and assign (if not found, pointer is set to NX_NULL). */
193     status = _find_cipher(NX_CRYPTO_PRF_HMAC_SHA1, NX_CRYPTO_ROLE_PRF, 0, crypto_array, crypto_array_size, &cipher_method);
194     crypto_table->nx_secure_tls_prf_1_method = cipher_method;
195 
196     if(status != NX_SUCCESS)
197     {
198         /* TLS 1.0, 1.1 NOT supported! */
199         tls_session->nx_secure_tls_supported_versions = (tls_session->nx_secure_tls_supported_versions & (USHORT)(~(NX_SECURE_TLS_BITFIELD_VERSION_1_0)));
200         tls_session->nx_secure_tls_supported_versions = (tls_session->nx_secure_tls_supported_versions & (USHORT)(~(NX_SECURE_TLS_BITFIELD_VERSION_1_1)));
201     }
202 
203 #endif
204 
205     /* TLS 1.2 - the default PRF uses SHA-256 so make sure we have at least that routine. */
206 #if (NX_SECURE_TLS_TLS_1_2_ENABLED)
207     status = _find_cipher(NX_CRYPTO_HASH_SHA256, NX_CRYPTO_ROLE_RAW_HASH, 0, crypto_array, crypto_array_size, &cipher_method);
208     crypto_table->nx_secure_tls_handshake_hash_sha256_method = cipher_method;
209 
210     if(status != NX_SUCCESS)
211     {
212         /* Version 1.2 NOT supported! */
213         tls_session->nx_secure_tls_supported_versions = (tls_session->nx_secure_tls_supported_versions & (USHORT)(~(NX_SECURE_TLS_BITFIELD_VERSION_1_2)));
214     }
215 
216     /* Find TLS PRF (for TLS 1.0 and 1.1) and assign (if not found, pointer is set to NX_NULL). */
217     status = _find_cipher(NX_CRYPTO_PRF_HMAC_SHA2_256, NX_CRYPTO_ROLE_PRF, 0, crypto_array, crypto_array_size, &cipher_method);
218     crypto_table->nx_secure_tls_prf_sha256_method = cipher_method;
219 
220     if(status != NX_SUCCESS)
221     {
222         /* TLS 1.0, 1.1 NOT supported! */
223         tls_session->nx_secure_tls_supported_versions = (tls_session->nx_secure_tls_supported_versions & (USHORT)(~(NX_SECURE_TLS_BITFIELD_VERSION_1_0)));
224         tls_session->nx_secure_tls_supported_versions = (tls_session->nx_secure_tls_supported_versions & (USHORT)(~(NX_SECURE_TLS_BITFIELD_VERSION_1_1)));
225     }
226 
227 #endif
228 
229 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
230     /* TLS 1.3. */
231     /* TLS 1.3 supports only ECDHE and DHE key exchanges. */
232     ecdhe_found = _find_cipher(NX_CRYPTO_KEY_EXCHANGE_ECDHE, NX_CRYPTO_ROLE_KEY_EXCHANGE, 0, crypto_array, crypto_array_size, &cipher_method);
233     crypto_table->nx_secure_tls_ecdhe_method = cipher_method;
234     dhe_found = _find_cipher(NX_CRYPTO_KEY_EXCHANGE_DHE, NX_CRYPTO_ROLE_KEY_EXCHANGE, 0, crypto_array, crypto_array_size, &cipher_method);
235     if(!(ecdhe_found || dhe_found))
236     {
237         /* TLS 1.3 NOT supported! */
238         tls_session->nx_secure_tls_supported_versions = (tls_session->nx_secure_tls_supported_versions & (USHORT)(~(NX_SECURE_TLS_BITFIELD_VERSION_1_3)));
239     }
240 
241     /* TLS 1.3 needs at least one signature authentication routine. */
242     rsa_found = _find_cipher(NX_CRYPTO_DIGITAL_SIGNATURE_RSA, NX_CRYPTO_ROLE_SIGNATURE_CRYPTO, 0, crypto_array, crypto_array_size, &cipher_method);
243     dsa_found = _find_cipher(NX_CRYPTO_DIGITAL_SIGNATURE_DSA, NX_CRYPTO_ROLE_SIGNATURE_CRYPTO, 0, crypto_array, crypto_array_size, &cipher_method);
244     ecdsa_found = _find_cipher(NX_CRYPTO_DIGITAL_SIGNATURE_ECDSA, NX_CRYPTO_ROLE_SIGNATURE_CRYPTO, 0, crypto_array, crypto_array_size, &cipher_method);
245 
246     if(!((rsa_found == NX_SUCCESS) || (dsa_found == NX_SUCCESS) || (ecdsa_found == NX_SUCCESS)))
247     {
248         /* TLS 1.3 is  NOTsupported!. */
249         tls_session->nx_secure_tls_supported_versions = (tls_session->nx_secure_tls_supported_versions & (USHORT)(~(NX_SECURE_TLS_BITFIELD_VERSION_1_3)));
250     }
251 
252     /* TLS 1.3 needs HKDF and HMAC methods. */
253     status = _find_cipher(NX_CRYPTO_HASH_HMAC, NX_CRYPTO_ROLE_HMAC, 0, crypto_array, crypto_array_size, &cipher_method);
254     crypto_table->nx_secure_tls_hmac_method = cipher_method;
255     if(status != NX_SUCCESS)
256     {
257         /* TLS 1.3 is  NOTsupported!. */
258         tls_session->nx_secure_tls_supported_versions = (tls_session->nx_secure_tls_supported_versions & (USHORT)(~(NX_SECURE_TLS_BITFIELD_VERSION_1_3)));
259     }
260 
261     status = _find_cipher(NX_CRYPTO_HKDF_METHOD, NX_CRYPTO_ROLE_PRF, 0, crypto_array, crypto_array_size, &cipher_method);
262     crypto_table->nx_secure_tls_hkdf_method = cipher_method;
263     if(status != NX_SUCCESS)
264     {
265         /* TLS 1.3 is  NOTsupported!. */
266         tls_session->nx_secure_tls_supported_versions = (tls_session->nx_secure_tls_supported_versions & (USHORT)(~(NX_SECURE_TLS_BITFIELD_VERSION_1_3)));
267     }
268 #endif
269 
270 
271     /* Loop through cipher map, check each ciphersuite. */
272     for(suite = 0; suite < cipher_map_size; ++suite)
273     {
274         /* Search the crypto array for each cipher in this ciphersuite map. */
275         cipher_entry->nx_secure_tls_ciphersuite = cipher_map[suite]->nx_crypto_ciphersuite_id;
276 
277         /* Handle TLS mapping. */
278         if(cipher_map[suite]->nx_crypto_internal_id == NX_SECURE_APPLICATION_TLS)
279         {
280             /* Start with no crypto methods found. */
281             crypto_found = 0;
282 
283             /* Loop through the ciphers in this ciphersuite and map to a cipher method in the cipher array. */
284             for(cipher_counter = 0; cipher_counter < NX_CRYPTO_MAX_CIPHER_ROLES; ++cipher_counter)
285             {
286                 /* Get the current entry and role. */
287                 current_cipher = cipher_map[suite]->nx_crypto_ciphers[cipher_counter];
288                 cipher_id = current_cipher.nx_crypto_role_cipher_id;
289 
290                 /* Check for end of expected ciphers. */
291                 if(current_cipher.nx_crypto_role_id == NX_CRYPTO_ROLE_NONE)
292                 {
293                     /* Reached the end of the list - ciphersuite is good if we found the
294                        expected ciphers. */
295                     if(crypto_found != all_found)
296                     {
297                         break;
298                     }
299 
300                     /* The ciphersuite is fully supported given the input
301                        crypto method array. Add it to the table by advancing the pointer
302                        as a ciphersuite we can use. */
303                     cipher_entry = &cipher_entry[1];
304                     crypto_table->nx_secure_tls_ciphersuite_lookup_table_size++;
305 
306                     /* If there is not enough space, return error. */
307                     if(remaining_size < sizeof(NX_SECURE_TLS_CIPHERSUITE_INFO))
308                     {
309                         return(NX_SECURE_TLS_INSUFFICIENT_METADATA_SPACE);
310                     }
311 
312                     /* Update our bookkeeping. */
313                     remaining_size -= sizeof(NX_SECURE_TLS_CIPHERSUITE_INFO);
314 
315                     /* Exit the search loop. */
316                     break;
317                 }
318 
319                 /* Cipher is not "None" so we need to see if it is available. */
320                 status = _find_cipher(cipher_id, current_cipher.nx_crypto_role_id, cipher_map[suite] -> nx_crypto_symmetric_key_size, crypto_array, crypto_array_size, &cipher_method);
321                 if(status != NX_SUCCESS)
322                 {
323                     /* Did not find a cipher, break out of search. */
324                     break;
325                 }
326 
327                 /* Put the cipher method into the ciphersuite info structure. */
328                 switch(current_cipher.nx_crypto_role_id)
329                 {
330                 case NX_CRYPTO_ROLE_KEY_EXCHANGE:
331                     cipher_entry->nx_secure_tls_public_cipher = cipher_method;
332                     crypto_found |= key_ex_found;
333                     break;
334                 case NX_CRYPTO_ROLE_SIGNATURE_CRYPTO:
335                     cipher_entry->nx_secure_tls_public_auth = cipher_method;
336                     crypto_found |= sig_found;
337                     break;
338                 case NX_CRYPTO_ROLE_MAC_HASH:
339                     cipher_entry->nx_secure_tls_hash = cipher_method;
340                     cipher_entry->nx_secure_tls_hash_size = (USHORT)(cipher_method->nx_crypto_ICV_size_in_bits >> 3);
341                     crypto_found |= hash_found;
342                     break;
343                 case NX_CRYPTO_ROLE_SYMMETRIC:
344                     cipher_entry->nx_secure_tls_session_cipher = cipher_method;
345                     cipher_entry->nx_secure_tls_session_key_size = (UCHAR)cipher_map[suite]->nx_crypto_symmetric_key_size;
346                     cipher_entry->nx_secure_tls_iv_size = (UCHAR)(cipher_method->nx_crypto_IV_size_in_bits >> 3);
347                     crypto_found |= symm_found;
348                     break;
349                 case NX_CRYPTO_ROLE_PRF:
350                     cipher_entry->nx_secure_tls_prf = cipher_method;
351                     crypto_found |= prf_found;
352                     break;
353                 default:
354                     /* Cipher role not supported by TLS. Ignore. */
355                     break;
356                 }
357             }
358         }
359     }
360 
361     /* Return the used metadata size. */
362     *metadata_size = (*metadata_size - remaining_size);
363 
364     return(NX_SUCCESS);
365 }
366 
367 
368 #ifndef NX_SECURE_DISABLE_X509
_map_x509_ciphersuites(NX_SECURE_TLS_SESSION * tls_session,const NX_CRYPTO_METHOD ** crypto_array,UINT crypto_array_size,const NX_CRYPTO_CIPHERSUITE ** cipher_map,UINT cipher_map_size,UINT * metadata_size)369 static UINT _map_x509_ciphersuites(NX_SECURE_TLS_SESSION *tls_session,
370                                   const NX_CRYPTO_METHOD **crypto_array, UINT crypto_array_size,
371                                   const NX_CRYPTO_CIPHERSUITE **cipher_map, UINT cipher_map_size, UINT *metadata_size)
372 {
373 NX_CRYPTO_ROLE_ENTRY    current_cipher;
374 const NX_CRYPTO_METHOD *cipher_method;
375 NX_SECURE_X509_CRYPTO  *cert_crypto;
376 NX_SECURE_TLS_CRYPTO   *crypto_table;
377 UINT                    cipher_id;
378 UINT                    suite;
379 UINT                    cipher_counter;
380 UINT                    status;
381 UINT                    remaining_size;
382 UCHAR                   crypto_found;
383 
384 /* Constants for marking ciphers as found. */
385 const UCHAR pub_key_found = 0x1;
386 const UCHAR hash_found =    0x2;
387 const UCHAR all_found =     pub_key_found | hash_found;
388 
389     /* Get a pointer to our entry. */
390     crypto_table = tls_session->nx_secure_tls_crypto_table;
391     cert_crypto = crypto_table->nx_secure_tls_x509_cipher_table;
392 
393     /* For bookkeeping, keep track of remaining metadata space. */
394     remaining_size = *metadata_size;
395 
396     /* Loop through cipher map, check each ciphersuite. */
397     for(suite = 0; suite < cipher_map_size; ++suite)
398     {
399         /* Search the crypto array for each cipher in this ciphersuite map. */
400         cert_crypto->nx_secure_x509_crypto_identifier = cipher_map[suite]->nx_crypto_ciphersuite_id;
401 
402         /* Handle X.509 mapping. */
403         if(cipher_map[suite]->nx_crypto_internal_id == NX_SECURE_APPLICATION_X509)
404         {
405             crypto_found = 0;
406 
407             /* Loop through the ciphers in this ciphersuite and map to a cipher method in the cipher array. */
408             for(cipher_counter = 0; cipher_counter < NX_CRYPTO_MAX_CIPHER_ROLES; ++cipher_counter)
409             {
410                 /* Get the current entry and role. */
411                 current_cipher = cipher_map[suite]->nx_crypto_ciphers[cipher_counter];
412                 cipher_id = current_cipher.nx_crypto_role_cipher_id;
413 
414                 if(current_cipher.nx_crypto_role_id == NX_CRYPTO_ROLE_NONE)
415                 {
416                     /* Reached the end of the list - ciphersuite is good if all ciphers present. */
417                     if(crypto_found != all_found)
418                     {
419                         break;
420                     }
421 
422                     /* Advance to the next entry in the table. */
423                     cert_crypto = &cert_crypto[1];
424                     crypto_table->nx_secure_tls_x509_cipher_table_size++;
425 
426                     /* If there is not enough space, return error. */
427                     if(remaining_size < sizeof(NX_SECURE_X509_CRYPTO))
428                     {
429                         return(NX_SECURE_TLS_INSUFFICIENT_METADATA_SPACE);
430                     }
431 
432                     /* Update our bookkeeping. */
433                     remaining_size -= sizeof(NX_SECURE_X509_CRYPTO);
434 
435                     /* Break out of the search loop. */
436                     break;
437                 }
438 
439                 /* Cipher is not "none" so see if it's available. */
440                 status = _find_cipher(cipher_id, current_cipher.nx_crypto_role_id, 0, crypto_array, crypto_array_size, &cipher_method);
441                 if(status != NX_SUCCESS)
442                 {
443                     /* Did not find a cipher, break out of search. */
444                     break;
445                 }
446 
447                 /* Put the cipher method into the ciphersuite info structure. */
448                 switch(current_cipher.nx_crypto_role_id)
449                 {
450                 case NX_CRYPTO_ROLE_SIGNATURE_CRYPTO:
451                     cert_crypto->nx_secure_x509_public_cipher_method = cipher_method;
452                     crypto_found |= pub_key_found;
453                     break;
454                 case NX_CRYPTO_ROLE_SIGNATURE_HASH:
455                     cert_crypto->nx_secure_x509_hash_method = cipher_method;
456                     crypto_found |= hash_found;
457                     break;
458                 default:
459                     /* Cipher role not supported by X.509. Ignore. */
460                     break;
461                 }
462             }
463         }
464     }
465 
466     /* Return the used metadata size. */
467     *metadata_size = (*metadata_size - remaining_size);
468 
469     return(NX_SUCCESS);
470 }
471 #endif
472 
473 
_nx_secure_tls_session_create_ext(NX_SECURE_TLS_SESSION * tls_session,const NX_CRYPTO_METHOD ** crypto_array,UINT crypto_array_size,const NX_CRYPTO_CIPHERSUITE ** cipher_map,UINT cipher_map_size,VOID * metadata_buffer,ULONG metadata_size)474 UINT _nx_secure_tls_session_create_ext(NX_SECURE_TLS_SESSION *tls_session,
475                                    const NX_CRYPTO_METHOD **crypto_array, UINT crypto_array_size,
476                                    const NX_CRYPTO_CIPHERSUITE **cipher_map, UINT cipher_map_size,
477                                    VOID *metadata_buffer,
478                                    ULONG metadata_size)
479 {
480 NX_SECURE_TLS_SESSION          *tail_ptr;
481 UINT                            i;
482 UINT                            cipher_table_bytes;
483 UINT                            status;
484 
485 UINT                            max_public_cipher_metadata_size  = 0;
486 UINT                            max_public_auth_metadata_size    = 0;
487 UINT                            max_session_cipher_metadata_size = 0;
488 UINT                            max_hash_mac_metadata_size       = 0;
489 UINT                            max_tls_prf_metadata_size        = 0;
490 UINT                            max_handshake_hash_metadata_size = 0;
491 UINT                            max_handshake_hash_scratch_size  = 0;
492 ULONG                           max_total_metadata_size;
493 ULONG                           offset;
494 CHAR                           *metadata_area;
495 
496 NX_SECURE_TLS_CRYPTO *          crypto_table;
497 
498 NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite_table;
499 USHORT                          ciphersuite_table_size;
500 #ifndef NX_SECURE_DISABLE_X509
501 NX_SECURE_X509_CRYPTO          *cert_crypto;
502 USHORT                          cert_crypto_size;
503 #endif
504 
505 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
506 NX_CRYPTO_METHOD              **curve_crypto_list = NX_NULL;
507 USHORT                         *supported_groups = NX_NULL;
508 USHORT                          ecc_curves_count = 0;
509 UINT                            supported_groups_bytes;
510 #endif
511 
512 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
513 const NX_CRYPTO_METHOD *crypto_method_md5;
514 const NX_CRYPTO_METHOD *crypto_method_sha1;
515 ULONG metadata_size_md5 = 0;
516 ULONG metadata_size_sha1 = 0;
517 #endif
518 
519 #if (NX_SECURE_TLS_TLS_1_2_ENABLED)
520 const NX_CRYPTO_METHOD *crypto_method_sha256;
521 ULONG metadata_size_sha256 = 0;
522 #endif
523 
524     /* Get a working pointer to the metadata buffer. */
525     metadata_area = (CHAR*)metadata_buffer;
526 
527     /* Check and adjust metadata for four byte alignment. */
528     if (((ULONG)metadata_area) & 0x3)
529     {
530         if (metadata_size < 4 - (((ULONG)metadata_area) & 0x3))
531         {
532             return(NX_SECURE_TLS_INSUFFICIENT_METADATA_SPACE);
533         }
534 
535         metadata_size -= 4 - (((ULONG)metadata_area) & 0x3);
536         metadata_area += 4 - (((ULONG)metadata_area) & 0x3);
537     }
538 
539     if((crypto_array == NX_NULL) || (cipher_map == NX_NULL))
540     {
541 
542         /* Coming from the old-style API. Don't allocate crypto table. */
543         crypto_table = tls_session->nx_secure_tls_crypto_table;
544 
545         if (crypto_table == NX_NULL)
546         {
547             return(NX_PTR_ERROR);
548         }
549 
550         /* Start by assuming all versions are enabled, remove versions without the appropriate ciphers. */
551         tls_session->nx_secure_tls_supported_versions = NX_SECURE_TLS_BITFIELD_VERSIONS_ALL;
552     }
553     else
554     {
555         NX_SECURE_MEMSET(tls_session, 0, sizeof(NX_SECURE_TLS_SESSION));
556 
557         /* Start by assuming all versions are enabled, remove versions without the appropriate ciphers. */
558         tls_session->nx_secure_tls_supported_versions = NX_SECURE_TLS_BITFIELD_VERSIONS_ALL;
559 
560         /* Make sure we can allocate our crypto table. */
561         if(metadata_size < sizeof(NX_SECURE_TLS_CRYPTO))
562         {
563             return(NX_SECURE_TLS_INSUFFICIENT_METADATA_SPACE);
564         }
565 
566         /* Carve out space for our dynamic crypto table. */
567         tls_session->nx_secure_tls_crypto_table = (NX_SECURE_TLS_CRYPTO *)(&metadata_area[0]);
568 
569         /* Advance the metadata buffer pointer. */
570         metadata_area += sizeof(NX_SECURE_TLS_CRYPTO);
571         metadata_size -= sizeof(NX_SECURE_TLS_CRYPTO);
572 
573         /* Get a working pointer to our newly-allocated crypto table. */
574         crypto_table = tls_session->nx_secure_tls_crypto_table;
575 
576         /* Allocate space for our ciphersuite lookup table prior to mapping crypto methods. */
577         crypto_table->nx_secure_tls_ciphersuite_lookup_table = (NX_SECURE_TLS_CIPHERSUITE_INFO*)(&metadata_area[0]);
578         crypto_table->nx_secure_tls_ciphersuite_lookup_table_size = 0;
579 
580         /* Map crypto methods to TLS ciphersuites. */
581         cipher_table_bytes = metadata_size;
582         status = _map_tls_ciphersuites(tls_session, crypto_array, crypto_array_size, cipher_map, cipher_map_size, &cipher_table_bytes);
583 
584         if(status != NX_SUCCESS)
585         {
586             return(status);
587         }
588 
589         /* Update metadata pointers. */
590         metadata_area += cipher_table_bytes;
591         metadata_size -= cipher_table_bytes;
592         cipher_table_bytes = metadata_size;
593 
594 #ifndef NX_SECURE_DISABLE_X509
595 
596         /* Carve out space for our dynamic X.509 ciphersuite table. */
597         crypto_table->nx_secure_tls_x509_cipher_table = (NX_SECURE_X509_CRYPTO*)(&metadata_area[0]);
598         crypto_table->nx_secure_tls_x509_cipher_table_size = 0;
599 
600         /* Map crypto methods to X.509 ciphersuites. */
601         status = _map_x509_ciphersuites(tls_session, crypto_array, crypto_array_size, cipher_map, cipher_map_size, &cipher_table_bytes);
602 
603         if(status != NX_SUCCESS)
604         {
605             return(status);
606         }
607 
608 
609         /* Advance the metadata area past the end of the crypto table. */
610         metadata_area += cipher_table_bytes;
611         metadata_size -= cipher_table_bytes;
612 #endif
613 
614 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
615         curve_crypto_list = (NX_CRYPTO_METHOD **)(&metadata_area[0]);
616 
617         /* Find ECC curves in the crypto array. */
618         for (i = 0; i < crypto_array_size; i++)
619         {
620             if ((crypto_array[i] -> nx_crypto_algorithm & 0xFFFF0000) == NX_CRYPTO_EC_MASK)
621             {
622                 if (metadata_size < sizeof(NX_CRYPTO_METHOD *))
623                 {
624                     return(NX_SECURE_TLS_INSUFFICIENT_METADATA_SPACE);
625                 }
626                 curve_crypto_list[ecc_curves_count] = (NX_CRYPTO_METHOD *)crypto_array[i];
627                 ecc_curves_count++;
628                 metadata_size -= sizeof(NX_CRYPTO_METHOD *);
629             }
630         }
631 
632         if (ecc_curves_count > 0)
633         {
634             metadata_area += ecc_curves_count * sizeof(NX_CRYPTO_METHOD *);
635             supported_groups = (USHORT *)(&metadata_area[0]);
636 
637             supported_groups_bytes = ecc_curves_count * sizeof(USHORT);
638 
639             /* Align length to 4 bytes. */
640             if (supported_groups_bytes & 0x3)
641             {
642                 supported_groups_bytes += 4 - (supported_groups_bytes & 0x3);
643             }
644 
645             if (metadata_size < supported_groups_bytes)
646             {
647                 return(NX_SECURE_TLS_INSUFFICIENT_METADATA_SPACE);
648             }
649 
650             metadata_area += supported_groups_bytes;
651             metadata_size -= supported_groups_bytes;
652 
653             for (i = 0; i < ecc_curves_count; i++)
654             {
655                 supported_groups[i] = (USHORT)(curve_crypto_list[i] -> nx_crypto_algorithm & 0xFFFF);
656             }
657 
658             _nx_secure_tls_ecc_initialize(tls_session, supported_groups, ecc_curves_count, (const NX_CRYPTO_METHOD **)curve_crypto_list);
659         }
660 #endif
661 
662     }
663 
664     /* Get working pointers to our crypto methods. */
665     ciphersuite_table = crypto_table -> nx_secure_tls_ciphersuite_lookup_table;
666     ciphersuite_table_size = crypto_table -> nx_secure_tls_ciphersuite_lookup_table_size;
667 
668 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
669     crypto_method_md5 = crypto_table -> nx_secure_tls_handshake_hash_md5_method;
670     crypto_method_sha1 = crypto_table -> nx_secure_tls_handshake_hash_sha1_method;
671 
672     if (crypto_method_md5 != NX_NULL)
673     {
674         metadata_size_md5 = crypto_method_md5 -> nx_crypto_metadata_area_size;
675 
676         /* Align metadata size to four bytes. */
677         if (metadata_size_md5 & 0x3)
678         {
679             metadata_size_md5 += 4 - (metadata_size_md5 & 0x3);
680         }
681     }
682 
683     if (crypto_method_sha1 != NX_NULL)
684     {
685         metadata_size_sha1 = crypto_method_sha1 -> nx_crypto_metadata_area_size;
686 
687         if (metadata_size_sha1 & 0x3)
688         {
689             metadata_size_sha1 += 4 - (metadata_size_sha1 & 0x3);
690         }
691     }
692 #endif
693 #if (NX_SECURE_TLS_TLS_1_2_ENABLED)
694     crypto_method_sha256 = crypto_table -> nx_secure_tls_handshake_hash_sha256_method;
695     if (crypto_method_sha256 != NX_NULL)
696     {
697         metadata_size_sha256 = crypto_method_sha256 -> nx_crypto_metadata_area_size;
698 
699         if (metadata_size_sha256 & 0x3)
700         {
701             metadata_size_sha256 += 4 - (metadata_size_sha256 & 0x3);
702         }
703     }
704 #endif
705 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
706     tls_session -> nx_secure_tls_1_3_supported = NX_FALSE;
707 #endif
708 
709     /* Loop through the ciphersuite table and find the largest metadata for each type of cipher. */
710     for (i = 0; i < ciphersuite_table_size; ++i)
711     {
712         if (max_public_cipher_metadata_size < ciphersuite_table[i].nx_secure_tls_public_cipher -> nx_crypto_metadata_area_size)
713         {
714             max_public_cipher_metadata_size = ciphersuite_table[i].nx_secure_tls_public_cipher -> nx_crypto_metadata_area_size;
715         }
716 
717         if (max_public_auth_metadata_size < ciphersuite_table[i].nx_secure_tls_public_auth -> nx_crypto_metadata_area_size)
718         {
719             max_public_auth_metadata_size = ciphersuite_table[i].nx_secure_tls_public_auth -> nx_crypto_metadata_area_size;
720         }
721 
722         if (max_session_cipher_metadata_size < ciphersuite_table[i].nx_secure_tls_session_cipher -> nx_crypto_metadata_area_size)
723         {
724             max_session_cipher_metadata_size = ciphersuite_table[i].nx_secure_tls_session_cipher -> nx_crypto_metadata_area_size;
725         }
726 
727         if (max_tls_prf_metadata_size < ciphersuite_table[i].nx_secure_tls_prf -> nx_crypto_metadata_area_size)
728         {
729             max_tls_prf_metadata_size = ciphersuite_table[i].nx_secure_tls_prf -> nx_crypto_metadata_area_size;
730         }
731 
732         if (max_hash_mac_metadata_size < ciphersuite_table[i].nx_secure_tls_hash -> nx_crypto_metadata_area_size)
733         {
734             max_hash_mac_metadata_size = ciphersuite_table[i].nx_secure_tls_hash -> nx_crypto_metadata_area_size;
735         }
736 
737 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
738         if ((ciphersuite_table[i].nx_secure_tls_ciphersuite >> 8) == 0x13)
739         {
740 
741             /* Enable TLS 1.3 only if the ciphersuite required by RFC 8446 is provided. */
742             tls_session->nx_secure_tls_1_3_supported = NX_TRUE;
743         }
744 #endif
745     }
746 
747 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
748     tls_session -> nx_secure_tls_1_3 = tls_session -> nx_secure_tls_1_3_supported;
749 #endif
750 
751 #ifndef NX_SECURE_DISABLE_X509
752     cert_crypto = crypto_table->nx_secure_tls_x509_cipher_table;
753     cert_crypto_size = crypto_table->nx_secure_tls_x509_cipher_table_size;
754 
755     /* Loop through the certificate cipher table as well. */
756     for (i = 0; i < cert_crypto_size; ++i)
757     {
758         if (max_public_auth_metadata_size < cert_crypto[i].nx_secure_x509_public_cipher_method -> nx_crypto_metadata_area_size)
759         {
760             max_public_auth_metadata_size = cert_crypto[i].nx_secure_x509_public_cipher_method -> nx_crypto_metadata_area_size;
761         }
762 
763         if (max_hash_mac_metadata_size < cert_crypto[i].nx_secure_x509_hash_method -> nx_crypto_metadata_area_size)
764         {
765             max_hash_mac_metadata_size = cert_crypto[i].nx_secure_x509_hash_method -> nx_crypto_metadata_area_size;
766         }
767 
768         if (max_handshake_hash_scratch_size < cert_crypto[i].nx_secure_x509_hash_method -> nx_crypto_metadata_area_size)
769         {
770             max_handshake_hash_scratch_size = cert_crypto[i].nx_secure_x509_hash_method -> nx_crypto_metadata_area_size;
771         }
772     }
773 #endif
774 
775     /* We also need metadata space for the TLS handshake hash, so add that into the total.
776        We need some scratch space to copy the handshake hash metadata during final hash generation
777        so figure out the largest metadata between SHA-1+MD5 (TLSv1.0, 1.1) and SHA256 (TLSv1.2). */
778 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
779     if (tls_session -> nx_secure_tls_supported_versions & (USHORT)(NX_SECURE_TLS_BITFIELD_VERSION_1_0 | NX_SECURE_TLS_BITFIELD_VERSION_1_1))
780     {
781         max_handshake_hash_metadata_size += (metadata_size_md5 + metadata_size_sha1);
782         if (max_handshake_hash_scratch_size < metadata_size_md5 + metadata_size_sha1)
783         {
784             max_handshake_hash_scratch_size = metadata_size_md5 + metadata_size_sha1;
785         }
786 
787         if (crypto_table -> nx_secure_tls_prf_1_method != NX_NULL)
788         {
789             if (max_tls_prf_metadata_size < crypto_table -> nx_secure_tls_prf_1_method -> nx_crypto_metadata_area_size)
790             {
791                 max_tls_prf_metadata_size = crypto_table -> nx_secure_tls_prf_1_method -> nx_crypto_metadata_area_size;
792             }
793         }
794     }
795 #endif
796 #if (NX_SECURE_TLS_TLS_1_2_ENABLED)
797     max_handshake_hash_metadata_size += metadata_size_sha256;
798 
799     /* See if the scratch size from above is bigger. */
800     if (max_handshake_hash_scratch_size < metadata_size_sha256)
801     {
802         max_handshake_hash_scratch_size = metadata_size_sha256;
803     }
804 
805     if ((crypto_table -> nx_secure_tls_prf_sha256_method != NX_NULL) &&
806         (max_tls_prf_metadata_size < crypto_table -> nx_secure_tls_prf_sha256_method -> nx_crypto_metadata_area_size))
807     {
808         max_tls_prf_metadata_size = crypto_table -> nx_secure_tls_prf_sha256_method -> nx_crypto_metadata_area_size;
809     }
810 #endif
811 
812 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
813     if (crypto_table -> nx_secure_tls_hmac_method != NX_NULL)
814     {
815         max_handshake_hash_scratch_size += crypto_table -> nx_secure_tls_hmac_method -> nx_crypto_metadata_area_size;
816     }
817 
818     if (crypto_table -> nx_secure_tls_hkdf_method != NX_NULL)
819     {
820         if (max_tls_prf_metadata_size < crypto_table -> nx_secure_tls_hkdf_method -> nx_crypto_metadata_area_size)
821         {
822             max_tls_prf_metadata_size = crypto_table -> nx_secure_tls_hkdf_method -> nx_crypto_metadata_area_size;
823         }
824     }
825 #endif
826 
827     /* The public cipher and authentication should never be used simultaneously, so it should be OK
828          to share their metadata areas. */
829     if (max_public_cipher_metadata_size < max_public_auth_metadata_size)
830     {
831         max_public_cipher_metadata_size = max_public_auth_metadata_size;
832     }
833 
834     /* Check and adjust every metadata sizes for four byte alignment. */
835     if (max_public_cipher_metadata_size & 0x3)
836     {
837         max_public_cipher_metadata_size += 4 - (max_public_cipher_metadata_size & 0x3);
838     }
839     if (max_session_cipher_metadata_size & 0x3)
840     {
841         max_session_cipher_metadata_size += 4 - (max_session_cipher_metadata_size & 0x3);
842     }
843     if (max_hash_mac_metadata_size & 0x3)
844     {
845         max_hash_mac_metadata_size += 4 - (max_hash_mac_metadata_size & 0x3);
846     }
847     if (max_tls_prf_metadata_size & 0x3)
848     {
849         max_tls_prf_metadata_size += 4 - (max_tls_prf_metadata_size & 0x3);
850     }
851     if (max_handshake_hash_scratch_size & 0x3)
852     {
853         max_handshake_hash_scratch_size += 4 - (max_handshake_hash_scratch_size & 0x3);
854     }
855 
856     /* The Total metadata size needed is the sum of all the maximums calculated above.
857        We need to keep track of two separate session cipher states, one for the server and one for the client,
858        so account for that extra space. */
859     max_total_metadata_size = max_public_cipher_metadata_size +
860                               (2 * max_session_cipher_metadata_size) +
861                               max_hash_mac_metadata_size +
862                               max_tls_prf_metadata_size +
863                               max_handshake_hash_metadata_size +
864                               max_handshake_hash_scratch_size;
865 
866     /* Check if the caller provided enough metadata space. */
867     if (max_total_metadata_size > metadata_size)
868     {
869         return(NX_INVALID_PARAMETERS);
870     }
871 
872     /* Get the protection. */
873     tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
874 
875 #ifndef NX_SECURE_DISABLE_X509
876 
877     /* Clear out the X509 certificate stores when we create a new TLS Session. */
878     tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store.nx_secure_x509_remote_certificates = NX_NULL;
879     tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store.nx_secure_x509_local_certificates = NX_NULL;
880     tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store.nx_secure_x509_trusted_certificates = NX_NULL;
881     tls_session -> nx_secure_tls_credentials.nx_secure_tls_active_certificate = NX_NULL;
882 #endif
883 
884     /* Release the protection. */
885     tx_mutex_put(&_nx_secure_tls_protection);
886 
887     /* Initialize/reset all the other TLS state. */
888     _nx_secure_tls_session_reset(tls_session);
889 
890     /* Get the protection. */
891     tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
892 
893     /* Now allocate cipher metadata space from our calculated numbers above. */
894     offset = 0;
895 
896     /* Handshake hash metadata. */
897 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
898     if (tls_session -> nx_secure_tls_supported_versions & (USHORT)(NX_SECURE_TLS_BITFIELD_VERSION_1_0 | NX_SECURE_TLS_BITFIELD_VERSION_1_1))
899     {
900         tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata = &metadata_area[offset];
901         tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size = metadata_size_md5;
902         offset += metadata_size_md5;
903 
904         tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata = &metadata_area[offset];
905         tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size = metadata_size_sha1;
906         offset += metadata_size_sha1;
907     }
908 #endif
909 
910 #if NX_SECURE_TLS_TLS_1_2_ENABLED
911     tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata = &metadata_area[offset];
912     tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size = metadata_size_sha256;
913     offset += metadata_size_sha256;
914 #endif
915 
916     tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch = &metadata_area[offset];
917     tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size = max_handshake_hash_scratch_size;
918     offset += max_handshake_hash_scratch_size;
919 
920     /* Client and server session cipher metadata. */
921     tls_session -> nx_secure_session_cipher_metadata_size = max_session_cipher_metadata_size;
922 
923     tls_session -> nx_secure_session_cipher_metadata_area_client = &metadata_area[offset];
924     offset += max_session_cipher_metadata_size;
925 
926     tls_session -> nx_secure_session_cipher_metadata_area_server = &metadata_area[offset];
927     offset += max_session_cipher_metadata_size;
928 
929     /* Public cipher metadata. */
930     tls_session -> nx_secure_public_cipher_metadata_area = &metadata_area[offset];
931     tls_session -> nx_secure_public_cipher_metadata_size = max_public_cipher_metadata_size;
932     offset += max_public_cipher_metadata_size;
933 
934     /* Public authentication metadata. For now it shares space with the public cipher. */
935     tls_session -> nx_secure_public_auth_metadata_area = tls_session -> nx_secure_public_cipher_metadata_area;
936     tls_session -> nx_secure_public_auth_metadata_size = max_public_cipher_metadata_size;
937 
938     /* Hash MAC metadata. */
939     tls_session -> nx_secure_hash_mac_metadata_area = &metadata_area[offset];
940     tls_session -> nx_secure_hash_mac_metadata_size = max_hash_mac_metadata_size;
941     offset += max_hash_mac_metadata_size;
942 
943     /* TLS PRF metadata. */
944     tls_session -> nx_secure_tls_prf_metadata_area = &metadata_area[offset];
945     tls_session -> nx_secure_tls_prf_metadata_size = max_tls_prf_metadata_size;
946 
947     /* Place the new TLS control block on the list of created TLS. */
948     if (_nx_secure_tls_created_ptr)
949     {
950 
951         /* Pickup tail pointer. */
952         tail_ptr = _nx_secure_tls_created_ptr -> nx_secure_tls_created_previous;
953 
954         /* Place the new TLS control block in the list. */
955         _nx_secure_tls_created_ptr -> nx_secure_tls_created_previous = tls_session;
956         tail_ptr -> nx_secure_tls_created_next = tls_session;
957 
958         /* Setup this TLS's created links. */
959         tls_session -> nx_secure_tls_created_previous = tail_ptr;
960         tls_session -> nx_secure_tls_created_next = _nx_secure_tls_created_ptr;
961     }
962     else
963     {
964 
965         /* The created TLS list is empty. Add TLS control block to empty list. */
966         _nx_secure_tls_created_ptr = tls_session;
967         tls_session -> nx_secure_tls_created_previous = tls_session;
968         tls_session -> nx_secure_tls_created_next = tls_session;
969     }
970     _nx_secure_tls_created_count++;
971 
972 #ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION
973 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
974     /* Flag to indicate when a session renegotiation is enabled. Enabled by default. */
975     if (tls_session -> nx_secure_tls_1_3)
976     {
977         tls_session -> nx_secure_tls_renegotation_enabled = NX_FALSE;
978     }
979     else
980 #endif
981     {
982         tls_session -> nx_secure_tls_renegotation_enabled = NX_TRUE;
983     }
984 #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */
985 
986     /* Set the secret generation functions to the default implementation. */
987     tls_session -> nx_secure_generate_premaster_secret = _nx_secure_generate_premaster_secret;
988     tls_session -> nx_secure_generate_master_secret = _nx_secure_generate_master_secret;
989     tls_session -> nx_secure_generate_session_keys = _nx_secure_generate_session_keys;
990     tls_session -> nx_secure_session_keys_set = _nx_secure_session_keys_set;
991 #ifndef NX_SECURE_TLS_CLIENT_DISABLED
992     tls_session -> nx_secure_process_server_key_exchange = _nx_secure_process_server_key_exchange;
993     tls_session -> nx_secure_generate_client_key_exchange = _nx_secure_generate_client_key_exchange;
994 #endif
995 #ifndef NX_SECURE_TLS_SERVER_DISABLED
996     tls_session -> nx_secure_process_client_key_exchange = _nx_secure_process_client_key_exchange;
997     tls_session -> nx_secure_generate_server_key_exchange = _nx_secure_generate_server_key_exchange;
998 #endif
999     tls_session -> nx_secure_verify_mac = _nx_secure_verify_mac;
1000     tls_session -> nx_secure_remote_certificate_verify = _nx_secure_remote_certificate_verify;
1001     tls_session -> nx_secure_trusted_certificate_add = _nx_secure_trusted_certificate_add;
1002 
1003 #ifdef NX_SECURE_CUSTOM_SECRET_GENERATION
1004 
1005     /* Customized secret generation functions can be set by the user in nx_secure_custom_secret_generation_init. */
1006     status = nx_secure_custom_secret_generation_init(tls_session);
1007     if (status != NX_SUCCESS)
1008     {
1009         return(status);
1010     }
1011 #endif
1012 
1013     /* Set ID to check initialization status. */
1014     tls_session -> nx_secure_tls_id = NX_SECURE_TLS_ID;
1015 
1016     /* Create the mutex used for TLS session while transmitting packets. */
1017     tx_mutex_create(&(tls_session -> nx_secure_tls_session_transmit_mutex), "TLS transmit mutex", TX_NO_INHERIT);
1018 
1019     /* Release the protection. */
1020     tx_mutex_put(&_nx_secure_tls_protection);
1021 
1022     return(NX_SUCCESS);
1023 }
1024 
1025