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 /**************************************************************************/
27 /*                                                                        */
28 /*  FUNCTION                                               RELEASE        */
29 /*                                                                        */
30 /*    _nx_secure_tls_session_end                          PORTABLE C      */
31 /*                                                           6.1          */
32 /*  AUTHOR                                                                */
33 /*                                                                        */
34 /*    Timothy Stapko, Microsoft Corporation                               */
35 /*                                                                        */
36 /*  DESCRIPTION                                                           */
37 /*                                                                        */
38 /*    This function ends an active TLS session by sending the TLS         */
39 /*    CloseNotify alert to the remote host, then waiting for the response */
40 /*    CloseNotify before returning.                                       */
41 /*                                                                        */
42 /*  INPUT                                                                 */
43 /*                                                                        */
44 /*    tls_session                           TLS control block             */
45 /*    wait_option                           Indicates how long the caller */
46 /*                                          should wait for the response  */
47 /*                                                                        */
48 /*  OUTPUT                                                                */
49 /*                                                                        */
50 /*    status                                Completion status             */
51 /*                                                                        */
52 /*  CALLS                                                                 */
53 /*                                                                        */
54 /*    _nx_secure_tls_packet_allocate        Allocate internal TLS packet  */
55 /*    _nx_secure_tls_send_alert             Generate the CloseNotify      */
56 /*    _nx_secure_tls_send_record            Send the CloseNotify          */
57 /*    _nx_secure_tls_session_reset          Clear out the session         */
58 /*    nx_secure_tls_packet_release          Release packet                */
59 /*    tx_mutex_get                          Get protection mutex          */
60 /*    tx_mutex_put                          Put protection mutex          */
61 /*                                                                        */
62 /*  CALLED BY                                                             */
63 /*                                                                        */
64 /*    Application Code                                                    */
65 /*                                                                        */
66 /*  RELEASE HISTORY                                                       */
67 /*                                                                        */
68 /*    DATE              NAME                      DESCRIPTION             */
69 /*                                                                        */
70 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
71 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
72 /*                                            supported chained packet,   */
73 /*                                            resulting in version 6.1    */
74 /*                                                                        */
75 /**************************************************************************/
_nx_secure_tls_session_end(NX_SECURE_TLS_SESSION * tls_session,UINT wait_option)76 UINT  _nx_secure_tls_session_end(NX_SECURE_TLS_SESSION *tls_session, UINT wait_option)
77 {
78 UINT       status;
79 UINT       error_return;
80 UINT       send_close_notify;
81 NX_PACKET *send_packet;
82 NX_PACKET *tmp_ptr;
83 
84     /* Get the protection. */
85     tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
86 
87     /* Release packets in queue. */
88     while (tls_session -> nx_secure_record_queue_header)
89     {
90         tmp_ptr = tls_session -> nx_secure_record_queue_header;
91         tls_session -> nx_secure_record_queue_header = tmp_ptr -> nx_packet_queue_next;
92         tmp_ptr -> nx_packet_queue_next = NX_NULL;
93         nx_secure_tls_packet_release(tmp_ptr);
94     }
95     if (tls_session -> nx_secure_record_decrypted_packet)
96     {
97         nx_secure_tls_packet_release(tls_session -> nx_secure_record_decrypted_packet);
98         tls_session -> nx_secure_record_decrypted_packet = NX_NULL;
99     }
100 
101     /* See if we want to send a CloseNotify alert, or if there was an error, don't send
102        a CloseNotify, just reset the TLS session. */
103     send_close_notify = 0;
104 
105 #ifndef NX_SECURE_TLS_SERVER_DISABLED
106     /* Only send a CloseNotify if the handshake was finished. */
107     if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_SERVER)
108     {
109         send_close_notify = tls_session -> nx_secure_tls_server_state == NX_SECURE_TLS_SERVER_STATE_HANDSHAKE_FINISHED;
110     }
111 #endif
112 
113 #ifndef NX_SECURE_TLS_CLIENT_DISABLED
114     if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_CLIENT)
115     {
116         send_close_notify = tls_session -> nx_secure_tls_client_state == NX_SECURE_TLS_CLIENT_STATE_HANDSHAKE_FINISHED;
117     }
118 #endif
119 
120     if (send_close_notify)
121     {
122         /* Release the protection before suspending on nx_packet_allocate. */
123         tx_mutex_put(&_nx_secure_tls_protection);
124 
125         /* Allocate a packet for our close-notify alert. */
126         status = _nx_secure_tls_packet_allocate(tls_session, tls_session -> nx_secure_tls_packet_pool, &send_packet, wait_option);
127 
128         /* Check for errors in allocating packet. */
129         if (status != NX_SUCCESS)
130         {
131             /* Save the return status before resetting the TLS session. */
132             error_return = status;
133 
134             /* Reset the TLS state so this socket can be reused. */
135             status = _nx_secure_tls_session_reset(tls_session);
136 
137 
138             if(status != NX_SUCCESS)
139             {
140                 return(status);
141             }
142 
143             return(error_return);
144         }
145 
146         /* Get the protection after nx_packet_allocate. */
147         tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
148 
149         /* A close-notify alert shuts down the TLS session cleanly. */
150         _nx_secure_tls_send_alert(tls_session, send_packet, NX_SECURE_TLS_ALERT_CLOSE_NOTIFY, NX_SECURE_TLS_ALERT_LEVEL_WARNING);
151 
152         /* Finally, send the alert record to the remote host. */
153         status = _nx_secure_tls_send_record(tls_session, send_packet, NX_SECURE_TLS_ALERT, wait_option);
154 
155         if (status)
156         {
157             /* Release the packet on send errors. */
158             nx_secure_tls_packet_release(send_packet);
159 
160             /* Release the protection. */
161             tx_mutex_put(&_nx_secure_tls_protection);
162 
163             /* Save the return status before resetting the TLS session. */
164             error_return = status;
165 
166             /* Reset the TLS state so this socket can be reused. */
167             status = _nx_secure_tls_session_reset(tls_session);
168 
169 
170             if(status != NX_SUCCESS)
171             {
172                 return(status);
173             }
174 
175             return(error_return);
176         }
177     }
178 
179     /* Release the protection. */
180     tx_mutex_put(&_nx_secure_tls_protection);
181 
182     /* Reset the TLS state so this socket can be reused. */
183     status = _nx_secure_tls_session_reset(tls_session);
184 
185     return(status);
186 }
187 
188