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