1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** NetX Secure Component */
16 /** */
17 /** Transport Layer Security (TLS) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_SECURE_SOURCE_CODE
23
24 #include "nx_secure_tls.h"
25
26 #if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION)
27 static UINT _nx_secure_tls_proc_clienthello_sec_reneg_extension(NX_SECURE_TLS_SESSION *tls_session,
28 UCHAR *packet_buffer,
29 UINT extension_length);
30 #endif
31
32
33 #if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED)
34 static UINT _nx_secure_tls_proc_clienthello_keyshare_extension(NX_SECURE_TLS_SESSION *tls_session,
35 UCHAR *packet_buffer,
36 USHORT extension_length);
37 static UINT _nx_secure_tls_proc_clienthello_supported_versions_extension(NX_SECURE_TLS_SESSION *tls_session,
38 UCHAR *packet_buffer,
39 USHORT *supported_version,
40 USHORT extension_length);
41 static VOID _nx_secure_tls_proc_clienthello_signature_algorithms_extension(NX_SECURE_TLS_SESSION *tls_session,
42 const UCHAR *packet_buffer,
43 USHORT extension_length);
44
45 #ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
46 static UINT _nx_secure_tls_process_clienthello_psk_extension(NX_SECURE_TLS_SESSION *tls_session, const UCHAR *packet_buffer,
47 USHORT extension_length, const UCHAR *client_hello_buffer, UINT client_hello_length);
48 #endif
49 #endif
50
51
52 /**************************************************************************/
53 /* */
54 /* FUNCTION RELEASE */
55 /* */
56 /* _nx_secure_tls_process_clienthello_extensions PORTABLE C */
57 /* 6.1.9 */
58 /* AUTHOR */
59 /* */
60 /* Timothy Stapko, Microsoft Corporation */
61 /* */
62 /* DESCRIPTION */
63 /* */
64 /* This function processes any extensions included in an incoming */
65 /* ClientHello message from a remote host. */
66 /* */
67 /* INPUT */
68 /* */
69 /* tls_session TLS control block */
70 /* packet_buffer Pointer to message data */
71 /* message_length Length of message data (bytes)*/
72 /* extensions Extensions for output */
73 /* num_extensions Number of extensions */
74 /* */
75 /* OUTPUT */
76 /* */
77 /* status Completion status */
78 /* */
79 /* CALLS */
80 /* */
81 /* _nx_secure_tls_proc_clienthello_sec_reneg_extension */
82 /* Process ClientHello */
83 /* Renegotiation extension */
84 /* _nx_secure_tls_proc_clienthello_ec_groups_extension */
85 /* Process ClientHello */
86 /* EC groups extension */
87 /* _nx_secure_tls_proc_clienthello_ec_point_formats_extension */
88 /* Process ClientHello */
89 /* EC point formats extension */
90 /* */
91 /* CALLED BY */
92 /* */
93 /* _nx_secure_tls_process_clienthello Process ClientHello */
94 /* */
95 /* RELEASE HISTORY */
96 /* */
97 /* DATE NAME DESCRIPTION */
98 /* */
99 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
100 /* 09-30-2020 Timothy Stapko Modified comment(s), */
101 /* fixed renegotiation bug, */
102 /* resulting in version 6.1 */
103 /* 10-15-2021 Timothy Stapko Modified comment(s), added */
104 /* ability to disable client */
105 /* initiated renegotiation, */
106 /* resulting in version 6.1.9 */
107 /* */
108 /**************************************************************************/
_nx_secure_tls_process_clienthello_extensions(NX_SECURE_TLS_SESSION * tls_session,UCHAR * packet_buffer,UINT message_length,NX_SECURE_TLS_HELLO_EXTENSION * extensions,UINT * num_extensions,UCHAR * client_hello_buffer,UINT client_hello_length)109 UINT _nx_secure_tls_process_clienthello_extensions(NX_SECURE_TLS_SESSION *tls_session,
110 UCHAR *packet_buffer, UINT message_length,
111 NX_SECURE_TLS_HELLO_EXTENSION *extensions,
112 UINT *num_extensions, UCHAR *client_hello_buffer, UINT client_hello_length)
113 {
114 UINT status = NX_SUCCESS;
115 UINT offset;
116 UINT max_extensions;
117 USHORT extension_id;
118 UINT extension_length;
119 #if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED)
120 USHORT supported_version = tls_session -> nx_secure_tls_protocol_version;
121 #endif
122
123 #if defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION) || defined(NX_SECURE_TLS_DISABLE_CLIENT_INITIATED_RENEGOTIATION)
124 NX_PARAMETER_NOT_USED(tls_session);
125 #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */
126
127 #if !(NX_SECURE_TLS_TLS_1_3_ENABLED) || !defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES)
128 NX_PARAMETER_NOT_USED(client_hello_buffer);
129 NX_PARAMETER_NOT_USED(client_hello_length);
130 #endif
131
132 max_extensions = *num_extensions;
133 offset = 0;
134 *num_extensions = 0;
135
136 /* Process extensions until we run out. */
137 while (offset < message_length && *num_extensions < max_extensions)
138 {
139
140 /* Make sure there are at least 4 bytes available so we can read extension_id and
141 extension_length. */
142 if((offset + 4) > message_length)
143 {
144 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
145 }
146
147 /* See what the extension is. */
148 extension_id = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
149 offset += 2;
150
151 /* Get extension length. */
152 extension_length = (UINT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
153 offset += 2;
154
155 /* Verify the message_length is at least "extension_length". */
156 if((offset + extension_length) > message_length)
157 {
158 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
159 }
160
161 /* Parse the extension. */
162 switch (extension_id)
163 {
164 #if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION)
165 case NX_SECURE_TLS_EXTENSION_SECURE_RENEGOTIATION:
166 status = _nx_secure_tls_proc_clienthello_sec_reneg_extension(tls_session,
167 &packet_buffer[offset],
168 extension_length);
169
170 if (status)
171 {
172 return(status);
173 }
174 break;
175 #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */
176
177 #if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED)
178 case NX_SECURE_TLS_EXTENSION_KEY_SHARE:
179 if(tls_session -> nx_secure_tls_1_3)
180 {
181 /* If TLS 1.3, process the key share extension. */
182 status = _nx_secure_tls_proc_clienthello_keyshare_extension(tls_session,
183 &packet_buffer[offset],
184 (USHORT)extension_length);
185
186 if (status)
187 {
188 return(status);
189 }
190 }
191 /* TLS 1.2 and earlier: ignore extension. */
192 break;
193 case NX_SECURE_TLS_EXTENSION_SUPPORTED_VERSIONS:
194 if(tls_session -> nx_secure_tls_1_3)
195 {
196
197 /* Process the TLS 1.3 supported_versions extension. */
198 status = _nx_secure_tls_proc_clienthello_supported_versions_extension(tls_session,
199 &packet_buffer[offset],
200 &supported_version,
201 (USHORT)extension_length);
202
203 if (status)
204 {
205 return(status);
206 }
207 }
208
209 /* Ignore if not TLS 1.3. */
210 break;
211 #ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
212 case NX_SECURE_TLS_EXTENSION_PRE_SHARED_KEY:
213 if(tls_session -> nx_secure_tls_1_3)
214 {
215
216 /* Process the TLS 1.3 PSK extension. */
217 status = _nx_secure_tls_process_clienthello_psk_extension(tls_session, &packet_buffer[offset],
218 (USHORT)extension_length, client_hello_buffer, client_hello_length);
219
220 if (status)
221 {
222 return(status);
223 }
224 }
225 break;
226 #endif
227 #endif
228
229 case NX_SECURE_TLS_EXTENSION_SIGNATURE_ALGORITHMS:
230 case NX_SECURE_TLS_EXTENSION_SERVER_NAME_INDICATION:
231 case NX_SECURE_TLS_EXTENSION_MAX_FRAGMENT_LENGTH:
232 case NX_SECURE_TLS_EXTENSION_CLIENT_CERTIFICATE_URL:
233 case NX_SECURE_TLS_EXTENSION_TRUSTED_CA_INDICATION:
234 case NX_SECURE_TLS_EXTENSION_CERTIFICATE_STATUS_REQUEST:
235 case NX_SECURE_TLS_EXTENSION_EC_GROUPS:
236 case NX_SECURE_TLS_EXTENSION_EC_POINT_FORMATS:
237 case NX_SECURE_TLS_EXTENSION_ECJPAKE_KEY_KP_PAIR:
238 /* These extensions require information to be passed to the application. Save off
239 the extension data in our extensions array to pass along in the hello callback. */
240 extensions[*num_extensions].nx_secure_tls_extension_id = extension_id;
241 extensions[*num_extensions].nx_secure_tls_extension_data = &packet_buffer[offset];
242 extensions[*num_extensions].nx_secure_tls_extension_data_length = (USHORT)extension_length;
243
244 /* Added another extension to the array. */
245 *num_extensions = *num_extensions + 1;
246
247 break;
248 case NX_SECURE_TLS_EXTENSION_TRUNCATED_HMAC:
249 default:
250 /* Unknown or unsupported extension, just ignore - TLS supports multiple extensions and the default
251 behavior is to ignore any extensions that we don't know. */
252 break;
253 }
254
255 /* Adjust our offset with the length of the extension we just parsed. */
256 offset += extension_length;
257 }
258
259 #if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED)
260 if((tls_session -> nx_secure_tls_1_3) && (supported_version != NX_SECURE_TLS_VERSION_TLS_1_3))
261 {
262
263 /* Negotiate a version of TLS prior to TLS 1.3. */
264 if (tls_session -> nx_secure_tls_protocol_version_override == 0)
265 {
266 tls_session -> nx_secure_tls_1_3 = NX_FALSE;
267 #if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION)
268 tls_session -> nx_secure_tls_renegotation_enabled = NX_TRUE;
269 #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */
270 tls_session -> nx_secure_tls_protocol_version = supported_version;
271 }
272 else
273 {
274
275 /* Protocol version is overridden to TLS 1.3. */
276 return(NX_SECURE_TLS_UNSUPPORTED_TLS_VERSION);
277 }
278 }
279 #endif
280
281 return(status);
282 }
283
284
285
286 /**************************************************************************/
287 /* */
288 /* FUNCTION RELEASE */
289 /* */
290 /* _nx_secure_tls_proc_clienthello_sec_reneg_extension PORTABLE C */
291 /* 6.1.9 */
292 /* AUTHOR */
293 /* */
294 /* Timothy Stapko, Microsoft Corporation */
295 /* */
296 /* DESCRIPTION */
297 /* */
298 /* This function parses the Secure Renegotiation Indication extension */
299 /* from an incoming ClientHello record.See RFC 5746 for more */
300 /* information. */
301 /* */
302 /* INPUT */
303 /* */
304 /* tls_session TLS control block */
305 /* packet_buffer Outgoing TLS packet buffer */
306 /* extension_length Length of extension data */
307 /* */
308 /* OUTPUT */
309 /* */
310 /* status Completion status */
311 /* */
312 /* CALLS */
313 /* */
314 /* None */
315 /* */
316 /* CALLED BY */
317 /* */
318 /* _nx_secure_tls_process_clienthello_extensions */
319 /* Process ClientHello extensions*/
320 /* */
321 /* RELEASE HISTORY */
322 /* */
323 /* DATE NAME DESCRIPTION */
324 /* */
325 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
326 /* 09-30-2020 Timothy Stapko Modified comment(s), */
327 /* fixed renegotiation bug, */
328 /* resulting in version 6.1 */
329 /* 10-15-2021 Timothy Stapko Modified comment(s), added */
330 /* ability to disable client */
331 /* initiated renegotiation, */
332 /* resulting in version 6.1.9 */
333 /* */
334 /**************************************************************************/
335 #if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION)
_nx_secure_tls_proc_clienthello_sec_reneg_extension(NX_SECURE_TLS_SESSION * tls_session,UCHAR * packet_buffer,UINT extension_length)336 static UINT _nx_secure_tls_proc_clienthello_sec_reneg_extension(NX_SECURE_TLS_SESSION *tls_session,
337 UCHAR *packet_buffer,
338 UINT extension_length)
339 {
340 ULONG offset = 0;
341 UCHAR renegotiated_connection_length;
342 INT compare_value;
343
344 /* Secure Renegotiation Indication Extensions structure:
345 * Initial ClientHello:
346 * | 2 | 2 | 1 |
347 * | Ext Type | Ext Len | Reneg Info Len |
348 * | 0xff01 | 0x0001 | 0x00 |
349 *
350 * Renegotiating ClientHello:
351 * | 2 | 2 | 1 | 12 |
352 * | Ext Type | Ext Len | Reneg Info Len | client_verify_data |
353 * | 0xff01 | 0x000d | 0x0c | |
354 */
355 /* From RFC 5746:
356 struct {
357 opaque renegotiated_connection<0..255>;
358 } RenegotiationInfo;
359
360 The contents of this extension are specified as follows.
361
362 - If this is the initial handshake for a connection, then the
363 "renegotiated_connection" field is of zero length in both the
364 ClientHello and the ServerHello. Thus, the entire encoding of the
365 extension is ff 01 00 01 00. The first two octets represent the
366 extension type, the third and fourth octets the length of the
367 extension itself, and the final octet the zero length byte for the
368 "renegotiated_connection" field.
369
370 - For ClientHellos that are renegotiating, this field contains the
371 "client_verify_data" specified in Section 3.1.
372
373 - For ServerHellos that are renegotiating, this field contains the
374 concatenation of client_verify_data and server_verify_data. For
375 current versions of TLS, this will be a 24-byte value (for SSLv3,
376 it will be a 72-byte value).
377 */
378
379 if (extension_length < 1)
380 {
381 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
382 }
383
384 /* Get the "renegotiated_connection" field. */
385 renegotiated_connection_length = packet_buffer[offset];
386 offset++;
387
388 if (offset + renegotiated_connection_length > extension_length)
389 {
390 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
391 }
392
393 /* See if the client is attempting to renegotiate an established connection. */
394 if (renegotiated_connection_length)
395 {
396 /* The remote host is attempting a renegotiation - make sure our local session is active and renegotiation is OK. */
397 if (!tls_session -> nx_secure_tls_local_session_active || !tls_session -> nx_secure_tls_remote_session_active)
398 {
399 /* Remote host is attempting a renegotiation but the server is not currently in a session! */
400 return(NX_SECURE_TLS_RENEGOTIATION_SESSION_INACTIVE);
401 }
402
403 if(!tls_session -> nx_secure_tls_secure_renegotiation)
404 {
405 return(NX_SECURE_TLS_RENEGOTIATION_FAILURE);
406 }
407
408 if (renegotiated_connection_length != NX_SECURE_TLS_FINISHED_HASH_SIZE)
409 {
410 /* Do not have the right amount of data for comparison. */
411 return(NX_SECURE_TLS_RENEGOTIATION_EXTENSION_ERROR);
412 }
413
414 /* Compare the received verify data to our locally-stored version. */
415 compare_value = NX_SECURE_MEMCMP(&packet_buffer[offset], tls_session -> nx_secure_tls_remote_verify_data, NX_SECURE_TLS_FINISHED_HASH_SIZE);
416
417 if (compare_value)
418 {
419 /* Session verify data did not match what we expect - error. */
420 return(NX_SECURE_TLS_RENEGOTIATION_EXTENSION_ERROR);
421 }
422
423 tls_session -> nx_secure_tls_secure_renegotiation_verified = NX_TRUE;
424 }
425 else
426 {
427 /* Verify that the extension contains only the initial handshake data - this is a new connection. */
428 if ((extension_length != 1) || (tls_session -> nx_secure_tls_local_session_active))
429 {
430 /* Error - the provided extension length was not expected for an initial handshake. */
431 return(NX_SECURE_TLS_RENEGOTIATION_EXTENSION_ERROR);
432 }
433
434 /* The remote host supports renegotiation. */
435 tls_session -> nx_secure_tls_secure_renegotiation = NX_TRUE;
436 }
437
438 return(NX_SUCCESS);
439 }
440 #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */
441
442 /**************************************************************************/
443 /* */
444 /* FUNCTION RELEASE */
445 /* */
446 /* _nx_secure_tls_proc_clienthello_sec_sa_extension PORTABLE C */
447 /* 6.2.1 */
448 /* AUTHOR */
449 /* */
450 /* Timothy Stapko, Microsoft Corporation */
451 /* */
452 /* DESCRIPTION */
453 /* */
454 /* This function processes the supported groups extensions included in */
455 /* an incoming ClientHello message from a remote host. */
456 /* */
457 /* INPUT */
458 /* */
459 /* tls_session TLS control block */
460 /* exts Parsed extensions */
461 /* num_extensions Number of extensions */
462 /* selected_curve Output selected ECDHE curve */
463 /* cert_curve Named curve of local cert */
464 /* cert_curve_supported Output whether curve used by */
465 /* local cert is supported */
466 /* ecdhe_signature_algorithm Output signature algorithm */
467 /* for ECDHE key exchange */
468 /* */
469 /* OUTPUT */
470 /* */
471 /* status Completion status */
472 /* */
473 /* CALLS */
474 /* */
475 /* _nx_secure_tls_find_curve_method Find named curve used by cert */
476 /* */
477 /* CALLED BY */
478 /* */
479 /* _nx_secure_tls_process_clienthello Process ClientHello */
480 /* */
481 /* RELEASE HISTORY */
482 /* */
483 /* DATE NAME DESCRIPTION */
484 /* */
485 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
486 /* 09-30-2020 Timothy Stapko Modified comment(s), added */
487 /* curve priority logic, */
488 /* resulting in version 6.1 */
489 /* 10-15-2021 Timothy Stapko Modified comment(s), fixed */
490 /* compilation issue with */
491 /* TLS 1.3 and disabling TLS */
492 /* server, */
493 /* resulting in version 6.1.9 */
494 /* 10-31-2022 Yanwu Cai Modified comment(s), */
495 /* updated parameters list, */
496 /* resulting in version 6.2.0 */
497 /* 03-08-2023 Yanwu Cai Modified comment(s), */
498 /* fixed compiler errors when */
499 /* x509 is disabled, */
500 /* resulting in version 6.2.1 */
501 /* */
502 /**************************************************************************/
503 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
_nx_secure_tls_proc_clienthello_sec_sa_extension(NX_SECURE_TLS_SESSION * tls_session,NX_SECURE_TLS_HELLO_EXTENSION * exts,UINT num_extensions,UINT * selected_curve,USHORT cert_curve,UINT * cert_curve_supported,USHORT * ecdhe_signature_algorithm,NX_SECURE_X509_CERT * cert)504 UINT _nx_secure_tls_proc_clienthello_sec_sa_extension(NX_SECURE_TLS_SESSION *tls_session,
505 NX_SECURE_TLS_HELLO_EXTENSION *exts,
506 UINT num_extensions,
507 UINT *selected_curve, USHORT cert_curve,
508 UINT *cert_curve_supported,
509 USHORT *ecdhe_signature_algorithm,
510 NX_SECURE_X509_CERT *cert)
511 {
512 UINT status = NX_SUCCESS;
513 UINT i, j, k;
514 const UCHAR *groups;
515 USHORT group;
516 USHORT groups_len;
517 const NX_CRYPTO_METHOD *curve_method;
518 UINT curve_priority;
519 UINT new_curve_priority = 0;
520 #if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED)
521 NX_SECURE_TLS_ECC *ecc_info;
522 UINT signature_algorithm_exist = NX_FALSE;
523 #endif
524 const UCHAR *signature_algorithms;
525 USHORT signature_algorithms_len;
526 USHORT signature_algorithm;
527 USHORT signature_algorithm_id;
528 UCHAR expected_signature = 0;
529
530
531 /* Select SHA256 as the signature hash. */
532 *ecdhe_signature_algorithm = NX_SECURE_TLS_SIGNATURE_RSA_SHA256;
533
534
535 *cert_curve_supported = NX_FALSE;
536 *selected_curve = 0;
537
538 if (cert_curve)
539 {
540 status = _nx_secure_tls_find_curve_method(&tls_session -> nx_secure_tls_ecc, cert_curve, &curve_method, NX_NULL);
541 if (status == NX_SUCCESS && curve_method != NX_NULL)
542 {
543 *cert_curve_supported = NX_TRUE;
544 }
545 }
546
547 if (cert != NX_NULL)
548 {
549 if (cert -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_EC)
550 {
551 expected_signature = NX_SECURE_TLS_SIGNATURE_ALGORITHM_ECDSA;
552 }
553 else if (cert -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_RSA)
554 {
555 expected_signature = NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA;
556 }
557
558 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
559 if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
560 tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)
561 {
562 *ecdhe_signature_algorithm = (USHORT)((NX_SECURE_TLS_HASH_ALGORITHM_SHA1 << 8) | (expected_signature & 0xFF));
563 }
564 #endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */
565 }
566
567 for (i = 0; i < num_extensions; i++)
568 {
569 switch (exts[i].nx_secure_tls_extension_id)
570 {
571 case NX_SECURE_TLS_EXTENSION_EC_GROUPS:
572 groups = exts[i].nx_secure_tls_extension_data;
573 groups_len = exts[i].nx_secure_tls_extension_data_length;
574
575 /* Set our start priority to the size of our supported curves list (lowest priority). */
576 curve_priority = tls_session -> nx_secure_tls_ecc.nx_secure_tls_ecc_supported_groups_count;
577
578 /* Loop through curves sent by client. */
579 for (j = 0; j < groups_len; j += 2)
580 {
581 group = (USHORT)((groups[j] << 8) + groups[j + 1]);
582
583 status = _nx_secure_tls_find_curve_method(&tls_session -> nx_secure_tls_ecc, group, &curve_method, &new_curve_priority);
584
585 if ((status == NX_CRYTPO_MISSING_ECC_CURVE) || (new_curve_priority > curve_priority))
586 {
587
588 /* Keep searching list. */
589 continue;
590 }
591
592 /* Found a higher-priority curve. */
593 if (status == NX_SUCCESS)
594 {
595 /* Found shared named curve. */
596 *selected_curve = group;
597 curve_priority = new_curve_priority;
598
599 #if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED)
600 if (tls_session -> nx_secure_tls_1_3 &&
601 (tls_session -> nx_secure_tls_server_state == NX_SECURE_TLS_SERVER_STATE_SEND_HELLO_RETRY))
602 {
603
604 /* Get our session ECC data. */
605 ecc_info = &(tls_session -> nx_secure_tls_ecc);
606
607 /* Loop through all supported ECC curves in this session. */
608 for (k = 0; k < ecc_info -> nx_secure_tls_ecc_supported_groups_count; k++)
609 {
610 /* Find the matching group in the keys we generated and saved. */
611 if(group == tls_session -> nx_secure_tls_key_material.nx_secure_tls_ecc_key_data[k].nx_secure_tls_ecdhe_named_curve)
612 {
613
614 /* Store selected ECDHE key data index. */
615 tls_session -> nx_secure_tls_key_material.nx_secure_tls_ecc_key_data_selected = k;
616
617 }
618 }
619 }
620 #endif
621 }
622 else
623 {
624
625 /* status is not NX_CRYTPO_MISSING_ECC_CURVE or NX_SUCCESS, return error. */
626 return(status);
627 }
628 /* Continue searching our supported curves list until we find the highest-priority curve. */
629 }
630
631 /* Reset status as we do not return NX_CRYTPO_MISSING_ECC_CURVE. */
632 status = NX_SUCCESS;
633 break;
634
635 case NX_SECURE_TLS_EXTENSION_SIGNATURE_ALGORITHMS:
636 /* This extension is not meaningful for TLS versions prior to 1.2. */
637 #if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED)
638 if (tls_session -> nx_secure_tls_1_3)
639 {
640 _nx_secure_tls_proc_clienthello_signature_algorithms_extension(tls_session,
641 exts[i].nx_secure_tls_extension_data,
642 exts[i].nx_secure_tls_extension_data_length);
643 signature_algorithm_exist = NX_TRUE;
644 }
645 else
646 #endif
647 #if (NX_SECURE_TLS_TLS_1_2_ENABLED)
648 if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2)
649 {
650
651 signature_algorithms = exts[i].nx_secure_tls_extension_data;
652 signature_algorithms_len = (USHORT)exts[i].nx_secure_tls_extension_data_length;
653
654 if (signature_algorithms_len < 2 || (((signature_algorithms[0] << 8) + signature_algorithms[1]) != (signature_algorithms_len - 2)))
655 {
656 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
657 }
658
659 /* Loop the signature algorithms in the extension. */
660 for (j = 2; j < signature_algorithms_len; j += 2)
661 {
662 if (signature_algorithms[j + 1] != expected_signature)
663 {
664 continue;
665 }
666
667 signature_algorithm = (USHORT)((signature_algorithms[j] << 8) + signature_algorithms[j + 1]);
668
669 /* Map signature algorithm to internal ID. */
670 _nx_secure_tls_get_signature_algorithm_id((UINT)signature_algorithm, &signature_algorithm_id);
671
672 if (signature_algorithm_id == NX_SECURE_TLS_X509_TYPE_UNKNOWN)
673 {
674 continue;
675 }
676
677 /* Check if this signature algorithm is supported. */
678 for (k = 0; k < tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_x509_cipher_table_size; k++)
679 {
680 if (signature_algorithm_id == tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_x509_cipher_table[k].nx_secure_x509_crypto_identifier)
681 {
682 *ecdhe_signature_algorithm = signature_algorithm;
683 break;
684 }
685 }
686
687 /* Signature algorithm is selected. */
688 if (*ecdhe_signature_algorithm == signature_algorithm)
689 {
690 break;
691 }
692 }
693 }
694 #endif
695 break;
696 }
697 }
698
699 #if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED)
700 /* RFC8446 4.2.3: If a server is authenticating via a certificate and
701 the client has not sent a "signature_algorithms" extension,
702 then the server MUST abort the handshake with a "missing_extension" alert. */
703 if ((cert != NX_NULL) && (tls_session -> nx_secure_tls_1_3))
704 {
705 if (signature_algorithm_exist == NX_FALSE)
706 {
707 return(NX_SECURE_TLS_MISSING_EXTENSION);
708 }
709
710 if (tls_session -> nx_secure_tls_signature_algorithm == 0)
711 {
712 return(NX_SECURE_TLS_UNKNOWN_CERT_SIG_ALGORITHM);
713 }
714 }
715 #endif
716
717 return(status);
718 }
719 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE && !NX_SECURE_DISABLE_X509 */
720
721
722 /**************************************************************************/
723 /* */
724 /* FUNCTION RELEASE */
725 /* */
726 /* _nx_secure_tls_proc_clienthello_keyshare_extension PORTABLE C */
727 /* 6.2.0 */
728 /* AUTHOR */
729 /* */
730 /* Timothy Stapko, Microsoft Corporation */
731 /* */
732 /* DESCRIPTION */
733 /* */
734 /* This function parses the Key Share extension introduced in TLS 1.3. */
735 /* */
736 /* INPUT */
737 /* */
738 /* tls_session TLS control block */
739 /* packet_buffer Outgoing TLS packet buffer */
740 /* extension_length Length of extension data */
741 /* */
742 /* OUTPUT */
743 /* */
744 /* status Completion status */
745 /* */
746 /* CALLS */
747 /* */
748 /* None */
749 /* */
750 /* CALLED BY */
751 /* */
752 /* _nx_secure_tls_process_serverhello_extensions */
753 /* Process ServerHello extensions*/
754 /* */
755 /* RELEASE HISTORY */
756 /* */
757 /* DATE NAME DESCRIPTION */
758 /* */
759 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
760 /* 09-30-2020 Timothy Stapko Modified comment(s), */
761 /* resulting in version 6.1 */
762 /* 10-15-2021 Timothy Stapko Modified comment(s), fixed */
763 /* compilation issue with */
764 /* TLS 1.3 and disabling TLS */
765 /* server, */
766 /* resulting in version 6.1.9 */
767 /* 04-25-2022 Yuxin Zhou Modified comment(s), removed */
768 /* public key format checking, */
769 /* resulting in version 6.1.11 */
770 /* 10-31-2022 Yanwu Cai Modified comment(s), */
771 /* updated parameters list, */
772 /* resulting in version 6.2.0 */
773 /* */
774 /**************************************************************************/
775 #if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED)
776
777 extern NX_CRYPTO_METHOD crypto_method_ecdhe;
778
_nx_secure_tls_proc_clienthello_keyshare_extension(NX_SECURE_TLS_SESSION * tls_session,UCHAR * packet_buffer,USHORT extension_length)779 static UINT _nx_secure_tls_proc_clienthello_keyshare_extension(NX_SECURE_TLS_SESSION *tls_session,
780 UCHAR *packet_buffer,
781 USHORT extension_length)
782 {
783 UINT status;
784 UINT i;
785 USHORT offset;
786 USHORT key_share_length;
787 USHORT key_group;
788 USHORT key_length;
789 NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecc_key_data;
790 UCHAR *pubkey = NX_NULL;
791 UCHAR *private_key;
792 UINT private_key_length;
793 NX_CRYPTO_EXTENDED_OUTPUT extended_output;
794 NX_CRYPTO_METHOD *ecdhe_method;
795 const NX_CRYPTO_METHOD *curve_method;
796 VOID *handler = NX_NULL;
797 NX_SECURE_TLS_ECC *ecc_info;
798
799 /* Key Share Extension structure (for clienthello):
800 *
801 * ClientHello KeyShare:
802 * | <list length> |
803 * | 2 | 2 | <| 2 | 2 | <Key len> |> |
804 * | Ext Type | Extension length | <| Named Group | Key len | key_exchange data |> |
805
806 */
807
808 if (extension_length == 0)
809 {
810
811 /* The client_shares may be empty if the client is requesting a HelloRetryRequest. */
812 tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_SEND_HELLO_RETRY;
813 return(NX_SUCCESS);
814 }
815
816 offset = 0;
817
818 /* ecc_key_data will hold the key information from the chosen named curve. */
819 ecc_key_data = NX_NULL;
820
821 /* Get our session ECC data. */
822 ecc_info = &(tls_session -> nx_secure_tls_ecc);
823
824 if (extension_length < 2)
825 {
826 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
827 }
828
829 /* Get the key share length. */
830 key_share_length = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
831 offset = (USHORT)(offset + 2);
832
833 if(offset + key_share_length > extension_length)
834 {
835 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
836 }
837
838 /* Loop through the list of keys looking for a supported group. */
839 while(offset < extension_length && ecc_key_data == NX_NULL)
840 {
841 if (offset + 4 > extension_length)
842 {
843 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
844 }
845
846 /* Get the key group. */
847 key_group = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
848 offset = (USHORT)(offset + 2);
849
850 /* Get the key length. */
851 key_length = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
852 offset = (USHORT)(offset + 2);
853
854 if (offset + key_length > extension_length)
855 {
856 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
857 }
858
859 /* Check the key group. */
860 key_group = (USHORT)((ULONG)key_group | NX_CRYPTO_EC_MASK);
861
862 /* Loop through all supported ECC curves in this session - see if we support the current group. */
863 for (i = 0; i < ecc_info -> nx_secure_tls_ecc_supported_groups_count; i++)
864 {
865 /* Find the matching group in the keys we generated and saved. */
866 if(key_group == tls_session -> nx_secure_tls_key_material.nx_secure_tls_ecc_key_data[i].nx_secure_tls_ecdhe_named_curve)
867 {
868 /* Got a matching key/curve combo, get a pointer to the selected key data. */
869 ecc_key_data = &tls_session -> nx_secure_tls_key_material.nx_secure_tls_ecc_key_data[i];
870
871 /* Extract the remote public key from our packet. */
872 pubkey = &packet_buffer[offset];
873
874 /* Store selected ECDHE key data index. */
875 tls_session -> nx_secure_tls_key_material.nx_secure_tls_ecc_key_data_selected = i;
876
877 break;
878 }
879 }
880
881 /* Advance past the key data. */
882 offset = (USHORT)(offset + key_length);
883 }
884
885 /* If we didn't find a matching curve, return error. */
886 if(ecc_key_data == NX_NULL || offset > extension_length)
887 {
888 tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_SEND_HELLO_RETRY;
889 return(NX_SUCCESS);
890 }
891
892 /* Get the curve method to initialize the remote public key data. */
893 _nx_secure_tls_find_curve_method(&tls_session -> nx_secure_tls_ecc, key_group, &curve_method, NX_NULL);
894
895 if (curve_method == NX_NULL)
896 {
897 return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
898 }
899
900 /* Get the ECDHE method we are going to use. */
901 ecdhe_method = &crypto_method_ecdhe;
902
903 if (ecdhe_method -> nx_crypto_operation == NX_NULL )
904 {
905 return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
906 }
907
908 /* Initialize the ECDHE method. */
909 if (ecdhe_method -> nx_crypto_init != NX_NULL)
910 {
911 status = ecdhe_method -> nx_crypto_init(ecdhe_method,
912 NX_NULL,
913 0,
914 &handler,
915 tls_session -> nx_secure_public_cipher_metadata_area,
916 tls_session -> nx_secure_public_cipher_metadata_size);
917
918 if (status != NX_CRYPTO_SUCCESS)
919 {
920 return(status);
921 }
922 }
923
924 /* Set the curve we want to use. */
925 status = ecdhe_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler,
926 ecdhe_method, NX_NULL, 0,
927 (UCHAR *)curve_method, sizeof(NX_CRYPTO_METHOD *), NX_NULL,
928 NX_NULL, 0,
929 tls_session -> nx_secure_public_cipher_metadata_area,
930 tls_session -> nx_secure_public_cipher_metadata_size,
931 NX_NULL, NX_NULL);
932 if (status != NX_CRYPTO_SUCCESS)
933 {
934 return(status);
935 }
936
937 /* Import the private key to the ECDH context. */
938 private_key = &ecc_key_data -> nx_secure_tls_ecdhe_private_key[0];
939 private_key_length = ecc_key_data -> nx_secure_tls_ecdhe_private_key_length;
940
941 status = ecdhe_method -> nx_crypto_operation(NX_CRYPTO_DH_KEY_PAIR_IMPORT, handler,
942 (NX_CRYPTO_METHOD*)ecdhe_method,
943 private_key, private_key_length << 3,
944 NX_NULL, 0, NX_NULL,
945 NX_NULL,
946 0,
947 tls_session -> nx_secure_public_cipher_metadata_area,
948 tls_session -> nx_secure_public_cipher_metadata_size,
949 NX_NULL, NX_NULL);
950
951
952 if (status != NX_CRYPTO_SUCCESS)
953 {
954 return(status);
955 }
956
957 //tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data[0] = (UCHAR)extended_output.nx_crypto_extended_output_actual_size;
958
959 /* Calculate the final pre_master_secret - the "private key" here is the Pre-Master Secret. */
960 extended_output.nx_crypto_extended_output_data = tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret;
961 extended_output.nx_crypto_extended_output_length_in_byte = sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret);
962 extended_output.nx_crypto_extended_output_actual_size = 0;
963 status = ecdhe_method -> nx_crypto_operation(NX_CRYPTO_DH_CALCULATE, handler,
964 ecdhe_method, NX_NULL, 0,
965 pubkey, key_length, NX_NULL,
966 (UCHAR *)&extended_output,
967 sizeof(extended_output),
968 tls_session -> nx_secure_public_cipher_metadata_area,
969 tls_session -> nx_secure_public_cipher_metadata_size,
970 NX_NULL, NX_NULL);
971 if (status != NX_CRYPTO_SUCCESS)
972 {
973 return(status);
974 }
975
976 tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size = extended_output.nx_crypto_extended_output_actual_size;
977
978 if (ecdhe_method -> nx_crypto_cleanup)
979 {
980 status = ecdhe_method -> nx_crypto_cleanup(tls_session -> nx_secure_public_cipher_metadata_area);
981 }
982
983 return(status);
984 }
985
986 /**************************************************************************/
987 /* */
988 /* FUNCTION RELEASE */
989 /* */
990 /* _nx_secure_tls_proc_clienthello_supported_versions_extension */
991 /* PORTABLE C */
992 /* 6.1 */
993 /* AUTHOR */
994 /* */
995 /* Timothy Stapko, Microsoft Corporation */
996 /* */
997 /* DESCRIPTION */
998 /* */
999 /* This function parses the supported versions extension introduced in */
1000 /* TLS 1.3. */
1001 /* */
1002 /* INPUT */
1003 /* */
1004 /* tls_session TLS control block */
1005 /* packet_buffer Outgoing TLS packet buffer */
1006 /* supported_version Supported version */
1007 /* extension_length Length of extension data */
1008 /* */
1009 /* OUTPUT */
1010 /* */
1011 /* status Completion status */
1012 /* */
1013 /* CALLS */
1014 /* */
1015 /* None */
1016 /* */
1017 /* CALLED BY */
1018 /* */
1019 /* _nx_secure_tls_process_clienthello_extensions */
1020 /* Process ClientHello extensions*/
1021 /* */
1022 /* RELEASE HISTORY */
1023 /* */
1024 /* DATE NAME DESCRIPTION */
1025 /* */
1026 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
1027 /* 09-30-2020 Timothy Stapko Modified comment(s), */
1028 /* resulting in version 6.1 */
1029 /* */
1030 /**************************************************************************/
_nx_secure_tls_proc_clienthello_supported_versions_extension(NX_SECURE_TLS_SESSION * tls_session,UCHAR * packet_buffer,USHORT * supported_version,USHORT extension_length)1031 static UINT _nx_secure_tls_proc_clienthello_supported_versions_extension(NX_SECURE_TLS_SESSION *tls_session,
1032 UCHAR *packet_buffer,
1033 USHORT *supported_version,
1034 USHORT extension_length)
1035 {
1036 UINT i;
1037 ULONG offset;
1038
1039 NX_PARAMETER_NOT_USED(tls_session);
1040
1041 /* Supported Versions Extension structure (for clienthello):
1042 *
1043 * ClientHello:
1044 * | 1 | <list length> |
1045 * | List Length | TLS Versions |
1046 */
1047
1048 offset = 0;
1049
1050 /* Extract the extension length. */
1051 if ((extension_length) < 1 || (packet_buffer[0] != (extension_length - 1)))
1052 {
1053
1054 /* Invalid Supported Versions Length. */
1055 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
1056 }
1057
1058 offset = 1;
1059
1060 /* Loop through all supported versions in this session. */
1061 for (i = 0; i < (UINT)(extension_length - 1); i += 2)
1062 {
1063
1064 /* Find the preferred protocol version. */
1065 *supported_version = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
1066 if (*supported_version == NX_SECURE_TLS_VERSION_TLS_1_3)
1067 {
1068 return(NX_SUCCESS);
1069 }
1070 else if (_nx_secure_tls_check_protocol_version(tls_session, *supported_version, NX_SECURE_TLS) == NX_SUCCESS)
1071 {
1072 return(NX_SUCCESS);
1073 }
1074 offset = (USHORT)(offset + 2);
1075 }
1076
1077 return(NX_SECURE_TLS_UNSUPPORTED_TLS_VERSION);
1078 }
1079
1080 /**************************************************************************/
1081 /* */
1082 /* FUNCTION RELEASE */
1083 /* */
1084 /* _nx_secure_tls_proc_clienthello_signature_algorithms_extension */
1085 /* PORTABLE C */
1086 /* 6.1.9 */
1087 /* AUTHOR */
1088 /* */
1089 /* Timothy Stapko, Microsoft Corporation */
1090 /* */
1091 /* DESCRIPTION */
1092 /* */
1093 /* This function parses the siganture algorithms extension introduced */
1094 /* in TLS 1.3. */
1095 /* */
1096 /* INPUT */
1097 /* */
1098 /* tls_session TLS control block */
1099 /* packet_buffer Outgoing TLS packet buffer */
1100 /* extension_length Length of extension data */
1101 /* */
1102 /* OUTPUT */
1103 /* */
1104 /* None */
1105 /* */
1106 /* CALLS */
1107 /* */
1108 /* None */
1109 /* */
1110 /* CALLED BY */
1111 /* */
1112 /* _nx_secure_tls_process_clienthello_extensions */
1113 /* Process ClientHello extensions*/
1114 /* */
1115 /* RELEASE HISTORY */
1116 /* */
1117 /* DATE NAME DESCRIPTION */
1118 /* */
1119 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
1120 /* 09-30-2020 Timothy Stapko Modified comment(s), */
1121 /* resulting in version 6.1 */
1122 /* 10-15-2021 Timothy Stapko Modified comment(s), fixed */
1123 /* compilation issue with */
1124 /* TLS 1.3 and disabling TLS */
1125 /* server, */
1126 /* resulting in version 6.1.9 */
1127 /* */
1128 /**************************************************************************/
_nx_secure_tls_proc_clienthello_signature_algorithms_extension(NX_SECURE_TLS_SESSION * tls_session,const UCHAR * packet_buffer,USHORT extension_length)1129 static VOID _nx_secure_tls_proc_clienthello_signature_algorithms_extension(NX_SECURE_TLS_SESSION *tls_session,
1130 const UCHAR *packet_buffer,
1131 USHORT extension_length)
1132 {
1133 UINT i;
1134 USHORT offset;
1135 UINT status = 0;
1136 UINT expected_sign_alg = 0;
1137 UINT sign_alg = 0;
1138 NX_SECURE_X509_CERT *local_certificate = NX_NULL;
1139
1140
1141 /* Signature Algorithm Extension structure (for clienthello):
1142 *
1143 * ClientHello:
1144 * | 2 | <list length> |
1145 * | List Length | Signature Algorithems |
1146 */
1147
1148 tls_session -> nx_secure_tls_signature_algorithm = 0;
1149 offset = 0;
1150
1151 /* Extract the extension length. */
1152 if ((extension_length < 2) || (((packet_buffer[0] << 8) + packet_buffer[1]) != (extension_length - 2)))
1153 {
1154
1155 /* Invalid Supported Versions Length. */
1156 return;
1157 }
1158
1159 offset = 2;
1160
1161 /* Get the local certificate. */
1162 if (tls_session -> nx_secure_tls_credentials.nx_secure_tls_active_certificate != NX_NULL)
1163 {
1164 local_certificate = tls_session -> nx_secure_tls_credentials.nx_secure_tls_active_certificate;
1165 }
1166 else
1167 {
1168 /* Get reference to local device certificate. NX_NULL is passed for name to get default entry. */
1169 status = _nx_secure_x509_local_device_certificate_get(&tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store,
1170 NX_NULL, &local_certificate);
1171 if (status != NX_SUCCESS)
1172 {
1173 local_certificate = NX_NULL;
1174 }
1175 }
1176
1177 if (local_certificate != NX_NULL)
1178 {
1179 if (local_certificate -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_RSA)
1180 {
1181 return;
1182 }
1183 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
1184 else if (local_certificate -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_EC)
1185 {
1186
1187 switch (local_certificate -> nx_secure_x509_private_key.ec_private_key.nx_secure_ec_named_curve)
1188 {
1189 case NX_CRYPTO_EC_SECP256R1:
1190 expected_sign_alg = NX_SECURE_TLS_SIGNATURE_ECDSA_SHA256;
1191 break;
1192 case NX_CRYPTO_EC_SECP384R1:
1193 expected_sign_alg = NX_SECURE_TLS_SIGNATURE_ECDSA_SHA384;
1194 break;
1195 case NX_CRYPTO_EC_SECP521R1:
1196 expected_sign_alg = NX_SECURE_TLS_SIGNATURE_ECDSA_SHA512;
1197 break;
1198 default:
1199 return;
1200 }
1201 }
1202 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
1203 }
1204
1205 /* Loop through all supported versions in this session. */
1206 for (i = 0; i < (UINT)(extension_length - 2); i += 2)
1207 {
1208
1209 /* Find the expected signature algorithm. */
1210 sign_alg = (UINT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
1211
1212 if (sign_alg == expected_sign_alg)
1213 {
1214 break;
1215 }
1216
1217 offset = (USHORT)(offset + 2);
1218 }
1219
1220 /* Make sure we are using the right signature algorithm! */
1221 if (sign_alg != expected_sign_alg)
1222 {
1223 return;
1224 }
1225
1226 tls_session -> nx_secure_tls_signature_algorithm = sign_alg;
1227 }
1228 #endif /* NX_SECURE_TLS_TLS_1_3_ENABLED */
1229
1230 /**************************************************************************/
1231 /* */
1232 /* FUNCTION RELEASE */
1233 /* */
1234 /* _nx_secure_tls_get_signature_algorithm_id PORTABLE C */
1235 /* 6.1 */
1236 /* AUTHOR */
1237 /* */
1238 /* Timothy Stapko, Microsoft Corporation */
1239 /* */
1240 /* DESCRIPTION */
1241 /* */
1242 /* Get internal x509 ID of signature algorithm. */
1243 /* */
1244 /* INPUT */
1245 /* */
1246 /* signature_algorithm Signature algorithm */
1247 /* signature_algorithm_id Internal ID */
1248 /* */
1249 /* OUTPUT */
1250 /* */
1251 /* None */
1252 /* */
1253 /* CALLS */
1254 /* */
1255 /* */
1256 /* CALLED BY */
1257 /* */
1258 /* */
1259 /* */
1260 /* RELEASE HISTORY */
1261 /* */
1262 /* DATE NAME DESCRIPTION */
1263 /* */
1264 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
1265 /* 09-30-2020 Timothy Stapko Modified comment(s), */
1266 /* resulting in version 6.1 */
1267 /* */
1268 /**************************************************************************/
_nx_secure_tls_get_signature_algorithm_id(UINT signature_algorithm,USHORT * signature_algorithm_id)1269 VOID _nx_secure_tls_get_signature_algorithm_id(UINT signature_algorithm, USHORT *signature_algorithm_id)
1270 {
1271
1272 *signature_algorithm_id = NX_SECURE_TLS_X509_TYPE_UNKNOWN;
1273
1274 switch (signature_algorithm)
1275 {
1276 case NX_SECURE_TLS_SIGNATURE_RSA_MD5:
1277 *signature_algorithm_id = NX_SECURE_TLS_X509_TYPE_RSA_MD5;
1278 break;
1279 case NX_SECURE_TLS_SIGNATURE_RSA_SHA1:
1280 *signature_algorithm_id = NX_SECURE_TLS_X509_TYPE_RSA_SHA_1;
1281 break;
1282 case NX_SECURE_TLS_SIGNATURE_RSA_SHA256:
1283 *signature_algorithm_id = NX_SECURE_TLS_X509_TYPE_RSA_SHA_256;
1284 break;
1285 case NX_SECURE_TLS_SIGNATURE_RSA_SHA384:
1286 *signature_algorithm_id = NX_SECURE_TLS_X509_TYPE_RSA_SHA_384;
1287 break;
1288 case NX_SECURE_TLS_SIGNATURE_RSA_SHA512:
1289 *signature_algorithm_id = NX_SECURE_TLS_X509_TYPE_RSA_SHA_512;
1290 break;
1291 case NX_SECURE_TLS_SIGNATURE_ECDSA_SHA1:
1292 *signature_algorithm_id = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_1;
1293 break;
1294 case NX_SECURE_TLS_SIGNATURE_ECDSA_SHA224:
1295 *signature_algorithm_id = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_224;
1296 break;
1297 case NX_SECURE_TLS_SIGNATURE_ECDSA_SHA256:
1298 *signature_algorithm_id = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_256;
1299 break;
1300 case NX_SECURE_TLS_SIGNATURE_ECDSA_SHA384:
1301 *signature_algorithm_id = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_384;
1302 break;
1303 case NX_SECURE_TLS_SIGNATURE_ECDSA_SHA512:
1304 *signature_algorithm_id = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_512;
1305 break;
1306 default:
1307 return;
1308 }
1309 }
1310
1311
1312 /**************************************************************************/
1313 /* */
1314 /* FUNCTION RELEASE */
1315 /* */
1316 /* _nx_secure_tls_process_clienthello_psk_extension PORTABLE C */
1317 /* 6.1.8 */
1318 /* AUTHOR */
1319 /* */
1320 /* Timothy Stapko, Microsoft Corporation */
1321 /* */
1322 /* DESCRIPTION */
1323 /* */
1324 /* Process an incoming TLS 1.3 PSK extension from a TLS Client. */
1325 /* */
1326 /* INPUT */
1327 /* */
1328 /* tls_session TLS control block */
1329 /* packet_buffer Incoming packet data */
1330 /* extension_length Length of PSK extension */
1331 /* */
1332 /* OUTPUT */
1333 /* */
1334 /* None */
1335 /* */
1336 /* CALLS */
1337 /* */
1338 /* */
1339 /* CALLED BY */
1340 /* */
1341 /* */
1342 /* */
1343 /* RELEASE HISTORY */
1344 /* */
1345 /* DATE NAME DESCRIPTION */
1346 /* */
1347 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
1348 /* 09-30-2020 Timothy Stapko Modified comment(s), */
1349 /* verified memcpy use cases, */
1350 /* resulting in version 6.1 */
1351 /* 08-02-2021 Timothy Stapko Modified comment(s), added */
1352 /* hash clone and cleanup, */
1353 /* resulting in version 6.1.8 */
1354 /* */
1355 /**************************************************************************/
1356 #if (NX_SECURE_TLS_TLS_1_3_ENABLED) && defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES)
_nx_secure_tls_process_clienthello_psk_extension(NX_SECURE_TLS_SESSION * tls_session,const UCHAR * packet_buffer,USHORT extension_length,const UCHAR * client_hello_buffer,UINT client_hello_length)1357 static UINT _nx_secure_tls_process_clienthello_psk_extension(NX_SECURE_TLS_SESSION *tls_session, const UCHAR *packet_buffer,
1358 USHORT extension_length, const UCHAR *client_hello_buffer, UINT client_hello_length)
1359 {
1360 UINT list_length;
1361 UCHAR *psk_data = NX_NULL;
1362 UINT psk_length;
1363 UCHAR binder_len;
1364 UINT psk_index;
1365 UINT binder_index;
1366 UINT psk_store_index = 0;
1367 ULONG offset;
1368 UINT id_len;
1369 const UCHAR *id;
1370 const UCHAR *binder;
1371 INT binder_total;
1372 UINT status;
1373 UINT age;
1374 UINT psk_found = NX_FALSE;
1375 UINT partial_hello_length;
1376
1377 NX_SECURE_TLS_PSK_STORE *psk_store;
1378
1379
1380 /* PSK Extension structure (From TLS 1.3 RFC 8446):
1381 struct {
1382 opaque identity<1..2^16-1>;
1383 uint32 obfuscated_ticket_age;
1384 } PskIdentity;
1385
1386 opaque PskBinderEntry<32..255>;
1387
1388 struct {
1389 PskIdentity identities<7..2^16-1>;
1390 PskBinderEntry binders<33..2^16-1>;
1391 } OfferedPsks;
1392
1393 struct {
1394 select (Handshake.msg_type) {
1395 case client_hello: OfferedPsks;
1396 case server_hello: uint16 selected_identity;
1397 };
1398 } PreSharedKeyExtension;
1399
1400 identity: A label for a key. For instance, a ticket (as defined in
1401 Appendix B.3.4) or a label for a pre-shared key established
1402 externally.
1403
1404 obfuscated_ticket_age: An obfuscated version of the age of the key.
1405 Section 4.2.11.1 describes how to form this value for identities
1406 established via the NewSessionTicket message. For identities
1407 established externally, an obfuscated_ticket_age of 0 SHOULD be
1408 used, and servers MUST ignore the value.
1409
1410 identities: A list of the identities that the client is willing to
1411 negotiate with the server. If sent alongside the "early_data"
1412 extension (see Section 4.2.10), the first identity is the one used
1413 for 0-RTT data.
1414
1415 binders: A series of HMAC values, one for each value in the
1416 identities list and in the same order, computed as described
1417 below.
1418
1419 selected_identity: The server's chosen identity expressed as a
1420 (0-based) index into the identities in the client's list.
1421
1422
1423 ClientHello PSK extension layout:
1424 | 2 | <ID list len> | 2 | <binders len> |
1425 | ID list len | <|<ID len> | ID | age |> | binders len | <len> | binder |
1426 */
1427
1428
1429 if (tls_session == NX_NULL)
1430 {
1431 return(NX_PTR_ERROR);
1432 }
1433
1434 offset = 0;
1435
1436 if (extension_length < 2)
1437 {
1438 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
1439 }
1440
1441 /* Get the length of the ID list. (Extension id and length already removed by caller). */
1442 list_length = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
1443 offset += 2;
1444
1445 /* Make sure the length is reasonable. */
1446 if(list_length > extension_length)
1447 {
1448 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
1449 }
1450
1451 /* Get our PSK store for easy access. */
1452 psk_store = tls_session -> nx_secure_tls_credentials.nx_secure_tls_psk_store;
1453 binder_total = 0;
1454 psk_index = 0;
1455
1456 /* Loop through all IDs. */
1457 while(list_length > 0)
1458 {
1459
1460 if (list_length < 2)
1461 {
1462 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
1463 }
1464
1465 /* Extract ID length. */
1466 id_len = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
1467 offset += 2;
1468
1469 if(offset + id_len > extension_length || list_length < 2 + id_len + 4)
1470 {
1471 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
1472 }
1473
1474 /* Reference to ID data. */
1475 id = &packet_buffer[offset];
1476 offset += id_len;
1477
1478 /* Extract the age field. */
1479 age = (UINT)((packet_buffer[offset] << 24) + (packet_buffer[offset + 1] << 16) +
1480 (packet_buffer[offset + 2] << 8) + packet_buffer[offset + 3]);
1481 offset += 4;
1482
1483 /* Only support external PSKs (no session resumption). */
1484 if(age != 0)
1485 {
1486 return(NX_SECURE_TLS_BAD_CLIENTHELLO_PSK_EXTENSION);
1487 }
1488
1489 /* Size of entry = 2 bytes id_len + <id_len> + 4 bytes age field. */
1490 list_length -= (2 + id_len + 4);
1491
1492 /* Check the ID list against our PSK store. */
1493 status = _nx_secure_tls_psk_identity_find(tls_session, &psk_data, &psk_length, (UCHAR*)id, id_len, &psk_store_index);
1494
1495 /* No match? Continue. */
1496 if(status == NX_SECURE_TLS_NO_MATCHING_PSK)
1497 {
1498 /* Advance our selected PSK index. */
1499 psk_index++;
1500
1501 continue;
1502 }
1503 else if(status != NX_SUCCESS)
1504 {
1505 return(status);
1506 }
1507
1508 /* At this point, we have a match - use this PSK if the age and binder check out.
1509 * Add the remaining list length to the offset to reach the binder list. */
1510 psk_found = NX_TRUE;
1511 offset += list_length;
1512 break;
1513 }
1514
1515 /* If we didn't find a match, return the error. */
1516 if(!psk_found)
1517 {
1518 return(NX_SECURE_TLS_NO_MATCHING_PSK);
1519 }
1520
1521 /* Now we can verify the age. */
1522
1523 if (extension_length < offset + 2)
1524 {
1525 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
1526 }
1527
1528 /* Extract the total binder list length. */
1529 binder_total = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
1530 offset += 2;
1531
1532 /* Make sure the length is reasonable. */
1533 if((UINT)binder_total + offset > extension_length)
1534 {
1535 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
1536 }
1537
1538 /* We need to subtract the binders from the ClientHello for our binder generation
1539 since the hash for the binder is generated from a partial ClientHello before
1540 the binders are generated. Include 2 bytes for the length field. */
1541 partial_hello_length = client_hello_length - ((UINT)binder_total + 2);
1542
1543 binder = NX_NULL;
1544 binder_index = 0;
1545
1546 /* Loop through the binders to get the binder for our selected PSK. */
1547 while(binder_total > 0)
1548 {
1549 /* Extract binder length. */
1550 binder_len = packet_buffer[offset];
1551 offset++;
1552
1553 if (1 + binder_len > binder_total)
1554 {
1555 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
1556 }
1557
1558 /* Subtract the binder length and field from the total. */
1559 binder_total--;
1560 binder_total -= binder_len;
1561
1562 /* Check our current binder index against the selected PSK index. */
1563 if(binder_index == psk_index)
1564 {
1565 /* Extract binder and exit loop. */
1566 binder = &packet_buffer[offset];
1567 break;
1568 }
1569
1570 /* Advance the binder index. */
1571 binder_index++;
1572 }
1573
1574 if(binder == NX_NULL)
1575 {
1576 /* Binder is missing! */
1577 return(NX_SECURE_TLS_BAD_CLIENTHELLO_PSK_EXTENSION);
1578 }
1579
1580 /* Check binder against locally-generated version. */
1581 /* If nx_secure_tls_psk_data_size is zero, it means this is ClientHello1, need to initialize the handshake hash.
1582 If not, it means this is ClientHello2, need to save the metadata(ClientHello1 and HelloRetryRequest) to sratch buffer. */
1583 if (tls_session -> nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_data_size == 0)
1584 {
1585
1586 /* Initialize the handshake hash to hash the ClientHello up to now. */
1587 _nx_secure_tls_handshake_hash_init(tls_session);
1588 }
1589 else
1590 {
1591
1592 /* Save the handshake hash state. */
1593 NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
1594 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
1595 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */
1596 }
1597
1598 /* Hash the ClientHello, adding the TLS record header. */
1599 UCHAR header[] = { 0x01, 0x00, 0x00, 0x00 };
1600 header[2] = (UCHAR)((client_hello_length) >> 8);
1601 header[3] = (UCHAR)((client_hello_length) & 0xFF);
1602 _nx_secure_tls_handshake_hash_update(tls_session, header, sizeof(header));
1603 _nx_secure_tls_handshake_hash_update(tls_session, (UCHAR*)client_hello_buffer, partial_hello_length);
1604
1605 /* Save the transcript hash for the ClientHello, which is used in generating the PSK binders. */
1606 status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_CLIENTHELLO, NX_FALSE);
1607 if (status != NX_SUCCESS)
1608 {
1609
1610 if (tls_session -> nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_data_size)
1611 {
1612 NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
1613 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size);
1614 }
1615
1616 return(status);
1617 }
1618
1619 /* Restore the original metadata(ClientHello1 and HelloRetryRequest) from scratch buffer. */
1620 if (tls_session -> nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_data_size)
1621 {
1622
1623 NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
1624 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size);
1625
1626 NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
1627 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
1628 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */
1629
1630 NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
1631 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size);
1632 }
1633
1634 /* Generate the binder for our selected PSK. */
1635 _nx_secure_tls_psk_binder_generate(tls_session, &psk_store[psk_store_index]);
1636
1637 /* Compare the generated binder to the received binder, using our generated length to avoid overflow
1638 from incoming length problems. */
1639 status = (UINT)NX_SECURE_MEMCMP(binder, psk_store[psk_store_index].nx_secure_tls_psk_binder, psk_store[psk_store_index].nx_secure_tls_psk_binder_size);
1640
1641 /* Make sure the generated binder matches the one sent by the client. */
1642 if((status != 0) || (binder_len != psk_store[psk_store_index].nx_secure_tls_psk_binder_size))
1643 {
1644 return(NX_SECURE_TLS_PSK_BINDER_MISMATCH);
1645 }
1646
1647 /* The PSK is too big to save in our internal buffer. */
1648 if(psk_length > NX_SECURE_TLS_MAX_PSK_SIZE)
1649 {
1650 return(NX_SECURE_TLS_NO_MORE_PSK_SPACE);
1651 }
1652
1653 /* Make sure the Client PSK is initialized for later key generation. */
1654 NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_data, psk_data, psk_length); /* Use case of memcpy is verified. */
1655 tls_session -> nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_data_size = psk_length;
1656
1657 return(NX_SUCCESS);
1658 }
1659 #endif
1660
1661
1662
1663