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 /** Datagram Transport Layer Security (DTLS) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_SECURE_SOURCE_CODE
23
24 #include "nx_secure_dtls.h"
25
26 /**************************************************************************/
27 /* */
28 /* FUNCTION RELEASE */
29 /* */
30 /* _nx_secure_dtls_session_start PORTABLE C */
31 /* 6.1 */
32 /* AUTHOR */
33 /* */
34 /* Timothy Stapko, Microsoft Corporation */
35 /* */
36 /* DESCRIPTION */
37 /* */
38 /* This function starts a DTLS session given a UDP socket. */
39 /* */
40 /* INPUT */
41 /* */
42 /* dtls_session DTLS control block */
43 /* udp_socket UDP socket pointer */
44 /* is_client Is client or server */
45 /* wait_option Suspension option */
46 /* */
47 /* OUTPUT */
48 /* */
49 /* status Completion status */
50 /* */
51 /* CALLS */
52 /* */
53 /* _nx_secure_dtls_allocate_handshake_packet */
54 /* Allocate DTLS handshake packet*/
55 /* _nx_secure_dtls_retransmit Retransmit UDP packet */
56 /* _nx_secure_dtls_retransmit_queue_flush */
57 /* Flush retransmit queue */
58 /* _nx_secure_dtls_send_clienthello Send ClientHello */
59 /* _nx_secure_dtls_send_handshake_record Send DTLS handshake record */
60 /* _nx_secure_dtls_session_receive Receive DTLS data */
61 /* nx_secure_tls_packet_release Release packet */
62 /* tx_mutex_get Get protection mutex */
63 /* tx_mutex_put Put protection mutex */
64 /* */
65 /* CALLED BY */
66 /* */
67 /* Application Code */
68 /* _nx_secure_dtls_client_session_start Client session start */
69 /* _nx_secure_dtls_server_session_start Server session start */
70 /* */
71 /* RELEASE HISTORY */
72 /* */
73 /* DATE NAME DESCRIPTION */
74 /* */
75 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
76 /* 09-30-2020 Timothy Stapko Modified comment(s), */
77 /* released packet securely, */
78 /* fixed renegotiation bug, */
79 /* resulting in version 6.1 */
80 /* */
81 /**************************************************************************/
_nx_secure_dtls_session_start(NX_SECURE_DTLS_SESSION * dtls_session,NX_UDP_SOCKET * udp_socket,UINT is_client,UINT wait_option)82 UINT _nx_secure_dtls_session_start(NX_SECURE_DTLS_SESSION *dtls_session, NX_UDP_SOCKET *udp_socket,
83 UINT is_client, UINT wait_option)
84 {
85 #ifdef NX_SECURE_ENABLE_DTLS
86 UINT status = NX_NOT_SUCCESSFUL;
87 NX_PACKET *incoming_packet;
88
89 NX_SECURE_TLS_SESSION *tls_session;
90
91 UINT minimum_wait_option;
92
93 #ifndef NX_SECURE_TLS_CLIENT_DISABLED
94 NX_PACKET *send_packet;
95 #endif
96
97 /* Get the protection. */
98 tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
99
100 /* Get reference to internal TLS state. */
101 tls_session = &dtls_session -> nx_secure_dtls_tls_session;
102
103 /* Assign the packet pool from which TLS will allocate internal message packets. */
104 tls_session -> nx_secure_tls_packet_pool = udp_socket -> nx_udp_socket_ip_ptr -> nx_ip_default_packet_pool;
105
106 /* Make sure we are starting with a fresh session. */
107 tls_session -> nx_secure_tls_received_remote_credentials = NX_FALSE;
108
109 #ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION
110
111 /* Renegotiation is not enabled in DTLS session. */
112 tls_session -> nx_secure_tls_renegotation_enabled = NX_FALSE;
113 #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */
114
115 /* Assign the TCP socket to the TLS session. */
116 dtls_session -> nx_secure_dtls_udp_socket = udp_socket;
117
118 /* Reset the record queue. */
119 tls_session -> nx_secure_record_queue_header = NX_NULL;
120 tls_session -> nx_secure_record_decrypted_packet = NX_NULL;
121
122 /* See if this is a TCP server started with listen/accept, or a TCP client started with connect. */
123 if (is_client)
124 {
125 /* The TCP socket is a client, so our TLS session is a TLS Client. */
126 tls_session -> nx_secure_tls_socket_type = NX_SECURE_TLS_SESSION_TYPE_CLIENT;
127 }
128 else
129 {
130 /* This session is now being treated as a server - indicate that fact to the TLS stack. */
131 tls_session -> nx_secure_tls_socket_type = NX_SECURE_TLS_SESSION_TYPE_SERVER;
132 }
133
134 /* Now process the handshake depending on the TLS session type. */
135 #ifndef NX_SECURE_TLS_CLIENT_DISABLED
136 if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_CLIENT)
137 {
138
139 /* Allocate a handshake packet so we can send the ClientHello. */
140 status = _nx_secure_dtls_allocate_handshake_packet(dtls_session, tls_session -> nx_secure_tls_packet_pool, &send_packet, wait_option);
141
142 if (status != NX_SUCCESS)
143 {
144
145 /* Release the protection. */
146 tx_mutex_put(&_nx_secure_tls_protection);
147 return(status);
148 }
149
150 /* Populate our packet with clienthello data. */
151 status = _nx_secure_dtls_send_clienthello(dtls_session, send_packet);
152
153 if (status == NX_SUCCESS)
154 {
155
156 /* Send the ClientHello to kick things off. */
157 status = _nx_secure_dtls_send_handshake_record(dtls_session, send_packet, NX_SECURE_TLS_CLIENT_HELLO, wait_option, 0);
158
159 /* Clear the protocol version to avoid checking the version in the HelloVerifyRequest which is always DTLS 1.0. */
160 tls_session->nx_secure_tls_protocol_version = 0;
161 }
162
163 /* If anything after the allocate fails, we need to release our packet. */
164 if (status != NX_SUCCESS)
165 {
166
167 /* Release the protection. */
168 tx_mutex_put(&_nx_secure_tls_protection);
169 nx_secure_tls_packet_release(send_packet);
170 return(status);
171 }
172 }
173 #endif
174
175 /* Now handle our incoming handshake messages. Continue processing until the handshake is complete
176 * or an error/timeout occurs. */
177 for (;;)
178 {
179 #ifndef NX_SECURE_TLS_CLIENT_DISABLED
180 if ((tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_CLIENT) &&
181 (tls_session -> nx_secure_tls_client_state == NX_SECURE_TLS_CLIENT_STATE_HANDSHAKE_FINISHED))
182 {
183 break;
184 }
185 #endif
186
187 #ifndef NX_SECURE_TLS_SERVER_DISABLED
188 if ((tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_SERVER) &&
189 (tls_session -> nx_secure_tls_server_state == NX_SECURE_TLS_SERVER_STATE_HANDSHAKE_FINISHED))
190 {
191 break;
192 }
193 #endif
194
195 if ((dtls_session -> nx_secure_dtls_handshake_timeout > wait_option) ||
196 (dtls_session -> nx_secure_dtls_handshake_timeout == 0) ||
197 (dtls_session -> nx_secure_dtls_transmit_sent_head == NX_NULL))
198 {
199 minimum_wait_option = wait_option;
200 }
201 else
202 {
203 minimum_wait_option = dtls_session -> nx_secure_dtls_handshake_timeout;
204 }
205
206 /* Release the protection. */
207 tx_mutex_put(&_nx_secure_tls_protection);
208
209 status = _nx_secure_dtls_session_receive(dtls_session, &incoming_packet,
210 minimum_wait_option);
211
212 /* Get the protection. */
213 tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
214
215 /* Make sure we didn't have an error during the receive. */
216 if (status != NX_SUCCESS)
217 {
218
219 /* Check error status. */
220 if (status != NX_NO_PACKET && status != NX_CONTINUE)
221 {
222 break;
223 }
224
225 if (minimum_wait_option == wait_option)
226 {
227 break;
228 }
229
230 if (dtls_session -> nx_secure_dtls_timeout_retries >=
231 NX_SECURE_DTLS_MAXIMUM_RETRANSMIT_RETRIES)
232 {
233 break;
234 }
235
236 /* Retransmit timeout. */
237 _nx_secure_dtls_retransmit(dtls_session);
238
239 /* Decrease the wait option. */
240 wait_option -= minimum_wait_option;
241 }
242 else
243 {
244
245 /* On any error, the handshake has failed so break out of our processing loop and return. */
246 nx_secure_tls_packet_release(incoming_packet);
247 }
248 }
249
250 /* This is the end of a flight, clear out the transmit queue. */
251 _nx_secure_dtls_retransmit_queue_flush(dtls_session);
252
253 /* Release the protection. */
254 tx_mutex_put(&_nx_secure_tls_protection);
255
256 return(status);
257 #else
258 NX_PARAMETER_NOT_USED(dtls_session);
259 NX_PARAMETER_NOT_USED(udp_socket);
260 NX_PARAMETER_NOT_USED(is_client);
261 NX_PARAMETER_NOT_USED(wait_option);
262
263 return(NX_NOT_SUPPORTED);
264 #endif /* NX_SECURE_ENABLE_DTLS */
265 }
266
267