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