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 
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 #ifndef NX_SECURE_TLS_CLIENT_DISABLED
31 
32 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(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 decrypted_signature[512];
35 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE && !NX_SECURE_DISABLE_X509 */
36 
37 /**************************************************************************/
38 /*                                                                        */
39 /*  FUNCTION                                               RELEASE        */
40 /*                                                                        */
41 /*    _nx_secure_process_server_key_exchange               PORTABLE C     */
42 /*                                                           6.2.1        */
43 /*  AUTHOR                                                                */
44 /*                                                                        */
45 /*    Yanwu Cai, Microsoft Corporation                                    */
46 /*                                                                        */
47 /*  DESCRIPTION                                                           */
48 /*                                                                        */
49 /*    This function processes an incoming ServerKeyExchange message,      */
50 /*    which is sent by the remote TLS Server host when certain            */
51 /*    ciphersuites (e.g. those using Diffie-Hellman) are used.            */
52 /*                                                                        */
53 /*  INPUT                                                                 */
54 /*                                                                        */
55 /*    ciphersuite                           Selected cipher suite         */
56 /*    tls_crypto_table                      TLS crypto methods            */
57 /*    protocol_version                      Selected TLS version          */
58 /*    packet_buffer                         Pointer to message data       */
59 /*    message_length                        Length of message data (bytes)*/
60 /*    tls_key_material                      TLS key material              */
61 /*    tls_credentials                       TLS credentials               */
62 /*    tls_handshake_hash                    Metadata for handshake hash   */
63 /*    public_cipher_metadata                Metadata for public cipher    */
64 /*    public_cipher_metadata_size           Size of public cipher metadata*/
65 /*    public_auth_metadata                  Metadata for public auth      */
66 /*    public_auth_metadata_size             Size of public auth metadata  */
67 /*    tls_ecc_curves                        ECC curves                    */
68 /*                                                                        */
69 /*  OUTPUT                                                                */
70 /*                                                                        */
71 /*    status                                Completion status             */
72 /*                                                                        */
73 /*  CALLS                                                                 */
74 /*                                                                        */
75 /*    _nx_secure_tls_find_curve_method      Find named curve used         */
76 /*    _nx_secure_x509_remote_endpoint_certificate_get                     */
77 /*                                          Get remote host certificate   */
78 /*    _nx_secure_x509_find_certificate_methods                            */
79 /*                                          Find certificate methods      */
80 /*    _nx_secure_x509_pkcs7_decode          Decode the PKCS#7 signature   */
81 /*    [nx_crypto_init]                      Crypto initialization         */
82 /*    [nx_crypto_operation]                 Crypto operation              */
83 /*                                                                        */
84 /*  CALLED BY                                                             */
85 /*                                                                        */
86 /*    _nx_secure_tls_process_server_key_exchange                          */
87 /*                                          Process ServerKeyExchange     */
88 /*                                                                        */
89 /*  RELEASE HISTORY                                                       */
90 /*                                                                        */
91 /*    DATE              NAME                      DESCRIPTION             */
92 /*                                                                        */
93 /*  10-31-2022     Yanwu Cai                Initial Version 6.2.0         */
94 /*  03-08-2023     Yanwu Cai                Modified comment(s),          */
95 /*                                            fixed compiler errors when  */
96 /*                                            x509 is disabled,           */
97 /*                                            resulting in version 6.2.1  */
98 /*                                                                        */
99 /**************************************************************************/
_nx_secure_process_server_key_exchange(const NX_SECURE_TLS_CIPHERSUITE_INFO * ciphersuite,NX_SECURE_TLS_CRYPTO * tls_crypto_table,USHORT protocol_version,UCHAR * packet_buffer,UINT message_length,NX_SECURE_TLS_KEY_MATERIAL * tls_key_material,NX_SECURE_TLS_CREDENTIALS * tls_credentials,NX_SECURE_TLS_HANDSHAKE_HASH * tls_handshake_hash,VOID * public_cipher_metadata,ULONG public_cipher_metadata_size,VOID * public_auth_metadata,ULONG public_auth_metadata_size,VOID * tls_ecc_curves)100 UINT _nx_secure_process_server_key_exchange(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, NX_SECURE_TLS_CRYPTO *tls_crypto_table,
101                                             USHORT protocol_version, UCHAR *packet_buffer, UINT message_length,
102                                             NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, NX_SECURE_TLS_CREDENTIALS *tls_credentials,
103                                             NX_SECURE_TLS_HANDSHAKE_HASH *tls_handshake_hash,
104                                             VOID *public_cipher_metadata, ULONG public_cipher_metadata_size,
105                                             VOID *public_auth_metadata, ULONG public_auth_metadata_size, VOID *tls_ecc_curves)
106 {
107 
108 #ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
109 USHORT                                length;
110 #endif /* NX_SECURE_ENABLE_PSK_CIPHERSUITES */
111 #if defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || \
112    (defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509))
113 UINT                                  status;
114 #endif
115 #if (defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)) || \
116     defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE)
117 VOID                                 *handler = NX_NULL;
118 #endif
119 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
120 const NX_CRYPTO_METHOD               *curve_method;
121 const NX_CRYPTO_METHOD               *ecdh_method;
122 NX_SECURE_X509_CERT                  *certificate;
123 NX_CRYPTO_EXTENDED_OUTPUT             extended_output;
124 UINT                                  key_length;
125 UCHAR                                *key;
126 const NX_CRYPTO_METHOD               *curve_method_cert;
127 const NX_CRYPTO_METHOD               *hash_method;
128 const NX_CRYPTO_METHOD               *auth_method;
129 USHORT                                signature_length;
130 NX_SECURE_X509_CRYPTO                *crypto_methods;
131 UINT                                  sig_oid_length;
132 const UCHAR                          *sig_oid;
133 UINT                                  decrypted_hash_length;
134 const UCHAR                          *decrypted_hash;
135 UINT                                  compare_result;
136 NX_SECURE_EC_PUBLIC_KEY              *ec_pubkey;
137 UCHAR                                *current_buffer;
138 UCHAR                                 hash_algorithm;
139 UCHAR                                 signature_algorithm;
140 USHORT                                signature_algorithm_id;
141 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
142 UINT                                  i;
143 #endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */
144 #endif /* defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509) */
145 
146 #if !defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) || defined(NX_SECURE_DISABLE_X509) || \
147     (!NX_SECURE_TLS_TLS_1_0_ENABLED && !NX_SECURE_TLS_TLS_1_1_ENABLED)
148     NX_PARAMETER_NOT_USED(tls_crypto_table);
149     NX_PARAMETER_NOT_USED(protocol_version);
150     NX_PARAMETER_NOT_USED(ciphersuite);
151     NX_PARAMETER_NOT_USED(tls_key_material);
152     NX_PARAMETER_NOT_USED(tls_credentials);
153     NX_PARAMETER_NOT_USED(tls_handshake_hash);
154     NX_PARAMETER_NOT_USED(public_cipher_metadata);
155     NX_PARAMETER_NOT_USED(public_cipher_metadata_size);
156     NX_PARAMETER_NOT_USED(public_auth_metadata);
157     NX_PARAMETER_NOT_USED(public_auth_metadata_size);
158     NX_PARAMETER_NOT_USED(tls_ecc_curves);
159 #endif
160 
161     NX_PARAMETER_NOT_USED(packet_buffer);
162     NX_PARAMETER_NOT_USED(message_length);
163 
164 
165 #ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
166     /* Check for PSK ciphersuites. */
167     if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK)
168     {
169 
170         /* Get identity hint length. */
171         length = (USHORT)((packet_buffer[0] << 8) + (USHORT)packet_buffer[1]);
172         packet_buffer += 2;
173 
174         if (length > message_length || length > NX_SECURE_TLS_MAX_PSK_ID_SIZE)
175         {
176             /* The payload is larger than the header indicated. */
177             return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
178         }
179 
180         /* Extract the identity hint and save in the TLS Session. Then when pre-master is generated
181             in client_handshake, we can do the right thing... */
182         NX_SECURE_MEMCPY(tls_credentials -> nx_secure_tls_remote_psk_id, &packet_buffer[0], length); /* Use case of memcpy is verified. */
183         tls_credentials -> nx_secure_tls_remote_psk_id_size = length;
184         return(NX_SECURE_TLS_SUCCESS);
185 
186 
187     }
188 #endif
189 
190 #ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
191     /* Check for ECJ-PAKE ciphersuites. */
192     if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE)
193     {
194         /* Make sure curve type is named_curve (3). */
195         if (packet_buffer[0] != 3)
196         {
197             return(NX_SECURE_TLS_UNSUPPORTED_ECC_FORMAT);
198         }
199 
200         /* Only secp256r1 (23) is supported.  */
201         if (packet_buffer[1] != 0 || packet_buffer[2] != 23)
202         {
203             return(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE);
204         }
205 
206         packet_buffer += 3;
207 
208 
209         tls_key_material -> nx_secure_tls_pre_master_secret_size = 32;
210 
211         status = ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_operation(NX_CRYPTO_ECJPAKE_SERVER_KEY_EXCHANGE_PROCESS,
212                                                                                  &handler,
213                                                                                  (NX_CRYPTO_METHOD *)ciphersuite -> nx_secure_tls_public_auth,
214                                                                                  NX_NULL, 0,
215                                                                                  packet_buffer,
216                                                                                  message_length,
217                                                                                  NX_NULL,
218                                                                                  tls_key_material -> nx_secure_tls_pre_master_secret,
219                                                                                  tls_key_material -> nx_secure_tls_pre_master_secret_size,
220                                                                                  public_auth_metadata,
221                                                                                  public_auth_metadata_size,
222                                                                                  NX_NULL, NX_NULL);
223         if (status)
224         {
225             return(status);
226         }
227 
228         if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_cleanup)
229         {
230             status = ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_cleanup(public_auth_metadata);
231         }
232 
233         return(status);
234     }
235 #endif
236 
237 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
238 #ifndef NX_SECURE_TLS_CLIENT_DISABLED
239     if ((ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE))
240     {
241 
242         if (message_length < 4)
243         {
244             return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
245         }
246 
247         /* Make sure curve type is named_curve (3). */
248         if (packet_buffer[0] != 3)
249         {
250             return(NX_SECURE_TLS_UNSUPPORTED_ECC_FORMAT);
251         }
252 
253         /* Find out which named curve the server is using. */
254         status = _nx_secure_tls_find_curve_method((NX_SECURE_TLS_ECC *)tls_ecc_curves, (USHORT)((packet_buffer[1] << 8) + packet_buffer[2]), &curve_method, NX_NULL);
255 
256         if (status != NX_SUCCESS)
257         {
258 
259             /* The remote server is using an unsupported curve. */
260             return(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE);
261         }
262 
263         current_buffer = &packet_buffer[3];
264 
265         /* Get reference to remote server certificate so we can get the public key for signature verification. */
266         status = _nx_secure_x509_remote_endpoint_certificate_get(&tls_credentials -> nx_secure_tls_certificate_store,
267                                                                  &certificate);
268         if (status)
269         {
270             /* No certificate found, error! */
271             return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND);
272         }
273 
274         key_length = current_buffer[0];
275         key = &current_buffer[1];
276 
277         current_buffer += key_length + 1;
278 
279 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
280 #ifdef NX_SECURE_ENABLE_DTLS
281         if (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
282             protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 ||
283             protocol_version == NX_SECURE_DTLS_VERSION_1_0)
284 #else
285         if (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
286             protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)
287 #endif /* NX_SECURE_ENABLE_DTLS */
288         {
289             if ((UINT)key_length + 6 > message_length)
290             {
291                 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
292             }
293 
294             hash_algorithm = NX_SECURE_TLS_HASH_ALGORITHM_SHA1;
295             if (certificate -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_EC)
296             {
297                 signature_algorithm = NX_SECURE_TLS_SIGNATURE_ALGORITHM_ECDSA;
298             }
299             else
300             {
301                 signature_algorithm = NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA;
302             }
303         }
304         else
305 #endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */
306         {
307             if ((UINT)key_length + 8 > message_length)
308             {
309                 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
310             }
311 
312             hash_algorithm = current_buffer[0];
313             signature_algorithm = current_buffer[1];
314             current_buffer += 2;
315         }
316 
317         /* Find out the hash algorithm used for the signature. */
318         /* Map signature algorithm to internal ID. */
319         _nx_secure_tls_get_signature_algorithm_id(((UINT)(hash_algorithm << 8) + signature_algorithm),
320                                                   &signature_algorithm_id);
321 
322         /* Get the cypto method. */
323         status = _nx_secure_x509_find_certificate_methods(certificate,
324                                                           signature_algorithm_id,
325                                                           &crypto_methods);
326         if (status)
327         {
328             return(NX_SECURE_TLS_UNSUPPORTED_SIGNATURE_ALGORITHM);
329         }
330 
331 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
332 #ifdef NX_SECURE_ENABLE_DTLS
333         if (signature_algorithm == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
334            (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
335             protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 ||
336             protocol_version == NX_SECURE_DTLS_VERSION_1_0))
337 #else
338         if (signature_algorithm == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
339            (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
340             protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1))
341 #endif /* NX_SECURE_ENABLE_DTLS */
342         {
343 
344             /* TLS 1.0 and TLS 1.1 use MD5 + SHA1 hash for RSA signatures. */
345             hash_method = tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method;
346         }
347         else
348 #endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */
349         {
350             hash_method = crypto_methods -> nx_secure_x509_hash_method;
351         }
352 
353 
354         /* Calculate the hash: SHA(ClientHello.random + ServerHello.random +
355                                    ServerKeyExchange.params); */
356         if (hash_method -> nx_crypto_init)
357         {
358             status = hash_method -> nx_crypto_init((NX_CRYPTO_METHOD*)hash_method,
359                                           NX_NULL,
360                                           0,
361                                           &handler,
362                                           tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
363                                           tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size);
364 
365             if(status != NX_CRYPTO_SUCCESS)
366             {
367                 return(status);
368             }
369         }
370 
371         if (hash_method -> nx_crypto_operation != NX_NULL)
372         {
373             status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE,
374                                                handler,
375                                                (NX_CRYPTO_METHOD*)hash_method,
376                                                NX_NULL,
377                                                0,
378                                                NX_NULL,
379                                                0,
380                                                NX_NULL,
381                                                NX_NULL,
382                                                0,
383                                                tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
384                                                tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
385                                                NX_NULL,
386                                                NX_NULL);
387 
388             if(status != NX_CRYPTO_SUCCESS)
389             {
390                 return(status);
391             }
392         }
393         else
394         {
395             return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
396         }
397 
398         status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
399                                            handler,
400                                            (NX_CRYPTO_METHOD*)hash_method,
401                                            NX_NULL,
402                                            0,
403                                            tls_key_material -> nx_secure_tls_client_random,
404                                            32,
405                                            NX_NULL,
406                                            NX_NULL,
407                                            0,
408                                            tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
409                                            tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
410                                            NX_NULL,
411                                            NX_NULL);
412 
413         if(status != NX_CRYPTO_SUCCESS)
414         {
415             return(status);
416         }
417 
418         status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
419                                            handler,
420                                            (NX_CRYPTO_METHOD*)hash_method,
421                                            NX_NULL,
422                                            0,
423                                            tls_key_material -> nx_secure_tls_server_random,
424                                            32,
425                                            NX_NULL,
426                                            NX_NULL,
427                                            0,
428                                            tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
429                                            tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
430                                            NX_NULL,
431                                            NX_NULL);
432 
433         if(status != NX_CRYPTO_SUCCESS)
434         {
435             return(status);
436         }
437 
438         status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
439                                            handler,
440                                            (NX_CRYPTO_METHOD*)hash_method,
441                                            NX_NULL,
442                                            0,
443                                            packet_buffer,
444                                            (ULONG)(4 + key_length),
445                                            NX_NULL,
446                                            NX_NULL,
447                                            0,
448                                            tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
449                                            tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
450                                            NX_NULL,
451                                            NX_NULL);
452 
453         if(status != NX_CRYPTO_SUCCESS)
454         {
455             return(status);
456         }
457 
458         status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE,
459                                            handler,
460                                            (NX_CRYPTO_METHOD*)hash_method,
461                                            NX_NULL,
462                                            0,
463                                            NX_NULL,
464                                            0,
465                                            NX_NULL,
466                                            hash,
467                                            hash_method -> nx_crypto_ICV_size_in_bits >> 3,
468                                            tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
469                                            tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
470                                            NX_NULL,
471                                            NX_NULL);
472         if(status != NX_CRYPTO_SUCCESS)
473         {
474             return(status);
475         }
476 
477         if (hash_method -> nx_crypto_cleanup)
478         {
479             status = hash_method -> nx_crypto_cleanup(tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch);
480 
481             if(status != NX_CRYPTO_SUCCESS)
482             {
483                 return(status);
484             }
485         }
486         handler = NX_NULL;
487 
488 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
489 #ifdef NX_SECURE_ENABLE_DTLS
490         if (signature_algorithm == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
491            (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
492             protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 ||
493             protocol_version == NX_SECURE_DTLS_VERSION_1_0))
494 #else
495         if (signature_algorithm == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
496            (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
497             protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1))
498 #endif /* NX_SECURE_ENABLE_DTLS */
499         {
500             hash_method = tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method;;
501 
502             /* Calculate the hash: SHA(ClientHello.random + ServerHello.random +
503                                        ServerKeyExchange.params); */
504             if (hash_method -> nx_crypto_init)
505             {
506                 status = hash_method -> nx_crypto_init((NX_CRYPTO_METHOD*)hash_method,
507                                                 NX_NULL,
508                                                 0,
509                                                 &handler,
510                                                 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
511                                                 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size);
512 
513                 if(status != NX_CRYPTO_SUCCESS)
514                 {
515                     return(status);
516                 }
517             }
518 
519             if (hash_method -> nx_crypto_operation != NX_NULL)
520             {
521                 status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE,
522                                                     handler,
523                                                     (NX_CRYPTO_METHOD*)hash_method,
524                                                     NX_NULL,
525                                                     0,
526                                                     NX_NULL,
527                                                     0,
528                                                     NX_NULL,
529                                                     NX_NULL,
530                                                     0,
531                                                     tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
532                                                     tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
533                                                     NX_NULL,
534                                                     NX_NULL);
535 
536                 if(status != NX_CRYPTO_SUCCESS)
537                 {
538                     return(status);
539                 }
540             }
541             else
542             {
543                 return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
544             }
545 
546             status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
547                                                 handler,
548                                                 (NX_CRYPTO_METHOD*)hash_method,
549                                                 NX_NULL,
550                                                 0,
551                                                 tls_key_material -> nx_secure_tls_client_random,
552                                                 32,
553                                                 NX_NULL,
554                                                 NX_NULL,
555                                                 0,
556                                                 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
557                                                 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
558                                                 NX_NULL,
559                                                 NX_NULL);
560 
561             if(status != NX_CRYPTO_SUCCESS)
562             {
563                 return(status);
564             }
565 
566             status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
567                                                 handler,
568                                                 (NX_CRYPTO_METHOD*)hash_method,
569                                                 NX_NULL,
570                                                 0,
571                                                 tls_key_material -> nx_secure_tls_server_random,
572                                                 32,
573                                                 NX_NULL,
574                                                 NX_NULL,
575                                                 0,
576                                                 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
577                                                 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
578                                                 NX_NULL,
579                                                 NX_NULL);
580 
581             if (status != NX_CRYPTO_SUCCESS)
582             {
583                 return(status);
584             }
585 
586             status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
587                                                 handler,
588                                                 (NX_CRYPTO_METHOD*)hash_method,
589                                                 NX_NULL,
590                                                 0,
591                                                 packet_buffer,
592                                                 (ULONG)(4 + key_length),
593                                                 NX_NULL,
594                                                 NX_NULL,
595                                                 0,
596                                                 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
597                                                 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
598                                                 NX_NULL,
599                                                 NX_NULL);
600 
601             if(status != NX_CRYPTO_SUCCESS)
602             {
603                 return(status);
604             }
605 
606             status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE,
607                                                 handler,
608                                                 (NX_CRYPTO_METHOD*)hash_method,
609                                                 NX_NULL,
610                                                 0,
611                                                 NX_NULL,
612                                                 0,
613                                                 NX_NULL,
614                                                 &hash[16],
615                                                 hash_method -> nx_crypto_ICV_size_in_bits >> 3,
616                                                 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
617                                                 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
618                                                 NX_NULL,
619                                                 NX_NULL);
620 
621             if (status != NX_CRYPTO_SUCCESS)
622             {
623                 return(status);
624             }
625 
626             if (hash_method -> nx_crypto_cleanup)
627             {
628                 status = hash_method -> nx_crypto_cleanup(tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch);
629 
630                 if(status != NX_CRYPTO_SUCCESS)
631                 {
632                     return(status);
633                 }
634             }
635             handler = NX_NULL;
636         }
637 #endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */
638 
639         signature_length = (USHORT)((current_buffer[0] << 8) + current_buffer[1]);
640         current_buffer += 2;
641 
642 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
643 #ifdef NX_SECURE_ENABLE_DTLS
644         if (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
645             protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 ||
646             protocol_version == NX_SECURE_DTLS_VERSION_1_0)
647 #else
648         if (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
649             protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)
650 #endif /* NX_SECURE_ENABLE_DTLS */
651         {
652             if ((UINT)signature_length + key_length + 6 > message_length)
653             {
654                 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
655             }
656         }
657         else
658 #endif
659         {
660             if ((UINT)signature_length + key_length + 8 > message_length)
661             {
662                 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
663             }
664         }
665 
666         /* Verify the signature. */
667         auth_method = ciphersuite -> nx_secure_tls_public_auth;
668 
669         if (signature_algorithm == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
670             (auth_method -> nx_crypto_algorithm == NX_CRYPTO_DIGITAL_SIGNATURE_RSA ||
671             auth_method -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_RSA))
672         {
673             /* Verify the RSA signature. */
674 
675             if (auth_method -> nx_crypto_init != NX_NULL)
676             {
677                 /* Initialize the crypto method with public key. */
678                 status = auth_method -> nx_crypto_init((NX_CRYPTO_METHOD*)auth_method,
679                                                        (UCHAR *)certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus,
680                                                        (NX_CRYPTO_KEY_SIZE)(certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus_length << 3),
681                                                        &handler,
682                                                        public_auth_metadata,
683                                                        public_auth_metadata_size);
684                 if(status != NX_CRYPTO_SUCCESS)
685                 {
686                     return(status);
687                 }
688             }
689 
690             if (auth_method -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_RSA)
691             {
692                 status = auth_method -> nx_crypto_operation(NX_CRYPTO_DECRYPT,
693                                                             handler,
694                                                             (NX_CRYPTO_METHOD*)auth_method,
695                                                             (UCHAR *)certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_exponent,
696                                                             (NX_CRYPTO_KEY_SIZE)(certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_exponent_length << 3),
697                                                             current_buffer,
698                                                             signature_length,
699                                                             NX_NULL,
700                                                             decrypted_signature,
701                                                             sizeof(decrypted_signature),
702                                                             public_auth_metadata,
703                                                             public_auth_metadata_size,
704                                                             NX_NULL, NX_NULL);
705                 if(status != NX_CRYPTO_SUCCESS)
706                 {
707                     return(status);
708                 }
709             }
710 
711             if (auth_method -> nx_crypto_cleanup)
712             {
713                 status = auth_method -> nx_crypto_cleanup(public_auth_metadata);
714                 if(status != NX_CRYPTO_SUCCESS)
715                 {
716                     return(status);
717                 }
718             }
719             handler = NX_NULL;
720 
721 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
722 #ifdef NX_SECURE_ENABLE_DTLS
723             if (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
724                 protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 ||
725                 protocol_version == NX_SECURE_DTLS_VERSION_1_0)
726 #else
727             if (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
728                 protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)
729 #endif /* NX_SECURE_ENABLE_DTLS */
730             {
731                 if (signature_length < 39)
732                 {
733                     return(NX_SECURE_TLS_SIGNATURE_VERIFICATION_ERROR);
734                 }
735 
736                 /* Block type is 0x00, 0x01 for signatures */
737                 if (decrypted_signature[0] != 0x0 && decrypted_signature[1] != 0x1)
738                 {
739                     /* Unknown block type. */
740                     return(NX_SECURE_TLS_PADDING_CHECK_FAILED);
741                 }
742 
743                 /* Check padding. */
744                 for (i = 2; i < (UINT)(signature_length - 37); ++i)
745                 {
746                     if (decrypted_signature[i] != (UCHAR)0xFF)
747                     {
748                         /* Bad padding value. */
749                         return(NX_SECURE_TLS_PADDING_CHECK_FAILED);
750                     }
751                 }
752 
753                 /* Make sure we actually saw a NULL byte. */
754                 if (decrypted_signature[i] != 0x00)
755                 {
756                     return(NX_SECURE_TLS_PADDING_CHECK_FAILED);
757                 }
758 
759                 decrypted_hash = &decrypted_signature[i + 1];
760                 decrypted_hash_length = 36;
761             }
762             else
763 #endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */
764             {
765                 /* Decode the decrypted signature. */
766                 status = _nx_secure_x509_pkcs7_decode(decrypted_signature, signature_length, &sig_oid, &sig_oid_length,
767                                                       &decrypted_hash, &decrypted_hash_length);
768                 if (status != NX_SUCCESS)
769                 {
770                     return(NX_SECURE_TLS_SIGNATURE_VERIFICATION_ERROR);
771                 }
772 
773                 if (decrypted_hash_length != (hash_method -> nx_crypto_ICV_size_in_bits >> 3))
774                 {
775                     return(NX_SECURE_TLS_SIGNATURE_VERIFICATION_ERROR);
776                 }
777             }
778 
779             /* Compare generated hash with decrypted hash. */
780             compare_result = (UINT)NX_SECURE_MEMCMP(hash, decrypted_hash, decrypted_hash_length);
781 
782 #ifdef NX_SECURE_KEY_CLEAR
783             NX_SECURE_MEMSET(hash, 0, sizeof(hash));
784             NX_SECURE_MEMSET(decrypted_signature, 0, sizeof(decrypted_signature));
785 #endif /* NX_SECURE_KEY_CLEAR  */
786 
787             if (compare_result != 0)
788             {
789                 return(NX_SECURE_TLS_SIGNATURE_VERIFICATION_ERROR);
790             }
791         }
792         else if (signature_algorithm == NX_SECURE_TLS_SIGNATURE_ALGORITHM_ECDSA &&
793                  auth_method -> nx_crypto_algorithm == NX_CRYPTO_DIGITAL_SIGNATURE_ECDSA)
794         {
795             /* Verify the ECDSA signature. */
796 
797             ec_pubkey = &certificate -> nx_secure_x509_public_key.ec_public_key;
798 
799             /* Find out which named curve the remote certificate is using. */
800             status = _nx_secure_tls_find_curve_method((NX_SECURE_TLS_ECC *)tls_ecc_curves, (USHORT)(ec_pubkey -> nx_secure_ec_named_curve), &curve_method_cert, NX_NULL);
801 
802             if(status != NX_SUCCESS)
803             {
804 
805                 /* The remote certificate is using an unsupported curve. */
806                 return(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE);
807             }
808 
809             if (auth_method -> nx_crypto_init != NX_NULL)
810             {
811                 status = auth_method -> nx_crypto_init((NX_CRYPTO_METHOD*)auth_method,
812                                                        (UCHAR *)ec_pubkey -> nx_secure_ec_public_key,
813                                                        (NX_CRYPTO_KEY_SIZE)(ec_pubkey -> nx_secure_ec_public_key_length << 3),
814                                                        &handler,
815                                                        public_auth_metadata,
816                                                        public_auth_metadata_size);
817                 if (status != NX_CRYPTO_SUCCESS)
818                 {
819                     return(status);
820                 }
821             }
822             if (auth_method -> nx_crypto_operation == NX_NULL)
823             {
824                 return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
825             }
826 
827             status = auth_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler,
828                                                         (NX_CRYPTO_METHOD*)auth_method, NX_NULL, 0,
829                                                         (UCHAR *)curve_method_cert, sizeof(NX_CRYPTO_METHOD *), NX_NULL,
830                                                         NX_NULL, 0,
831                                                         public_auth_metadata,
832                                                         public_auth_metadata_size,
833                                                         NX_NULL, NX_NULL);
834             if (status != NX_CRYPTO_SUCCESS)
835             {
836                 return(status);
837             }
838 
839             status = auth_method -> nx_crypto_operation(NX_CRYPTO_VERIFY, handler,
840                                                         (NX_CRYPTO_METHOD*)auth_method,
841                                                         (UCHAR *)ec_pubkey -> nx_secure_ec_public_key,
842                                                         (NX_CRYPTO_KEY_SIZE)(ec_pubkey -> nx_secure_ec_public_key_length << 3),
843                                                         hash,
844                                                         hash_method -> nx_crypto_ICV_size_in_bits >> 3,
845                                                         NX_NULL,
846                                                         current_buffer,
847                                                         signature_length,
848                                                         public_auth_metadata,
849                                                         public_auth_metadata_size,
850                                                         NX_NULL, NX_NULL);
851 
852             if (status == NX_CRYPTO_AUTHENTICATION_FAILED)
853             {
854                 return(NX_SECURE_TLS_SIGNATURE_VERIFICATION_ERROR);
855             }
856 
857             if (status != NX_CRYPTO_SUCCESS)
858             {
859                 return(status);
860             }
861 
862             if (auth_method -> nx_crypto_cleanup)
863             {
864                 status = auth_method -> nx_crypto_cleanup(public_auth_metadata);
865                 if(status != NX_CRYPTO_SUCCESS)
866                 {
867                     return(status);
868                 }
869             }
870         }
871         else
872         {
873             /* The signature hash algorithm used by the server is not supported. */
874             return(NX_SECURE_TLS_UNSUPPORTED_SIGNATURE_ALGORITHM);
875         }
876 
877         ecdh_method = ciphersuite -> nx_secure_tls_public_cipher;
878         if (ecdh_method -> nx_crypto_operation == NX_NULL)
879         {
880             return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
881         }
882 
883         if (ecdh_method -> nx_crypto_init != NX_NULL)
884         {
885             status = ecdh_method -> nx_crypto_init((NX_CRYPTO_METHOD*)ecdh_method,
886                                            NX_NULL,
887                                            0,
888                                            &handler,
889                                            public_cipher_metadata,
890                                            public_cipher_metadata_size);
891             if(status != NX_CRYPTO_SUCCESS)
892             {
893                 return(status);
894             }
895         }
896 
897         status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler,
898                                                      (NX_CRYPTO_METHOD*)ecdh_method, NX_NULL, 0,
899                                                      (UCHAR *)curve_method, sizeof(NX_CRYPTO_METHOD *), NX_NULL,
900                                                      NX_NULL, 0,
901                                                      public_cipher_metadata,
902                                                      public_cipher_metadata_size,
903                                                      NX_NULL, NX_NULL);
904         if (status != NX_CRYPTO_SUCCESS)
905         {
906             return(status);
907         }
908 
909         /* Store public key in the nx_secure_tls_new_key_material_data. */
910         extended_output.nx_crypto_extended_output_data = &tls_key_material -> nx_secure_tls_new_key_material_data[1];
911         extended_output.nx_crypto_extended_output_length_in_byte = sizeof(tls_key_material -> nx_secure_tls_new_key_material_data) - 1;
912         extended_output.nx_crypto_extended_output_actual_size = 0;
913         status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_DH_SETUP, handler,
914                                                      (NX_CRYPTO_METHOD*)ecdh_method, NX_NULL, 0,
915                                                      NX_NULL, 0, NX_NULL,
916                                                      (UCHAR *)&extended_output,
917                                                      sizeof(extended_output),
918                                                      public_cipher_metadata,
919                                                      public_cipher_metadata_size,
920                                                      NX_NULL, NX_NULL);
921         if (status != NX_CRYPTO_SUCCESS)
922         {
923             return(status);
924         }
925 
926         /* Store the length in the first octet. */
927         tls_key_material -> nx_secure_tls_new_key_material_data[0] = (UCHAR)extended_output.nx_crypto_extended_output_actual_size;
928 
929         extended_output.nx_crypto_extended_output_data = tls_key_material -> nx_secure_tls_pre_master_secret;
930         extended_output.nx_crypto_extended_output_length_in_byte = sizeof(tls_key_material -> nx_secure_tls_pre_master_secret);
931         extended_output.nx_crypto_extended_output_actual_size = 0;
932         status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_DH_CALCULATE, handler,
933                                                      (NX_CRYPTO_METHOD*)ecdh_method, NX_NULL, 0,
934                                                      key, key_length, NX_NULL,
935                                                      (UCHAR *)&extended_output,
936                                                      sizeof(extended_output),
937                                                      public_cipher_metadata,
938                                                      public_cipher_metadata_size,
939                                                      NX_NULL, NX_NULL);
940         if (status != NX_CRYPTO_SUCCESS)
941         {
942             return(status);
943         }
944 
945         tls_key_material -> nx_secure_tls_pre_master_secret_size = extended_output.nx_crypto_extended_output_actual_size;
946 
947         if (ecdh_method -> nx_crypto_cleanup)
948         {
949             status = ecdh_method -> nx_crypto_cleanup(public_cipher_metadata);
950         }
951 
952         return(status);
953     }
954 #endif /* NX_SECURE_TLS_CLIENT_DISABLED */
955 #endif /* defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) */
956 
957     /* No key exchange should be received by the current cipher suite. */
958     return(NX_SECURE_TLS_UNEXPECTED_MESSAGE);
959 }
960 
961 #endif
962