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 #ifndef NX_SECURE_TLS_CLIENT_DISABLED
27
28
29 #ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION
30 static UINT _nx_secure_tls_proc_serverhello_sec_reneg_extension(NX_SECURE_TLS_SESSION *tls_session,
31 UCHAR *packet_buffer,
32 USHORT *extension_length, UINT message_length);
33 #endif
34
35 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
36 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
37 static UINT _nx_secure_tls_proc_serverhello_keyshare_extension(NX_SECURE_TLS_SESSION *tls_session,
38 UCHAR *packet_buffer,
39 USHORT *extension_length, UINT message_length);
40 #endif
41 static UINT _nx_secure_tls_proc_serverhello_supported_versions_extension(NX_SECURE_TLS_SESSION *tls_session,
42 UCHAR *packet_buffer,
43 USHORT *supported_version,
44 USHORT *extension_length, UINT message_length);
45 #endif
46
47 #ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
48 static UINT _nx_secure_tls_proc_serverhello_ecc_point_formats(NX_SECURE_TLS_SESSION *tls_session,
49 UCHAR *packet_buffer,
50 USHORT *extension_length, UINT message_length);
51 static UINT _nx_secure_tls_proc_serverhello_ecjpake_key_kp_pair(NX_SECURE_TLS_SESSION *tls_session,
52 UCHAR *packet_buffer,
53 USHORT *extension_length, UINT message_length);
54 #endif
55
56 #endif /* NX_SECURE_TLS_CLIENT_DISABLED */
57
58 /**************************************************************************/
59 /* */
60 /* FUNCTION RELEASE */
61 /* */
62 /* _nx_secure_tls_process_serverhello_extensions PORTABLE C */
63 /* 6.1.9 */
64 /* AUTHOR */
65 /* */
66 /* Timothy Stapko, Microsoft Corporation */
67 /* */
68 /* DESCRIPTION */
69 /* */
70 /* This function processes any extensions included in an incoming */
71 /* ServerHello message from a remote host. */
72 /* */
73 /* INPUT */
74 /* */
75 /* tls_session TLS control block */
76 /* packet_buffer Pointer to message data */
77 /* message_length Length of message data (bytes)*/
78 /* extensions Extensions for output */
79 /* num_extensions Number of extensions */
80 /* */
81 /* OUTPUT */
82 /* */
83 /* status Completion status */
84 /* */
85 /* CALLS */
86 /* */
87 /* _nx_secure_tls_proc_serverhello_ecc_point_formats */
88 /* Process ServerHello ECC */
89 /* point formats extension */
90 /* _nx_secure_tls_proc_serverhello_ecjpake_key_kp_pair */
91 /* Process ServerHello ECJPAKE */
92 /* key kp pair extension */
93 /* _nx_secure_tls_proc_serverhello_sec_reneg_extension */
94 /* Process ServerHello */
95 /* Renegotiation extension */
96 /* */
97 /* CALLED BY */
98 /* */
99 /* _nx_secure_tls_server_handshake Process ServerHello */
100 /* */
101 /* RELEASE HISTORY */
102 /* */
103 /* DATE NAME DESCRIPTION */
104 /* */
105 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
106 /* 09-30-2020 Timothy Stapko Modified comment(s), */
107 /* fixed renegotiation bug, */
108 /* resulting in version 6.1 */
109 /* 10-15-2021 Timothy Stapko Modified comment(s), fixed */
110 /* TLS 1.3 compilation issue, */
111 /* resulting in version 6.1.9 */
112 /* */
113 /**************************************************************************/
_nx_secure_tls_process_serverhello_extensions(NX_SECURE_TLS_SESSION * tls_session,UCHAR * packet_buffer,UINT message_length,NX_SECURE_TLS_HELLO_EXTENSION * extensions,UINT * num_extensions)114 UINT _nx_secure_tls_process_serverhello_extensions(NX_SECURE_TLS_SESSION *tls_session,
115 UCHAR *packet_buffer, UINT message_length,
116 NX_SECURE_TLS_HELLO_EXTENSION *extensions,
117 UINT *num_extensions)
118 {
119 #ifndef NX_SECURE_TLS_CLIENT_DISABLED
120
121 UINT status;
122
123 #ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
124 USHORT ec_point_formats_match, zkp_verified;
125 #endif
126 UINT offset;
127 USHORT extension_id;
128 USHORT extension_length;
129 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
130 USHORT supported_version = tls_session -> nx_secure_tls_protocol_version;
131 #endif
132
133 #ifdef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION
134 #ifndef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
135 NX_PARAMETER_NOT_USED(tls_session);
136 #endif
137 #endif
138
139 #ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
140 if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL)
141 {
142 return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE);
143 }
144
145 ec_point_formats_match = NX_FALSE;
146 zkp_verified = NX_FALSE;
147 #endif
148
149 offset = 0;
150 status = NX_SUCCESS;
151 *num_extensions = 0;
152
153 /* Process extensions until we run out. */
154 while (offset < message_length)
155 {
156
157 /* Make sure there are at least 4 bytes available so we can read extension_id and
158 extension_length. */
159 if (offset + 4 > message_length)
160 {
161 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
162 }
163
164 /* See what the extension is. */
165 extension_id = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
166
167 /* Skip type id of extentions. */
168 offset += 2;
169
170 /* Parse the extension. */
171 switch (extension_id)
172 {
173 #ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION
174 case NX_SECURE_TLS_EXTENSION_SECURE_RENEGOTIATION:
175 status = _nx_secure_tls_proc_serverhello_sec_reneg_extension(tls_session, &packet_buffer[offset], &extension_length, message_length - offset);
176
177 if (status)
178 {
179 return(status);
180 }
181 break;
182 #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */
183 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
184 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
185 case NX_SECURE_TLS_EXTENSION_KEY_SHARE:
186
187 if (tls_session -> nx_secure_tls_1_3)
188 {
189 /* Process the TLS 1.3 key share extension. */
190 status = _nx_secure_tls_proc_serverhello_keyshare_extension(tls_session, &packet_buffer[offset], &extension_length, message_length - offset);
191
192 if (status)
193 {
194 return(status);
195 }
196 }
197 else
198 {
199 extension_length = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
200 if (extension_length + offset + 2 > message_length)
201 {
202 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
203 }
204 }
205 offset += 2;
206
207 /* Ignore if not TLS 1.3. */
208 break;
209 #endif
210 case NX_SECURE_TLS_EXTENSION_SUPPORTED_VERSIONS:
211 if (tls_session -> nx_secure_tls_1_3)
212 {
213
214 /* Process the TLS 1.3 supported_versions extension. */
215 status = _nx_secure_tls_proc_serverhello_supported_versions_extension(tls_session, &packet_buffer[offset], &supported_version, &extension_length, message_length - offset);
216
217 if (status)
218 {
219 return(status);
220 }
221 }
222 else
223 {
224 extension_length = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
225 if (extension_length + offset + 2 > message_length)
226 {
227 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
228 }
229 }
230 offset += 2;
231
232 /* Ignore if not TLS 1.3. */
233 break;
234 case NX_SECURE_TLS_EXTENSION_COOKIE:
235 extension_length = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
236 offset += 2;
237
238 if (extension_length + offset > message_length)
239 {
240 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
241 }
242
243 /* Store the pointer of cookie. */
244 /* Note: Cookie data is stored in ServerHello packet buffer. This buffer should not be released
245 or overwrote before Cookie is copied to ClientHello. */
246 if (tls_session -> nx_secure_tls_1_3)
247 {
248 if (extension_length < 2)
249 {
250 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
251 }
252
253 tls_session -> nx_secure_tls_cookie_length = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
254 tls_session -> nx_secure_tls_cookie = &packet_buffer[offset + 2];
255
256 if (tls_session -> nx_secure_tls_cookie_length + 2 > extension_length)
257 {
258 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
259 }
260 }
261
262 break;
263 #endif
264 #ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
265 /* ECJPAKE ciphersuite extensions. */
266 case NX_SECURE_TLS_EXTENSION_EC_POINT_FORMATS:
267 status = _nx_secure_tls_proc_serverhello_ecc_point_formats(tls_session, &packet_buffer[offset], &extension_length, message_length - offset);
268 if (status == NX_SUCCESS)
269 {
270 ec_point_formats_match = NX_TRUE;
271 }
272 break;
273 case NX_SECURE_TLS_EXTENSION_ECJPAKE_KEY_KP_PAIR:
274 status = _nx_secure_tls_proc_serverhello_ecjpake_key_kp_pair(tls_session, &packet_buffer[offset], &extension_length, message_length - offset);
275 if (status == NX_SUCCESS)
276 {
277 zkp_verified = NX_TRUE;
278 }
279 break;
280 #else
281 case NX_SECURE_TLS_EXTENSION_EC_GROUPS:
282 case NX_SECURE_TLS_EXTENSION_EC_POINT_FORMATS:
283 case NX_SECURE_TLS_EXTENSION_ECJPAKE_KEY_KP_PAIR:
284 #endif /* NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE */
285 case NX_SECURE_TLS_EXTENSION_SERVER_NAME_INDICATION:
286 case NX_SECURE_TLS_EXTENSION_MAX_FRAGMENT_LENGTH:
287 case NX_SECURE_TLS_EXTENSION_CLIENT_CERTIFICATE_URL:
288 case NX_SECURE_TLS_EXTENSION_TRUSTED_CA_INDICATION:
289 case NX_SECURE_TLS_EXTENSION_CERTIFICATE_STATUS_REQUEST:
290 /* These extensions require information to be passed to the application. Save off
291 the extension data in our extensions array to pass along in the hello callback. */
292 extension_length = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
293 offset += 2;
294
295 if (extension_length + offset > message_length)
296 {
297 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
298 }
299
300 if (*num_extensions < NX_SECURE_TLS_HELLO_EXTENSIONS_MAX)
301 {
302 extensions[*num_extensions].nx_secure_tls_extension_id = extension_id;
303 extensions[*num_extensions].nx_secure_tls_extension_data = &packet_buffer[offset];
304 extensions[*num_extensions].nx_secure_tls_extension_data_length = extension_length;
305
306 /* Added another extension to the array. */
307 *num_extensions = *num_extensions + 1;
308 }
309
310 break;
311 case NX_SECURE_TLS_EXTENSION_SIGNATURE_ALGORITHMS:
312 case NX_SECURE_TLS_EXTENSION_TRUNCATED_HMAC:
313 default:
314 /* Unknown extension, just ignore - TLS supports multiple extensions and the default
315 behavior is to ignore any extensions that we don't know. Assume the next two
316 octets are the length field so we can continue processing. */
317 extension_length = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
318 offset += 2;
319
320 if (extension_length + offset > message_length)
321 {
322 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
323 }
324
325 break;
326 }
327
328 /* Adjust our offset with the length of the extension we just parsed. */
329 offset += extension_length;
330 }
331
332 #ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
333 /* Make sure no ECJPAKE extensions are missing. */
334 if ((tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE) &&
335 (ec_point_formats_match == 0 || zkp_verified == 0))
336 {
337 return(NX_SECURE_TLS_UNSUPPORTED_ECC_FORMAT);
338 }
339 #endif /* NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE */
340
341 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
342 if (tls_session -> nx_secure_tls_1_3)
343 {
344 if (supported_version != NX_SECURE_TLS_VERSION_TLS_1_3)
345 {
346
347 /* Server negotiates a version of TLS prior to TLS 1.3. */
348 if (tls_session -> nx_secure_tls_protocol_version_override == 0)
349 {
350 tls_session -> nx_secure_tls_1_3 = NX_FALSE;
351 #ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION
352 tls_session -> nx_secure_tls_renegotation_enabled = NX_TRUE;
353 #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */
354 }
355 else
356 {
357
358 /* Protocol version is overridden to TLS 1.3. */
359 return(NX_SECURE_TLS_UNSUPPORTED_TLS_VERSION);
360 }
361 }
362 else
363 {
364 if (tls_session -> nx_secure_tls_protocol_version != NX_SECURE_TLS_VERSION_TLS_1_2)
365 {
366
367 /* Server negotiates TLS 1.3 must set the legacy version to TLS 1.2. */
368 return(NX_SECURE_TLS_UNKNOWN_TLS_VERSION);
369 }
370 }
371 }
372 #endif
373
374 return(status);
375 #else
376 /* If Client TLS is disabled and we recieve a server key exchange, error! */
377 NX_PARAMETER_NOT_USED(tls_session);
378 NX_PARAMETER_NOT_USED(packet_buffer);
379 NX_PARAMETER_NOT_USED(message_length);
380 NX_PARAMETER_NOT_USED(extensions);
381 NX_PARAMETER_NOT_USED(num_extensions);
382
383 return(NX_SECURE_TLS_UNEXPECTED_MESSAGE);
384 #endif
385 }
386
387
388 #ifndef NX_SECURE_TLS_CLIENT_DISABLED
389
390 /**************************************************************************/
391 /* */
392 /* FUNCTION RELEASE */
393 /* */
394 /* _nx_secure_tls_proc_serverhello_ecc_point_formats PORTABLE C */
395 /* 6.1 */
396 /* AUTHOR */
397 /* */
398 /* Timothy Stapko, Microsoft Corporation */
399 /* */
400 /* DESCRIPTION */
401 /* */
402 /* This function parses the ec_point_formats extension when ECC */
403 /* ciphersuites are being used. */
404 /* */
405 /* INPUT */
406 /* */
407 /* tls_session TLS control block */
408 /* packet_buffer Outgoing TLS packet buffer */
409 /* extension_length Length of extension data */
410 /* message_length Length of message data (bytes)*/
411 /* */
412 /* OUTPUT */
413 /* */
414 /* status Completion status */
415 /* */
416 /* CALLS */
417 /* */
418 /* None */
419 /* */
420 /* CALLED BY */
421 /* */
422 /* _nx_secure_tls_process_serverhello_extensions */
423 /* Process ServerHello extensions*/
424 /* */
425 /* RELEASE HISTORY */
426 /* */
427 /* DATE NAME DESCRIPTION */
428 /* */
429 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
430 /* 09-30-2020 Timothy Stapko Modified comment(s), */
431 /* resulting in version 6.1 */
432 /* */
433 /**************************************************************************/
434 #ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
_nx_secure_tls_proc_serverhello_ecc_point_formats(NX_SECURE_TLS_SESSION * tls_session,UCHAR * packet_buffer,USHORT * extension_length,UINT message_length)435 static UINT _nx_secure_tls_proc_serverhello_ecc_point_formats(NX_SECURE_TLS_SESSION *tls_session,
436 UCHAR *packet_buffer,
437 USHORT *extension_length, UINT message_length)
438 {
439 UINT status;
440 UINT i;
441 UCHAR ec_point_formats_length;
442 UINT offset;
443
444 *extension_length = (USHORT)((*packet_buffer << 8) + packet_buffer[1] + 2);
445
446 if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL)
447 {
448 return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE);
449 }
450
451 /* Skip the length field of this extension. */
452 offset = 2;
453
454 if (*extension_length > message_length || *extension_length < 3)
455 {
456 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
457 }
458
459 /* ec_point_formats Extension. */
460 ec_point_formats_length = packet_buffer[offset];
461 offset += 1;
462
463 if (offset + ec_point_formats_length != *extension_length)
464 {
465 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
466 }
467
468 /* Ignore the extension if we are not using ECJPAKE. */
469 if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE)
470 {
471 /* Make sure uncompressed (0) format is supported. */
472 status = NX_SECURE_TLS_UNSUPPORTED_CIPHER;
473 for (i = 0; i < ec_point_formats_length; ++i)
474 {
475 if (packet_buffer[offset + i] == 0x0)
476 {
477 status = NX_SUCCESS;
478 break;
479 }
480 }
481
482 /* Check for error. */
483 if (status != NX_SUCCESS)
484 {
485 return(status);
486 }
487 }
488
489 return(NX_SUCCESS);
490 }
491 #endif
492
493
494 /**************************************************************************/
495 /* */
496 /* FUNCTION RELEASE */
497 /* */
498 /* _nx_secure_tls_proc_serverhello_ecjpake_key_kp_pair PORTABLE C */
499 /* 6.1 */
500 /* AUTHOR */
501 /* */
502 /* Timothy Stapko, Microsoft Corporation */
503 /* */
504 /* DESCRIPTION */
505 /* */
506 /* This function parses the ecjpake_key_kp_pair extension when ECC */
507 /* JPAKE ciphersuites are being used. */
508 /* */
509 /* INPUT */
510 /* */
511 /* tls_session TLS control block */
512 /* packet_buffer Outgoing TLS packet buffer */
513 /* extension_length Length of extension data */
514 /* message_length Length of message data (bytes)*/
515 /* */
516 /* OUTPUT */
517 /* */
518 /* status Completion status */
519 /* */
520 /* CALLS */
521 /* */
522 /* [nx_crypto_operation] Crypto operation */
523 /* */
524 /* CALLED BY */
525 /* */
526 /* _nx_secure_tls_process_serverhello_extensions */
527 /* Process ServerHello extensions*/
528 /* */
529 /* RELEASE HISTORY */
530 /* */
531 /* DATE NAME DESCRIPTION */
532 /* */
533 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
534 /* 09-30-2020 Timothy Stapko Modified comment(s), */
535 /* resulting in version 6.1 */
536 /* */
537 /**************************************************************************/
538 #ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
_nx_secure_tls_proc_serverhello_ecjpake_key_kp_pair(NX_SECURE_TLS_SESSION * tls_session,UCHAR * packet_buffer,USHORT * extension_length,UINT message_length)539 static UINT _nx_secure_tls_proc_serverhello_ecjpake_key_kp_pair(NX_SECURE_TLS_SESSION *tls_session,
540 UCHAR *packet_buffer,
541 USHORT *extension_length, UINT message_length)
542 {
543 UINT status;
544 NX_CRYPTO_METHOD *crypto_method;
545
546 *extension_length = (USHORT)((*packet_buffer << 8) + packet_buffer[1] + 2);
547
548 if (*extension_length > message_length || *extension_length <= 2)
549 {
550 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
551 }
552
553 if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL)
554 {
555 return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE);
556 }
557
558 /* Ignore the extension if we are not using ECJPAKE. */
559 if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE)
560 {
561
562 crypto_method = (NX_CRYPTO_METHOD*)tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth;
563
564 /* ecjpake_key_kp_pair Extension. */
565 status = crypto_method -> nx_crypto_operation(NX_CRYPTO_ECJPAKE_SERVER_HELLO_PROCESS,
566 tls_session -> nx_secure_public_auth_handler,
567 crypto_method,
568 NX_NULL, 0,
569 &packet_buffer[2], /* Skip extension length. */
570 (ULONG)(*extension_length - 2),
571 NX_NULL, NX_NULL, 0,
572 tls_session -> nx_secure_public_auth_metadata_area,
573 tls_session -> nx_secure_public_auth_metadata_size,
574 NX_NULL, NX_NULL);
575 if (status)
576 {
577 return(status);
578 }
579 }
580
581 return(NX_SUCCESS);
582 }
583 #endif
584
585 /**************************************************************************/
586 /* */
587 /* FUNCTION RELEASE */
588 /* */
589 /* _nx_secure_tls_proc_serverhello_sec_reneg_extension PORTABLE C */
590 /* 6.1 */
591 /* AUTHOR */
592 /* */
593 /* Timothy Stapko, Microsoft Corporation */
594 /* */
595 /* DESCRIPTION */
596 /* */
597 /* This function parses the Secure Renegotiation Indication extension */
598 /* from an incoming ServerHello record.See RFC 5746 for more */
599 /* information. */
600 /* */
601 /* INPUT */
602 /* */
603 /* tls_session TLS control block */
604 /* packet_buffer Outgoing TLS packet buffer */
605 /* extension_length Length of extension data */
606 /* message_length Length of message data (bytes)*/
607 /* */
608 /* OUTPUT */
609 /* */
610 /* status Completion status */
611 /* */
612 /* CALLS */
613 /* */
614 /* None */
615 /* */
616 /* CALLED BY */
617 /* */
618 /* _nx_secure_tls_process_serverhello_extensions */
619 /* Process ServerHello extensions*/
620 /* */
621 /* RELEASE HISTORY */
622 /* */
623 /* DATE NAME DESCRIPTION */
624 /* */
625 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
626 /* 09-30-2020 Timothy Stapko Modified comment(s), */
627 /* fixed renegotiation bug, */
628 /* resulting in version 6.1 */
629 /* */
630 /**************************************************************************/
631 #ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION
_nx_secure_tls_proc_serverhello_sec_reneg_extension(NX_SECURE_TLS_SESSION * tls_session,UCHAR * packet_buffer,USHORT * extension_length,UINT message_length)632 static UINT _nx_secure_tls_proc_serverhello_sec_reneg_extension(NX_SECURE_TLS_SESSION *tls_session,
633 UCHAR *packet_buffer,
634 USHORT *extension_length, UINT message_length)
635 {
636 ULONG offset;
637 UCHAR renegotiated_connection_length;
638 USHORT parsed_length;
639 INT compare_value;
640
641 /* Secure Renegotiation Indication Extensions structure (for serverhello):
642 * Initial ServerHello:
643 * | 2 | 2 | 1 |
644 * | Ext Type | Ext Len | Reneg Info Len |
645 * | 0xff01 | 0x0001 | 0x00 |
646 *
647 * Renegotiating ServerHello:
648 * | 2 | 2 | 1 | 12 | 12 |
649 * | Ext Type | Ext Len | Reneg Info Len | client_verify_data | server_verify_data |
650 * | 0xff01 | 0x0019 | 0x18 | | |
651 */
652 /* From RFC 5746:
653 struct {
654 opaque renegotiated_connection<0..255>;
655 } RenegotiationInfo;
656
657 The contents of this extension are specified as follows.
658
659 - If this is the initial handshake for a connection, then the
660 "renegotiated_connection" field is of zero length in both the
661 ClientHello and the ServerHello. Thus, the entire encoding of the
662 extension is ff 01 00 01 00. The first two octets represent the
663 extension type, the third and fourth octets the length of the
664 extension itself, and the final octet the zero length byte for the
665 "renegotiated_connection" field.
666
667 - For ClientHellos that are renegotiating, this field contains the
668 "client_verify_data" specified in Section 3.1.
669
670 - For ServerHellos that are renegotiating, this field contains the
671 concatenation of client_verify_data and server_verify_data. For
672 current versions of TLS, this will be a 24-byte value (for SSLv3,
673 it will be a 72-byte value).
674 */
675
676 /* Get the extension length. */
677 parsed_length = (USHORT)((packet_buffer[0] << 8) + packet_buffer[1]);
678 *extension_length = (USHORT)(2 + parsed_length);
679 offset = 2;
680
681 if (*extension_length > message_length || *extension_length < 3)
682 {
683 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
684 }
685
686 /* Get the "renegotiated_connection" field. */
687 renegotiated_connection_length = packet_buffer[offset];
688 offset++;
689
690 if (offset + renegotiated_connection_length > *extension_length)
691 {
692 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
693 }
694
695 /* See if the client is attempting to renegotiate an established connection. */
696 if (renegotiated_connection_length)
697 {
698 /* The remote host is attempting a renegotiation - make sure our local session is active and renegotiation is OK. */
699 if (!tls_session -> nx_secure_tls_local_session_active || !tls_session -> nx_secure_tls_remote_session_active)
700 {
701 /* Remote host is attempting a renegotiation but the server is not currently in a session! */
702 return(NX_SECURE_TLS_RENEGOTIATION_EXTENSION_ERROR);
703 }
704
705 if(!tls_session -> nx_secure_tls_secure_renegotiation)
706 {
707 return(NX_SECURE_TLS_RENEGOTIATION_EXTENSION_ERROR);
708 }
709
710
711 /* Check that the received verification data is the expected size. For ServerHello, the size is twice the
712 finished verification hash size because it includes both client and server hashes. */
713 if (renegotiated_connection_length != (2 * NX_SECURE_TLS_FINISHED_HASH_SIZE))
714 {
715 /* Do not have the right amount of data for comparison. */
716 return(NX_SECURE_TLS_RENEGOTIATION_EXTENSION_ERROR);
717 }
718
719 /* Compare the received verify data to our locally-stored version - start with client (local) verify data. */
720 compare_value = NX_SECURE_MEMCMP(&packet_buffer[offset], tls_session -> nx_secure_tls_local_verify_data, NX_SECURE_TLS_FINISHED_HASH_SIZE);
721
722 if (compare_value)
723 {
724 /* Session verify data did not match what we expect - error. */
725 return(NX_SECURE_TLS_RENEGOTIATION_EXTENSION_ERROR);
726 }
727
728 /* Now compare the remote verify data with what we just received. */
729 offset += NX_SECURE_TLS_FINISHED_HASH_SIZE;
730 compare_value = NX_SECURE_MEMCMP(&packet_buffer[offset], tls_session -> nx_secure_tls_remote_verify_data, NX_SECURE_TLS_FINISHED_HASH_SIZE);
731
732 if (compare_value)
733 {
734 /* Session verify data did not match what we expect - error. */
735 return(NX_SECURE_TLS_RENEGOTIATION_EXTENSION_ERROR);
736 }
737
738 /* If we get here, the verification data is good! */
739 tls_session -> nx_secure_tls_secure_renegotiation_verified = NX_TRUE;
740 }
741 else
742 {
743 /* Verify that the extension contains only the initial handshake data - this is a new connection. */
744 if ((parsed_length != 1) || (tls_session -> nx_secure_tls_local_session_active))
745 {
746 /* Error - the provided extension length was not expected for an initial handshake. */
747 return(NX_SECURE_TLS_RENEGOTIATION_EXTENSION_ERROR);
748 }
749
750 /* The remote host supports secure renegotiation. */
751 tls_session -> nx_secure_tls_secure_renegotiation = NX_TRUE;
752 }
753
754 return(NX_SUCCESS);
755 }
756 #endif
757
758
759 /**************************************************************************/
760 /* */
761 /* FUNCTION RELEASE */
762 /* */
763 /* _nx_secure_tls_proc_serverhello_keyshare_extension PORTABLE C */
764 /* 6.2.0 */
765 /* AUTHOR */
766 /* */
767 /* Timothy Stapko, Microsoft Corporation */
768 /* */
769 /* DESCRIPTION */
770 /* */
771 /* This function parses the Key Share extension introduced in TLS 1.3. */
772 /* */
773 /* INPUT */
774 /* */
775 /* tls_session TLS control block */
776 /* packet_buffer Outgoing TLS packet buffer */
777 /* extension_length Length of extension data */
778 /* message_length Length of message data (bytes)*/
779 /* */
780 /* OUTPUT */
781 /* */
782 /* status Completion status */
783 /* */
784 /* CALLS */
785 /* */
786 /* None */
787 /* */
788 /* CALLED BY */
789 /* */
790 /* _nx_secure_tls_process_serverhello_extensions */
791 /* Process ServerHello extensions*/
792 /* */
793 /* RELEASE HISTORY */
794 /* */
795 /* DATE NAME DESCRIPTION */
796 /* */
797 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
798 /* 09-30-2020 Timothy Stapko Modified comment(s), update */
799 /* ECC find curve method, */
800 /* resulting in version 6.1 */
801 /* 04-25-2022 Yuxin Zhou Modified comment(s), removed */
802 /* public key format checking, */
803 /* resulting in version 6.1.11 */
804 /* 10-31-2022 Yanwu Cai Modified comment(s), */
805 /* updated parameters list, */
806 /* resulting in version 6.2.0 */
807 /* */
808 /**************************************************************************/
809 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
810
811 extern NX_CRYPTO_METHOD crypto_method_ecdhe;
812
_nx_secure_tls_proc_serverhello_keyshare_extension(NX_SECURE_TLS_SESSION * tls_session,UCHAR * packet_buffer,USHORT * extension_length,UINT message_length)813 static UINT _nx_secure_tls_proc_serverhello_keyshare_extension(NX_SECURE_TLS_SESSION *tls_session,
814 UCHAR *packet_buffer,
815 USHORT *extension_length, UINT message_length)
816 {
817 UINT status;
818 UINT i;
819 ULONG offset;
820 USHORT key_group;
821 USHORT key_length;
822 NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecc_key_data;
823 UCHAR *pubkey;
824 UCHAR *private_key;
825 UINT private_key_length;
826 NX_CRYPTO_EXTENDED_OUTPUT extended_output;
827 NX_CRYPTO_METHOD *ecdhe_method;
828 const NX_CRYPTO_METHOD *curve_method;
829 VOID *handler = NX_NULL;
830 NX_SECURE_TLS_ECC *ecc_info;
831
832 /* Key Share Extension structure (for serverhello):
833 *
834 * ServerHello:
835 * | 2 | 2 | <key len> |
836 * | Key Group | Key Len | Key Exchange value |
837 */
838
839 offset = 0;
840
841 /* Extract the extension length. */
842 *extension_length = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
843 offset = (USHORT)(offset + 2);
844
845 if (offset + *extension_length > message_length || *extension_length < 2)
846 {
847 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
848 }
849
850 /* Get the key group. It must match one we sent in our ClientHello KeyShare extension. */
851 key_group = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
852 offset = (USHORT)(offset + 2);
853
854 /* Get our session ECC data. */
855 ecc_info = &(tls_session -> nx_secure_tls_ecc);
856
857 /* Check the key group. */
858 key_group = (USHORT)((ULONG)key_group | NX_CRYPTO_EC_MASK);
859
860
861 /* Loop through all supported ECC curves in this session. */
862 for (i = 0; i < ecc_info -> nx_secure_tls_ecc_supported_groups_count; i++)
863 {
864 /* Find the matchin group in the keys we generated and saved. */
865 if (key_group != tls_session -> nx_secure_tls_key_material.nx_secure_tls_ecc_key_data[i].nx_secure_tls_ecdhe_named_curve)
866 {
867 continue;
868 }
869
870 /* Store selected ECDHE key data index. */
871 tls_session -> nx_secure_tls_key_material.nx_secure_tls_ecc_key_data_selected = i;
872
873 if (tls_session -> nx_secure_tls_client_state == NX_SECURE_TLS_CLIENT_STATE_HELLO_RETRY)
874 {
875
876 /* A HelloRetryRequest is received. Done here. */
877 return(NX_SUCCESS);
878 }
879
880 /* Got a matching key/curve combo, get a pointer to the selected key data. */
881 ecc_key_data = tls_session -> nx_secure_tls_key_material.nx_secure_tls_ecc_key_data;
882
883 if (*extension_length < 4)
884 {
885 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
886 }
887
888 /* Get the key length. */
889 key_length = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
890 if (offset + key_length > *extension_length)
891 {
892 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
893 }
894 offset = (USHORT)(offset + 2);
895
896 /* Initialize the remote public key in our session. */
897 pubkey = &packet_buffer[offset];
898
899 /* Get the curve method to initialize the remote public key data. */
900 _nx_secure_tls_find_curve_method(&tls_session -> nx_secure_tls_ecc, key_group, &curve_method, NX_NULL);
901
902 if (curve_method == NX_NULL)
903 {
904 return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
905 }
906
907 /* Get the ECDHE method we are going to use. */
908 ecdhe_method = &crypto_method_ecdhe;
909
910 if (ecdhe_method -> nx_crypto_operation == NX_NULL )
911 {
912 return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
913 }
914
915 /* Initialize the ECDHE method. */
916 if (ecdhe_method -> nx_crypto_init != NX_NULL)
917 {
918 status = ecdhe_method -> nx_crypto_init(ecdhe_method,
919 NX_NULL,
920 0,
921 &handler,
922 tls_session -> nx_secure_public_cipher_metadata_area,
923 tls_session -> nx_secure_public_cipher_metadata_size);
924
925 if (status != NX_CRYPTO_SUCCESS)
926 {
927 return(status);
928 }
929 }
930
931 /* Set the curve we want to use. */
932 status = ecdhe_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler,
933 ecdhe_method, NX_NULL, 0,
934 (UCHAR *)curve_method, sizeof(NX_CRYPTO_METHOD *), NX_NULL,
935 NX_NULL, 0,
936 tls_session -> nx_secure_public_cipher_metadata_area,
937 tls_session -> nx_secure_public_cipher_metadata_size,
938 NX_NULL, NX_NULL);
939 if (status != NX_CRYPTO_SUCCESS)
940 {
941 return(status);
942 }
943
944 /* Import the private key to the ECDH context. */
945 private_key = &ecc_key_data[i].nx_secure_tls_ecdhe_private_key[0];
946 private_key_length = ecc_key_data[i].nx_secure_tls_ecdhe_private_key_length;
947
948 status = ecdhe_method -> nx_crypto_operation(NX_CRYPTO_DH_KEY_PAIR_IMPORT, handler,
949 (NX_CRYPTO_METHOD*)ecdhe_method,
950 private_key, private_key_length << 3,
951 NX_NULL, 0, NX_NULL,
952 NX_NULL,
953 0,
954 tls_session -> nx_secure_public_cipher_metadata_area,
955 tls_session -> nx_secure_public_cipher_metadata_size,
956 NX_NULL, NX_NULL);
957
958
959 if (status != NX_CRYPTO_SUCCESS)
960 {
961 return(status);
962 }
963
964 //tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data[0] = (UCHAR)extended_output.nx_crypto_extended_output_actual_size;
965
966 /* Calculate the final pre_master_secret - the "private key" here is the Pre-Master Secret. */
967 extended_output.nx_crypto_extended_output_data = tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret;
968 extended_output.nx_crypto_extended_output_length_in_byte = sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret);
969 extended_output.nx_crypto_extended_output_actual_size = 0;
970 status = ecdhe_method -> nx_crypto_operation(NX_CRYPTO_DH_CALCULATE, handler,
971 ecdhe_method, NX_NULL, 0,
972 pubkey, key_length, NX_NULL,
973 (UCHAR *)&extended_output,
974 sizeof(extended_output),
975 tls_session -> nx_secure_public_cipher_metadata_area,
976 tls_session -> nx_secure_public_cipher_metadata_size,
977 NX_NULL, NX_NULL);
978 if (status != NX_CRYPTO_SUCCESS)
979 {
980 return(status);
981 }
982
983 tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size = extended_output.nx_crypto_extended_output_actual_size;
984
985 if (ecdhe_method -> nx_crypto_cleanup)
986 {
987 status = ecdhe_method -> nx_crypto_cleanup(tls_session -> nx_secure_public_cipher_metadata_area);
988 }
989
990 return(status);
991 }
992
993 /* If we exhaust the list of ECC curves we sent, the server is doing something weird. */
994 return(NX_SECURE_TLS_BAD_SERVERHELLO_KEYSHARE);
995
996 }
997
998 /**************************************************************************/
999 /* */
1000 /* FUNCTION RELEASE */
1001 /* */
1002 /* _nx_secure_tls_proc_serverhello_supported_versions_extension */
1003 /* PORTABLE C */
1004 /* 6.1 */
1005 /* AUTHOR */
1006 /* */
1007 /* Timothy Stapko, Microsoft Corporation */
1008 /* */
1009 /* DESCRIPTION */
1010 /* */
1011 /* This function parses the supported versions extension introduced in */
1012 /* TLS 1.3. */
1013 /* */
1014 /* INPUT */
1015 /* */
1016 /* tls_session TLS control block */
1017 /* packet_buffer Outgoing TLS packet buffer */
1018 /* supported_version Supported version */
1019 /* extension_length Length of extension data */
1020 /* message_length Length of message data (bytes)*/
1021 /* */
1022 /* OUTPUT */
1023 /* */
1024 /* status Completion status */
1025 /* */
1026 /* CALLS */
1027 /* */
1028 /* None */
1029 /* */
1030 /* CALLED BY */
1031 /* */
1032 /* _nx_secure_tls_process_serverhello_extensions */
1033 /* Process ServerHello extensions*/
1034 /* */
1035 /* RELEASE HISTORY */
1036 /* */
1037 /* DATE NAME DESCRIPTION */
1038 /* */
1039 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
1040 /* 09-30-2020 Timothy Stapko Modified comment(s), */
1041 /* resulting in version 6.1 */
1042 /* */
1043 /**************************************************************************/
_nx_secure_tls_proc_serverhello_supported_versions_extension(NX_SECURE_TLS_SESSION * tls_session,UCHAR * packet_buffer,USHORT * supported_version,USHORT * extension_length,UINT message_length)1044 static UINT _nx_secure_tls_proc_serverhello_supported_versions_extension(NX_SECURE_TLS_SESSION *tls_session,
1045 UCHAR *packet_buffer,
1046 USHORT *supported_version,
1047 USHORT *extension_length, UINT message_length)
1048 {
1049 ULONG offset;
1050
1051 NX_PARAMETER_NOT_USED(tls_session);
1052
1053 /* Supported Versions Extension structure (for serverhello):
1054 *
1055 * ServerHello:
1056 * | 2 | 2 | ... |
1057 * | Type | Length | Selected Version |
1058 */
1059
1060 /* RFC 8446, section 4.2.1, page 39.
1061 * A server negotiates TLS 1.3 MUST respond with 0x0304 in supported_versions extension.
1062 */
1063
1064 offset = 0;
1065
1066 /* Extract the extension length. */
1067 *extension_length = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
1068 offset = (USHORT)(offset + 2);
1069
1070 if (offset + *extension_length > message_length || *extension_length != 2)
1071 {
1072 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
1073 }
1074
1075 /* Find the selected version 0x0304(TLS 1.3). */
1076 *supported_version = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]);
1077 if (*supported_version == NX_SECURE_TLS_VERSION_TLS_1_3)
1078 {
1079 return(NX_SUCCESS);
1080 }
1081
1082 return(NX_SECURE_TLS_UNKNOWN_TLS_VERSION);
1083
1084 }
1085 #endif
1086
1087 #endif /* NX_SECURE_TLS_CLIENT_DISABLED */
1088