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