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 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
31 static UINT _nx_secure_dtls_send_clienthello_sec_spf_extensions(NX_SECURE_TLS_SESSION *tls_session,
32                                                                 UCHAR *packet_buffer, ULONG *packet_offset,
33                                                                 USHORT *extension_length, ULONG available_size);
34 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
35 
36 /**************************************************************************/
37 /*                                                                        */
38 /*  FUNCTION                                               RELEASE        */
39 /*                                                                        */
40 /*    _nx_secure_dtls_send_clienthello                    PORTABLE C      */
41 /*                                                           6.1.10       */
42 /*  AUTHOR                                                                */
43 /*                                                                        */
44 /*    Timothy Stapko, Microsoft Corporation                               */
45 /*                                                                        */
46 /*  DESCRIPTION                                                           */
47 /*                                                                        */
48 /*    This function populates an NX_PACKET with a ClientHello message,    */
49 /*    which kicks off a DTLS handshake when sent to a remote DTLS server. */
50 /*                                                                        */
51 /*  INPUT                                                                 */
52 /*                                                                        */
53 /*    dtls_session                          DTLS control block            */
54 /*    send_packet                           Outgoing TLS packet           */
55 /*                                                                        */
56 /*  OUTPUT                                                                */
57 /*                                                                        */
58 /*    status                                Completion status             */
59 /*                                                                        */
60 /*  CALLS                                                                 */
61 /*                                                                        */
62 /*    _nx_secure_tls_handshake_hash_init    Initialize the finished hash  */
63 /*    _nx_secure_tls_newest_supported_version                             */
64 /*                                          Get the version of DTLS to use*/
65 /*    [nx_crypto_init]                      Crypto initialization         */
66 /*    [nx_crypto_operation]                 Crypto operation              */
67 /*    [nx_secure_tls_session_time_function] Get the current time for the  */
68 /*                                            TLS timestamp               */
69 /*                                                                        */
70 /*  CALLED BY                                                             */
71 /*                                                                        */
72 /*    nx_secure_dtls_session_start                                        */
73 /*    nx_secure_dtls_client_handshake                                     */
74 /*                                                                        */
75 /*  RELEASE HISTORY                                                       */
76 /*                                                                        */
77 /*    DATE              NAME                      DESCRIPTION             */
78 /*                                                                        */
79 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
80 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
81 /*                                            verified memcpy use cases,  */
82 /*                                            resulting in version 6.1    */
83 /*  01-31-2022     Yuxin Zhou               Modified comment(s), and      */
84 /*                                            updated cookie handling,    */
85 /*                                            resulting in version 6.1.10 */
86 /*                                                                        */
87 /**************************************************************************/
_nx_secure_dtls_send_clienthello(NX_SECURE_DTLS_SESSION * dtls_session,NX_PACKET * send_packet)88 UINT _nx_secure_dtls_send_clienthello(NX_SECURE_DTLS_SESSION *dtls_session, NX_PACKET *send_packet)
89 {
90 ULONG  length;
91 UINT   gmt_time;
92 UINT   random_value;
93 UINT   i;
94 USHORT ciphersuite;
95 USHORT ciphersuites_length;
96 
97 #ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
98 USHORT                      extension_length;
99 USHORT                      extension_type;
100 UINT                        status;
101 NX_SECURE_TLS_PSK_STORE    *psk_store;
102 NX_CRYPTO_EXTENDED_OUTPUT   extended_output;
103 #endif
104 #if defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE)
105 UCHAR                      *extension_total_length_ptr;
106 USHORT                      extension_total_length;
107 const NX_CRYPTO_METHOD     *crypto_method = NX_NULL;
108 #endif
109 UCHAR                      *packet_buffer;
110 NX_SECURE_TLS_SESSION      *tls_session;
111 const NX_SECURE_TLS_CRYPTO *crypto_table;
112 USHORT                      protocol_version;
113 
114     /* ClientHello structure:
115      * |     2       |          4 + 28          |    1       |   <SID len>  |   2    | <CS Len>     |    1    | <Comp Len>  |    2    | <Ext. Len> |
116      * | TLS version |  Random (time + random)  | SID length |  Session ID  | CS Len | Ciphersuites |Comp Len | Compression |Ext. Len | Extensions |
117      */
118 
119     tls_session = &dtls_session -> nx_secure_dtls_tls_session;
120 
121     packet_buffer = send_packet -> nx_packet_prepend_ptr;
122 
123     /* Initialize the handshake hashes used for the Finished message. */
124     _nx_secure_tls_handshake_hash_init(tls_session);
125 
126     /* At this point, the remote session is not active - that is, incoming records are not encrypted. */
127     tls_session -> nx_secure_tls_remote_session_active = 0;
128 
129     /* Since we are establishing a new session, we start in non-encrypted mode. */
130     tls_session -> nx_secure_tls_local_session_active = 0;
131 
132     /* Length of the ciphersuites list that follows. The client can send any number of suites for the
133      * server to choose from, with a 2-byte length field. */
134     crypto_table = tls_session -> nx_secure_tls_crypto_table;
135     ciphersuites_length = (USHORT)(2 + (crypto_table -> nx_secure_tls_ciphersuite_lookup_table_size << 1));
136 
137     if ((10u + sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random) +
138          tls_session -> nx_secure_tls_session_id_length + dtls_session -> nx_secure_dtls_cookie_length + ciphersuites_length) >
139         ((ULONG)(send_packet -> nx_packet_data_end) - (ULONG)(send_packet -> nx_packet_prepend_ptr)))
140     {
141 
142         /* Packet buffer is too small. */
143         return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
144     }
145 
146     /* First two bytes of the hello following the header are the DTLS major and minor version numbers. */
147     _nx_secure_tls_protocol_version_get(tls_session, &protocol_version, NX_SECURE_DTLS);
148 
149     if (protocol_version == 0x0)
150     {
151         /* Error, no versions enabled. */
152         return(NX_SECURE_TLS_UNSUPPORTED_TLS_VERSION);
153     }
154     tls_session -> nx_secure_tls_protocol_version = protocol_version;
155 
156     if (dtls_session -> nx_secure_dtls_cookie_length > 0)
157     {
158 
159         /* Skip record header. */
160         send_packet -> nx_packet_prepend_ptr += (NX_SECURE_DTLS_RECORD_HEADER_SIZE +
161                                                  NX_SECURE_DTLS_HANDSHAKE_HEADER_SIZE);
162         length = send_packet -> nx_packet_length - (NX_SECURE_DTLS_RECORD_HEADER_SIZE +
163                                                     NX_SECURE_DTLS_HANDSHAKE_HEADER_SIZE);
164 
165         /* Locate the buffer to add cookie. */
166         packet_buffer = send_packet -> nx_packet_prepend_ptr +
167             (2 + sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random) +
168              1 + tls_session -> nx_secure_tls_session_id_length);
169 
170         /* Put the length into the record. */
171         packet_buffer[0] = (UCHAR)dtls_session -> nx_secure_dtls_cookie_length;
172         packet_buffer++;
173 
174         /* Move the data to insert cookie. */
175         NX_SECURE_MEMMOVE(packet_buffer + dtls_session -> nx_secure_dtls_cookie_length,
176                 packet_buffer, (UINT)(send_packet -> nx_packet_append_ptr - packet_buffer)); /* Use case of memmove is verified.  */
177 
178         /* Set cookie. */
179         NX_SECURE_MEMCPY(packet_buffer, dtls_session -> nx_secure_dtls_client_cookie_ptr,
180                dtls_session -> nx_secure_dtls_cookie_length); /* Use case of memcpy is verified. */
181         length += dtls_session -> nx_secure_dtls_cookie_length;
182 
183         /* Finally, we have a complete length and can put it into the buffer. Before that,
184            save off and return the number of bytes we wrote and need to send. */
185         send_packet -> nx_packet_append_ptr = send_packet -> nx_packet_prepend_ptr + length;
186         send_packet -> nx_packet_length = length;
187 
188         return(NX_SUCCESS);
189     }
190 
191     /* Use our length as an index into the buffer. */
192     length = 0;
193 
194     packet_buffer[length]     = (UCHAR)((protocol_version & 0xFF00) >> 8);
195     packet_buffer[length + 1] = (UCHAR)(protocol_version & 0x00FF);
196     length += 2;
197 
198     /* Set the Client random data, used in key generation. First 4 bytes is GMT time. */
199     gmt_time = 0;
200     if (tls_session -> nx_secure_tls_session_time_function != NX_NULL)
201     {
202         gmt_time = tls_session -> nx_secure_tls_session_time_function();
203     }
204     NX_CHANGE_ULONG_ENDIAN(gmt_time);
205     NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random, (UCHAR *)&gmt_time, sizeof(gmt_time)); /* Use case of memcpy is verified. */
206 
207     /* Next 28 bytes is random data. */
208     for (i = 0; i < 28; i += (UINT)sizeof(random_value))
209     {
210         random_value = (UINT)NX_RAND();
211         NX_CHANGE_ULONG_ENDIAN(random_value);
212         *(tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random + (i + 4))     = (UCHAR)(random_value);
213         *(tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random + (i + 5)) = (UCHAR)(random_value >> 8);
214         *(tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random + (i + 6)) = (UCHAR)(random_value >> 16);
215         *(tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random + (i + 7)) = (UCHAR)(random_value >> 24);
216     }
217 
218     /* Copy the random data into the packet. */
219     NX_SECURE_MEMCPY(&packet_buffer[length], tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random,
220                      sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random)); /* Use case of memcpy is verified. */
221     length += sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random);
222 
223     /* Session ID length is one byte. */
224     packet_buffer[length] = tls_session -> nx_secure_tls_session_id_length;
225     length++;
226 
227     /* Session ID follows. */
228     if (tls_session -> nx_secure_tls_session_id_length > 0)
229     {
230         NX_SECURE_MEMCPY(&packet_buffer[length], tls_session -> nx_secure_tls_session_id, tls_session -> nx_secure_tls_session_id_length); /* Use case of memcpy is verified. */
231         length += tls_session -> nx_secure_tls_session_id_length;
232     }
233 
234     /* Cookie length - 0 for first client hello */
235     packet_buffer[length] = 0;
236     length += 1;
237 
238     /* Length of the ciphersuites list that follows. The client can send any number of suites for the
239      * server to choose from, with a 2-byte length field. */
240     packet_buffer[length] = (UCHAR)((ciphersuites_length & 0xFF00) >> 8);
241     packet_buffer[length + 1] = (UCHAR)(ciphersuites_length & 0x00FF);
242     length += 2;
243 
244     /* Our chosen ciphersuites. In sending a ClientHello, we need to include all the ciphersuites
245      * we are interested in speaking. This will be a list of ciphersuites the user has chosen to support
246      * and all of them will be presented to the remote server in this initial message. */
247 
248     for (i = 0; i < crypto_table -> nx_secure_tls_ciphersuite_lookup_table_size; i++)
249     {
250         ciphersuite = crypto_table -> nx_secure_tls_ciphersuite_lookup_table[i].nx_secure_tls_ciphersuite;
251         packet_buffer[length] = (UCHAR)((ciphersuite & 0xFF00) >> 8);
252         packet_buffer[length + 1] = (UCHAR)(ciphersuite & 0x00FF);
253         length += 2;
254 
255 #if defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE)
256         if (crypto_table -> nx_secure_tls_ciphersuite_lookup_table[i].nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE)
257         {
258             crypto_method = crypto_table -> nx_secure_tls_ciphersuite_lookup_table[i].nx_secure_tls_public_auth;
259         }
260 #endif /* NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE || NX_SECURE_ENABLE_ECC_CIPHERSUITE */
261     }
262 
263     /* For the secure rengotiation indication extension, we need to send a
264        Signalling Ciphersuite Value (SCSV) as detailled in RFC5746. */
265     ciphersuite = TLS_EMPTY_RENEGOTIATION_INFO_SCSV;
266     packet_buffer[length] = (UCHAR)((ciphersuite & 0xFF00) >> 8);
267     packet_buffer[length + 1] = (UCHAR)(ciphersuite & 0x00FF);
268     length += 2;
269 
270     /* Compression methods length - one byte. For now we only have the NULL method, for a length of 1. */
271     packet_buffer[length] = 0x1;
272     length++;
273 
274     /* Compression methods - for now this is NULL. */
275     packet_buffer[length] = 0x0;
276     length++;
277 
278     /* TLS extensions, once supported, will be here in the ClientHello. */
279 
280 #ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
281     if (crypto_method)
282     {
283         if (crypto_method -> nx_crypto_init == NX_NULL)
284         {
285             return(NX_SECURE_TLS_HANDSHAKE_FAILURE);
286         }
287 
288         if (tls_session -> nx_secure_tls_credentials.nx_secure_tls_psk_count == 0)
289         {
290             return(NX_SECURE_TLS_HANDSHAKE_FAILURE);
291         }
292 
293         if (((ULONG)(send_packet -> nx_packet_data_end) - (ULONG)(send_packet -> nx_packet_prepend_ptr)) < (20u + length))
294         {
295 
296             /* Packet buffer is too small. */
297             return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
298         }
299 
300         psk_store = &tls_session -> nx_secure_tls_credentials.nx_secure_tls_psk_store[0];
301         status = crypto_method -> nx_crypto_init((NX_CRYPTO_METHOD*)crypto_method,
302                                                  psk_store -> nx_secure_tls_psk_data,
303                                                  (USHORT)(psk_store -> nx_secure_tls_psk_data_size << 3),
304                                                  NX_NULL,
305                                                  tls_session -> nx_secure_public_auth_metadata_area,
306                                                  tls_session -> nx_secure_public_auth_metadata_size);
307         if (status)
308         {
309             return(status);
310         }
311 
312         status = crypto_method -> nx_crypto_operation(NX_CRYPTO_ECJPAKE_HASH_METHOD_SET,
313                                                       NX_NULL,
314                                                       (NX_CRYPTO_METHOD*)crypto_method,
315                                                       NX_NULL,
316                                                       (USHORT)(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size << 3),
317                                                       (UCHAR *)(tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha256_method),
318                                                       sizeof(NX_CRYPTO_METHOD),
319                                                       NX_NULL, NX_NULL, 0,
320                                                       tls_session -> nx_secure_public_auth_metadata_area,
321                                                       tls_session -> nx_secure_public_auth_metadata_size,
322                                                       NX_NULL, NX_NULL);
323         if (status)
324         {
325             return(status);
326         }
327 
328         status = crypto_method -> nx_crypto_operation(NX_CRYPTO_ECJPAKE_CURVE_SET,
329                                                       NX_NULL,
330                                                       (NX_CRYPTO_METHOD*)crypto_method,
331                                                       NX_NULL, 0,
332                                                       (UCHAR *)&crypto_method_ec_secp256,
333                                                       sizeof(NX_CRYPTO_METHOD),
334                                                       NX_NULL, NX_NULL, 0,
335                                                       tls_session -> nx_secure_public_auth_metadata_area,
336                                                       tls_session -> nx_secure_public_auth_metadata_size,
337                                                       NX_NULL, NX_NULL);
338         if (status)
339         {
340             return(status);
341         }
342 
343         extension_total_length_ptr = &packet_buffer[length];
344         extension_total_length = 18;
345         length += 2;
346 
347         /* Supported Elliptic Curves Extension.  */
348         extension_type = NX_SECURE_TLS_EXTENSION_EC_GROUPS;
349         packet_buffer[length] = (UCHAR)((extension_type >> 8) & 0xFF);
350         packet_buffer[length + 1] = (UCHAR)(extension_type & 0xFF);
351         length += 2;
352 
353         /* Supported Groups Length: 4.  */
354         extension_length = 4;
355         packet_buffer[length] = (UCHAR)((extension_length >> 8) & 0xFF);
356         packet_buffer[length + 1] = (UCHAR)(extension_length & 0xFF);
357         length += 2;
358 
359         /* Supported Groups List Length: 2.  */
360         extension_length = 2;
361         packet_buffer[length] = (UCHAR)((extension_length >> 8) & 0xFF);
362         packet_buffer[length + 1] = (UCHAR)(extension_length & 0xFF);
363         length += 2;
364 
365         /* Supported Group: secp256r1.  */
366         extension_type = (USHORT)NX_CRYPTO_EC_SECP256R1;
367         packet_buffer[length] = (UCHAR)((extension_type >> 8) & 0xFF);
368         packet_buffer[length + 1] = (UCHAR)(extension_type & 0xFF);
369         length += 2;
370 
371         /* ec_point_formats Extension.  */
372         extension_type = NX_SECURE_TLS_EXTENSION_EC_POINT_FORMATS;
373         packet_buffer[length] = (UCHAR)((extension_type >> 8) & 0xFF);
374         packet_buffer[length + 1] = (UCHAR)(extension_type & 0xFF);
375         length += 2;
376 
377         /* ec_point_formats Length: 2.  */
378         extension_length = 2;
379         packet_buffer[length] = (UCHAR)((extension_length >> 8) & 0xFF);
380         packet_buffer[length + 1] = (UCHAR)(extension_length & 0xFF);
381         length += 2;
382 
383         /* EC point formats Length: 1.  */
384         packet_buffer[length] = 1;
385         length += 1;
386 
387         /* EC point format: uncompressed(0).  */
388         packet_buffer[length] = 0;
389         length += 1;
390 
391         /* ecjpake_key_kp_pair Extension.  */
392         extension_type = NX_SECURE_TLS_EXTENSION_ECJPAKE_KEY_KP_PAIR;
393         packet_buffer[length] = (UCHAR)((extension_type >> 8) & 0xFF);
394         packet_buffer[length + 1] = (UCHAR)(extension_type & 0xFF);
395         length += 2;
396 
397         /* ecjpake_key_kp_pair Length.  */
398         length += 2;
399         extended_output.nx_crypto_extended_output_data = &packet_buffer[length];
400         extended_output.nx_crypto_extended_output_length_in_byte =
401             (ULONG)send_packet -> nx_packet_data_end - (ULONG)&packet_buffer[length];
402         extended_output.nx_crypto_extended_output_actual_size = 0;
403         status = crypto_method -> nx_crypto_operation(NX_CRYPTO_ECJPAKE_CLIENT_HELLO_GENERATE,
404                                                       NX_NULL,
405                                                       (NX_CRYPTO_METHOD*)crypto_method,
406                                                       NX_NULL, 0,
407                                                       NX_NULL, 0, NX_NULL,
408                                                       (UCHAR *)&extended_output,
409                                                       sizeof(extended_output),
410                                                       tls_session -> nx_secure_public_auth_metadata_area,
411                                                       tls_session -> nx_secure_public_auth_metadata_size,
412                                                       NX_NULL, NX_NULL);
413         if (status)
414         {
415             return(status);
416         }
417 
418         /* Set length for ecjpake_key_kp_pair extension. */
419         extension_length = (USHORT)extended_output.nx_crypto_extended_output_actual_size;
420         packet_buffer[length - 2] = (UCHAR)((extension_length >> 8) & 0xFF);
421         packet_buffer[length - 1] = (UCHAR)(extension_length & 0xFF);
422 
423         extension_total_length = (USHORT)(extension_total_length +
424                                           extended_output.nx_crypto_extended_output_actual_size);
425         length += extended_output.nx_crypto_extended_output_actual_size;
426 
427         /* Set extension total length. */
428         extension_total_length_ptr[0] = (UCHAR)((extension_total_length >> 8) & 0xFF);
429         extension_total_length_ptr[1] = (UCHAR)(extension_total_length & 0xFF);
430     }
431 #endif
432 
433 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
434     if (crypto_method == NX_NULL)
435     {
436         extension_total_length_ptr = &packet_buffer[length];
437         extension_total_length = 18;
438         length += 2;
439 
440         _nx_secure_dtls_send_clienthello_sec_spf_extensions(&dtls_session -> nx_secure_dtls_tls_session,
441                                                             packet_buffer, &length, &extension_total_length,
442                                                             ((ULONG)send_packet -> nx_packet_data_end -
443                                                              (ULONG)packet_buffer));
444         if (extension_total_length == 0)
445         {
446 
447             /* No extensions, remove the extensions length. */
448             length -= 2;
449         }
450         else
451         {
452 
453             /* Set extension total length. */
454             extension_total_length_ptr[0] = (UCHAR)((extension_total_length >> 8) & 0xFF);
455             extension_total_length_ptr[1] = (UCHAR)(extension_total_length & 0xFF);
456         }
457     }
458 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
459 
460     /* Finally, we have a complete length and can put it into the buffer. Before that,
461        save off and return the number of bytes we wrote and need to send. */
462     send_packet -> nx_packet_append_ptr = send_packet -> nx_packet_prepend_ptr + length;
463     send_packet -> nx_packet_length = send_packet -> nx_packet_length + length;
464 
465     /* We are starting a new handshake, so both local and remote sessions are not
466      * active. */
467     dtls_session -> nx_secure_dtls_tls_session.nx_secure_tls_remote_session_active = 0;
468     dtls_session -> nx_secure_dtls_tls_session.nx_secure_tls_local_session_active = 0;
469 
470     return(NX_SUCCESS);
471 }
472 
473 /**************************************************************************/
474 /*                                                                        */
475 /*  FUNCTION                                               RELEASE        */
476 /*                                                                        */
477 /*    _nx_secure_dtls_send_clienthello_sec_spf_extensions PORTABLE C      */
478 /*                                                           6.1          */
479 /*  AUTHOR                                                                */
480 /*                                                                        */
481 /*    Timothy Stapko, Microsoft Corporation                               */
482 /*                                                                        */
483 /*  DESCRIPTION                                                           */
484 /*                                                                        */
485 /*    This function adds the Supported Elliptic Curves extension and the  */
486 /*    Supported Point Formats extension to an outgoing ClientHello        */
487 /*    record. See RFC 4492 section 5.1.                                   */
488 /*                                                                        */
489 /*  INPUT                                                                 */
490 /*                                                                        */
491 /*    tls_session                           TLS control block             */
492 /*    packet_buffer                         Outgoing TLS packet buffer    */
493 /*    packet_offset                         Offset into packet buffer     */
494 /*    extension_length                      Return length of data         */
495 /*    available_size                        Available size of buffer      */
496 /*                                                                        */
497 /*  OUTPUT                                                                */
498 /*                                                                        */
499 /*    status                                Completion status             */
500 /*                                                                        */
501 /*  CALLS                                                                 */
502 /*                                                                        */
503 /*    None                                                                */
504 /*                                                                        */
505 /*  CALLED BY                                                             */
506 /*                                                                        */
507 /*    _nx_secure_dtls_send_clienthello      Send TLS ClientHello extension*/
508 /*                                                                        */
509 /*  RELEASE HISTORY                                                       */
510 /*                                                                        */
511 /*    DATE              NAME                      DESCRIPTION             */
512 /*                                                                        */
513 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
514 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
515 /*                                            resulting in version 6.1    */
516 /*                                                                        */
517 /**************************************************************************/
518 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
_nx_secure_dtls_send_clienthello_sec_spf_extensions(NX_SECURE_TLS_SESSION * tls_session,UCHAR * packet_buffer,ULONG * packet_offset,USHORT * extension_length,ULONG available_size)519 static UINT _nx_secure_dtls_send_clienthello_sec_spf_extensions(NX_SECURE_TLS_SESSION *tls_session,
520                                                                 UCHAR *packet_buffer, ULONG *packet_offset,
521                                                                 USHORT *extension_length,
522                                                                 ULONG available_size)
523 {
524 ULONG  offset;
525 USHORT ext_len, list_len, ext, i;
526 NX_SECURE_TLS_ECC *ecc_info;
527 
528     ecc_info = &(tls_session -> nx_secure_tls_ecc);
529 
530     if (ecc_info -> nx_secure_tls_ecc_supported_groups_count == 0)
531     {
532         *extension_length = 0;
533         return(NX_SUCCESS);
534     }
535 
536     /* Start with our passed-in packet offset. */
537     offset = *packet_offset;
538 
539     if (available_size < (offset + 12u + (ULONG)(ecc_info -> nx_secure_tls_ecc_supported_groups_count << 1)))
540     {
541 
542         /* Packet buffer too small. */
543         return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
544     }
545 
546     /* Supported Elliptic Curves Extension. */
547     ext = NX_SECURE_TLS_EXTENSION_EC_GROUPS;  /* Supported Groups */
548     list_len = (USHORT)(ecc_info -> nx_secure_tls_ecc_supported_groups_count * sizeof(USHORT));
549     ext_len = (USHORT)(list_len + 2);
550 
551     packet_buffer[offset] = (UCHAR)((ext & 0xFF00) >> 8);
552     packet_buffer[offset + 1] = (UCHAR)(ext & 0x00FF);
553     offset += 2;
554 
555     packet_buffer[offset] = (UCHAR)((ext_len & 0xFF00) >> 8);
556     packet_buffer[offset + 1] = (UCHAR)(ext_len & 0x00FF);
557     offset += 2;
558 
559     packet_buffer[offset] = (UCHAR)((list_len & 0xFF00) >> 8);
560     packet_buffer[offset + 1] = (UCHAR)(list_len & 0x00FF);
561     offset += 2;
562 
563     for (i = 0; i < ecc_info -> nx_secure_tls_ecc_supported_groups_count; i++)
564     {
565         packet_buffer[offset] = (UCHAR)((ecc_info -> nx_secure_tls_ecc_supported_groups[i] & 0xFF00) >> 8);
566         packet_buffer[offset + 1] = (UCHAR)(ecc_info -> nx_secure_tls_ecc_supported_groups[i] & 0x00FF);
567         offset += 2;
568     }
569 
570     /* ec_point_formats Extension.  */
571     ext = NX_SECURE_TLS_EXTENSION_EC_POINT_FORMATS;
572     ext_len = 2; /* ec_point_formats Length: 2.  */
573 
574     packet_buffer[offset] = (UCHAR)((ext & 0xFF00) >> 8);
575     packet_buffer[offset + 1] = (UCHAR)(ext & 0x00FF);
576     offset += 2;
577 
578     packet_buffer[offset] = (UCHAR)((ext_len & 0xFF00) >> 8);
579     packet_buffer[offset + 1] = (UCHAR)(ext_len & 0x00FF);
580     offset += 2;
581 
582     packet_buffer[offset] = 1;
583     offset += 1;
584 
585     packet_buffer[offset] = 0;
586     offset += 1;
587 
588     /* Return our updated packet offset. */
589     *extension_length = (USHORT)(offset - *packet_offset);
590     *packet_offset = offset;
591 
592     return(NX_SUCCESS);
593 }
594 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
595 
596 #endif /* NX_SECURE_ENABLE_DTLS */
597 
598