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 #ifdef NX_SECURE_ENABLE_DTLS
26 #include "nx_secure_dtls.h"
27 #endif /* NX_SECURE_ENABLE_DTLS */
28 
29 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
30 
31 #ifndef NX_SECURE_DISABLE_X509
32 static UCHAR hash[64]; /* We concatenate MD5 and SHA-1 hashes into this buffer, OR SHA-256, SHA-384, SHA512. */
33 static UCHAR _nx_secure_padded_signature[512];
34 /* DER encodings (with OIDs for common algorithms) from RFC 8017.
35  * NOTE: This is the equivalent DER-encoding for the value "T" described in RFC 8017 section 9.2. */
36 static const UCHAR _NX_CRYPTO_DER_OID_MD5[]         =  {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10};
37 static const UCHAR _NX_CRYPTO_DER_OID_SHA_1[]       =  {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14};
38 static const UCHAR _NX_CRYPTO_DER_OID_SHA_224[]     =  {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c};
39 static const UCHAR _NX_CRYPTO_DER_OID_SHA_256[]     =  {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
40 static const UCHAR _NX_CRYPTO_DER_OID_SHA_384[]     =  {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30};
41 static const UCHAR _NX_CRYPTO_DER_OID_SHA_512[]     =  {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
42 #endif
43 
44 
45 /**************************************************************************/
46 /*                                                                        */
47 /*  FUNCTION                                               RELEASE        */
48 /*                                                                        */
49 /*    _nx_secure_tls_ecc_generate_keys                    PORTABLE C      */
50 /*                                                           6.2.1        */
51 /*  AUTHOR                                                                */
52 /*                                                                        */
53 /*    Timothy Stapko, Microsoft Corporation                               */
54 /*                                                                        */
55 /*  DESCRIPTION                                                           */
56 /*                                                                        */
57 /*    This function is used to generate ECC key pairs (public, private)   */
58 /*    for use in TLS. TLS ECC keys need to be signed using a trusted      */
59 /*    certificate or other mechanism - this function handles the signature*/
60 /*    generation and outputs the public key and it's signature in the     */
61 /*    proper over-the-wire format for TLS. The private key is also        */
62 /*    exported (conditionally) for later use (usually when used to        */
63 /*    calculate the shared secret.                                        */
64 /*                                                                        */
65 /*    NOTE: The key sizes should contain the size of their respective     */
66 /*          buffers as input. The value will be replaced with the actual  */
67 /*          size of the generated key.                                    */
68 /*                                                                        */
69 /*  INPUT                                                                 */
70 /*                                                                        */
71 /*    ciphersuite                           Selected cipher suite         */
72 /*    protocol_version                      Selected TLS version          */
73 /*    tls_1_3                               Whether TLS 1.3 is chosen     */
74 /*    tls_crypto_table                      TLS crypto methods            */
75 /*    tls_handshake_hash                    Metadata for handshake hash   */
76 /*    tls_ecc_curves                        ECC curves                    */
77 /*    tls_key_material                      TLS key material              */
78 /*    tls_credentials                       TLS credentials               */
79 /*    ecc_named_curve                       IANA ECC curve identifier     */
80 /*    sign_key                              True/False generate signature */
81 /*    public_key                            Signed ECC public key         */
82 /*    public_key_size                       Size of public key            */
83 /*    ecc_data                              ECC data (incl. private key)  */
84 /*    public_cipher_metadata                Metadata for public cipher    */
85 /*    public_cipher_metadata_size           Size of public cipher metadata*/
86 /*    public_auth_metadata                  Metadata for public auth      */
87 /*    public_auth_metadata_size             Size of public auth metadata  */
88 /*                                                                        */
89 /*  OUTPUT                                                                */
90 /*                                                                        */
91 /*    status                                Completion status             */
92 /*                                                                        */
93 /*  CALLS                                                                 */
94 /*                                                                        */
95 /*    None                                                                */
96 /*                                                                        */
97 /*  CALLED BY                                                             */
98 /*                                                                        */
99 /*    Application Code                                                    */
100 /*                                                                        */
101 /*  RELEASE HISTORY                                                       */
102 /*                                                                        */
103 /*    DATE              NAME                      DESCRIPTION             */
104 /*                                                                        */
105 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
106 /*  09-30-2020     Timothy Stapko           Modified comment(s), update   */
107 /*                                            ECC find curve method,      */
108 /*                                            verified memcpy use cases,  */
109 /*                                            resulting in version 6.1    */
110 /*  04-25-2022     Yuxin Zhou               Modified comment(s), removed  */
111 /*                                            internal unreachable logic, */
112 /*                                            resulting in version 6.1.11 */
113 /*  10-31-2022     Yanwu Cai                Modified comment(s),          */
114 /*                                            updated parameters list,    */
115 /*                                            resulting in version 6.2.0  */
116 /*  03-08-2023     Yanwu Cai                Modified comment(s),          */
117 /*                                            fixed compiler errors when  */
118 /*                                            x509 is disabled,           */
119 /*                                            resulting in version 6.2.1  */
120 /*                                                                        */
121 /**************************************************************************/
_nx_secure_tls_ecc_generate_keys(const NX_SECURE_TLS_CIPHERSUITE_INFO * ciphersuite,USHORT protocol_version,UCHAR tls_1_3,NX_SECURE_TLS_CRYPTO * tls_crypto_table,NX_SECURE_TLS_HANDSHAKE_HASH * tls_handshake_hash,NX_SECURE_TLS_ECC * tls_ecc_curves,NX_SECURE_TLS_KEY_MATERIAL * tls_key_material,NX_SECURE_TLS_CREDENTIALS * tls_credentials,UINT ecc_named_curve,USHORT sign_key,UCHAR * public_key,UINT * public_key_size,NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA * ecc_data,VOID * public_cipher_metadata,ULONG public_cipher_metadata_size,VOID * public_auth_metadata,ULONG public_auth_metadata_size)122 UINT _nx_secure_tls_ecc_generate_keys(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, UCHAR tls_1_3,
123                                       NX_SECURE_TLS_CRYPTO *tls_crypto_table, NX_SECURE_TLS_HANDSHAKE_HASH *tls_handshake_hash,
124                                       NX_SECURE_TLS_ECC *tls_ecc_curves, NX_SECURE_TLS_KEY_MATERIAL *tls_key_material,
125                                       NX_SECURE_TLS_CREDENTIALS *tls_credentials, UINT ecc_named_curve, USHORT sign_key,
126                                       UCHAR *public_key, UINT *public_key_size, NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecc_data,
127                                       VOID *public_cipher_metadata, ULONG public_cipher_metadata_size,
128                                       VOID *public_auth_metadata, ULONG public_auth_metadata_size)
129 {
130 UINT                       length;
131 UINT                       output_size;
132 UINT                       status;
133 NX_CRYPTO_EXTENDED_OUTPUT  extended_output;
134 VOID                      *handler = NX_NULL;
135 const NX_CRYPTO_METHOD    *curve_method;
136 const NX_CRYPTO_METHOD    *ecdhe_method;
137 #ifndef NX_SECURE_DISABLE_X509
138 USHORT                     signature_length;
139 UINT                       signature_offset;
140 const UCHAR               *der_encoding = NX_NULL;
141 UINT                       der_encoding_length = 0;
142 UINT                       hash_length;
143 const NX_CRYPTO_METHOD    *curve_method_cert;
144 const NX_CRYPTO_METHOD    *hash_method;
145 const NX_CRYPTO_METHOD    *auth_method;
146 NX_SECURE_X509_CERT       *certificate;
147 NX_SECURE_X509_CRYPTO     *crypto_methods;
148 NX_SECURE_EC_PRIVATE_KEY  *ec_privkey;
149 NX_SECURE_EC_PUBLIC_KEY   *ec_pubkey;
150 USHORT                     signature_algorithm_id;
151 #endif
152 
153 #if !(NX_SECURE_TLS_TLS_1_0_ENABLED) && !(NX_SECURE_TLS_TLS_1_1_ENABLED)
154     NX_PARAMETER_NOT_USED(protocol_version);
155 #endif
156 
157 #if !(NX_SECURE_TLS_TLS_1_3_ENABLED) || (!(NX_SECURE_TLS_TLS_1_0_ENABLED) && !(NX_SECURE_TLS_TLS_1_1_ENABLED))
158     NX_PARAMETER_NOT_USED(tls_1_3);
159     NX_PARAMETER_NOT_USED(tls_crypto_table);
160 #endif
161 #ifdef NX_SECURE_DISABLE_X509
162     NX_PARAMETER_NOT_USED(tls_handshake_hash);
163     NX_PARAMETER_NOT_USED(tls_key_material);
164     NX_PARAMETER_NOT_USED(tls_credentials);
165     NX_PARAMETER_NOT_USED(sign_key);
166     NX_PARAMETER_NOT_USED(public_auth_metadata);
167     NX_PARAMETER_NOT_USED(public_auth_metadata_size);
168 #endif
169 
170 
171 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
172     if(tls_1_3)
173     {
174         ecdhe_method = tls_crypto_table -> nx_secure_tls_ecdhe_method;
175     }
176     else
177 #endif
178     {
179 
180         /* Generate ECDHE key pair using ECDHE crypto method. */
181         ecdhe_method = ciphersuite -> nx_secure_tls_public_cipher;
182     }
183 
184     /* Make sure we have a method to use. */
185     if (ecdhe_method == NX_NULL || ecdhe_method -> nx_crypto_operation == NX_NULL)
186     {
187         return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
188     }
189 
190     /* Set the curve we are using. */
191     ecc_data -> nx_secure_tls_ecdhe_named_curve = ecc_named_curve;
192 
193     /* Find out which named curve the we are using. */
194     status = _nx_secure_tls_find_curve_method(tls_ecc_curves, (USHORT)ecc_named_curve, &curve_method, NX_NULL);
195     if(status != NX_SUCCESS)
196     {
197         return(status);
198     }
199 
200     if (ecdhe_method -> nx_crypto_init != NX_NULL)
201     {
202         status = ecdhe_method -> nx_crypto_init((NX_CRYPTO_METHOD*)ecdhe_method,
203                                        NX_NULL,
204                                        0,
205                                        &handler,
206                                        public_cipher_metadata,
207                                        public_cipher_metadata_size);
208         if(status != NX_CRYPTO_SUCCESS)
209         {
210             return(status);
211         }
212     }
213 
214     status = ecdhe_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler,
215                                                  (NX_CRYPTO_METHOD*)ecdhe_method, NX_NULL, 0,
216                                                  (UCHAR *)curve_method, sizeof(NX_CRYPTO_METHOD *), NX_NULL,
217                                                  NX_NULL, 0,
218                                                  public_cipher_metadata,
219                                                  public_cipher_metadata_size,
220                                                  NX_NULL, NX_NULL);
221     if (status != NX_CRYPTO_SUCCESS)
222     {
223         return(status);
224     }
225 
226 
227     /* Start to fill the public key buffer. */
228     length = 0;
229     output_size = *public_key_size;
230     *public_key_size = 0;
231 
232 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
233     if(!tls_1_3)
234 #endif
235     {
236         /* ECCurveType: named_curve (3). */
237         public_key[length] = 3;
238         length += 1;
239 
240         /* NamedCurve */
241         public_key[length] = (UCHAR)((ecc_data -> nx_secure_tls_ecdhe_named_curve & 0xFF00) >> 8);
242         public_key[length + 1] = (UCHAR)(ecc_data -> nx_secure_tls_ecdhe_named_curve & 0x00FF);
243         length += 2;
244     }
245 
246 
247     /* Generate the key pair and output the public key. */
248 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
249     if(tls_1_3)
250     {
251         extended_output.nx_crypto_extended_output_data = &public_key[length];
252         extended_output.nx_crypto_extended_output_length_in_byte = output_size - length;
253     }
254     else
255 #endif
256     {
257         extended_output.nx_crypto_extended_output_data = &public_key[length + 1];
258         extended_output.nx_crypto_extended_output_length_in_byte = output_size - (length + 1);
259     }
260     extended_output.nx_crypto_extended_output_actual_size = 0;
261     status = ecdhe_method -> nx_crypto_operation(NX_CRYPTO_DH_SETUP, handler,
262                                                  (NX_CRYPTO_METHOD*)ecdhe_method, NX_NULL, 0,
263                                                  NX_NULL, 0, NX_NULL,
264                                                  (UCHAR *)&extended_output,
265                                                  sizeof(extended_output),
266                                                  public_cipher_metadata,
267                                                  public_cipher_metadata_size,
268                                                  NX_NULL, NX_NULL);
269     if (status != NX_CRYPTO_SUCCESS)
270     {
271         return(status);
272     }
273 
274 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
275     if(!tls_1_3)
276 #endif
277     {
278         /* Put the length into the buffer before the key data. */
279         public_key[length] = (UCHAR)extended_output.nx_crypto_extended_output_actual_size;
280         length += 1;
281 
282     }
283 
284     length += (UINT)(extended_output.nx_crypto_extended_output_actual_size);
285 
286     /* Export the private key for later use. */
287     extended_output.nx_crypto_extended_output_data = ecc_data -> nx_secure_tls_ecdhe_private_key;
288     extended_output.nx_crypto_extended_output_length_in_byte =
289         sizeof(ecc_data -> nx_secure_tls_ecdhe_private_key);
290     extended_output.nx_crypto_extended_output_actual_size = 0;
291     status = ecdhe_method -> nx_crypto_operation(NX_CRYPTO_DH_PRIVATE_KEY_EXPORT, handler,
292                                                  (NX_CRYPTO_METHOD*)ecdhe_method, NX_NULL, 0,
293                                                  NX_NULL, 0, NX_NULL,
294                                                  (UCHAR *)&extended_output,
295                                                  sizeof(extended_output),
296                                                  public_cipher_metadata,
297                                                  public_cipher_metadata_size,
298                                                  NX_NULL, NX_NULL);
299     if (status != NX_CRYPTO_SUCCESS)
300     {
301         return(status);
302     }
303 
304     /* Set the private key length. */
305     ecc_data -> nx_secure_tls_ecdhe_private_key_length = (USHORT)extended_output.nx_crypto_extended_output_actual_size;
306 
307     /* Cleanup the ECC crypto state. */
308     if (ecdhe_method -> nx_crypto_cleanup)
309     {
310         status = ecdhe_method -> nx_crypto_cleanup(public_cipher_metadata);
311         if(status != NX_CRYPTO_SUCCESS)
312         {
313             return(status);
314         }
315     }
316 
317 #ifndef NX_SECURE_DISABLE_X509
318 
319     /* If signing the key, generate the signature now using the local device certificate (if available). */
320     if(sign_key == NX_TRUE)
321     {
322         /* Get the local certificate. */
323         if (tls_credentials -> nx_secure_tls_active_certificate != NX_NULL)
324         {
325             certificate = tls_credentials -> nx_secure_tls_active_certificate;
326         }
327         else
328         {
329             /* Get reference to local device certificate. NX_NULL is passed for name to get default entry. */
330             status = _nx_secure_x509_local_device_certificate_get(&tls_credentials -> nx_secure_tls_certificate_store,
331                                                                   NX_NULL, &certificate);
332             if (status != NX_SUCCESS)
333             {
334                 certificate = NX_NULL;
335             }
336         }
337 
338         if (certificate == NX_NULL)
339         {
340             /* No certificate found, error! */
341             return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND);
342         }
343 
344 
345         /* Find out the hash algorithm used for the signature. */
346         /* Map signature algorithm to internal ID. */
347         _nx_secure_tls_get_signature_algorithm_id((UINT)(ecc_data -> nx_secure_tls_ecdhe_signature_algorithm),
348                                                   &signature_algorithm_id);
349 
350         /* Get the crypto method. */
351         status = _nx_secure_x509_find_certificate_methods(certificate,
352                                                           signature_algorithm_id,
353                                                           &crypto_methods);
354         if (status)
355         {
356             return(NX_SECURE_TLS_UNSUPPORTED_SIGNATURE_ALGORITHM);
357         }
358 
359 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
360 #ifdef NX_SECURE_ENABLE_DTLS
361         if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
362            (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
363             protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 ||
364             protocol_version == NX_SECURE_DTLS_VERSION_1_0))
365 #else
366         if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
367            (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
368             protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1))
369 #endif /* NX_SECURE_ENABLE_DTLS */
370         {
371 
372             /* TLS 1.0 and TLS 1.1 use MD5 + SHA1 hash for RSA signatures. */
373             hash_method = tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method;
374         }
375         else
376 #endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */
377         {
378             hash_method = crypto_methods -> nx_secure_x509_hash_method;
379         }
380 
381         hash_length = hash_method -> nx_crypto_ICV_size_in_bits >> 3;
382 
383         /* Calculate the hash: SHA(ClientHello.random + ServerHello.random +
384                                     ServerKeyExchange.params); */
385         if (hash_method -> nx_crypto_init)
386         {
387             status = hash_method -> nx_crypto_init((NX_CRYPTO_METHOD*)hash_method,
388                                           NX_NULL,
389                                           0,
390                                           &handler,
391                                           tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
392                                           tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size);
393 
394             if(status != NX_CRYPTO_SUCCESS)
395             {
396                 return(status);
397             }
398         }
399 
400         if (hash_method -> nx_crypto_operation != NX_NULL)
401         {
402             status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE,
403                                                handler,
404                                                (NX_CRYPTO_METHOD*)hash_method,
405                                                NX_NULL,
406                                                0,
407                                                NX_NULL,
408                                                0,
409                                                NX_NULL,
410                                                NX_NULL,
411                                                0,
412                                                tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
413                                                tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
414                                                NX_NULL,
415                                                NX_NULL);
416 
417             if(status != NX_CRYPTO_SUCCESS)
418             {
419                 return(status);
420             }
421         }
422         else
423         {
424             return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
425         }
426 
427         status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
428                                            handler,
429                                            (NX_CRYPTO_METHOD*)hash_method,
430                                            NX_NULL,
431                                            0,
432                                            tls_key_material -> nx_secure_tls_client_random,
433                                            32,
434                                            NX_NULL,
435                                            NX_NULL,
436                                            0,
437                                            tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
438                                            tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
439                                            NX_NULL,
440                                            NX_NULL);
441 
442         if(status != NX_CRYPTO_SUCCESS)
443         {
444             return(status);
445         }
446 
447         status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
448                                            handler,
449                                            (NX_CRYPTO_METHOD*)hash_method,
450                                            NX_NULL,
451                                            0,
452                                            tls_key_material -> nx_secure_tls_server_random,
453                                            32,
454                                            NX_NULL,
455                                            NX_NULL,
456                                            0,
457                                            tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
458                                            tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
459                                            NX_NULL,
460                                            NX_NULL);
461 
462         if(status != NX_CRYPTO_SUCCESS)
463         {
464             return(status);
465         }
466 
467         status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
468                                            handler,
469                                            (NX_CRYPTO_METHOD*)hash_method,
470                                            NX_NULL,
471                                            0,
472                                            public_key,
473                                            length,
474                                            NX_NULL,
475                                            NX_NULL,
476                                            0,
477                                            tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
478                                            tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
479                                            NX_NULL,
480                                            NX_NULL);
481 
482         if(status != NX_CRYPTO_SUCCESS)
483         {
484             return(status);
485         }
486 
487         status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE,
488                                            handler,
489                                            (NX_CRYPTO_METHOD*)hash_method,
490                                            NX_NULL,
491                                            0,
492                                            NX_NULL,
493                                            0,
494                                            NX_NULL,
495                                            hash,
496                                            hash_length,
497                                            tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
498                                            tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
499                                            NX_NULL,
500                                            NX_NULL);
501 
502         if(status != NX_CRYPTO_SUCCESS)
503         {
504             return(status);
505         }
506 
507         if (hash_method -> nx_crypto_cleanup)
508         {
509             status = hash_method -> nx_crypto_cleanup(tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch);
510 
511             if(status != NX_CRYPTO_SUCCESS)
512             {
513                 return(status);
514             }
515         }
516         handler = NX_NULL;
517 
518 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
519 #ifdef NX_SECURE_ENABLE_DTLS
520         if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
521            (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
522             protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 ||
523             protocol_version == NX_SECURE_DTLS_VERSION_1_0))
524 #else
525         if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
526            (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
527             protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1))
528 #endif /* NX_SECURE_ENABLE_DTLS */
529         {
530             hash_method = tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method;;
531 
532             /* Calculate the hash: SHA(ClientHello.random + ServerHello.random +
533                                        ServerKeyExchange.params); */
534             if (hash_method -> nx_crypto_init)
535             {
536                 status = hash_method -> nx_crypto_init((NX_CRYPTO_METHOD*)hash_method,
537                                               NX_NULL,
538                                               0,
539                                               &handler,
540                                               tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
541                                               tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size);
542 
543                 if(status != NX_CRYPTO_SUCCESS)
544                 {
545                     return(status);
546                 }
547             }
548 
549             if (hash_method -> nx_crypto_operation != NX_NULL)
550             {
551                 status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE,
552                                                    handler,
553                                                    (NX_CRYPTO_METHOD*)hash_method,
554                                                    NX_NULL,
555                                                    0,
556                                                    NX_NULL,
557                                                    0,
558                                                    NX_NULL,
559                                                    NX_NULL,
560                                                    0,
561                                                    tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
562                                                    tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
563                                                    NX_NULL,
564                                                    NX_NULL);
565 
566                 if(status != NX_CRYPTO_SUCCESS)
567                 {
568                     return(status);
569                 }
570             }
571             else
572             {
573                 return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
574             }
575 
576             status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
577                                                handler,
578                                                (NX_CRYPTO_METHOD*)hash_method,
579                                                NX_NULL,
580                                                0,
581                                                tls_key_material -> nx_secure_tls_client_random,
582                                                32,
583                                                NX_NULL,
584                                                NX_NULL,
585                                                0,
586                                                tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
587                                                tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
588                                                NX_NULL,
589                                                NX_NULL);
590 
591             if(status != NX_CRYPTO_SUCCESS)
592             {
593                 return(status);
594             }
595 
596             status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
597                                                handler,
598                                                (NX_CRYPTO_METHOD*)hash_method,
599                                                NX_NULL,
600                                                0,
601                                                tls_key_material -> nx_secure_tls_server_random,
602                                                32,
603                                                NX_NULL,
604                                                NX_NULL,
605                                                0,
606                                                tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
607                                                tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
608                                                NX_NULL,
609                                                NX_NULL);
610 
611             if(status != NX_CRYPTO_SUCCESS)
612             {
613                 return(status);
614             }
615 
616             status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
617                                                handler,
618                                                (NX_CRYPTO_METHOD*)hash_method,
619                                                NX_NULL,
620                                                0,
621                                                public_key,
622                                                length,
623                                                NX_NULL,
624                                                NX_NULL,
625                                                0,
626                                                tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
627                                                tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
628                                                NX_NULL,
629                                                NX_NULL);
630 
631             if(status != NX_CRYPTO_SUCCESS)
632             {
633                 return(status);
634             }
635 
636             status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE,
637                                                handler,
638                                                (NX_CRYPTO_METHOD*)hash_method,
639                                                NX_NULL,
640                                                0,
641                                                NX_NULL,
642                                                0,
643                                                NX_NULL,
644                                                &hash[16],
645                                                hash_method -> nx_crypto_ICV_size_in_bits >> 3,
646                                                tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
647                                                tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
648                                                NX_NULL,
649                                                NX_NULL);
650 
651             if(status != NX_CRYPTO_SUCCESS)
652             {
653                 return(status);
654             }
655 
656             if (hash_method -> nx_crypto_cleanup)
657             {
658                 status = hash_method -> nx_crypto_cleanup(tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch);
659 
660                 if(status != NX_CRYPTO_SUCCESS)
661                 {
662                     return(status);
663                 }
664             }
665             handler = NX_NULL;
666         }
667 #endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */
668 
669 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
670 #ifdef NX_SECURE_ENABLE_DTLS
671         if (protocol_version != NX_SECURE_TLS_VERSION_TLS_1_0 &&
672             protocol_version != NX_SECURE_TLS_VERSION_TLS_1_1 &&
673             protocol_version != NX_SECURE_DTLS_VERSION_1_0)
674 #else
675         if (protocol_version != NX_SECURE_TLS_VERSION_TLS_1_0 &&
676             protocol_version != NX_SECURE_TLS_VERSION_TLS_1_1)
677 #endif /* NX_SECURE_ENABLE_DTLS */
678 #endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */
679         {
680 
681             /* Signature Hash Algorithm. */
682             public_key[length] = (UCHAR)((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF00) >> 8);
683             public_key[length + 1] = (UCHAR)(ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0x00FF);
684             length += 2;
685         }
686 
687         /* Sign the hash. */
688         auth_method = ciphersuite -> nx_secure_tls_public_auth;
689         if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
690             (auth_method -> nx_crypto_algorithm == NX_CRYPTO_DIGITAL_SIGNATURE_RSA ||
691             auth_method -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_RSA))
692         {
693             signature_length = certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus_length;
694 
695             /* Signature Length */
696             public_key[length] = (UCHAR)((signature_length & 0xFF00) >> 8);
697             public_key[length + 1] = (UCHAR)(signature_length & 0x00FF);
698             length += 2;
699 
700 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
701 #ifdef NX_SECURE_ENABLE_DTLS
702             if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
703                (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
704                 protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 ||
705                 protocol_version == NX_SECURE_DTLS_VERSION_1_0))
706 #else
707             if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
708                (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
709                 protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1))
710 #endif /* NX_SECURE_ENABLE_DTLS */
711             {
712                 hash_length += hash_method -> nx_crypto_ICV_size_in_bits >> 3;
713                 der_encoding_length = 0;
714             }
715             else
716 #endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */
717             {
718                 switch ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF00) >> 8)
719                 {
720                 case NX_SECURE_TLS_HASH_ALGORITHM_MD5:
721                     der_encoding = _NX_CRYPTO_DER_OID_MD5;
722                     der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_MD5);
723                     break;
724                 case NX_SECURE_TLS_HASH_ALGORITHM_SHA1:
725                     der_encoding = _NX_CRYPTO_DER_OID_SHA_1;
726                     der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_SHA_1);
727                     break;
728                 case NX_SECURE_TLS_HASH_ALGORITHM_SHA224:
729                     der_encoding = _NX_CRYPTO_DER_OID_SHA_224;
730                     der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_SHA_224);
731                     break;
732                 case NX_SECURE_TLS_HASH_ALGORITHM_SHA256:
733                     der_encoding = _NX_CRYPTO_DER_OID_SHA_256;
734                     der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_SHA_256);
735                     break;
736                 case NX_SECURE_TLS_HASH_ALGORITHM_SHA384:
737                     der_encoding = _NX_CRYPTO_DER_OID_SHA_384;
738                     der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_SHA_384);
739                     break;
740                 case NX_SECURE_TLS_HASH_ALGORITHM_SHA512:
741                     der_encoding = _NX_CRYPTO_DER_OID_SHA_512;
742                     der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_SHA_512);
743                     break;
744                 default:
745                     return(NX_SECURE_TLS_UNSUPPORTED_SIGNATURE_ALGORITHM);
746                 }
747             }
748 
749             /* Build the RSA signature. */
750             /* C-STAT: If signature_length is ever exactly equal to (der_encoding_length + hash_length)
751                        then signature_offset will be 0 and the (signature_offset - 1) expression below
752                        would result in a negative array subscript. Thus, also check for equality in the
753                        second condition (a zero-length signature offset). */
754             signature_offset = signature_length - (der_encoding_length + hash_length);
755             if ((signature_offset > sizeof(_nx_secure_padded_signature)) ||
756                 (signature_length > sizeof(_nx_secure_padded_signature)) ||
757                 (signature_offset == 0))
758             {
759 
760                 /* Buffer too small. */
761                 return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
762             }
763             NX_CRYPTO_MEMSET(_nx_secure_padded_signature, 0xff, signature_offset);
764             _nx_secure_padded_signature[0] = 0x0;
765             _nx_secure_padded_signature[1] = 0x1;
766             _nx_secure_padded_signature[signature_offset - 1] = 0x0;
767 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
768             if (der_encoding_length > 0)
769 #endif
770             {
771                 NX_CRYPTO_MEMCPY(&_nx_secure_padded_signature[signature_offset], der_encoding, der_encoding_length); /* Use case of memcpy is verified. */
772                 signature_offset += der_encoding_length;
773             }
774             NX_CRYPTO_MEMCPY(&_nx_secure_padded_signature[signature_offset], hash, hash_length); /* Use case of memcpy is verified. */
775             if (auth_method -> nx_crypto_init != NX_NULL)
776             {
777                 /* Initialize the crypto method with public key. */
778                 status = auth_method -> nx_crypto_init((NX_CRYPTO_METHOD*)auth_method,
779                                                        (UCHAR *)certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus,
780                                                        (NX_CRYPTO_KEY_SIZE)(certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus_length << 3),
781                                                        &handler,
782                                                        public_auth_metadata,
783                                                        public_auth_metadata_size);
784                 if (status != NX_CRYPTO_SUCCESS)
785                 {
786                     return(status);
787                 }
788             }
789             if (auth_method -> nx_crypto_operation != NX_NULL)
790             {
791                 /* Sign the hash we just generated using our local RSA private key (associated with our local cert). */
792                 status = auth_method -> nx_crypto_operation(NX_CRYPTO_DECRYPT,
793                                                             handler,
794                                                             (NX_CRYPTO_METHOD*)auth_method,
795                                                             (UCHAR *)certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_exponent,
796                                                             (NX_CRYPTO_KEY_SIZE)(certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_exponent_length << 3),
797                                                             _nx_secure_padded_signature,
798                                                             signature_length,
799                                                             NX_NULL,
800                                                             &public_key[length],
801                                                             signature_length,
802                                                             public_auth_metadata,
803                                                             public_auth_metadata_size,
804                                                             NX_NULL, NX_NULL);
805                 if (status != NX_CRYPTO_SUCCESS)
806                 {
807                     return(status);
808                 }
809             }
810 
811             length += signature_length;
812 
813             if (auth_method -> nx_crypto_cleanup)
814             {
815                 status = auth_method -> nx_crypto_cleanup(public_auth_metadata);
816 
817                 if(status != NX_CRYPTO_SUCCESS)
818                 {
819                     return(status);
820                 }
821             }
822         }
823         else if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_ECDSA &&
824                  auth_method -> nx_crypto_algorithm == NX_CRYPTO_DIGITAL_SIGNATURE_ECDSA)
825         {
826             ec_privkey = &certificate -> nx_secure_x509_private_key.ec_private_key;
827             ec_pubkey = &certificate -> nx_secure_x509_public_key.ec_public_key;
828 
829             /* Find out which named curve the local certificate is using. */
830             status = _nx_secure_tls_find_curve_method(tls_ecc_curves, (USHORT)(ec_privkey -> nx_secure_ec_named_curve), &curve_method_cert, NX_NULL);
831             if(status != NX_SUCCESS)
832             {
833                 return(status);
834             }
835 
836             if (auth_method -> nx_crypto_init != NX_NULL)
837             {
838                 status = auth_method -> nx_crypto_init((NX_CRYPTO_METHOD*)auth_method,
839                                                         (UCHAR *)ec_pubkey -> nx_secure_ec_public_key,
840                                                         (NX_CRYPTO_KEY_SIZE)(ec_pubkey -> nx_secure_ec_public_key_length << 3),
841                                                         &handler,
842                                                         public_auth_metadata,
843                                                         public_auth_metadata_size);
844                 if (status != NX_CRYPTO_SUCCESS)
845                 {
846                     return(status);
847                 }
848             }
849             if (auth_method -> nx_crypto_operation == NX_NULL)
850             {
851                 return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
852             }
853 
854             status = auth_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler,
855                                                         (NX_CRYPTO_METHOD*)auth_method, NX_NULL, 0,
856                                                         (UCHAR *)curve_method_cert, sizeof(NX_CRYPTO_METHOD *), NX_NULL,
857                                                         NX_NULL, 0,
858                                                         public_auth_metadata,
859                                                         public_auth_metadata_size,
860                                                         NX_NULL, NX_NULL);
861             if (status != NX_CRYPTO_SUCCESS)
862             {
863                 return(status);
864             }
865 
866             /* Generate the signature and put it in the packet. */
867             extended_output.nx_crypto_extended_output_data = &public_key[length + 2];
868             extended_output.nx_crypto_extended_output_length_in_byte = output_size - length;
869             extended_output.nx_crypto_extended_output_actual_size = 0;
870             status = auth_method -> nx_crypto_operation(NX_CRYPTO_AUTHENTICATE, handler,
871                                                         (NX_CRYPTO_METHOD*)auth_method,
872                                                         (UCHAR *)ec_privkey -> nx_secure_ec_private_key,
873                                                         (NX_CRYPTO_KEY_SIZE)(ec_privkey -> nx_secure_ec_private_key_length << 3),
874                                                         hash,
875                                                         hash_method -> nx_crypto_ICV_size_in_bits >> 3, NX_NULL,
876                                                         (UCHAR *)&extended_output,
877                                                         sizeof(extended_output),
878                                                         public_auth_metadata,
879                                                         public_auth_metadata_size,
880                                                         NX_NULL, NX_NULL);
881             if (status != NX_CRYPTO_SUCCESS)
882             {
883                 return(status);
884             }
885 
886             if (auth_method -> nx_crypto_cleanup)
887             {
888                 status = auth_method -> nx_crypto_cleanup(public_auth_metadata);
889 
890                 if(status != NX_CRYPTO_SUCCESS)
891                 {
892                     return(status);
893                 }
894             }
895 
896             /* Signature Length */
897             public_key[length] = (UCHAR)((extended_output.nx_crypto_extended_output_actual_size & 0xFF00) >> 8);
898             public_key[length + 1] = (UCHAR)(extended_output.nx_crypto_extended_output_actual_size & 0x00FF);
899 
900             length += extended_output.nx_crypto_extended_output_actual_size + 2;
901         }
902         else
903         {
904             /* The signature algorithm is not supported. */
905             *public_key_size = 0;
906             return(NX_SECURE_TLS_UNSUPPORTED_SIGNATURE_ALGORITHM);
907         }
908     }
909 #endif
910 
911     /* Return the length of our generated data. */
912     *public_key_size = length;
913 
914     return(NX_SUCCESS);
915 }
916 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
917 
918 
919