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