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