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