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