1 /* This test concentrates on DTLS connections.  */
2 
3 #include   "nx_api.h"
4 #include   "nx_secure_dtls_api.h"
5 #include   "test_ca_cert.c"
6 #include   "test_device_cert.c"
7 
8 extern VOID    test_control_return(UINT status);
9 
10 
11 #if !defined(NX_SECURE_TLS_CLIENT_DISABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED) && defined(NX_SECURE_ENABLE_DTLS)
12 #define NUM_PACKETS                 24
13 #define PACKET_SIZE                 1536
14 #define PACKET_POOL_SIZE            (NUM_PACKETS * (PACKET_SIZE + sizeof(NX_PACKET)))
15 #define THREAD_STACK_SIZE           1024
16 #define ARP_CACHE_SIZE              1024
17 #define BUFFER_SIZE                 64
18 #define METADATA_SIZE               16000
19 #define CERT_BUFFER_SIZE            (2048 + sizeof(NX_SECURE_X509_CERT))
20 #define PSK                         "simple_psk"
21 #define PSK_IDENTITY                "psk_indentity"
22 #define PSK_HINT                    "psk_hint"
23 #define SERVER_PORT                 4433
24 
25 
26 /* Define the ThreadX and NetX object control blocks...  */
27 
28 static TX_THREAD                thread_0;
29 static TX_THREAD                thread_1;
30 static NX_PACKET_POOL           pool_0;
31 static NX_IP                    ip_0;
32 static UINT                     error_counter;
33 
34 static NX_UDP_SOCKET            client_socket_0;
35 static NX_SECURE_DTLS_SESSION   dtls_client_session_0;
36 static NX_SECURE_DTLS_SERVER    dtls_server_0;
37 static NX_SECURE_X509_CERT      client_trusted_ca;
38 static NX_SECURE_X509_CERT      client_remote_cert;
39 static NX_SECURE_X509_CERT      server_local_certificate;
40 extern const NX_SECURE_TLS_CRYPTO
41                                 nx_crypto_tls_ciphers;
42 
43 static ULONG                    pool_0_memory[PACKET_POOL_SIZE / sizeof(ULONG)];
44 static ULONG                    thread_0_stack[THREAD_STACK_SIZE / sizeof(ULONG)];
45 static ULONG                    thread_1_stack[THREAD_STACK_SIZE / sizeof(ULONG)];
46 static ULONG                    ip_0_stack[THREAD_STACK_SIZE / sizeof(ULONG)];
47 static ULONG                    arp_cache[ARP_CACHE_SIZE];
48 static UCHAR                    client_metadata[METADATA_SIZE];
49 static UCHAR                    server_metadata[METADATA_SIZE];
50 static UCHAR                    client_cert_buffer[CERT_BUFFER_SIZE];
51 
52 static UCHAR                    request_buffer[BUFFER_SIZE];
53 static UCHAR                    response_buffer[BUFFER_SIZE];
54 static UCHAR                    tls_packet_buffer[2][4000];
55 static UINT                     drop_packet_sequence[] =
56 {
57     0,  /* ClientHello */
58     2,  /* ClientHello_Verify */
59     7,  /* Certificate */
60 };
61 static UINT                     packet_sequence;
62 static UINT                     drop_index;
63 
64 /* Session buffer for DTLS server. Must be equal to the size of NX_SECURE_DTLS_SESSION times the
65    number of desired DTLS sessions. */
66 static UCHAR                    server_session_buffer[sizeof(NX_SECURE_DTLS_SESSION)];
67 
68 /* Define thread prototypes.  */
69 
70 static VOID    ntest_0_entry(ULONG thread_input);
71 static VOID    ntest_1_entry(ULONG thread_input);
72 extern VOID    _nx_ram_network_driver_1500(struct NX_IP_DRIVER_STRUCT *driver_req);
73 extern VOID    _nx_udp_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
74 
75 static TX_SEMAPHORE            semaphore_receive;
76 static TX_SEMAPHORE            semaphore_connect;
77 
78 
79 /* Define what the initial system looks like.  */
80 
81 
ERROR_COUNTER()82 static VOID    ERROR_COUNTER()
83 {
84     error_counter++;
85 }
86 
87 #ifdef CTEST
88 void test_application_define(void *first_unused_memory);
test_application_define(void * first_unused_memory)89 void test_application_define(void *first_unused_memory)
90 #else
91 VOID    nx_secure_dtls_retransmit_test_application_define(void *first_unused_memory)
92 #endif
93 {
94 UINT     status;
95 CHAR    *pointer;
96 
97 
98     error_counter = 0;
99     packet_sequence = 0;
100     drop_index = 0;
101 
102 
103     /* Setup the working pointer.  */
104     pointer =  (CHAR *) first_unused_memory;
105 
106     /* Create the server thread.  */
107     tx_thread_create(&thread_0, "thread 0", ntest_0_entry, 0,
108                      thread_0_stack, sizeof(thread_0_stack),
109                      7, 7, TX_NO_TIME_SLICE, TX_AUTO_START);
110 
111     /* Create the client thread.  */
112     tx_thread_create(&thread_1, "thread 1", ntest_1_entry, 0,
113                      thread_1_stack, sizeof(thread_1_stack),
114                      8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
115 
116     tx_semaphore_create(&semaphore_receive, "semaphore receive", 0);
117     tx_semaphore_create(&semaphore_connect, "semaphore connect", 0);
118 
119     /* Initialize the NetX system.  */
120     nx_system_initialize();
121 
122     /* Create a packet pool.  */
123     status =  nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", PACKET_SIZE,
124                                     pool_0_memory, PACKET_POOL_SIZE);
125     if (status)
126     {
127         ERROR_COUNTER();
128     }
129 
130     /* Create an IP instance.  */
131     status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 4), 0xFFFFFF00UL,
132                           &pool_0, _nx_ram_network_driver_1500,
133                           ip_0_stack, sizeof(ip_0_stack), 1);
134     if (status)
135     {
136         ERROR_COUNTER();
137     }
138 
139     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
140     status =  nx_arp_enable(&ip_0, (VOID *)arp_cache, sizeof(arp_cache));
141     if (status)
142     {
143         ERROR_COUNTER();
144     }
145 
146     /* Enable UDP traffic.  */
147     status =  nx_udp_enable(&ip_0);
148     if (status)
149     {
150         ERROR_COUNTER();
151     }
152 
153     nx_secure_tls_initialize();
154     nx_secure_dtls_initialize();
155 }
156 
udp_packet_receive(NX_IP * ip_ptr,NX_PACKET * packet_ptr)157 static VOID udp_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
158 {
159     if ((drop_index < sizeof(drop_packet_sequence) / sizeof(UINT)) &&
160         (packet_sequence++ == drop_packet_sequence[drop_index]))
161     {
162         drop_index++;
163         nx_packet_release(packet_ptr);
164         return;
165     }
166     _nx_udp_packet_receive(ip_ptr, packet_ptr);
167 }
168 
client_dtls_setup(NX_SECURE_DTLS_SESSION * dtls_session_ptr)169 static VOID client_dtls_setup(NX_SECURE_DTLS_SESSION *dtls_session_ptr)
170 {
171 UINT status;
172 
173     status = nx_secure_dtls_session_create(dtls_session_ptr,
174                                            &nx_crypto_tls_ciphers,
175                                            client_metadata,
176                                            sizeof(client_metadata), tls_packet_buffer[0],
177                                            sizeof(tls_packet_buffer[0]), 1, client_cert_buffer,
178                                            sizeof(client_cert_buffer));
179     if (status)
180     {
181         ERROR_COUNTER();
182     }
183 
184     status = nx_secure_x509_certificate_initialize(&client_trusted_ca,
185                                                    test_ca_cert_der,
186                                                    test_ca_cert_der_len, NX_NULL, 0, NULL, 0, NX_SECURE_X509_KEY_TYPE_NONE);
187     if (status)
188     {
189         ERROR_COUNTER();
190     }
191 
192     status = nx_secure_dtls_session_trusted_certificate_add(dtls_session_ptr, &client_trusted_ca, 1);
193     if (status)
194     {
195         ERROR_COUNTER();
196     }
197 
198 
199 #if defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE)
200     /* For PSK ciphersuites, add a PSK and identity hint.  */
201     nx_secure_dtls_psk_add(dtls_session_ptr, PSK, strlen(PSK),
202                          PSK_IDENTITY, strlen(PSK_IDENTITY), PSK_HINT, strlen(PSK_HINT));
203 #endif
204 }
205 
206 /* Notification flags for DTLS server connect/receive. */
207 static UINT server_connect_notify_flag = NX_FALSE;
208 static UINT server_receive_notify_flag = NX_FALSE;
209 
210 NX_SECURE_DTLS_SESSION *connect_session;
211 NX_SECURE_DTLS_SESSION *receive_session;
212 
213 /* Connect notify callback for DTLS server - notifies the application thread that
214    a DTLS connection is ready to kickoff a handshake. */
server_connect_notify(NX_SECURE_DTLS_SESSION * dtls_session,NXD_ADDRESS * ip_address,UINT port)215 static UINT server_connect_notify(NX_SECURE_DTLS_SESSION *dtls_session, NXD_ADDRESS *ip_address, UINT port)
216 {
217     /* Drop connections if one is in progress. Better way would be to have
218      * an array of pointers to DTLS sessions and check the port/IP address
219      * to see if it's an existing connection. Application thread then loops
220      * through array servicing each session.
221      */
222     if (server_connect_notify_flag == NX_FALSE)
223     {
224         server_connect_notify_flag = NX_TRUE;
225         connect_session = dtls_session;
226         tx_semaphore_put(&semaphore_connect);
227     }
228 
229     return(NX_SUCCESS);
230 }
231 
232 /* Receive notify callback for DTLS server - notifies the application thread that
233    we have received a DTLS record over an established DTLS session. */
server_receive_notify(NX_SECURE_DTLS_SESSION * dtls_session)234 static UINT server_receive_notify(NX_SECURE_DTLS_SESSION *dtls_session)
235 {
236 
237     /* Drop records if more come in while processing one. Better would be to
238        service each session in a queue. */
239     if (server_receive_notify_flag == NX_FALSE)
240     {
241         server_receive_notify_flag = NX_TRUE;
242         receive_session = dtls_session;
243         tx_semaphore_put(&semaphore_receive);
244     }
245 
246     return(NX_SUCCESS);
247 }
248 
server_dtls_setup(NX_SECURE_DTLS_SERVER * dtls_server_ptr)249 static VOID server_dtls_setup(NX_SECURE_DTLS_SERVER *dtls_server_ptr)
250 {
251 UINT status;
252 
253     status = nx_secure_dtls_server_create(dtls_server_ptr, &ip_0, SERVER_PORT, NX_IP_PERIODIC_RATE,
254                                           server_session_buffer, sizeof(server_session_buffer),
255                                           &nx_crypto_tls_ciphers, server_metadata, sizeof(server_metadata),
256                                           tls_packet_buffer[1], sizeof(tls_packet_buffer[1]),
257                                           server_connect_notify, server_receive_notify);
258     if (status)
259     {
260         ERROR_COUNTER();
261     }
262 
263     memset(&server_local_certificate, 0, sizeof(server_local_certificate));
264     status = nx_secure_x509_certificate_initialize(&server_local_certificate,
265                                                    test_device_cert_der, test_device_cert_der_len,
266                                                    NX_NULL, 0, test_device_cert_key_der,
267                                                    test_device_cert_key_der_len, NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);
268     if (status)
269     {
270         ERROR_COUNTER();
271     }
272 
273     status = nx_secure_dtls_server_local_certificate_add(dtls_server_ptr, &server_local_certificate, 1);
274     if (status)
275     {
276         ERROR_COUNTER();
277     }
278 }
279 
ntest_0_entry(ULONG thread_input)280 static void ntest_0_entry(ULONG thread_input)
281 {
282 UINT status;
283 ULONG response_length;
284 NX_PACKET *packet_ptr;
285 
286     /* Print out test information banner.  */
287     printf("NetX Secure Test:   DTLS Retransmit Test...............................");
288 
289     ip_0.nx_ip_udp_packet_receive = udp_packet_receive;
290 
291     server_dtls_setup(&dtls_server_0);
292 
293     /* Start DTLS session. */
294     status = nx_secure_dtls_server_start(&dtls_server_0);
295     if (status)
296     {
297         printf("Error in starting DTLS server: 0x%02X\n", status);
298         ERROR_COUNTER();
299     }
300 
301     /* Wait for connection attempt. */
302     tx_semaphore_get(&semaphore_connect, NX_WAIT_FOREVER);
303     server_connect_notify_flag = NX_FALSE;
304 
305     status = nx_secure_dtls_server_session_start(connect_session, NX_WAIT_FOREVER);
306 
307     if(status)
308     {
309         printf("Error in establishing DTLS server session: 0x%02X\n", status);
310         ERROR_COUNTER();
311     }
312 
313     /* Wait for records to be received. */
314     tx_semaphore_get(&semaphore_receive, NX_WAIT_FOREVER);
315 
316     status = nx_secure_dtls_session_receive(receive_session,
317                                              &packet_ptr, NX_WAIT_FOREVER);
318     if (status)
319     {
320         printf("Error in DTLS server session receive: 0x%02X\n", status);
321         ERROR_COUNTER();
322     }
323 
324     nx_packet_data_retrieve(packet_ptr, response_buffer, &response_length);
325     nx_packet_release(packet_ptr);
326     if ((response_length != sizeof(request_buffer)) ||
327         memcmp(request_buffer, response_buffer, response_length))
328     {
329         ERROR_COUNTER();
330     }
331 
332     /* Clear the receive flag. */
333     server_receive_notify_flag = NX_FALSE;
334 
335     nx_secure_dtls_session_end(&dtls_server_0.nx_dtls_server_sessions[0], NX_NO_WAIT);
336 
337     tx_thread_suspend(&thread_0);
338 
339     /* Shutdown DTLS server. */
340     nx_secure_dtls_server_stop(&dtls_server_0);
341 
342     /* Delete server. */
343     nx_secure_dtls_server_delete(&dtls_server_0);
344 
345     if (error_counter)
346     {
347         printf("ERROR!\n");
348         test_control_return(1);
349     }
350     else
351     {
352         printf("SUCCESS!\n");
353         test_control_return(0);
354     }
355 }
356 
ntest_1_entry(ULONG thread_input)357 static void ntest_1_entry(ULONG thread_input)
358 {
359 UINT i;
360 UINT status;
361 NX_PACKET *packet_ptr;
362 NXD_ADDRESS server_address;
363 
364     for (i = 0; i < sizeof(request_buffer); i++)
365     {
366         request_buffer[i] = i;
367         response_buffer[i] = 0;
368     }
369 
370     server_address.nxd_ip_version = NX_IP_VERSION_V4;
371     server_address.nxd_ip_address.v4 = IP_ADDRESS(127, 0, 0, 1);
372 
373     /* Create UDP socket. */
374     status = nx_udp_socket_create(&ip_0, &client_socket_0, "Client socket", NX_IP_NORMAL,
375                                   NX_DONT_FRAGMENT, 0x80, 5);
376     if (status)
377     {
378         ERROR_COUNTER();
379     }
380 
381     status = nx_udp_socket_bind(&client_socket_0, NX_ANY_PORT, NX_NO_WAIT);
382     if (status)
383     {
384         ERROR_COUNTER();
385     }
386 
387     client_dtls_setup(&dtls_client_session_0);
388 
389     /* Start DTLS session. */
390     status = nx_secure_dtls_client_session_start(&dtls_client_session_0, &client_socket_0, &server_address, SERVER_PORT, NX_WAIT_FOREVER);
391     if (status)
392     {
393         ERROR_COUNTER();
394     }
395 
396     /* Prepare packet to send. */
397     status = nx_packet_allocate(&pool_0, &packet_ptr, NX_UDP_PACKET, NX_NO_WAIT);
398     if (status)
399     {
400         ERROR_COUNTER();
401     }
402 
403     packet_ptr -> nx_packet_prepend_ptr += NX_SECURE_DTLS_RECORD_HEADER_SIZE;
404     packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr;
405 
406     status = nx_packet_data_append(packet_ptr, request_buffer, sizeof(request_buffer),
407                                    &pool_0, NX_NO_WAIT);
408     if (status)
409     {
410         ERROR_COUNTER();
411     }
412 
413     /* Send the packet. */
414     status = nx_secure_dtls_client_session_send(&dtls_client_session_0, packet_ptr);
415     if (status)
416     {
417         ERROR_COUNTER();
418     }
419 
420     nx_secure_dtls_session_end(&dtls_client_session_0, NX_NO_WAIT);
421 
422     nx_secure_dtls_session_delete(&dtls_client_session_0);
423 
424     nx_udp_socket_unbind(&client_socket_0);
425 
426     nx_udp_socket_delete(&client_socket_0);
427 
428     tx_thread_resume(&thread_0);
429 }
430 #else
431 #ifdef CTEST
432 void test_application_define(void *first_unused_memory);
test_application_define(void * first_unused_memory)433 void test_application_define(void *first_unused_memory)
434 #else
435 VOID    nx_secure_dtls_retransmit_test_application_define(void *first_unused_memory)
436 #endif
437 {
438 
439     /* Print out test information banner.  */
440     printf("NetX Secure Test:   DTLS Retransmit Test...............................N/A\n");
441     test_control_return(3);
442 }
443 #endif
444