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