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