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