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_server_create PORTABLE C */
31 /* 6.1 */
32 /* AUTHOR */
33 /* */
34 /* Timothy Stapko, Microsoft Corporation */
35 /* */
36 /* DESCRIPTION */
37 /* */
38 /* This function creates an instance of a DTLS server to handle */
39 /* incoming DTLS requests on a particular UDP port. Due to the fact */
40 /* that UDP is stateless, DTLS requests from multiple clients can come */
41 /* in on a single port while other DTLS sessions are active. Thus, the */
42 /* server is needed to maintain active sessions and properly route */
43 /* incoming messages to the proper handler. */
44 /* */
45 /* The session buffer parameter is used to hold the control blocks for */
46 /* all the possible simultaneous DTLS sessions for the DTLS server. It */
47 /* should be allocated with a size that is an even multiple of the */
48 /* size of the NX_SECURE_DTLS_SESSION control block structure. */
49 /* */
50 /* To calculate the necessary metadata size, the API */
51 /* nx_secure_tls_metadata_size_calculate may be used. */
52 /* */
53 /* INPUT */
54 /* */
55 /* server_ptr DTLS server control block */
56 /* ip_ptr Pointer to IP instance */
57 /* port Server port */
58 /* timeout Timeout value */
59 /* session_buffer DTLS sessions buffer */
60 /* session_buffer_size Size of DTLS sessions buffer */
61 /* crypto_table Crypto table */
62 /* crypto_metadata_buffer Encryption metadata buffer */
63 /* crypto_metadata_size Encryption metadata size */
64 /* packet_reassembly_buffer DTLS reassembly buffer */
65 /* packet_reassembly_buffer_size Size of reassembly buffer */
66 /* connect_notify Callback for new connections */
67 /* receive_notify Callback for received data */
68 /* */
69 /* OUTPUT */
70 /* */
71 /* status Completion status */
72 /* */
73 /* CALLS */
74 /* */
75 /* _nx_secure_dtls_session_create Initialize DTLS control block */
76 /* nx_udp_socket_create Set up UDP socket */
77 /* tx_mutex_get Get protection mutex */
78 /* tx_mutex_put Put protection mutex */
79 /* */
80 /* CALLED BY */
81 /* */
82 /* Application Code */
83 /* */
84 /* RELEASE HISTORY */
85 /* */
86 /* DATE NAME DESCRIPTION */
87 /* */
88 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
89 /* 09-30-2020 Timothy Stapko Modified comment(s), */
90 /* resulting in version 6.1 */
91 /* */
92 /**************************************************************************/
_nx_secure_dtls_server_create(NX_SECURE_DTLS_SERVER * server_ptr,NX_IP * ip_ptr,UINT port,ULONG timeout,VOID * session_buffer,UINT session_buffer_size,const NX_SECURE_TLS_CRYPTO * crypto_table,VOID * crypto_metadata_buffer,ULONG crypto_metadata_size,UCHAR * packet_reassembly_buffer,UINT packet_reassembly_buffer_size,UINT (* connect_notify)(NX_SECURE_DTLS_SESSION * dtls_session,NXD_ADDRESS * ip_address,UINT port),UINT (* receive_notify)(NX_SECURE_DTLS_SESSION * dtls_session))93 UINT _nx_secure_dtls_server_create(NX_SECURE_DTLS_SERVER *server_ptr, NX_IP *ip_ptr, UINT port, ULONG timeout,
94 VOID *session_buffer, UINT session_buffer_size,
95 const NX_SECURE_TLS_CRYPTO *crypto_table,
96 VOID *crypto_metadata_buffer, ULONG crypto_metadata_size,
97 UCHAR *packet_reassembly_buffer, UINT packet_reassembly_buffer_size,
98 UINT (*connect_notify)(NX_SECURE_DTLS_SESSION *dtls_session, NXD_ADDRESS *ip_address, UINT port),
99 UINT (*receive_notify)(NX_SECURE_DTLS_SESSION *dtls_session))
100 {
101 #ifdef NX_SECURE_ENABLE_DTLS
102 UINT status;
103 UINT i;
104 NX_SECURE_DTLS_SESSION *current_session;
105 ULONG session_metadata_size;
106 UINT session_pkt_buffer_size;
107 UCHAR *session_pkt_buffer;
108 UCHAR *session_metadata;
109 UINT num_sessions;
110 NX_SECURE_DTLS_SERVER *tail_ptr;
111
112 /* Figure out number of sessions. */
113 num_sessions = session_buffer_size / sizeof(NX_SECURE_DTLS_SESSION);
114
115 /* Check sessions buffer size. */
116 if(num_sessions == 0)
117 {
118 return(NX_INVALID_PARAMETERS);
119 }
120
121 /* Set server parameters. */
122 server_ptr->nx_dtls_server_ip_ptr = ip_ptr;
123 server_ptr->nx_dtls_server_listen_port = port;
124 server_ptr->nx_dtls_server_sessions_count = num_sessions;
125 server_ptr->nx_dtls_server_timeout = timeout;
126
127 /* Set up session buffer. */
128 server_ptr->nx_dtls_server_sessions = (NX_SECURE_DTLS_SESSION*)session_buffer;
129
130 /* Setup per-session packet buffer. */
131 session_pkt_buffer_size = packet_reassembly_buffer_size / num_sessions;
132 session_pkt_buffer = packet_reassembly_buffer;
133
134 /* Get our per-session metadata. */
135 session_metadata = crypto_metadata_buffer;
136 session_metadata_size = crypto_metadata_size / num_sessions;
137
138 /* Set up UDP socket. */
139 status = nx_udp_socket_create(ip_ptr, &(server_ptr->nx_dtls_server_udp_socket), "DTLS Server",
140 NX_IP_NORMAL, NX_FRAGMENT_OKAY, timeout, 8192);
141
142 /* Store a pointer to our DTLS server instance in our UDP socket.
143 This enables the receive callback to access the right server. */
144 server_ptr->nx_dtls_server_udp_socket.nx_udp_socket_reserved_ptr = server_ptr;
145
146 if(status != NX_SUCCESS)
147 {
148 return(status);
149 }
150
151 /* Assign callbacks. */
152 server_ptr->nx_secure_dtls_receive_notify = receive_notify;
153 server_ptr->nx_secure_dtls_connect_notify = connect_notify;
154
155 /* Reset the protocol version override. */
156 server_ptr -> nx_dtls_server_protocol_version_override = 0;
157
158 /* Initialize sessions. */
159 for(i = 0; i < num_sessions; ++i)
160 {
161 /* Get the current session. */
162 current_session = &(server_ptr->nx_dtls_server_sessions[i]);
163
164 /* Initialize each DTLS session - don't add remote certificate data here. */
165 status = _nx_secure_dtls_session_create(current_session, crypto_table, session_metadata, session_metadata_size,
166 session_pkt_buffer, session_pkt_buffer_size, 0, NX_NULL, 0);
167
168 if(status != NX_SUCCESS)
169 {
170
171 /* Delete the created UDP socket. */
172 nx_udp_socket_delete(&(server_ptr->nx_dtls_server_udp_socket));
173 return(status);
174 }
175
176 /* Assign the parent server instance. */
177 current_session->nx_secure_dtls_server_parent = server_ptr;
178
179 /* Assign other parameters. */
180 current_session->nx_secure_dtls_local_port = port;
181 current_session->nx_secure_dtls_udp_socket = &(server_ptr->nx_dtls_server_udp_socket);
182
183 /* Advance metadata buffer. */
184 session_metadata = &session_metadata[session_metadata_size];
185
186 /* Advance packet buffer. */
187 session_pkt_buffer = &session_pkt_buffer[session_pkt_buffer_size];
188 }
189
190 /* Get the protection. */
191 tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
192
193 /* Place the new DTLS server control block on the list of created DTLS server. */
194 if (_nx_secure_dtls_server_created_ptr)
195 {
196
197 /* Pickup tail pointer. */
198 tail_ptr = _nx_secure_dtls_server_created_ptr -> nx_dtls_server_created_previous;
199
200 /* Place the new DTLS server control block in the list. */
201 _nx_secure_dtls_server_created_ptr -> nx_dtls_server_created_previous = server_ptr;
202 tail_ptr -> nx_dtls_server_created_next = server_ptr;
203
204 /* Setup this DTLS server's created links. */
205 server_ptr -> nx_dtls_server_created_previous = tail_ptr;
206 server_ptr -> nx_dtls_server_created_next = _nx_secure_dtls_server_created_ptr;
207 }
208 else
209 {
210
211 /* The created DTLS server list is empty. Add DTLS server control block to empty list. */
212 _nx_secure_dtls_server_created_ptr = server_ptr;
213 server_ptr -> nx_dtls_server_created_previous = server_ptr;
214 server_ptr -> nx_dtls_server_created_next = server_ptr;
215 }
216 _nx_secure_dtls_server_created_count++;
217
218 /* Release the protection. */
219 tx_mutex_put(&_nx_secure_tls_protection);
220
221 return(NX_SUCCESS);
222 #else
223 NX_PARAMETER_NOT_USED(server_ptr);
224 NX_PARAMETER_NOT_USED(ip_ptr);
225 NX_PARAMETER_NOT_USED(port);
226 NX_PARAMETER_NOT_USED(timeout);
227 NX_PARAMETER_NOT_USED(session_buffer);
228 NX_PARAMETER_NOT_USED(session_buffer_size);
229 NX_PARAMETER_NOT_USED(crypto_table);
230 NX_PARAMETER_NOT_USED(crypto_metadata_buffer);
231 NX_PARAMETER_NOT_USED(crypto_metadata_size);
232 NX_PARAMETER_NOT_USED(packet_reassembly_buffer);
233 NX_PARAMETER_NOT_USED(packet_reassembly_buffer_size);
234 NX_PARAMETER_NOT_USED(connect_notify);
235 NX_PARAMETER_NOT_USED(receive_notify);
236
237
238 return(NX_NOT_SUPPORTED);
239 #endif /* NX_SECURE_ENABLE_DTLS */
240 }
241
242