1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** NetX Secure Component */
17 /** */
18 /** Transport Layer Security (TLS) */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define NX_SECURE_SOURCE_CODE
24
25 #include "nx_secure_tls.h"
26
27 static VOID _nx_secure_tls_packet_trim(NX_PACKET *packet_ptr);
28
29 /**************************************************************************/
30 /* */
31 /* FUNCTION RELEASE */
32 /* */
33 /* _nx_secure_tls_process_record PORTABLE C */
34 /* 6.2.1 */
35 /* AUTHOR */
36 /* */
37 /* Timothy Stapko, Microsoft Corporation */
38 /* */
39 /* DESCRIPTION */
40 /* */
41 /* This function processes a single TLS record, handling both */
42 /* handshake and application records. When multiple records are */
43 /* received in a single lower-level network packet (e.g. TCP), the */
44 /* "record_offset" parameter is used to offset into the packet buffer. */
45 /* */
46 /* INPUT */
47 /* */
48 /* tls_session Pointer to TLS control block */
49 /* packet_ptr NX_PACKET containing a record */
50 /* bytes_processed Return for size of packet */
51 /* wait_option Control timeout options */
52 /* */
53 /* OUTPUT */
54 /* */
55 /* status Completion status */
56 /* */
57 /* CALLS */
58 /* */
59 /* _nx_secure_tls_client_handshake TLS Client state machine */
60 /* _nx_secure_tls_process_changecipherspec */
61 /* Process ChangeCipherSpec */
62 /* _nx_secure_tls_process_header Process record header */
63 /* _nx_secure_tls_record_payload_decrypt Decrypt record data */
64 /* _nx_secure_tls_server_handshake TLS Server state machine */
65 /* _nx_secure_tls_verify_mac Verify record MAC checksum */
66 /* nx_packet_allocate NetX Packet allocation call */
67 /* nx_packet_data_append Append data to packet */
68 /* nx_packet_data_extract_offset Extract data from NX_PACKET */
69 /* _nx_secure_tls_packet_trim Trim TLS packet */
70 /* tx_mutex_get Get protection mutex */
71 /* tx_mutex_put Put protection mutex */
72 /* */
73 /* CALLED BY */
74 /* */
75 /* _nx_secure_tls_session_receive_records */
76 /* Receive TLS records */
77 /* */
78 /* RELEASE HISTORY */
79 /* */
80 /* DATE NAME DESCRIPTION */
81 /* */
82 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
83 /* 09-30-2020 Timothy Stapko Modified comment(s), */
84 /* supported chained packet, */
85 /* fixed compiler warnings, */
86 /* resulting in version 6.1 */
87 /* 02-02-2021 Timothy Stapko Modified comment(s), added */
88 /* support for fragmented TLS */
89 /* Handshake messages, */
90 /* resulting in version 6.1.4 */
91 /* 08-02-2021 Timothy Stapko Modified comment(s), checked */
92 /* TLS state before processing,*/
93 /* resulting in version 6.1.8 */
94 /* 10-15-2021 Timothy Stapko Modified comment(s), fixed */
95 /* TLS 1.3 compile issue, */
96 /* resulting in version 6.1.9 */
97 /* 04-25-2022 Yuxin Zhou Modified comment(s), */
98 /* removed unnecessary code, */
99 /* resulting in version 6.1.11 */
100 /* 07-29-2022 Yuxin Zhou Modified comment(s), */
101 /* checked seq number overflow,*/
102 /* improved buffer length */
103 /* verification, */
104 /* resulting in version 6.1.12 */
105 /* 03-08-2023 Tiejun Zhou Modified comment(s), and */
106 /* corrected data cleanup, */
107 /* resulting in version 6.2.1 */
108 /* */
109 /**************************************************************************/
_nx_secure_tls_process_record(NX_SECURE_TLS_SESSION * tls_session,NX_PACKET * packet_ptr,ULONG * bytes_processed,ULONG wait_option)110 UINT _nx_secure_tls_process_record(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *packet_ptr,
111 ULONG *bytes_processed, ULONG wait_option)
112 {
113 UINT status;
114 UINT error_status;
115 USHORT header_length;
116 UCHAR header_data[NX_SECURE_TLS_RECORD_HEADER_SIZE] = {0}; /* DTLS record header is larger than TLS. Allocate enough space for both. */
117 USHORT message_type;
118 UINT message_length;
119 ULONG bytes_copied;
120 UCHAR *packet_data = NX_NULL;
121 ULONG record_offset = 0;
122 ULONG record_offset_next = 0;
123 NX_PACKET *decrypted_packet;
124
125 /* Basic state machine:
126 * 1. Process header, which will set the state and return some data.
127 * 2. Advance the packet pointer by the size of the header (returned by header processing)
128 * and process the record.
129 * 3. Take any actions necessary based on state.
130 *
131 *
132 * For reading TLS records from TCP packets we have two cases to worry about:
133 * 1. Multiple records per packet
134 * - Multiple TLS records are packed into a single packet.
135 * - Loop below continues to process records until queue is emptied
136 * 2. Multiple packets per record
137 * - Header or payload may span multiple chained packets
138 * - If we have less than a complete header, return NX_CONTINUE to read more bytes from TCP socket
139 * - If we have a complete header, process the header - this may happen multiple times
140 * if we returned NX_CONTINUE due to having an incomplete payload.
141 * - After processing the header, check to see if the entire payload (length from header) has
142 * been read from the socket into the queue. If incomplete, return NX_CONTINUE.
143 * - If the payload is complete, process it in the state machine (decrypt if necessary first)
144 * and update the record_offset and bytes_processed values accordingly.
145 */
146
147 status = NX_CONTINUE;
148 *bytes_processed = 0;
149
150 /* Make sure the TLS socket is not closed. */
151 if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_NONE)
152 {
153
154 /* Session already closed. Release the packet. */
155 if (packet_ptr != NX_NULL)
156 {
157 nx_packet_release(packet_ptr);
158 }
159 return(NX_SECURE_TLS_INVALID_STATE);
160 }
161
162 /* Process the packet. */
163 if (packet_ptr != NX_NULL)
164 {
165 if (packet_ptr -> nx_packet_last == NX_NULL)
166 {
167
168 /* The logic below requires nx_packet_last is set which is always TRUE
169 for chained packets coming from NetX. However, this packet is not chained
170 so set the nx_packet_last pointer to itself. */
171 packet_ptr -> nx_packet_last = packet_ptr;
172 }
173
174 /* Chain the packet. */
175 if (tls_session -> nx_secure_record_queue_header == NX_NULL)
176 {
177 tls_session -> nx_secure_record_queue_header = packet_ptr;
178 }
179 else
180 {
181
182 /* Link current packet. */
183 tls_session -> nx_secure_record_queue_header -> nx_packet_last -> nx_packet_next = packet_ptr;
184 tls_session -> nx_secure_record_queue_header -> nx_packet_last = packet_ptr -> nx_packet_last;
185 tls_session -> nx_secure_record_queue_header -> nx_packet_length += packet_ptr -> nx_packet_length;
186 }
187 }
188
189 /* Reset nx_secure_tls_packet_buffer_bytes_copied if there is no fragmented message to be processed. */
190 if (tls_session->nx_secure_tls_handshake_record_fragment_state == NX_SECURE_TLS_HANDSHAKE_NO_FRAGMENT)
191 {
192 tls_session->nx_secure_tls_packet_buffer_bytes_copied = 0;
193 }
194
195 /* Get packet from record queue. */
196 packet_ptr = tls_session -> nx_secure_record_queue_header;
197
198 /* Process multiple records per packet. */
199 while (status == NX_CONTINUE)
200 {
201
202 /* Make sure the decrypted packet is NULL. */
203 if (tls_session -> nx_secure_record_decrypted_packet)
204 {
205 nx_secure_tls_packet_release(tls_session -> nx_secure_record_decrypted_packet);
206 tls_session -> nx_secure_record_decrypted_packet = NX_NULL;
207 }
208 decrypted_packet = NX_NULL;
209
210 /* Retrieve the saved record offset when more TCP packet is received for this one record. */
211 if (tls_session -> nx_secure_tls_record_offset)
212 {
213 record_offset = tls_session -> nx_secure_tls_record_offset;
214 tls_session -> nx_secure_tls_record_offset = 0;
215 *bytes_processed = tls_session -> nx_secure_tls_bytes_processed;
216 tls_session -> nx_secure_tls_bytes_processed = 0;
217 }
218
219 /* Process the TLS record header, which will set the state. */
220 status = _nx_secure_tls_process_header(tls_session, packet_ptr, record_offset, &message_type, &message_length, header_data, &header_length);
221
222 if (status != NX_SECURE_TLS_SUCCESS)
223 {
224 return(status);
225 }
226
227 /* Ignore empty records. */
228 if (message_length == 0)
229 {
230
231 /* Update the number of bytes we processed. */
232 *bytes_processed += (ULONG)header_length;
233 return(NX_SUCCESS);
234 }
235
236 /* Is the entire payload of the current record received? */
237 if ((header_length + record_offset + message_length) > packet_ptr -> nx_packet_length)
238 {
239
240 /* Wait more TCP packets for this one record, save record_offset and bytes_processed for next record processing. */
241 tls_session -> nx_secure_tls_record_offset = record_offset;
242 tls_session -> nx_secure_tls_bytes_processed = *bytes_processed;
243 return(NX_CONTINUE);
244 }
245
246 /* Update the number of bytes we processed. */
247 *bytes_processed += (ULONG)header_length + message_length;
248 tls_session -> nx_secure_tls_bytes_processed = *bytes_processed;
249 record_offset += (ULONG)header_length;
250 record_offset_next = record_offset + message_length;
251
252 /* Check for active encryption of incoming records. If encrypted, decrypt before further processing. */
253 if (tls_session -> nx_secure_tls_remote_session_active
254 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
255 && (!tls_session -> nx_secure_tls_1_3 || message_type == NX_SECURE_TLS_APPLICATION_DATA)
256 #endif
257 )
258 {
259
260 /* Check the record length. */
261 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
262 if (tls_session -> nx_secure_tls_1_3)
263 {
264 if (message_length > NX_SECURE_TLS_MAX_CIPHERTEXT_LENGTH_1_3)
265 {
266 return(NX_SECURE_TLS_RECORD_OVERFLOW);
267 }
268 }
269 else
270 #endif
271 {
272 if (message_length > NX_SECURE_TLS_MAX_CIPHERTEXT_LENGTH)
273 {
274 return(NX_SECURE_TLS_RECORD_OVERFLOW);
275 }
276 }
277
278 /* Decrypt the record data. */
279 status = _nx_secure_tls_record_payload_decrypt(tls_session, packet_ptr, record_offset,
280 message_length, &decrypted_packet,
281 tls_session -> nx_secure_tls_remote_sequence_number,
282 (UCHAR)message_type, wait_option);
283
284 /* Set the error status to something appropriate. */
285 error_status = NX_SECURE_TLS_SUCCESS;
286
287 /* Check the MAC hash if we were able to decrypt the record. */
288 if (status != NX_SECURE_TLS_SUCCESS)
289 {
290 /* Save off the error status so we can return it after the mac check. */
291 error_status = status;
292 }
293 else
294 {
295
296 /* Record it so it can be release in case it is not returned to user application. */
297 tls_session -> nx_secure_record_decrypted_packet = decrypted_packet;
298 message_length = decrypted_packet -> nx_packet_length;
299 }
300
301 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
302 /* TLS 1.3 uses AEAD for all authentication and encryption. Therefore
303 the MAC verification is only needed for older TLS versions. */
304 if(tls_session->nx_secure_tls_1_3)
305 {
306
307 if (status == NX_SECURE_TLS_SUCCESS)
308 {
309
310 /* In TLS 1.3, encrypted records have a single byte at the
311 record that contains the message type (e.g. application data,
312 ect.), which is now the ACTUAL message type. */
313 status = nx_packet_data_extract_offset(decrypted_packet,
314 decrypted_packet -> nx_packet_length - 1,
315 &message_type, 1, &bytes_copied);
316 if (status || (bytes_copied != 1))
317 {
318 error_status = NX_SECURE_TLS_INVALID_PACKET;
319 }
320
321 /* Remove the content type byte from the data length to process. */
322 message_length = message_length - 1;
323
324 /* Adjust packet length. */
325 decrypted_packet -> nx_packet_length = message_length;
326
327 /* Increment the sequence number. This is done in the MAC verify
328 step for 1.2 and earlier, but AEAD includes the MAC so we don't
329 check the MAC and need to increment here. */
330 if ((tls_session -> nx_secure_tls_remote_sequence_number[0] + 1) == 0)
331 {
332 /* Check for overflow of the 32-bit unsigned number. */
333 tls_session -> nx_secure_tls_remote_sequence_number[1]++;
334
335 if (tls_session -> nx_secure_tls_remote_sequence_number[1] == 0)
336 {
337
338 /* Check for overflow of the 64-bit unsigned number. As it should not reach here
339 in practical, we return a general error to prevent overflow theoretically. */
340 return(NX_NOT_SUCCESSFUL);
341 }
342 }
343 tls_session -> nx_secure_tls_remote_sequence_number[0]++;
344 }
345 }
346 else
347 #endif
348 {
349 /* Verify the hash MAC in the decrypted record. */
350 if (status)
351 {
352
353 /* !!! NOTE - the MAC check MUST always be performed regardless of the error state of
354 the payload decryption operation. Skipping the MAC check on padding failures
355 could enable a timing-based attack allowing an attacker to determine whether
356 padding was valid or not, causing an information leak. */
357 status = _nx_secure_tls_verify_mac(tls_session, header_data, header_length, packet_ptr, record_offset, &message_length);
358 }
359 else
360 {
361 status = _nx_secure_tls_verify_mac(tls_session, header_data, header_length, decrypted_packet, 0, &message_length);
362
363 if (status == NX_SECURE_TLS_SUCCESS)
364 {
365
366 /* Adjust packet length. */
367 decrypted_packet -> nx_packet_length = message_length;
368 }
369 }
370 }
371
372 /* Check to see if decryption or verification failed. */
373 if(error_status != NX_SECURE_TLS_SUCCESS)
374 {
375 /* Decryption failed. */
376 return(error_status);
377 }
378
379 if (status != NX_SECURE_TLS_SUCCESS)
380 {
381 /* MAC verification failed. */
382 return(status);
383 }
384
385 if (message_length > NX_SECURE_TLS_MAX_PLAINTEXT_LENGTH)
386 {
387 return(NX_SECURE_TLS_RECORD_OVERFLOW);
388 }
389
390 /* Trim packet. */
391 _nx_secure_tls_packet_trim(decrypted_packet);
392 }
393
394 if (message_type != NX_SECURE_TLS_APPLICATION_DATA)
395 {
396
397 /* For message other than application data, extract to packet buffer to make sure all data are in contiguous memory. */
398 /* Check available area of buffer. */
399 packet_data = tls_session -> nx_secure_tls_packet_buffer;
400 if (tls_session->nx_secure_tls_packet_buffer_bytes_copied + message_length > tls_session -> nx_secure_tls_packet_buffer_size)
401 {
402 return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
403 }
404
405 if (decrypted_packet == NX_NULL)
406 {
407 status = nx_packet_data_extract_offset(packet_ptr, record_offset,
408 tls_session -> nx_secure_tls_packet_buffer + tls_session->nx_secure_tls_packet_buffer_bytes_copied,
409 message_length, &bytes_copied);
410 }
411 else
412 {
413 status = nx_packet_data_extract_offset(decrypted_packet, 0,
414 tls_session -> nx_secure_tls_packet_buffer + tls_session->nx_secure_tls_packet_buffer_bytes_copied,
415 message_length, &bytes_copied);
416 }
417
418 if (status)
419 {
420 return(NX_SECURE_TLS_INVALID_PACKET);
421 }
422
423 tls_session -> nx_secure_tls_packet_buffer_bytes_copied += bytes_copied;
424
425 /* fragment is assembled, or continue to process another message in the same record, or need to read a new TCP packet. */
426 if (tls_session->nx_secure_tls_handshake_record_fragment_state == NX_SECURE_TLS_HANDSHAKE_RECEIVED_FRAGMENT)
427 {
428
429 if (tls_session -> nx_secure_tls_packet_buffer_bytes_copied > tls_session->nx_secure_tls_handshake_record_expected_length)
430 {
431 return(NX_SECURE_TLS_INVALID_PACKET);
432 }
433 /* All fragments are received and copied to tls_session -> nx_secure_tls_packet_buffer. */
434 else if (tls_session -> nx_secure_tls_packet_buffer_bytes_copied == tls_session->nx_secure_tls_handshake_record_expected_length)
435 {
436 tls_session->nx_secure_tls_handshake_record_fragment_state = NX_SECURE_TLS_HANDSHAKE_NO_FRAGMENT;
437 message_length = tls_session->nx_secure_tls_handshake_record_expected_length;
438 tls_session->nx_secure_tls_handshake_record_expected_length = 0;
439 }
440 else
441 {
442 /* process another message in the same record. */
443 record_offset += message_length;
444 status = NX_CONTINUE;
445 continue;
446 }
447 }
448 }
449
450 switch (message_type)
451 {
452 case NX_SECURE_TLS_CHANGE_CIPHER_SPEC:
453 /* Received a ChangeCipherSpec message - from now on all messages from remote host
454 will be encrypted using the session keys. */
455 _nx_secure_tls_process_changecipherspec(tls_session, packet_data, message_length);
456
457 break;
458 case NX_SECURE_TLS_ALERT:
459
460 if (message_length < 2)
461 {
462 status = NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH;
463 break;
464 }
465
466 /* We have received an alert. Check what the alert was and take appropriate action. */
467 /* The alert level is the first octet in the alert. The alert number is the second. */
468 if(packet_data[0] == NX_SECURE_TLS_ALERT_LEVEL_FATAL)
469 {
470 /* If we receive a fatal alert, clear all session keys. */
471 _nx_secure_tls_session_reset(tls_session);
472 }
473
474 /* Save off the alert level and value for the application to access. */
475 tls_session->nx_secure_tls_received_alert_level = packet_data[0];
476 tls_session->nx_secure_tls_received_alert_value = packet_data[1];
477 /* We have received an alert. Check what the alert was and take appropriate action. */
478 status = NX_SECURE_TLS_ALERT_RECEIVED;
479 break;
480 case NX_SECURE_TLS_HANDSHAKE:
481 #if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_CLIENT_DISABLED)
482 /* TLS 1.3 can send post-handshake messages with TLS HANDSHAKE record type. Process those separately. */
483 if(tls_session->nx_secure_tls_1_3 && tls_session -> nx_secure_tls_client_state == NX_SECURE_TLS_CLIENT_STATE_HANDSHAKE_FINISHED)
484 {
485 /* Process post-handshake messages. */
486 status = NX_SECURE_TLS_POST_HANDSHAKE_RECEIVED;
487 break;
488 }
489 #endif /* (NX_SECURE_TLS_TLS_1_3_ENABLED) */
490
491 #ifndef NX_SECURE_TLS_SERVER_DISABLED
492 /* The socket is a TLS server, so process incoming handshake messages in that context. */
493 if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_SERVER)
494 {
495 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
496 if(tls_session->nx_secure_tls_1_3)
497 {
498 status = _nx_secure_tls_1_3_server_handshake(tls_session, packet_data, message_length, wait_option);
499
500 if ((status == NX_SUCCESS) && (tls_session -> nx_secure_tls_1_3 == NX_FALSE))
501 {
502
503 /* Negotiate a version of TLS prior to TLS 1.3. */
504 /* Handle the ClientHello packet by legacy routine. */
505 status = _nx_secure_tls_server_handshake(tls_session, packet_data, message_length, wait_option);
506 }
507 }
508 else
509 #endif
510 {
511 status = _nx_secure_tls_server_handshake(tls_session, packet_data, message_length, wait_option);
512 }
513 }
514 #endif
515
516
517 #ifndef NX_SECURE_TLS_CLIENT_DISABLED
518 /* The socket is a TLS client, so process incoming handshake messages in that context. */
519 if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_CLIENT)
520 {
521 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
522 if(tls_session->nx_secure_tls_1_3)
523 {
524 status = _nx_secure_tls_1_3_client_handshake(tls_session, packet_data, message_length, wait_option);
525 if ((status == NX_SUCCESS) && (tls_session -> nx_secure_tls_1_3 == NX_FALSE))
526 {
527
528 /* Server negotiates a version of TLS prior to TLS 1.3. */
529 #ifdef NX_SECURE_TLS_DISABLE_PROTOCOL_VERSION_DOWNGRADE
530 /* Protocol version downgrade is disabled. Return error status. */
531 status = NX_SECURE_TLS_UNSUPPORTED_TLS_VERSION;
532 #else
533 /* Handle the ServerHello packet by legacy routine. */
534 _nx_secure_tls_handshake_hash_init(tls_session);
535 status = _nx_secure_tls_client_handshake(tls_session, packet_data, message_length, wait_option);
536 #endif /* NX_SECURE_TLS_DISABLE_PROTOCOL_VERSION_DOWNGRADE */
537 }
538 }
539 else
540 #endif
541 {
542 status = _nx_secure_tls_client_handshake(tls_session, packet_data, message_length, wait_option);
543 }
544
545 }
546
547 #endif
548
549 if (status == NX_SECURE_TLS_HANDSHAKE_FRAGMENT_RECEIVED)
550 {
551 /* Update record_offset.*/
552 record_offset = record_offset_next;
553
554 /* Check if reaching the end of this TCP packet. */
555 if (record_offset == packet_ptr -> nx_packet_length)
556 {
557 /* Wait more TCP packets for this one record, save record_offset and bytes_processed for next record processing. */
558 tls_session -> nx_secure_tls_record_offset = record_offset;
559 tls_session -> nx_secure_tls_bytes_processed = *bytes_processed;
560 return(NX_CONTINUE);
561 }
562 else
563 {
564 /* Did not reach the end, continue to process this packet. */
565 status = NX_CONTINUE;
566 }
567 }
568
569 break;
570 case NX_SECURE_TLS_APPLICATION_DATA:
571 /* The remote host is sending application data records now. Pass decrypted data back
572 to the networking API for the application to process. */
573
574 /* First, check for 0-length records. These can be sent but are internal to TLS so tell the
575 caller to continue receiving. 0-length records are sent as part of the BEAST attack
576 mitigation by some TLS implementations (notably OpenSSL). */
577 if (message_length == 0)
578 {
579 record_offset = record_offset_next;
580 status = NX_CONTINUE;
581 }
582 else
583 {
584 status = NX_SECURE_TLS_SUCCESS;
585 }
586 break;
587 default:
588 /* An unrecognized message was received, likely an error, possibly an attack. */
589 status = NX_SECURE_TLS_UNRECOGNIZED_MESSAGE_TYPE;
590 break;
591 }
592
593 #ifdef NX_SECURE_KEY_CLEAR
594 if ((message_type != NX_SECURE_TLS_APPLICATION_DATA) &&
595 (status != NX_CONTINUE))
596 {
597 NX_SECURE_MEMSET(packet_data, 0, message_length);
598 }
599 #endif /* NX_SECURE_KEY_CLEAR */
600 }
601
602 return(status);
603 }
604
605 /**************************************************************************/
606 /* */
607 /* FUNCTION RELEASE */
608 /* */
609 /* _nx_secure_tls_packet_trim PORTABLE C */
610 /* 6.1 */
611 /* AUTHOR */
612 /* */
613 /* Timothy Stapko, Microsoft Corporation */
614 /* */
615 /* DESCRIPTION */
616 /* */
617 /* This function trims TLS packet after decryption and hash verify. */
618 /* */
619 /* INPUT */
620 /* */
621 /* packet_ptr NX_PACKET containing a record */
622 /* */
623 /* OUTPUT */
624 /* */
625 /* status Completion status */
626 /* */
627 /* CALLS */
628 /* */
629 /* nx_secure_tls_packet_release Release packet */
630 /* */
631 /* CALLED BY */
632 /* */
633 /* _nx_secure_tls_process_record Process TLS records */
634 /* */
635 /* RELEASE HISTORY */
636 /* */
637 /* DATE NAME DESCRIPTION */
638 /* */
639 /* 09-30-2020 Timothy Stapko Initial Version 6.1 */
640 /* */
641 /**************************************************************************/
_nx_secure_tls_packet_trim(NX_PACKET * packet_ptr)642 static VOID _nx_secure_tls_packet_trim(NX_PACKET *packet_ptr)
643 {
644 ULONG payload_length;
645 ULONG message_length = packet_ptr -> nx_packet_length;
646 NX_PACKET *current_ptr;
647
648 if (message_length == 0)
649 {
650
651 /* Make sure the head packet is not released when the length is zero. */
652 if (packet_ptr -> nx_packet_next)
653 {
654
655 /* Release packet if remaining data are in chained packet. */
656 nx_secure_tls_packet_release(packet_ptr -> nx_packet_next);
657 packet_ptr -> nx_packet_next = NX_NULL;
658 packet_ptr -> nx_packet_last = packet_ptr;
659 }
660 packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_data_start;
661 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_data_start;
662 return;
663 }
664
665 for (current_ptr = packet_ptr; current_ptr; current_ptr = current_ptr -> nx_packet_next)
666 {
667 payload_length = (ULONG)(current_ptr -> nx_packet_append_ptr - current_ptr -> nx_packet_prepend_ptr);
668 if (message_length < payload_length)
669 {
670
671 /* Trim data from this packet. */
672 current_ptr -> nx_packet_append_ptr = current_ptr -> nx_packet_prepend_ptr + message_length;
673 if (current_ptr -> nx_packet_next)
674 {
675
676 /* Release packet if remaining data are in chained packet. */
677 nx_secure_tls_packet_release(current_ptr -> nx_packet_next);
678 current_ptr -> nx_packet_next = NX_NULL;
679 packet_ptr -> nx_packet_last = current_ptr;
680 }
681 break;
682 }
683 message_length -= (ULONG)(current_ptr -> nx_packet_append_ptr - current_ptr -> nx_packet_prepend_ptr);
684 }
685 }
686