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 
26 #include "nx_secure_tls.h"
27 
28 #ifndef NX_SECURE_DISABLE_X509
29 static UCHAR _nx_secure_client_padded_pre_master[600];
30 #endif
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _nx_secure_process_client_key_exchange               PORTABLE C     */
37 /*                                                           6.2.1        */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Yanwu Cai, Microsoft Corporation                                    */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function processes an incoming ClientKeyExchange message,      */
45 /*    which contains the encrypted Pre-Master Secret. This function       */
46 /*    decrypts the Pre-Master Secret and saves it in the TLS session      */
47 /*    control block for use in generating session key material later.     */
48 /*                                                                        */
49 /*  INPUT                                                                 */
50 /*                                                                        */
51 /*    ciphersuite                           Selected cipher suite         */
52 /*    protocol_version                      Selected TLS version          */
53 /*    packet_buffer                         Pointer to message data       */
54 /*    message_length                        Length of message data (bytes)*/
55 /*    received_remote_credentials           Indicates credentials received*/
56 /*    tls_key_material                      TLS key material              */
57 /*    tls_credentials                       TLS credentials               */
58 /*    public_cipher_metadata                Metadata for public cipher    */
59 /*    public_cipher_metadata_size           Size of public cipher metadata*/
60 /*    public_auth_metadata                  Metadata for public auth      */
61 /*    public_auth_metadata_size             Size of public auth metadata  */
62 /*    tls_ecc_curves                        ECC curves                    */
63 /*                                                                        */
64 /*  OUTPUT                                                                */
65 /*                                                                        */
66 /*    status                                Completion status             */
67 /*                                                                        */
68 /*  CALLS                                                                 */
69 /*                                                                        */
70 /*    _nx_secure_generate_premaster_secret  Generate the shared secret    */
71 /*                                            used to generate keys later */
72 /*    _nx_secure_x509_local_device_certificate_get                        */
73 /*                                          Get the local certificate     */
74 /*                                            for its keys                */
75 /*    _nx_secure_tls_find_curve_method      Find named curve used         */
76 /*    [nx_crypto_init]                      Initialize crypto             */
77 /*    [nx_crypto_operation]                 Crypto operation              */
78 /*                                                                        */
79 /*  CALLED BY                                                             */
80 /*                                                                        */
81 /*    _nx_secure_tls_process_client_key_exchange                          */
82 /*                                          Process ClientKeyExchange     */
83 /*                                                                        */
84 /*  RELEASE HISTORY                                                       */
85 /*                                                                        */
86 /*    DATE              NAME                      DESCRIPTION             */
87 /*                                                                        */
88 /*  10-31-2022     Yanwu Cai                Initial Version 6.2.0         */
89 /*  03-08-2023     Yanwu Cai                Modified comment(s),          */
90 /*                                            fixed compiler errors when  */
91 /*                                            x509 is disabled,           */
92 /*                                            resulting in version 6.2.1  */
93 /*                                                                        */
94 /**************************************************************************/
_nx_secure_process_client_key_exchange(const NX_SECURE_TLS_CIPHERSUITE_INFO * ciphersuite,USHORT protocol_version,UCHAR * packet_buffer,UINT message_length,USHORT * received_remote_credentials,NX_SECURE_TLS_KEY_MATERIAL * tls_key_material,NX_SECURE_TLS_CREDENTIALS * tls_credentials,VOID * public_cipher_metadata,ULONG public_cipher_metadata_size,VOID * public_auth_metadata,ULONG public_auth_metadata_size,VOID * tls_ecc_curves)95 UINT _nx_secure_process_client_key_exchange(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version,
96                                             UCHAR *packet_buffer, UINT message_length, USHORT *received_remote_credentials,
97                                             NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, NX_SECURE_TLS_CREDENTIALS *tls_credentials,
98                                             VOID *public_cipher_metadata, ULONG public_cipher_metadata_size,
99                                             VOID *public_auth_metadata, ULONG public_auth_metadata_size, VOID *tls_ecc_curves)
100 {
101 #if !defined(NX_SECURE_DISABLE_X509) || \
102     (defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509))
103 USHORT                              length;
104 #endif
105 UINT                                status = NX_SECURE_TLS_UNEXPECTED_MESSAGE;
106 #if defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || !defined(NX_SECURE_DISABLE_X509)
107 const NX_CRYPTO_METHOD             *public_cipher_method;
108 #endif
109 #if defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || !defined(NX_SECURE_DISABLE_X509) || \
110     (defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509))
111 VOID                               *handler = NX_NULL;
112 #endif
113 #ifndef NX_SECURE_DISABLE_X509
114 UCHAR                              *encrypted_pre_master_secret;
115 NX_SECURE_X509_CERT                *local_certificate;
116 UINT                                user_defined_key;
117 UCHAR                               rand_byte;
118 UINT                                i;
119 #endif
120 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
121 NX_SECURE_EC_PRIVATE_KEY           *ec_privkey;
122 NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecdhe_data;
123 NX_CRYPTO_EXTENDED_OUTPUT           extended_output;
124 const NX_CRYPTO_METHOD             *curve_method;
125 const NX_CRYPTO_METHOD             *ecdh_method;
126 UCHAR                              *private_key;
127 UINT                                private_key_length;
128 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE && !NX_SECURE_DISABLE_X509 */
129 
130 #ifndef NX_SECURE_ENABLE_PSK_CIPHERSUITES
131     NX_PARAMETER_NOT_USED(received_remote_credentials);
132 #endif /* NX_SECURE_ENABLE_PSK_CIPHERSUITES */
133 #if !defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) || defined(NX_SECURE_DISABLE_X509)
134     NX_PARAMETER_NOT_USED(tls_ecc_curves);
135 #endif
136 #if !(defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)) && \
137     !defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) && defined(NX_SECURE_DISABLE_X509)
138     NX_PARAMETER_NOT_USED(packet_buffer);
139     NX_PARAMETER_NOT_USED(message_length);
140 #endif
141     NX_PARAMETER_NOT_USED(protocol_version);
142     NX_PARAMETER_NOT_USED(public_auth_metadata);
143     NX_PARAMETER_NOT_USED(public_auth_metadata_size);
144 
145     /* Process key material. The contents of the handshake record differ according to the
146        ciphersuite chosen in the Client/Server Hello negotiation. */
147 
148 #ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
149        /* Check for ECJ-PAKE ciphersuites and generate the pre-master-secret. */
150     if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE)
151     {
152 
153         tls_key_material -> nx_secure_tls_pre_master_secret_size = 32;
154 
155         public_cipher_method = ciphersuite -> nx_secure_tls_public_auth;
156         status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_ECJPAKE_CLIENT_KEY_EXCHANGE_PROCESS,
157                                                              handler,
158                                                              (NX_CRYPTO_METHOD *)public_cipher_method,
159                                                              NX_NULL, 0,
160                                                              packet_buffer,
161                                                              message_length,
162                                                              NX_NULL,
163                                                              tls_key_material -> nx_secure_tls_pre_master_secret,
164                                                              tls_key_material -> nx_secure_tls_pre_master_secret_size,
165                                                              public_auth_metadata,
166                                                              public_auth_metadata_size,
167                                                              NX_NULL, NX_NULL);
168         if (status)
169         {
170             return(status);
171         }
172 
173         if (public_cipher_method -> nx_crypto_cleanup)
174         {
175             status = public_cipher_method -> nx_crypto_cleanup(public_auth_metadata);
176 
177             if (status)
178             {
179                 return(status);
180             }
181         }
182     }
183     else
184 #endif
185     {
186 
187 #ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
188         /* Check for PSK ciphersuites and generate the pre-master-secret. */
189         if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK)
190         {
191             status = _nx_secure_generate_premaster_secret(ciphersuite, protocol_version, tls_key_material, tls_credentials,
192                                                           NX_SECURE_TLS_SESSION_TYPE_SERVER, received_remote_credentials,
193                                                           public_cipher_metadata, public_cipher_metadata_size, tls_ecc_curves);
194 
195             if (status != NX_SUCCESS)
196             {
197                 return(status);
198             }
199         }
200         else
201 #endif
202 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
203         if (ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDH ||
204             ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE)
205         {
206             length = packet_buffer[0];
207 
208             if ((UINT)length + 1 > message_length)
209             {
210                 /* The public key length is larger than the header indicated. */
211                 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
212             }
213 
214             if (ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDH)
215             {
216                 /* Get the local certificate. */
217                 if (tls_credentials -> nx_secure_tls_active_certificate != NX_NULL)
218                 {
219                     local_certificate = tls_credentials -> nx_secure_tls_active_certificate;
220                 }
221                 else
222                 {
223                     /* Get reference to local device certificate. NX_NULL is passed for name to get default entry. */
224                     status = _nx_secure_x509_local_device_certificate_get(&tls_credentials -> nx_secure_tls_certificate_store,
225                                                                           NX_NULL, &local_certificate);
226                     if (status != NX_SUCCESS)
227                     {
228                         local_certificate = NX_NULL;
229                     }
230                 }
231 
232                 if (local_certificate == NX_NULL)
233                 {
234                     /* No certificate found, error! */
235                     return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND);
236                 }
237 
238                 ec_privkey = &local_certificate -> nx_secure_x509_private_key.ec_private_key;
239 
240                 /* Find out which named curve the local certificate is using. */
241                 status = _nx_secure_tls_find_curve_method((NX_SECURE_TLS_ECC *)tls_ecc_curves, (USHORT)(ec_privkey -> nx_secure_ec_named_curve), &curve_method, NX_NULL);
242 
243                 if (status != NX_SUCCESS)
244                 {
245                     return(status);
246                 }
247 
248                 private_key = (UCHAR *)ec_privkey -> nx_secure_ec_private_key;
249                 private_key_length = ec_privkey -> nx_secure_ec_private_key_length;
250             }
251             else
252             {
253                 ecdhe_data = (NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *)tls_key_material -> nx_secure_tls_new_key_material_data;
254 
255                 /* Find out which named curve the we are using. */
256                 status = _nx_secure_tls_find_curve_method((NX_SECURE_TLS_ECC *)tls_ecc_curves, (USHORT)ecdhe_data -> nx_secure_tls_ecdhe_named_curve, &curve_method, NX_NULL);
257 
258                 if (status != NX_SUCCESS)
259                 {
260                     return(status);
261                 }
262 
263                 private_key = ecdhe_data -> nx_secure_tls_ecdhe_private_key;
264                 private_key_length = ecdhe_data -> nx_secure_tls_ecdhe_private_key_length;
265             }
266 
267             if (curve_method == NX_NULL)
268             {
269                 /* No named curve is selected. */
270                 return(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE);
271             }
272 
273             ecdh_method = ciphersuite -> nx_secure_tls_public_cipher;
274             if (ecdh_method -> nx_crypto_operation == NX_NULL)
275             {
276                 return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
277             }
278 
279             if (ecdh_method -> nx_crypto_init != NX_NULL)
280             {
281                 status = ecdh_method -> nx_crypto_init((NX_CRYPTO_METHOD *)ecdh_method,
282                                                        NX_NULL,
283                                                        0,
284                                                        &handler,
285                                                        public_cipher_metadata,
286                                                        public_cipher_metadata_size);
287                 if (status != NX_CRYPTO_SUCCESS)
288                 {
289                     return(status);
290                 }
291             }
292 
293             status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler,
294                                                         (NX_CRYPTO_METHOD *)ecdh_method, NX_NULL, 0,
295                                                         (UCHAR *)curve_method, sizeof(NX_CRYPTO_METHOD *), NX_NULL,
296                                                         NX_NULL, 0,
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             /* Import the private key to the ECDH context. */
306             status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_DH_KEY_PAIR_IMPORT, handler,
307                                                         (NX_CRYPTO_METHOD *)ecdh_method,
308                                                         private_key, private_key_length << 3,
309                                                         NX_NULL, 0, NX_NULL,
310                                                         NX_NULL,
311                                                         0,
312                                                         public_cipher_metadata,
313                                                         public_cipher_metadata_size,
314                                                         NX_NULL, NX_NULL);
315             if (status != NX_CRYPTO_SUCCESS)
316             {
317                 return(status);
318             }
319 
320             extended_output.nx_crypto_extended_output_data = tls_key_material -> nx_secure_tls_pre_master_secret;
321             extended_output.nx_crypto_extended_output_length_in_byte = sizeof(tls_key_material -> nx_secure_tls_pre_master_secret);
322             extended_output.nx_crypto_extended_output_actual_size = 0;
323             status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_DH_CALCULATE, handler,
324                                                         (NX_CRYPTO_METHOD *)ecdh_method, NX_NULL, 0,
325                                                         &packet_buffer[1],
326                                                         length, NX_NULL,
327                                                         (UCHAR *)&extended_output,
328                                                         sizeof(extended_output),
329                                                         public_cipher_metadata,
330                                                         public_cipher_metadata_size,
331                                                         NX_NULL, NX_NULL);
332             if (status != NX_CRYPTO_SUCCESS)
333             {
334                 return(status);
335             }
336 
337             tls_key_material -> nx_secure_tls_pre_master_secret_size = extended_output.nx_crypto_extended_output_actual_size;
338 
339             if (ecdh_method -> nx_crypto_cleanup)
340             {
341                 status = ecdh_method -> nx_crypto_cleanup(public_cipher_metadata);
342                 if (status != NX_CRYPTO_SUCCESS)
343                 {
344                     return(status);
345                 }
346             }
347         }
348         else
349 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE && !NX_SECURE_DISABLE_X509 */
350         {       /* Certificate-based authentication. */
351 #ifndef NX_SECURE_DISABLE_X509
352             if (message_length < 2)
353             {
354                 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
355             }
356 
357             /* Get pre-master-secret length. */
358             length = (USHORT)((packet_buffer[0] << 8) + (USHORT)packet_buffer[1]);
359             packet_buffer += 2;
360 
361             if ((UINT)length + 2 > message_length)
362             {
363                 /* The payload is larger than the header indicated. */
364                 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
365             }
366 
367             /* Pointer to the encrypted pre-master secret in our packet buffer. */
368             encrypted_pre_master_secret = &packet_buffer[0];
369 
370 
371             if (ciphersuite -> nx_secure_tls_ciphersuite == TLS_NULL_WITH_NULL_NULL)
372             {
373                 /* Special case - NULL ciphersuite. No keys are generated. */
374                 if (length > sizeof(tls_key_material -> nx_secure_tls_pre_master_secret))
375                 {
376                     length = sizeof(tls_key_material -> nx_secure_tls_pre_master_secret);
377                 }
378                 NX_SECURE_MEMCPY(tls_key_material -> nx_secure_tls_pre_master_secret, encrypted_pre_master_secret, length); /* Use case of memcpy is verified. */
379                 tls_key_material -> nx_secure_tls_pre_master_secret_size = length;
380             }
381 
382             /* Get reference to local device certificate. NX_NULL is passed for name to get default entry. */
383             status = _nx_secure_x509_local_device_certificate_get(&tls_credentials -> nx_secure_tls_certificate_store,
384                                                                   NX_NULL, &local_certificate);
385 
386             if (status)
387             {
388                 /* No certificate found, error! */
389                 return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND);
390             }
391 
392             /* Get the public cipher method pointer for this session. */
393             public_cipher_method = ciphersuite -> nx_secure_tls_public_cipher;
394 
395             /* Check for user-defined key types. */
396             user_defined_key = NX_FALSE;
397             if (((local_certificate -> nx_secure_x509_private_key_type & NX_SECURE_X509_KEY_TYPE_USER_DEFINED_MASK) != 0x0) ||
398                 (local_certificate -> nx_secure_x509_private_key_type == NX_SECURE_X509_KEY_TYPE_HARDWARE))
399             {
400                 user_defined_key = NX_TRUE;
401             }
402 
403             /* See if we are using RSA. Separate from other methods (e.g. ECC, DH) for proper handling of padding. */
404             if (public_cipher_method -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_RSA &&
405                 local_certificate -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_RSA)
406             {
407                 /* Check for user-defined keys. */
408                 if (user_defined_key)
409                 {
410                     /* A user-defined key is passed directly into the crypto routine. */
411                     status = public_cipher_method -> nx_crypto_operation(local_certificate -> nx_secure_x509_private_key_type,
412                                                                          NX_NULL,
413                                                                          (NX_CRYPTO_METHOD *)public_cipher_method,
414                                                                          (UCHAR *)local_certificate -> nx_secure_x509_private_key.user_key.key_data,
415                                                                          (NX_CRYPTO_KEY_SIZE)(local_certificate -> nx_secure_x509_private_key.user_key.key_length),
416                                                                          encrypted_pre_master_secret,
417                                                                          length,
418                                                                          NX_NULL,
419                                                                          _nx_secure_client_padded_pre_master,
420                                                                          sizeof(_nx_secure_client_padded_pre_master),
421                                                                          public_cipher_metadata,
422                                                                          public_cipher_metadata_size,
423                                                                          NX_NULL, NX_NULL);
424 
425                     if (status != NX_CRYPTO_SUCCESS)
426                     {
427                         return(status);
428                     }
429                 }
430                 else
431                 {
432                     /* Generic RSA operation, use pre-parsed RSA key data. */
433                     if (public_cipher_method -> nx_crypto_init != NX_NULL)
434                     {
435                         /* Initialize the crypto method with public key. */
436                         status = public_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD *)public_cipher_method,
437                                                                         (UCHAR *)local_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus,
438                                                                         (NX_CRYPTO_KEY_SIZE)(local_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus_length << 3),
439                                                                         &handler,
440                                                                         public_cipher_metadata,
441                                                                         public_cipher_metadata_size);
442 
443                         if (status != NX_CRYPTO_SUCCESS)
444                         {
445                             return(status);
446                         }
447                     }
448 
449                     if (public_cipher_method -> nx_crypto_operation != NX_NULL)
450                     {
451 
452 
453                         /* Check for P and Q in the private key. If they are present, we can use them to
454                            speed up RSA using the Chinese Remainder Theorem version of the algorithm. */
455                         if (local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_prime_p != NX_NULL &&
456                             local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_prime_q != NX_NULL)
457                         {
458 
459 
460                             status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_SET_PRIME_P,
461                                                                                  handler,
462                                                                                  (NX_CRYPTO_METHOD *)public_cipher_method,
463                                                                                  NX_NULL,
464                                                                                  0,
465                                                                                  (VOID *)local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_prime_p,
466                                                                                  local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_prime_p_length,
467                                                                                  NX_NULL,
468                                                                                  NX_NULL,
469                                                                                  0,
470                                                                                  public_cipher_metadata,
471                                                                                  public_cipher_metadata_size,
472                                                                                  NX_NULL, NX_NULL);
473 
474                             if (status != NX_CRYPTO_SUCCESS)
475                             {
476                                 return(status);
477                             }
478 
479                             status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_SET_PRIME_Q,
480                                                                                  handler,
481                                                                                  (NX_CRYPTO_METHOD *)public_cipher_method,
482                                                                                  NX_NULL,
483                                                                                  0,
484                                                                                  (VOID *)local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_prime_q,
485                                                                                  local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_prime_q_length,
486                                                                                  NX_NULL,
487                                                                                  NX_NULL,
488                                                                                  0,
489                                                                                  public_cipher_metadata,
490                                                                                  public_cipher_metadata_size,
491                                                                                  NX_NULL, NX_NULL);
492 
493                             if (status != NX_CRYPTO_SUCCESS)
494                             {
495                                 return(status);
496                             }
497 
498                         }
499 
500                         /* Decrypt the pre-master-secret using the private key provided by the user
501                             and place the result in the session key material space in our socket. */
502                         status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_DECRYPT,
503                                                                              handler,
504                                                                              (NX_CRYPTO_METHOD *)public_cipher_method,
505                                                                              (UCHAR *)local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_exponent,
506                                                                              (NX_CRYPTO_KEY_SIZE)(local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_exponent_length << 3),
507                                                                              encrypted_pre_master_secret,
508                                                                              length,
509                                                                              NX_NULL,
510                                                                              _nx_secure_client_padded_pre_master,
511                                                                              sizeof(_nx_secure_client_padded_pre_master),
512                                                                              public_cipher_metadata,
513                                                                              public_cipher_metadata_size,
514                                                                              NX_NULL, NX_NULL);
515 
516                         if (status != NX_CRYPTO_SUCCESS)
517                         {
518                             return(status);
519                         }
520 
521                     }
522 
523                     if (public_cipher_method -> nx_crypto_cleanup)
524                     {
525                         status = public_cipher_method -> nx_crypto_cleanup(public_cipher_metadata);
526 
527                         if (status != NX_CRYPTO_SUCCESS)
528                         {
529 #ifdef NX_SECURE_KEY_CLEAR
530                             NX_SECURE_MEMSET(_nx_secure_client_padded_pre_master, 0, sizeof(_nx_secure_client_padded_pre_master));
531 #endif /* NX_SECURE_KEY_CLEAR  */
532 
533                             return(status);
534                         }
535                     }
536                 }
537 
538                 if (length < NX_SECURE_TLS_RSA_PREMASTER_SIZE + 3)
539                 {
540                     return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
541                 }
542 
543                 /* Check padding - first 2 bytes should be 0x00, 0x02 for PKCS#1 padding. A 0x00 byte should immediately
544                    precede the data. */
545                 if (_nx_secure_client_padded_pre_master[0] != 0x00 ||
546                     _nx_secure_client_padded_pre_master[1] != 0x02 ||
547                     _nx_secure_client_padded_pre_master[length - NX_SECURE_TLS_RSA_PREMASTER_SIZE - 1] != 0x00)
548                 {
549 
550                     /* Invalid padding.  To avoid Bleichenbacher's attack, use random numbers to
551                        generate premaster secret and continue the operation (which will be properly
552                        taken care of later in _nx_secure_tls_process_finished()).
553 
554                        This is described in RFC 5246, section 7.4.7.1, page 58-59. */
555 
556                        /* Generate premaster secret using random numbers. */
557                     for (i = 0; i < NX_SECURE_TLS_RSA_PREMASTER_SIZE; ++i)
558                     {
559 
560                         /* PKCS#1 padding must be random, but CANNOT be 0. */
561                         do
562                         {
563                             rand_byte = (UCHAR)NX_RAND();
564                         } while (rand_byte == 0);
565                         tls_key_material -> nx_secure_tls_pre_master_secret[i] = rand_byte;
566                     }
567                 }
568                 else
569                 {
570 
571                     /* Extract the 48 bytes of the actual pre-master secret from the data we just decrypted, stripping the padding, which
572                        comes at the beginning of the decrypted block (the pre-master secret is the last 48 bytes. */
573                     NX_SECURE_MEMCPY(tls_key_material -> nx_secure_tls_pre_master_secret,
574                                      &_nx_secure_client_padded_pre_master[length - NX_SECURE_TLS_RSA_PREMASTER_SIZE], NX_SECURE_TLS_RSA_PREMASTER_SIZE); /* Use case of memcpy is verified. */
575                 }
576                 tls_key_material -> nx_secure_tls_pre_master_secret_size = NX_SECURE_TLS_RSA_PREMASTER_SIZE;
577             }   /* End RSA-specific section. */
578             else
579             {
580                 /* Unknown or invalid public cipher. */
581                 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
582             }
583 #endif /* !NX_SECURE_DISABLE_X509 */
584         }
585     }
586 #if defined(NX_SECURE_KEY_CLEAR) && !defined(NX_SECURE_DISABLE_X509)
587     NX_SECURE_MEMSET(_nx_secure_client_padded_pre_master, 0, sizeof(_nx_secure_client_padded_pre_master));
588 #endif /* NX_SECURE_KEY_CLEAR && !NX_SECURE_DISABLE_X509 */
589 
590     return(status);
591 }
592 
593