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 #include "nx_secure_tls.h"
25
26 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
27 static UINT _nx_secure_tls_check_ciphersuite(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite_info,
28 NX_SECURE_X509_CERT *cert, UINT selected_curve,
29 UINT cert_curve_supported);
30
31 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE && !NX_SECURE_DISABLE_X509 */
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _nx_secure_tls_process_clienthello PORTABLE C */
38 /* 6.2.1 */
39 /* AUTHOR */
40 /* */
41 /* Timothy Stapko, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function processes an incoming ClientHello message from a */
46 /* remote host, kicking off a TLS handshake. */
47 /* */
48 /* INPUT */
49 /* */
50 /* tls_session TLS control block */
51 /* packet_buffer Pointer to message data */
52 /* message_length Length of message data (bytes)*/
53 /* */
54 /* OUTPUT */
55 /* */
56 /* status Completion status */
57 /* */
58 /* CALLS */
59 /* */
60 /* _nx_secure_tls_ciphersuite_lookup Lookup current ciphersuite */
61 /* _nx_secure_tls_check_protocol_version Check incoming TLS version */
62 /* _nx_secure_tls_newest_supported_version */
63 /* Get newest TLS version */
64 /* _nx_secure_tls_process_clienthello_extensions */
65 /* Process ClientHello extensions*/
66 /* _nx_secure_tls_proc_clienthello_sec_sa_extension */
67 /* Process ECC extensions */
68 /* _nx_secure_tls_check_ciphersuite Check if ECC suite is usable */
69 /* _nx_secure_tls_remote_certificate_free_all */
70 /* Free all remote certificates */
71 /* [_nx_secure_tls_session_renegotiate_callback_set] */
72 /* Renegotiation callback */
73 /* [_nx_secure_tls_session_server_callback_set] */
74 /* Server session callback */
75 /* _nx_secure_x509_local_device_certificate_get */
76 /* Get the local certificate */
77 /* */
78 /* CALLED BY */
79 /* */
80 /* _nx_secure_tls_server_handshake TLS Server state machine */
81 /* */
82 /* RELEASE HISTORY */
83 /* */
84 /* DATE NAME DESCRIPTION */
85 /* */
86 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
87 /* 09-30-2020 Timothy Stapko Modified comment(s), added */
88 /* priority ciphersuite logic, */
89 /* verified memcpy use cases, */
90 /* fixed renegotiation bug, */
91 /* improved negotiation logic, */
92 /* resulting in version 6.1 */
93 /* 10-15-2021 Timothy Stapko Modified comment(s), added */
94 /* ability to disable client */
95 /* initiated renegotiation, */
96 /* resulting in version 6.1.9 */
97 /* 04-25-2022 Yuxin Zhou Modified comment(s), fixed */
98 /* the bug of processing */
99 /* extensions, */
100 /* resulting in version 6.1.11 */
101 /* 10-31-2022 Yanwu Cai Modified comment(s), fixed */
102 /* TLS 1.3 version negotiation,*/
103 /* resulting in version 6.2.0 */
104 /* 03-08-2023 Yanwu Cai Modified comment(s), */
105 /* fixed compiler errors when */
106 /* x509 is disabled, */
107 /* resulting in version 6.2.1 */
108 /* */
109 /**************************************************************************/
_nx_secure_tls_process_clienthello(NX_SECURE_TLS_SESSION * tls_session,UCHAR * packet_buffer,UINT message_length)110 UINT _nx_secure_tls_process_clienthello(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer,
111 UINT message_length)
112 {
113 UINT length;
114 USHORT ciphersuite_list_length;
115 UCHAR compression_methods_length;
116 USHORT cipher_entry;
117 UCHAR session_id_length;
118 UINT i;
119 UINT status;
120 USHORT protocol_version;
121 USHORT newest_version;
122 UINT total_extensions_length;
123 const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite_info;
124 USHORT ciphersuite_priority;
125 USHORT new_ciphersuite_priority = 0;
126 NX_SECURE_TLS_HELLO_EXTENSION extension_data[NX_SECURE_TLS_HELLO_EXTENSIONS_MAX];
127 UINT num_extensions = NX_SECURE_TLS_HELLO_EXTENSIONS_MAX;
128 UCHAR *ciphersuite_list;
129 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
130 NX_SECURE_X509_CERT *cert;
131 UINT selected_curve;
132 UINT cert_curve;
133 UINT cert_curve_supported;
134 NX_SECURE_EC_PUBLIC_KEY *ec_pubkey;
135 NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecdhe_data;
136 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE && !NX_SECURE_DISABLE_X509 */
137 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
138 USHORT tls_1_3 = tls_session -> nx_secure_tls_1_3;
139 USHORT no_extension = NX_FALSE;
140 #endif
141
142 /* Structure of ClientHello:
143 * | 2 | 4 + 28 | 1 | <SID len> | 2 | <CS Len> | 1 | <Comp Len> | 2 | <Ext. Len> |
144 * | TLS version | Random (time + random) | SID length | Session ID | CS Len | Ciphersuites |Comp Len | Compression |Ext. Len | Extensions |
145 */
146
147 if (message_length < 38)
148 {
149 /* Message was not the minimum required size for a ClientHello. */
150 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
151 }
152
153 /* Use our length as an index into the buffer. */
154 length = 0;
155
156 /* If we are currently in a session, we have a renegotiation handshake. */
157 if (tls_session -> nx_secure_tls_local_session_active)
158 {
159 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
160 if (tls_session->nx_secure_tls_1_3 == NX_TRUE)
161 {
162
163 /* RFC 8446, section 4.1.2, page 27.
164 * Server has negotiated TLS 1.3 and receives a ClientHello again.
165 * Send an unexpected message alert. */
166 return(NX_SECURE_TLS_UNEXPECTED_CLIENTHELLO);
167 }
168 #endif
169
170 #if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION)
171 /* If Client initiated renegotiation is enabled, handle the renegotiation
172 handshake if appropriate. Otherwise return "no renegotiation allowed" error. */
173 if (tls_session -> nx_secure_tls_renegotation_enabled && tls_session -> nx_secure_tls_secure_renegotiation
174 #if defined(NX_SECURE_TLS_DISABLE_CLIENT_INITIATED_RENEGOTIATION)
175 /* If client initiated renegotiation is disabled for TLS servers, only allow
176 server-initiated renegotiations requested by the server itself. */
177 && tls_session -> nx_secure_tls_server_renegotiation_requested
178 #endif
179 )
180 {
181 tls_session -> nx_secure_tls_renegotiation_handshake = NX_TRUE;
182
183 #ifndef NX_SECURE_DISABLE_X509
184
185 /* On a session resumption free all certificates for the new session.
186 * SESSION RESUMPTION: if session resumption is enabled, don't free!!
187 */
188 status = _nx_secure_tls_remote_certificate_free_all(tls_session);
189
190 if (status != NX_SUCCESS)
191 {
192 return(status);
193 }
194 #endif
195
196 /* Invoke user callback to notify application of renegotiation request. */
197 if (tls_session -> nx_secure_tls_session_renegotiation_callback != NX_NULL)
198 {
199 status = tls_session -> nx_secure_tls_session_renegotiation_callback(tls_session);
200
201 if (status != NX_SUCCESS)
202 {
203 return(status);
204 }
205 }
206
207 /* We don't want any more clienthellos to come in after this - only the first one
208 in response to our original request. */
209 tls_session -> nx_secure_tls_server_renegotiation_requested = NX_FALSE;
210 }
211 else
212 #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */
213 {
214 /* Session renegotiation is disabled, so this is an error! */
215 return(NX_SECURE_TLS_NO_RENEGOTIATION_ERROR);
216 }
217 }
218
219 /* Client is establishing a TLS session with our server. */
220 /* Extract the protocol version - only part of the ClientHello message. */
221 protocol_version = (USHORT)((packet_buffer[length] << 8) | packet_buffer[length + 1]);
222 length += 2;
223
224 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
225 if (tls_session->nx_secure_tls_1_3 == NX_FALSE)
226 #endif
227 {
228
229 /* Check protocol version provided by client. */
230 status = _nx_secure_tls_check_protocol_version(tls_session, protocol_version, NX_SECURE_TLS);
231
232 if (status != NX_SECURE_TLS_SUCCESS)
233 {
234 /* If we have an active session, this is a renegotiation attempt, treat the protocol error as
235 if we are starting a new session. */
236 if (status == NX_SECURE_TLS_UNSUPPORTED_TLS_VERSION || tls_session -> nx_secure_tls_local_session_active)
237 {
238 /* If the version isn't supported, it's not an issue - TLS is backward-compatible,
239 * so negotiate the highest supported version. If the version isn't recognized,
240 * flag an error. */
241 _nx_secure_tls_highest_supported_version_negotiate(tls_session, &protocol_version, NX_SECURE_TLS);
242
243 if (protocol_version == 0x0)
244 {
245 /* Error, no versions enabled. */
246 return(NX_SECURE_TLS_UNSUPPORTED_TLS_VERSION);
247 }
248 }
249 else
250 {
251 /* Protocol version unknown (not TLS or SSL!), return status. */
252 return(status);
253 }
254 }
255 }
256
257 /* Assign our protocol version to our socket. This is used for all further communications
258 * in this session. */
259 tls_session -> nx_secure_tls_protocol_version = protocol_version;
260
261 /* Save off the random value for key generation later. */
262 NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random, &packet_buffer[length], NX_SECURE_TLS_RANDOM_SIZE); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */
263 length += NX_SECURE_TLS_RANDOM_SIZE;
264
265 /* Extract the session ID if there is one. */
266 session_id_length = packet_buffer[length];
267 length++;
268
269 if ((length + session_id_length) > message_length)
270 {
271 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
272 }
273
274 /* If there is a session ID, copy it into our TLS socket structure. */
275 tls_session -> nx_secure_tls_session_id_length = session_id_length;
276 if (session_id_length > 0)
277 {
278 NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_session_id, &packet_buffer[length], session_id_length); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */
279 length += session_id_length;
280 }
281
282 /* Negotiate the ciphersuite we want to use. */
283 ciphersuite_list_length = (USHORT)((packet_buffer[length] << 8) + packet_buffer[length + 1]);
284 length += 2;
285
286 /* Make sure the list length makes sense. */
287 if (ciphersuite_list_length < 2 || (length + ciphersuite_list_length) > message_length)
288 {
289 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
290 }
291
292 ciphersuite_list = &packet_buffer[length];
293
294 length += ciphersuite_list_length;
295
296 /* Compression methods length - one byte. For now we only support the NULL method. */
297 compression_methods_length = packet_buffer[length];
298 length++;
299
300 /* Message length overflow. */
301 if ((length + compression_methods_length) > message_length)
302 {
303 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
304 }
305
306 /* Make sure NULL compression method is supported. */
307 status = NX_SECURE_TLS_BAD_COMPRESSION_METHOD;
308 for (i = 0; i < compression_methods_length; ++i)
309 {
310 if (packet_buffer[length + i] == 0x0)
311 {
312 status = NX_SUCCESS;
313 break;
314 }
315 }
316
317 /* Check for error. */
318 if (status != NX_SUCCESS)
319 {
320 return(status);
321 }
322
323 length += compression_methods_length;
324
325 /* Padding data? */
326 if (message_length >= (length + 2))
327 {
328
329 /* TLS Extensions come next. Get the total length of all extensions first. */
330 total_extensions_length = (USHORT)((packet_buffer[length] << 8) + packet_buffer[length + 1]);
331 length += 2;
332
333 /* Message length overflow. */
334 if ((length + total_extensions_length) > message_length)
335 {
336 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
337 }
338
339 if (total_extensions_length > 0)
340 {
341 /* Process serverhello extensions. */
342 status = _nx_secure_tls_process_clienthello_extensions(tls_session, &packet_buffer[length], total_extensions_length, extension_data, &num_extensions, packet_buffer, message_length);
343
344 /* Check for error. */
345 if (status != NX_SUCCESS)
346 {
347 return(status);
348 }
349
350 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
351 if (tls_session -> nx_secure_tls_1_3 != tls_1_3)
352 {
353
354 /* Negotiate a version of TLS prior to TLS 1.3. */
355 return(status);
356 }
357 #endif
358
359 /* If the server callback is set, invoke it now with the extensions that require application input. */
360 if (tls_session -> nx_secure_tls_session_server_callback != NX_NULL)
361 {
362 status = tls_session -> nx_secure_tls_session_server_callback(tls_session, extension_data, num_extensions);
363
364 /* Check for error. */
365 if (status != NX_SUCCESS)
366 {
367 return(status);
368 }
369 }
370 }
371 else
372 {
373 num_extensions = 0;
374 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
375 no_extension = NX_TRUE;
376 #endif
377 }
378 }
379 else
380 {
381 num_extensions = 0;
382 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
383 no_extension = NX_TRUE;
384 #endif
385 }
386
387 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
388 if ((tls_session -> nx_secure_tls_1_3) && (no_extension == NX_TRUE))
389 {
390
391 /* Negotiate a version of TLS prior to TLS 1.3. */
392 if (tls_session -> nx_secure_tls_protocol_version_override == 0)
393 {
394 tls_session -> nx_secure_tls_1_3 = NX_FALSE;
395 #if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION)
396 tls_session -> nx_secure_tls_renegotation_enabled = NX_TRUE;
397 #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */
398
399 return(NX_SUCCESS);
400 }
401 else
402 {
403
404 /* Protocol version is overridden to TLS 1.3. */
405 return(NX_SECURE_TLS_UNSUPPORTED_TLS_VERSION);
406 }
407 }
408 #endif
409
410 #if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION)
411 if ((tls_session -> nx_secure_tls_renegotiation_handshake) && (!tls_session -> nx_secure_tls_secure_renegotiation_verified))
412 {
413
414 /* The server did not receive the "renegotiation_info" extension, the handshake must be aborted. */
415 return(NX_SECURE_TLS_RENEGOTIATION_EXTENSION_ERROR);
416 }
417
418 tls_session -> nx_secure_tls_secure_renegotiation_verified = NX_FALSE;
419 #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */
420
421 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
422
423 /* Get the local certificate. */
424 if (tls_session -> nx_secure_tls_credentials.nx_secure_tls_active_certificate != NX_NULL)
425 {
426 cert = tls_session -> nx_secure_tls_credentials.nx_secure_tls_active_certificate;
427 }
428 else
429 {
430 /* Get reference to local device certificate. NX_NULL is passed for name to get default entry. */
431 status = _nx_secure_x509_local_device_certificate_get(&tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store,
432 NX_NULL, &cert);
433 if (status != NX_SUCCESS)
434 {
435 cert = NX_NULL;
436 }
437 }
438
439 if (cert != NX_NULL && cert -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_EC)
440 {
441 ec_pubkey = &cert -> nx_secure_x509_public_key.ec_public_key;
442 cert_curve = ec_pubkey -> nx_secure_ec_named_curve;
443 }
444 else
445 {
446 cert_curve = 0;
447 }
448
449 ecdhe_data = (NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *)tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data;
450
451 /* Parse the ECC extension of supported curve. */
452 status = _nx_secure_tls_proc_clienthello_sec_sa_extension(tls_session,
453 extension_data,
454 num_extensions,
455 &selected_curve,
456 (USHORT)cert_curve, &cert_curve_supported,
457 &ecdhe_data -> nx_secure_tls_ecdhe_signature_algorithm,
458 cert);
459
460 /* Check for error. */
461 if (status != NX_SUCCESS)
462 {
463 return(status);
464 }
465
466 ecdhe_data -> nx_secure_tls_ecdhe_named_curve = selected_curve;
467
468 /* Check if certificate curve is supported. */
469 if (cert != NX_NULL && cert -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_EC)
470 {
471 if (cert_curve_supported == NX_FALSE)
472 {
473 /* The named curve in our server certificate is not supported by the client. */
474 return(NX_SECURE_TLS_NO_SUPPORTED_CIPHERS);
475 }
476 }
477 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE && !NX_SECURE_DISABLE_X509 */
478
479 /* Set our initial priority to the maximum value - the size of our ciphersuite crypto table. */
480 ciphersuite_priority = (USHORT)(0xFFFFFFFF);
481
482 for (i = 0; i < ciphersuite_list_length; i += 2)
483 {
484 /* Loop through list of acceptable ciphersuites. */
485 cipher_entry = (USHORT)((ciphersuite_list[i] << 8) + ciphersuite_list[i + 1]);
486
487 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
488 if ((tls_session -> nx_secure_tls_1_3 == NX_TRUE) ^ (ciphersuite_list[i] == 0x13))
489 {
490
491 /* Ciphersuites for TLS 1.3 can not be used by TLS 1.2. */
492 continue;
493 }
494 #endif
495
496 /* Look up the ciphersuite in our crypto table, then check the priority of the chosen ciphersuite. */
497 status = _nx_secure_tls_ciphersuite_lookup(tls_session, cipher_entry, &ciphersuite_info, &new_ciphersuite_priority);
498
499 /* Save the first ciphersuite we find - assume cipher table is in priority order. */
500 if ((status == NX_SUCCESS) && (new_ciphersuite_priority < ciphersuite_priority))
501 {
502 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
503 if (NX_SUCCESS == _nx_secure_tls_check_ciphersuite(ciphersuite_info, cert, selected_curve, cert_curve_supported))
504 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
505 {
506 /* Save the ciphersuite and its priority but continue processing the entire list to see if there
507 is a better ciphersuite available. */
508 tls_session -> nx_secure_tls_session_ciphersuite = ciphersuite_info;
509 ciphersuite_priority = new_ciphersuite_priority;
510 }
511 }
512
513 #if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION)
514 if (cipher_entry == TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
515 {
516 if (tls_session -> nx_secure_tls_renegotiation_handshake)
517 {
518
519 /* When secure renegotiating, the server MUST verify that it
520 does not contain the TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. */
521 return(NX_SECURE_TLS_RENEGOTIATION_EXTENSION_ERROR);
522 }
523 else
524 {
525
526 /* Secure Renegotiation signalling ciphersuite value was encountered.
527 This indicates that the Client supports secure renegotiation. */
528 tls_session -> nx_secure_tls_secure_renegotiation = NX_TRUE;
529 }
530 }
531 #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */
532
533
534 /* Check for the fallback notification SCSV. */
535 if (cipher_entry == TLS_FALLBACK_NOTIFY_SCSV)
536 {
537
538 /* A fallback is indicated by the Client, check the TLS version. */
539 _nx_secure_tls_newest_supported_version(tls_session, &newest_version, NX_SECURE_TLS);
540
541 if (protocol_version != newest_version)
542 {
543 return(NX_SECURE_TLS_INAPPROPRIATE_FALLBACK);
544 }
545 }
546 /* Continue searching client ciphersuite list to get highest-priority selection. */
547 }
548
549 #if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION) && defined(NX_SECURE_TLS_REQUIRE_RENEGOTIATION_EXT)
550 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
551 if (!tls_session -> nx_secure_tls_1_3)
552 #endif /* NX_SECURE_TLS_TLS_1_3_ENABLED */
553 {
554 if ((tls_session -> nx_secure_tls_renegotation_enabled) && (!tls_session -> nx_secure_tls_secure_renegotiation))
555 {
556
557 /* No "renegotiation_info" extension present, some servers may want to terminate the handshake. */
558 return(NX_SECURE_TLS_RENEGOTIATION_EXTENSION_ERROR);
559 }
560 }
561 #endif /* !NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION && NX_SECURE_TLS_REQUIRE_RENEGOTIATION_EXT */
562
563 /* See if we found an acceptable ciphersuite. */
564 if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL)
565 {
566
567 /* No supported ciphersuites found. */
568 return(NX_SECURE_TLS_NO_SUPPORTED_CIPHERS);
569 }
570
571 #ifdef NX_SECURE_TLS_SERVER_DISABLED
572 /* If TLS Server is disabled and we have processed a ClientHello, something is wrong... */
573 tls_session -> nx_secure_tls_client_state = NX_SECURE_TLS_CLIENT_STATE_ERROR;
574 return(NX_SECURE_TLS_INVALID_STATE);
575 #else
576 return(NX_SUCCESS);
577 #endif
578 }
579
580 /**************************************************************************/
581 /* */
582 /* FUNCTION RELEASE */
583 /* */
584 /* _nx_secure_tls_check_ciphersuite PORTABLE C */
585 /* 6.1 */
586 /* AUTHOR */
587 /* */
588 /* Timothy Stapko, Microsoft Corporation */
589 /* */
590 /* DESCRIPTION */
591 /* */
592 /* This function checks whether the specified ciphersuite is */
593 /* suitable for the server certificate, the curve in the certificate */
594 /* and the common shared curve. */
595 /* */
596 /* INPUT */
597 /* */
598 /* ciphersuite_info The specified cipher suite */
599 /* cert Local server certificate */
600 /* selected_curve Curve selected for ECC */
601 /* cert_curve_supported If cert curve is supported */
602 /* */
603 /* OUTPUT */
604 /* */
605 /* status Completion status */
606 /* */
607 /* CALLS */
608 /* */
609 /* None */
610 /* */
611 /* CALLED BY */
612 /* */
613 /* _nx_secure_tls_server_handshake TLS Server state machine */
614 /* */
615 /* RELEASE HISTORY */
616 /* */
617 /* DATE NAME DESCRIPTION */
618 /* */
619 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
620 /* 09-30-2020 Timothy Stapko Modified comment(s), */
621 /* resulting in version 6.1 */
622 /* */
623 /**************************************************************************/
624 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
_nx_secure_tls_check_ciphersuite(const NX_SECURE_TLS_CIPHERSUITE_INFO * ciphersuite_info,NX_SECURE_X509_CERT * cert,UINT selected_curve,UINT cert_curve_supported)625 static UINT _nx_secure_tls_check_ciphersuite(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite_info,
626 NX_SECURE_X509_CERT *cert, UINT selected_curve,
627 UINT cert_curve_supported)
628 {
629 if (ciphersuite_info -> nx_secure_tls_public_cipher == NX_NULL)
630 {
631 return(NX_SUCCESS);
632 }
633
634 if (ciphersuite_info -> nx_secure_tls_public_auth == NX_NULL)
635 {
636 return(NX_SUCCESS);
637 }
638
639 switch (ciphersuite_info -> nx_secure_tls_public_cipher -> nx_crypto_algorithm)
640 {
641 case NX_CRYPTO_KEY_EXCHANGE_ECDHE:
642 if (selected_curve == 0 || cert == NX_NULL)
643 {
644 /* No common named curve supported for ECDHE. */
645 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
646 }
647
648 if (ciphersuite_info -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_DIGITAL_SIGNATURE_ECDSA)
649 {
650 if (cert -> nx_secure_x509_public_algorithm != NX_SECURE_TLS_X509_TYPE_EC)
651 {
652 /* ECDSA auth requires EC certificate. */
653 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
654 }
655 }
656 else
657 {
658 if (cert -> nx_secure_x509_public_algorithm != NX_SECURE_TLS_X509_TYPE_RSA)
659 {
660 /* RSA auth requires RSA certificate. */
661 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
662 }
663 }
664
665 break;
666
667 case NX_CRYPTO_KEY_EXCHANGE_ECDH:
668 if (selected_curve == 0)
669 {
670 /* No common named curve supported supported. */
671 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
672 }
673
674 /* Check for ECDH_anon. */
675 if (ciphersuite_info -> nx_secure_tls_public_auth -> nx_crypto_algorithm != NX_CRYPTO_DIGITAL_SIGNATURE_ANONYMOUS)
676 {
677 /* ECDH key exchange requires an EC certificate. */
678 if (cert == NX_NULL || cert -> nx_secure_x509_public_algorithm != NX_SECURE_TLS_X509_TYPE_EC)
679 {
680 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
681 }
682
683 if (cert_curve_supported == NX_FALSE)
684 {
685 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
686 }
687
688 /* Check the signatureAlgorithm of the certificate to determine the public auth algorithm. */
689 if (ciphersuite_info -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_DIGITAL_SIGNATURE_ECDSA)
690 {
691 if (cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_1 &&
692 cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_224 &&
693 cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_256 &&
694 cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_384 &&
695 cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_512)
696 {
697 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
698 }
699 }
700 else
701 {
702 if (cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_RSA_MD5 &&
703 cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_RSA_SHA_1 &&
704 cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_RSA_SHA_256 &&
705 cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_RSA_SHA_384 &&
706 cert -> nx_secure_x509_signature_algorithm != NX_SECURE_TLS_X509_TYPE_RSA_SHA_512)
707 {
708 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
709 }
710 }
711 }
712 break;
713
714 case NX_CRYPTO_KEY_EXCHANGE_RSA:
715 if (cert == NX_NULL || cert -> nx_secure_x509_public_algorithm != NX_SECURE_TLS_X509_TYPE_RSA)
716 {
717 /* RSA key exchange requires RSA certificate. */
718 return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER);
719 }
720 break;
721
722 default:
723 break;
724 }
725
726 return(NX_SUCCESS);
727 }
728 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE && !NX_SECURE_DISABLE_X509 */
729