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