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 = ¤t_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