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 /** Datagram Transport Layer Security (DTLS) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_SECURE_SOURCE_CODE
23
24 #include "nx_secure_dtls.h"
25
26 #ifdef NX_SECURE_ENABLE_DTLS
27 #ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
28 extern NX_CRYPTO_METHOD crypto_method_ec_secp256;
29 #endif /* NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE */
30
31 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
32 static UINT _nx_secure_dtls_check_ciphersuite(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite_info,
33 NX_SECURE_X509_CERT *cert, UINT selected_curve,
34 UINT cert_curve_supported);
35 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE && !NX_SECURE_DISABLE_X509 */
36
37 /**************************************************************************/
38 /* */
39 /* FUNCTION RELEASE */
40 /* */
41 /* _nx_secure_dtls_process_clienthello PORTABLE C */
42 /* 6.2.1 */
43 /* AUTHOR */
44 /* */
45 /* Timothy Stapko, Microsoft Corporation */
46 /* */
47 /* DESCRIPTION */
48 /* */
49 /* This function processes an incoming ClientHello message from a */
50 /* remote host, kicking off a DTLS handshake. */
51 /* */
52 /* INPUT */
53 /* */
54 /* dtls_session DTLS control block */
55 /* packet_buffer Pointer to message data */
56 /* message_length Length of message data (bytes)*/
57 /* */
58 /* OUTPUT */
59 /* */
60 /* status Completion status */
61 /* */
62 /* CALLS */
63 /* */
64 /* _nx_secure_tls_check_protocol_version Check protocol version */
65 /* _nx_secure_tls_ciphersuite_lookup Get cipher information */
66 /* _nx_secure_tls_proc_clienthello_sec_sa_extension */
67 /* Process ECC extensions */
68 /* _nx_secure_dtls_check_ciphersuite Check if ECC suite is usable */
69 /* _nx_secure_x509_local_device_certificate_get */
70 /* Get the local certificate */
71 /* [nx_crypto_init] Initialize crypto */
72 /* [nx_crypto_operation] Crypto operation */
73 /* */
74 /* CALLED BY */
75 /* */
76 /* _nx_secure_dtls_server_handshake DTLS server state machine */
77 /* */
78 /* RELEASE HISTORY */
79 /* */
80 /* DATE NAME DESCRIPTION */
81 /* */
82 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
83 /* 09-30-2020 Timothy Stapko Modified comment(s), added */
84 /* priority ciphersuite logic, */
85 /* verified memcpy use cases, */
86 /* fixed configuration problem */
87 /* that would result in */
88 /* compiler error, fixed */
89 /* renegotiation bug, */
90 /* improved negotiation logic, */
91 /* resulting in version 6.1 */
92 /* 12-31-2020 Timothy Stapko Modified comment(s), */
93 /* improved buffer length */
94 /* verification, */
95 /* resulting in version 6.1.3 */
96 /* 03-08-2023 Yanwu Cai Modified comment(s), */
97 /* fixed compiler errors when */
98 /* x509 is disabled, */
99 /* resulting in version 6.2.1 */
100 /* */
101 /**************************************************************************/
_nx_secure_dtls_process_clienthello(NX_SECURE_DTLS_SESSION * dtls_session,UCHAR * packet_buffer,UINT message_length)102 UINT _nx_secure_dtls_process_clienthello(NX_SECURE_DTLS_SESSION *dtls_session, UCHAR *packet_buffer,
103 UINT message_length)
104 {
105 USHORT ciphersuite_list_length;
106 UCHAR compression_methods_length;
107 USHORT cipher_entry;
108 UCHAR session_id_length;
109 UINT i;
110 UINT status;
111 USHORT protocol_version;
112 UINT total_extensions_length;
113 const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite_info = NX_NULL;
114 USHORT ciphersuite_priority;
115 USHORT new_ciphersuite_priority = 0;
116 NX_SECURE_TLS_SESSION *tls_session;
117 NX_SECURE_TLS_HELLO_EXTENSION extension_data[NX_SECURE_TLS_HELLO_EXTENSIONS_MAX];
118 UINT num_extensions = NX_SECURE_TLS_HELLO_EXTENSIONS_MAX;
119 UCHAR *ciphersuite_list;
120 UCHAR *packet_buffer_start;
121 #ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
122 INT extension_total_length;
123 USHORT extension_length;
124 USHORT extension_type;
125 USHORT supported_ec_length;
126 UCHAR ec_point_formats_length;
127 UCHAR supported_ec_match, ec_point_formats_match, zkp_verified;
128 const NX_CRYPTO_METHOD *crypto_method;
129 NX_SECURE_TLS_PSK_STORE *psk_store;
130 #endif /* NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE */
131 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
132 NX_SECURE_X509_CERT *cert;
133 UINT selected_curve;
134 UINT cert_curve;
135 UINT cert_curve_supported;
136 NX_SECURE_EC_PUBLIC_KEY *ec_pubkey;
137 NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecdhe_data;
138 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE && !NX_SECURE_DISABLE_X509 */
139
140
141 /* Structure of ClientHello:
142 * | 2 | 4 + 28 | 1 | <SID len> | 2 | <CS Len> | 1 | <Comp Len> | 2 | <Ext. Len> |
143 * | TLS version | Random (time + random) | SID length | Session ID | CS Len | Ciphersuites |Comp Len | Compression |Ext. Len | Extensions |
144 */
145
146 if (message_length < 38)
147 {
148 /* Message was not the minimum required size for a ClientHello. */
149 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
150 }
151
152 /* Get a pointer to the start of our packet buffer so we can read ahead later. */
153 packet_buffer_start = packet_buffer;
154
155 /* Get a reference to TLS state. */
156 tls_session = &dtls_session -> nx_secure_dtls_tls_session;
157
158 /* If we are currently in a session, we have a renegotiation handshake. */
159 if (tls_session -> nx_secure_tls_local_session_active)
160 {
161
162 /* Session renegotiation is disabled, send a "no_renegotiation" alert! */
163 return(NX_SECURE_TLS_NO_RENEGOTIATION_ERROR);
164 }
165
166 /* Client is establishing a TLS session with our server. */
167 /* Extract the protocol version - only part of the ClientHello message. */
168 protocol_version = (USHORT)(((USHORT)packet_buffer[0] << 8) | packet_buffer[1]);
169 packet_buffer += 2;
170
171
172 /* Check protocol version provided by client. */
173 status = _nx_secure_tls_check_protocol_version(tls_session, protocol_version, NX_SECURE_DTLS);
174
175 if (status != NX_SECURE_TLS_SUCCESS)
176 {
177 /* If we have an active session, this is a renegotiation attempt, treat the protocol error as
178 if we are starting a new session. */
179 if (status == NX_SECURE_TLS_UNSUPPORTED_TLS_VERSION || tls_session -> nx_secure_tls_local_session_active)
180 {
181 /* If the version isn't supported, it's not an issue - TLS is backward-compatible,
182 * so pick the highest version we do support. If the version isn't recognized,
183 * flag an error. */
184 _nx_secure_tls_highest_supported_version_negotiate(tls_session, &protocol_version, NX_SECURE_DTLS);
185
186 if (protocol_version == 0x0)
187 {
188 /* Error, no versions enabled. */
189 return(NX_SECURE_TLS_UNSUPPORTED_TLS_VERSION);
190 }
191 }
192 else
193 {
194 /* Protocol version unknown (not TLS or SSL!), return status. */
195 return(status);
196 }
197 }
198
199 /* Assign our protocol version to our socket. This is used for all further communications
200 * in this session. */
201 tls_session -> nx_secure_tls_protocol_version = protocol_version;
202
203 /* Save off the random value for key generation later. */
204 NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random, packet_buffer, NX_SECURE_TLS_RANDOM_SIZE); /* Use case of memcpy is verified. */
205 packet_buffer += NX_SECURE_TLS_RANDOM_SIZE;
206
207 /* Extract the session ID if there is one. */
208 session_id_length = packet_buffer[0];
209 packet_buffer++;
210
211 /* If there is a session ID, copy it into our TLS socket structure. */
212 tls_session -> nx_secure_tls_session_id_length = session_id_length;
213 if (session_id_length > 0)
214 {
215 NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_session_id, &packet_buffer[0], session_id_length); /* Use case of memcpy is verified. */
216 packet_buffer += session_id_length;
217 }
218
219 /* DTLS - there might be a cookie we need to save. */
220
221 /* Extract the cookie from the client. */
222 dtls_session -> nx_secure_dtls_cookie_length = packet_buffer[0];
223 packet_buffer += 1;
224
225 if (dtls_session -> nx_secure_dtls_cookie_length > sizeof(dtls_session -> nx_secure_dtls_cookie))
226 {
227 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
228 }
229
230 if (dtls_session -> nx_secure_dtls_cookie_length > 0)
231 {
232 NX_SECURE_MEMCPY(dtls_session -> nx_secure_dtls_cookie, packet_buffer, dtls_session -> nx_secure_dtls_cookie_length); /* Use case of memcpy is verified. */
233 packet_buffer += dtls_session -> nx_secure_dtls_cookie_length;
234 }
235
236 /* Negotiate the ciphersuite we want to use. */
237 ciphersuite_list_length = (USHORT)((packet_buffer[0] << 8) + packet_buffer[1]);
238 packet_buffer += 2;
239
240 /* Make sure the list length makes sense. */
241 if (ciphersuite_list_length > message_length)
242 {
243 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
244 }
245
246 ciphersuite_list = packet_buffer;
247 packet_buffer += ciphersuite_list_length;
248
249 /* Compression methods length - one byte. For now we only support the NULL method. */
250 compression_methods_length = packet_buffer[0];
251 packet_buffer += 1;
252
253 /* Message length overflow. */
254 if (((UINT)(packet_buffer - packet_buffer_start + compression_methods_length)) > message_length)
255 {
256 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
257 }
258
259 /* Make sure NULL compression method is supported. */
260 status = NX_SECURE_TLS_BAD_COMPRESSION_METHOD;
261 for (i = 0; i < compression_methods_length; ++i)
262 {
263 if (packet_buffer[i] == 0x0)
264 {
265 status = NX_SUCCESS;
266 break;
267 }
268 }
269
270 /* Check for error. */
271 if (status != NX_SUCCESS)
272 {
273 return(status);
274 }
275
276 packet_buffer += compression_methods_length;
277
278 /* Padding data? */
279 if (message_length >= (UINT)(packet_buffer - packet_buffer_start + 2))
280 {
281
282 /* TLS Extensions come next. Get the total length of all extensions first. */
283 total_extensions_length = (USHORT)((packet_buffer[0] << 8) + packet_buffer[1]);
284
285 /* Message length overflow. */
286 if (((UINT)(packet_buffer - packet_buffer_start + 2) + total_extensions_length) > message_length)
287 {
288 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
289 }
290
291 if (total_extensions_length > 0)
292 {
293 /* Process serverhello extensions. */
294 status = _nx_secure_tls_process_clienthello_extensions(tls_session, &packet_buffer[2], total_extensions_length, extension_data, &num_extensions, packet_buffer, message_length);
295
296 /* Check for error. */
297 if (status != NX_SUCCESS)
298 {
299 return(status);
300 }
301
302 /* If the server callback is set, invoke it now with the extensions that require application input. */
303 if (tls_session -> nx_secure_tls_session_server_callback != NX_NULL)
304 {
305 status = tls_session -> nx_secure_tls_session_server_callback(tls_session, extension_data, num_extensions);
306
307 /* Check for error. */
308 if (status != NX_SUCCESS)
309 {
310 return(status);
311 }
312 }
313 }
314 }
315
316 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
317
318 /* Get the local certificate. */
319 if (tls_session -> nx_secure_tls_credentials.nx_secure_tls_active_certificate != NX_NULL)
320 {
321 cert = tls_session -> nx_secure_tls_credentials.nx_secure_tls_active_certificate;
322 }
323 else
324 {
325 /* Get reference to local device certificate. NX_NULL is passed for name to get default entry. */
326 status = _nx_secure_x509_local_device_certificate_get(&tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store,
327 NX_NULL, &cert);
328 if (status != NX_SUCCESS)
329 {
330 cert = NX_NULL;
331 }
332 }
333
334 if (cert != NX_NULL && cert -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_EC)
335 {
336 ec_pubkey = &cert -> nx_secure_x509_public_key.ec_public_key;
337 cert_curve = ec_pubkey -> nx_secure_ec_named_curve;
338 }
339 else
340 {
341 cert_curve = 0;
342 }
343
344 ecdhe_data = (NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *)tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data;
345
346 /* Parse the ECC extension of supported curve. */
347 status = _nx_secure_tls_proc_clienthello_sec_sa_extension(tls_session,
348 extension_data,
349 num_extensions,
350 &selected_curve,
351 (USHORT)cert_curve, &cert_curve_supported,
352 &ecdhe_data -> nx_secure_tls_ecdhe_signature_algorithm,
353 cert);
354
355 ecdhe_data -> nx_secure_tls_ecdhe_named_curve = selected_curve;
356
357 /* Select signature algorithm by certificate type. */
358 if (cert != NX_NULL && cert -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_EC)
359 {
360 ecdhe_data -> nx_secure_tls_ecdhe_signature_algorithm =
361 (USHORT)((ecdhe_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF00) | NX_SECURE_TLS_SIGNATURE_ALGORITHM_ECDSA);
362
363 if (cert_curve_supported == NX_FALSE)
364 {
365 /* The named curve in our server certificate is not supported by the client. */
366 return(NX_SECURE_TLS_NO_SUPPORTED_CIPHERS);
367 }
368 }
369 else if (cert != NX_NULL && cert -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_RSA)
370 {
371 ecdhe_data -> nx_secure_tls_ecdhe_signature_algorithm =
372 (USHORT)((ecdhe_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF00) | NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA);
373 }
374 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE && !NX_SECURE_DISABLE_X509 */
375
376 /* Set our initial priority to the maximum value - the size of our ciphersuite crypto table. */
377 ciphersuite_priority = (USHORT)(0xFFFFFFFF);
378
379 for (i = 0; i < ciphersuite_list_length; i += 2)
380 {
381 /* Loop through list of acceptable ciphersuites. */
382 cipher_entry = (USHORT)((ciphersuite_list[i] << 8) + ciphersuite_list[i + 1]);
383
384 status = _nx_secure_tls_ciphersuite_lookup(tls_session, cipher_entry, &ciphersuite_info, &new_ciphersuite_priority);
385
386 if (status == NX_SUCCESS && (new_ciphersuite_priority < ciphersuite_priority))
387 {
388 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
389 if (NX_SUCCESS == _nx_secure_dtls_check_ciphersuite(ciphersuite_info, cert, selected_curve, cert_curve_supported))
390 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE && !NX_SECURE_DISABLE_X509 */
391 {
392 tls_session -> nx_secure_tls_session_ciphersuite = ciphersuite_info;
393 ciphersuite_priority = new_ciphersuite_priority;
394 }
395 }
396 }
397
398 /* See if we found an acceptable ciphersuite. */
399 if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL)
400 {
401
402 /* No supported ciphersuites found. */
403 return(NX_SECURE_TLS_NO_SUPPORTED_CIPHERS);
404 }
405
406 #ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
407
408 /* Check if there are extensions. */
409 if ((ciphersuite_info -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE) &&
410 (dtls_session -> nx_secure_dtls_cookie_length != 0))
411 {
412
413 if (packet_buffer - packet_buffer_start > (INT)message_length - 2)
414 {
415 return(NX_SECURE_TLS_HANDSHAKE_FAILURE);
416 }
417
418 extension_total_length = (packet_buffer[0] << 8) + packet_buffer[1];
419 packet_buffer += 2;
420
421 /* Make sure the extension length make sense. */
422 if (packet_buffer - packet_buffer_start + extension_total_length > (INT)message_length)
423 {
424 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
425 }
426
427 supported_ec_match = 0;
428 ec_point_formats_match = 0;
429 zkp_verified = 0;
430
431 crypto_method = ciphersuite_info -> nx_secure_tls_public_auth;
432 if (crypto_method == NX_NULL)
433 {
434 return(NX_SECURE_TLS_HANDSHAKE_FAILURE);
435 }
436
437 if (crypto_method -> nx_crypto_init == NX_NULL)
438 {
439 return(NX_SECURE_TLS_HANDSHAKE_FAILURE);
440 }
441
442 if (tls_session -> nx_secure_tls_credentials.nx_secure_tls_psk_count == 0)
443 {
444 return(NX_SECURE_TLS_HANDSHAKE_FAILURE);
445 }
446
447 psk_store = &tls_session -> nx_secure_tls_credentials.nx_secure_tls_psk_store[0];
448 status = crypto_method -> nx_crypto_init((NX_CRYPTO_METHOD*)crypto_method,
449 psk_store -> nx_secure_tls_psk_data,
450 (USHORT)(psk_store -> nx_secure_tls_psk_data_size << 3),
451 NX_NULL,
452 tls_session -> nx_secure_public_auth_metadata_area,
453 tls_session -> nx_secure_public_auth_metadata_size);
454
455 if (status)
456 {
457 return(status);
458 }
459
460 status = crypto_method -> nx_crypto_operation(NX_CRYPTO_ECJPAKE_HASH_METHOD_SET,
461 NX_NULL,
462 (NX_CRYPTO_METHOD*)crypto_method,
463 NX_NULL,
464 (USHORT)(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size << 3),
465 (UCHAR *)(tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha256_method),
466 sizeof(NX_CRYPTO_METHOD),
467 NX_NULL, NX_NULL, 0,
468 tls_session -> nx_secure_public_auth_metadata_area,
469 tls_session -> nx_secure_public_auth_metadata_size,
470 NX_NULL, NX_NULL);
471 if (status)
472 {
473 return(status);
474 }
475
476 status = crypto_method -> nx_crypto_operation(NX_CRYPTO_ECJPAKE_CURVE_SET,
477 NX_NULL,
478 (NX_CRYPTO_METHOD*)crypto_method,
479 NX_NULL, 0,
480 (UCHAR *)&crypto_method_ec_secp256,
481 sizeof(NX_CRYPTO_METHOD),
482 NX_NULL, NX_NULL, 0,
483 tls_session -> nx_secure_public_auth_metadata_area,
484 tls_session -> nx_secure_public_auth_metadata_size,
485 NX_NULL, NX_NULL);
486 if (status)
487 {
488 return(status);
489 }
490
491 /* Loop through all the extensions. */
492 while (extension_total_length > 0)
493 {
494 /* Get Extension Type. */
495 extension_type = (USHORT)((packet_buffer[0] << 8) + packet_buffer[1]);
496 packet_buffer += 2;
497
498 /* Get Extension Length. */
499 extension_length = (USHORT)((packet_buffer[0] << 8) + packet_buffer[1]);
500 packet_buffer += 2;
501
502 extension_total_length -= 4;
503
504 /* Make sure Extension Length is within the total extension length. */
505 if (extension_length > extension_total_length)
506 {
507 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
508 }
509
510 extension_total_length -= extension_length;
511
512 switch (extension_type)
513 {
514 case NX_SECURE_TLS_EXTENSION_EC_GROUPS:
515 /* Supported Elliptic Curves Extension. */
516 supported_ec_length = (USHORT)((packet_buffer[0] << 8) + packet_buffer[1]);
517 packet_buffer += 2;
518
519 /* Make sure secp256r1 (23) format is supported. */
520 status = NX_SECURE_TLS_UNSUPPORTED_CIPHER;
521 for (i = 0; i < (UINT)(supported_ec_length >> 1); ++i)
522 {
523 if (packet_buffer[i * 2] == 0x0 && packet_buffer[i * 2 + 1] == 0x17)
524 {
525 status = NX_SUCCESS;
526 break;
527 }
528 }
529
530 /* Check for error. */
531 if (status != NX_SUCCESS)
532 {
533 return(status);
534 }
535
536 packet_buffer += supported_ec_length;
537 supported_ec_match = 1;
538 break;
539
540 case NX_SECURE_TLS_EXTENSION_EC_POINT_FORMATS:
541 /* ec_point_formats Extension. */
542 ec_point_formats_length = packet_buffer[0];
543 packet_buffer += 1;
544
545 /* Make sure uncompressed (0) format is supported. */
546 status = NX_SECURE_TLS_UNSUPPORTED_CIPHER;
547 for (i = 0; i < ec_point_formats_length; ++i)
548 {
549 if (packet_buffer[i] == 0x0)
550 {
551 status = NX_SUCCESS;
552 break;
553 }
554 }
555
556 /* Check for error. */
557 if (status != NX_SUCCESS)
558 {
559 return(status);
560 }
561
562 packet_buffer += ec_point_formats_length;
563 ec_point_formats_match = 1;
564 break;
565
566 case NX_SECURE_TLS_EXTENSION_ECJPAKE_KEY_KP_PAIR:
567 /* ecjpake_key_kp_pair Extension. */
568 status = crypto_method -> nx_crypto_operation(NX_CRYPTO_ECJPAKE_CLIENT_HELLO_PROCESS,
569 NX_NULL,
570 (NX_CRYPTO_METHOD*)crypto_method,
571 NX_NULL, 0,
572 packet_buffer, extension_length,
573 NX_NULL, NX_NULL, 0,
574 tls_session -> nx_secure_public_auth_metadata_area,
575 tls_session -> nx_secure_public_auth_metadata_size,
576 NX_NULL, NX_NULL);
577 if (status)
578 {
579 return(status);
580 }
581
582 packet_buffer += extension_length;
583
584 zkp_verified = 1;
585 break;
586 }
587 }
588
589 /* Make sure no extension is missing. */
590 if (supported_ec_match == 0 || ec_point_formats_match == 0 || zkp_verified == 0)
591 {
592 return(NX_SECURE_TLS_UNSUPPORTED_ECC_FORMAT);
593 }
594 }
595 #endif
596
597 #ifdef NX_SECURE_TLS_SERVER_DISABLED
598 /* If TLS Server is disabled and we have processed a ClientHello, something is wrong... */
599 tls_session -> nx_secure_tls_client_state = NX_SECURE_TLS_CLIENT_STATE_ERROR;
600 return(NX_SECURE_TLS_INVALID_STATE);
601 #else
602 if (dtls_session -> nx_secure_dtls_cookie_length == 0)
603 {
604 /* In DTLS, we actually send a HelloVerifyReqeust (expecting a second ClientHello in
605 * response) before sending our ServerHello. */
606 dtls_session -> nx_secure_dtls_tls_session.nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_SEND_HELLO_VERIFY;
607 }
608 else
609 {
610 dtls_session -> nx_secure_dtls_tls_session.nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_SEND_HELLO;
611 }
612 return(NX_SUCCESS);
613 #endif
614 }
615
616 /**************************************************************************/
617 /* */
618 /* FUNCTION RELEASE */
619 /* */
620 /* _nx_secure_dtls_check_ciphersuite PORTABLE C */
621 /* 6.1 */
622 /* AUTHOR */
623 /* */
624 /* Timothy Stapko, Microsoft Corporation */
625 /* */
626 /* DESCRIPTION */
627 /* */
628 /* This function checks whether the specified ciphersuite is */
629 /* suitable for the server certificate, the curve in the certificate */
630 /* and the common shared curve. */
631 /* */
632 /* INPUT */
633 /* */
634 /* ciphersuite_info The specified cipher suite */
635 /* cert Local server certificate */
636 /* selected_curve Curve selected for ECC */
637 /* cert_curve_supported If cert curve is supported */
638 /* */
639 /* OUTPUT */
640 /* */
641 /* status Completion status */
642 /* */
643 /* CALLS */
644 /* */
645 /* None */
646 /* */
647 /* CALLED BY */
648 /* */
649 /* _nx_secure_dtls_process_clienthello Process ClientHello */
650 /* */
651 /* RELEASE HISTORY */
652 /* */
653 /* DATE NAME DESCRIPTION */
654 /* */
655 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
656 /* 09-30-2020 Timothy Stapko Modified comment(s), */
657 /* resulting in version 6.1 */
658 /* */
659 /**************************************************************************/
660 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
_nx_secure_dtls_check_ciphersuite(const NX_SECURE_TLS_CIPHERSUITE_INFO * ciphersuite_info,NX_SECURE_X509_CERT * cert,UINT selected_curve,UINT cert_curve_supported)661 static UINT _nx_secure_dtls_check_ciphersuite(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite_info,
662 NX_SECURE_X509_CERT *cert, UINT selected_curve,
663 UINT cert_curve_supported)
664 {
665 if (ciphersuite_info -> nx_secure_tls_public_cipher == NX_NULL)
666 {
667 return(NX_SUCCESS);
668 }
669
670 if (ciphersuite_info -> nx_secure_tls_public_auth == NX_NULL)
671 {
672 return(NX_SUCCESS);
673 }
674
675 switch (ciphersuite_info -> nx_secure_tls_public_cipher -> nx_crypto_algorithm)
676 {
677 case NX_CRYPTO_KEY_EXCHANGE_ECDHE:
678 if (selected_curve == NX_NULL || cert == NX_NULL)
679 {
680 /* No common named curve supported for ECDHE. */
681 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
682 }
683
684 if (ciphersuite_info -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_DIGITAL_SIGNATURE_ECDSA)
685 {
686 if (cert -> nx_secure_x509_public_algorithm != NX_SECURE_TLS_X509_TYPE_EC)
687 {
688 /* ECDSA auth requires EC certificate. */
689 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
690 }
691 }
692 else
693 {
694 if (cert -> nx_secure_x509_public_algorithm != NX_SECURE_TLS_X509_TYPE_RSA)
695 {
696 /* RSA auth requires RSA certificate. */
697 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
698 }
699 }
700
701 break;
702
703 case NX_CRYPTO_KEY_EXCHANGE_ECDH:
704 /* Check for ECDH_anon. */
705 if (ciphersuite_info -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_DIGITAL_SIGNATURE_ANONYMOUS)
706 {
707 if (selected_curve == NX_NULL)
708 {
709 /* No common named curve supported supported. */
710 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
711 }
712 }
713 else
714 {
715 /* ECDH key exchange requires an EC certificate. */
716 if (cert == NX_NULL || cert -> nx_secure_x509_public_algorithm != NX_SECURE_TLS_X509_TYPE_EC)
717 {
718 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
719 }
720
721 if (cert_curve_supported == NX_FALSE)
722 {
723 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
724 }
725
726 /* Check the signatureAlgorithm of the certificate to determine the public auth algorithm. */
727 if (ciphersuite_info -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_DIGITAL_SIGNATURE_ECDSA)
728 {
729 if (cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_1 &&
730 cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_224 &&
731 cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_256 &&
732 cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_384 &&
733 cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_512)
734 {
735 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
736 }
737 }
738 else
739 {
740 if (cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_RSA_MD5 &&
741 cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_RSA_SHA_1 &&
742 cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_RSA_SHA_256 &&
743 cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_RSA_SHA_384 &&
744 cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_RSA_SHA_512)
745 {
746 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
747 }
748 }
749 }
750 break;
751
752 case NX_CRYPTO_KEY_EXCHANGE_RSA:
753 if (cert == NX_NULL || cert -> nx_secure_x509_public_algorithm != NX_SECURE_TLS_X509_TYPE_RSA)
754 {
755 /* RSA key exchange requires RSA certificate. */
756 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
757 }
758 break;
759
760 default:
761 break;
762 }
763
764 return(NX_SUCCESS);
765 }
766 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE && !NX_SECURE_DISABLE_X509 */
767
768 #endif /* NX_SECURE_ENABLE_DTLS */
769
770