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