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