blob: 3cba3ee2abfe522ed84379a3493af32b53971d9a [file] [log] [blame]
Jens Wiklander02389a92016-12-16 11:13:38 +01001/*
2 * Copyright (c) 2016, Linaro Limited
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <assert.h>
15#include <err.h>
16#include <pthread.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <sys/param.h>
21#include <sys/socket.h>
22#include <sys/types.h>
23#include <ta_socket.h>
24#include <tee_isocket.h>
25#include <tee_tcpsocket.h>
26#include <__tee_tcpsocket_defines_extensions.h>
27#include <tee_udpsocket.h>
28#include <unistd.h>
29
30#include "xtest_test.h"
31#include "xtest_helpers.h"
32#include "sock_server.h"
33#include "rand_stream.h"
34
35struct socket_handle {
36 uint64_t buf[2];
37 size_t blen;
38};
39
40static TEE_Result socket_tcp_open(TEEC_Session *session, uint32_t ip_vers,
41 const char *addr, uint16_t port,
42 struct socket_handle *handle,
43 uint32_t *error, uint32_t *ret_orig)
44{
45 TEE_Result res;
46 TEEC_Operation op = TEEC_OPERATION_INITIALIZER;
47
48 memset(handle, 0, sizeof(*handle));
49
50 op.params[0].value.a = ip_vers;
51 op.params[0].value.b = port;
52 op.params[1].tmpref.buffer = (void *)addr;
53 op.params[1].tmpref.size = strlen(addr) + 1;
54 op.params[2].tmpref.buffer = handle->buf;
55 op.params[2].tmpref.size = sizeof(handle->buf);
56
57 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT,
58 TEEC_MEMREF_TEMP_INPUT,
59 TEEC_MEMREF_TEMP_OUTPUT,
60 TEEC_VALUE_OUTPUT);
61
62 res = TEEC_InvokeCommand(session, TA_SOCKET_CMD_TCP_OPEN,
63 &op, ret_orig);
64
65 handle->blen = op.params[2].tmpref.size;
66 *error = op.params[3].value.a;
67 return res;
68}
69
70static TEE_Result socket_udp_open(TEEC_Session *session, uint32_t ip_vers,
71 const char *addr, uint16_t port,
72 struct socket_handle *handle,
73 uint32_t *error, uint32_t *ret_orig)
74{
75 TEE_Result res;
76 TEEC_Operation op = TEEC_OPERATION_INITIALIZER;
77
78 memset(handle, 0, sizeof(*handle));
79
80 op.params[0].value.a = ip_vers;
81 op.params[0].value.b = port;
82 op.params[1].tmpref.buffer = (void *)addr;
83 op.params[1].tmpref.size = strlen(addr) + 1;
84 op.params[2].tmpref.buffer = handle->buf;
85 op.params[2].tmpref.size = sizeof(handle->buf);
86
87 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT,
88 TEEC_MEMREF_TEMP_INPUT,
89 TEEC_MEMREF_TEMP_OUTPUT,
90 TEEC_VALUE_OUTPUT);
91
92 res = TEEC_InvokeCommand(session, TA_SOCKET_CMD_UDP_OPEN,
93 &op, ret_orig);
94
95 handle->blen = op.params[2].tmpref.size;
96 *error = op.params[3].value.a;
97 return res;
98}
99
100static TEE_Result socket_send(TEEC_Session *session,
101 struct socket_handle *handle,
102 const void *data, size_t *dlen,
103 uint32_t timeout, uint32_t *ret_orig)
104{
105 TEE_Result res;
106 TEEC_Operation op = TEEC_OPERATION_INITIALIZER;
107
108 op.params[0].tmpref.buffer = handle->buf;
109 op.params[0].tmpref.size = handle->blen;
110 op.params[1].tmpref.buffer = (void *)data;
111 op.params[1].tmpref.size = *dlen;
112 op.params[2].value.a = timeout;
113
114 op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
115 TEEC_MEMREF_TEMP_INPUT,
116 TEEC_VALUE_INOUT, TEEC_NONE);
117
118 res = TEEC_InvokeCommand(session, TA_SOCKET_CMD_SEND, &op, ret_orig);
119
120 *dlen = op.params[2].value.b;
121 return res;
122}
123
124static TEE_Result socket_recv(TEEC_Session *session,
125 struct socket_handle *handle,
126 void *data, size_t *dlen,
127 uint32_t timeout, uint32_t *ret_orig)
128{
129 TEE_Result res;
130 TEEC_Operation op = TEEC_OPERATION_INITIALIZER;
131
132 op.params[0].tmpref.buffer = handle->buf;
133 op.params[0].tmpref.size = handle->blen;
134 op.params[1].tmpref.buffer = (void *)data;
135 op.params[1].tmpref.size = *dlen;
136 op.params[2].value.a = timeout;
137
138 op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
139 TEEC_MEMREF_TEMP_OUTPUT,
140 TEEC_VALUE_INPUT, TEEC_NONE);
141
142 res = TEEC_InvokeCommand(session, TA_SOCKET_CMD_RECV, &op, ret_orig);
143
144 *dlen = op.params[1].tmpref.size;
145 return res;
146}
147
148static TEE_Result socket_get_error(TEEC_Session *session,
149 struct socket_handle *handle,
150 uint32_t *proto_error, uint32_t *ret_orig)
151{
152 TEE_Result res;
153 TEEC_Operation op = TEEC_OPERATION_INITIALIZER;
154
155 op.params[0].tmpref.buffer = handle->buf;
156 op.params[0].tmpref.size = handle->blen;
157
158 op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
159 TEEC_VALUE_OUTPUT,
160 TEEC_NONE, TEEC_NONE);
161
162 res = TEEC_InvokeCommand(session, TA_SOCKET_CMD_ERROR, &op, ret_orig);
163
164 *proto_error = op.params[1].value.a;
165 return res;
166}
167
168static TEE_Result socket_close(TEEC_Session *session,
169 struct socket_handle *handle, uint32_t *ret_orig)
170{
171 TEEC_Operation op = TEEC_OPERATION_INITIALIZER;
172
173 op.params[0].tmpref.buffer = handle->buf;
174 op.params[0].tmpref.size = handle->blen;
175
176 op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
177 TEEC_NONE, TEEC_NONE, TEEC_NONE);
178
179 return TEEC_InvokeCommand(session, TA_SOCKET_CMD_CLOSE, &op, ret_orig);
180}
181
182static TEE_Result socket_ioctl(TEEC_Session *session,
183 struct socket_handle *handle, uint32_t ioctl_cmd,
184 void *data, size_t *dlen, uint32_t *ret_orig)
185{
186 TEE_Result res;
187 TEEC_Operation op = TEEC_OPERATION_INITIALIZER;
188
189 op.params[0].tmpref.buffer = handle->buf;
190 op.params[0].tmpref.size = handle->blen;
191 op.params[1].tmpref.buffer = data;
192 op.params[1].tmpref.size = *dlen;
193 op.params[2].value.a = ioctl_cmd;
194
195 op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
196 TEEC_MEMREF_TEMP_INOUT,
197 TEEC_VALUE_INPUT, TEEC_NONE);
198
199 res = TEEC_InvokeCommand(session, TA_SOCKET_CMD_IOCTL, &op, ret_orig);
200
201 *dlen = op.params[1].tmpref.size;
202 return res;
203}
204
205
206
207struct test_200x_io_state {
208 struct rand_stream *read_rs;
209 struct rand_stream *write_rs;
210 bool rfail;
211};
212
213static void test_200x_init_io_state(struct test_200x_io_state *s,
214 int read_seed, int write_seed)
215{
216 memset(s, 0, sizeof(*s));
217 s->read_rs = rand_stream_alloc(read_seed, 100);
218 s->write_rs = rand_stream_alloc(write_seed, 100);
219 assert(s->read_rs && s->write_rs);
220}
221
222static bool test_200x_tcp_accept_cb(void *ptr, int fd, short *events)
223{
224 (void)ptr;
225 (void)fd;
226 (void)events;
227 return true;
228}
229
230static bool test_200x_tcp_read_cb(void *ptr, int fd, short *events)
231{
232 struct test_200x_io_state *iostate = ptr;
233 ssize_t r;
234 uint8_t buf[100];
235 uint8_t buf2[100];
236
237 (void)events;
238 r = read(fd, buf, sizeof(buf));
239 if (r <= 0)
240 return false;
241
242 rand_stream_read(iostate->read_rs, buf2, r);
243 if (memcmp(buf, buf2, r)) {
244 iostate->rfail = true;
245 return false;
246 }
247
248 return true;
249}
250
251static bool test_200x_tcp_write_cb(void *ptr, int fd, short *events)
252{
253 struct test_200x_io_state *iostate = ptr;
254 size_t num_bytes = 100;
255 const void *bytes;
256 ssize_t r;
257
258 (void)events;
259
260 bytes = rand_stream_peek(iostate->write_rs, &num_bytes);
261 r = write(fd, bytes, num_bytes);
262 if (r < 0)
263 return false;
264
265 rand_stream_advance(iostate->write_rs, num_bytes);
266 return true;
267}
268
269static void xtest_tee_test_2001(ADBG_Case_t *c)
270{
271 struct sock_server ts;
272 TEEC_Session session = { 0 };
273 uint32_t ret_orig;
274 uint32_t proto_error;
275 struct socket_handle sh;
276 uint8_t buf[64];
277 uint8_t buf2[64];
278 size_t blen;
279 struct test_200x_io_state server_iostate;
280 struct test_200x_io_state local_iostate;
281 struct sock_io_cb cb = {
282 .accept = test_200x_tcp_accept_cb,
283 .read = test_200x_tcp_read_cb,
284 .write = test_200x_tcp_write_cb,
285 .ptr = &server_iostate,
286 };
287
288 test_200x_init_io_state(&server_iostate, 1, 2);
289 test_200x_init_io_state(&local_iostate, 2, 1);
290
291 Do_ADBG_BeginSubCase(c, "Start server");
292 if (!ADBG_EXPECT_TRUE(c, sock_server_init_tcp(&ts, &cb)))
293 return;
294 Do_ADBG_EndSubCase(c, "Start server");
295
296 Do_ADBG_BeginSubCase(c, "TCP Socket open");
297 if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session(
298 &session, &socket_ta_uuid, NULL, &ret_orig)))
299 goto out;
300
301 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_tcp_open(&session,
302 TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port,
303 &sh, &proto_error, &ret_orig)))
304 goto out_close_session;
305
306 Do_ADBG_EndSubCase(c, "TCP Socket open");
307
308 Do_ADBG_BeginSubCase(c, "TCP Socket send");
309 blen = sizeof(buf);
310 rand_stream_read(local_iostate.write_rs, buf, blen);
311 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_send(&session, &sh,
312 buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig)))
313 goto out_close_session;
314 ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, sizeof(buf));
315 Do_ADBG_EndSubCase(c, "TCP Socket send");
316
317 Do_ADBG_BeginSubCase(c, "TCP Socket recv");
318 blen = sizeof(buf);
319 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_recv(&session, &sh,
320 buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig)))
321 goto out_close_session;
322 ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, sizeof(buf));
323 rand_stream_read(local_iostate.read_rs, buf2, blen);
324 ADBG_EXPECT_BUFFER(c, buf2, blen, buf, blen);
325 Do_ADBG_EndSubCase(c, "TCP Socket recv");
326
327 /*
328 * All written bytes above (with the TA) is quite likely to have
329 * hit the tcp server by now.
330 */
331 ADBG_EXPECT_TRUE(c, !server_iostate.rfail);
332
333 Do_ADBG_BeginSubCase(c, "TCP Socket get error");
334 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_get_error(&session, &sh,
335 &proto_error, &ret_orig)))
336 goto out_close_session;
337 if (!ADBG_EXPECT_TEEC_SUCCESS(c, proto_error))
338 goto out_close_session;
339 Do_ADBG_EndSubCase(c, "TCP Socket get error");
340
341 Do_ADBG_BeginSubCase(c, "TCP Socket close");
342 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_close(&session, &sh,
343 &ret_orig)))
344 goto out_close_session;
345 Do_ADBG_EndSubCase(c, "TCP Socket close");
346
347 Do_ADBG_BeginSubCase(c, "TCP Socket ioctl");
348
349
350 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_tcp_open(&session,
351 TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port,
352 &sh, &proto_error, &ret_orig)))
353 goto out_close_session;
354
355 blen = sizeof(buf);
356 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh, 0x00F00000,
357 buf, &blen, &ret_orig)))
358 goto out_close_session;
359
360 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_close(&session, &sh,
361 &ret_orig)))
362 goto out_close_session;
363
364
365 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_tcp_open(&session,
366 TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port,
367 &sh, &proto_error, &ret_orig)))
368 goto out_close_session;
369
370 blen = sizeof(buf);
371 ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD,
372 socket_ioctl(&session, &sh,
373 TEE_ISOCKET_PROTOCOLID_TCP << 24,
374 buf, &blen, &ret_orig));
375 TEEC_CloseSession(&session);
376
377 if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session(
378 &session, &socket_ta_uuid, NULL, &ret_orig)))
379 goto out;
380
381 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_tcp_open(&session,
382 TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port,
383 &sh, &proto_error, &ret_orig)))
384 goto out_close_session;
385
386 blen = sizeof(buf);
387 ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD,
388 socket_ioctl(&session, &sh, 0x32 << 24,
389 buf, &blen, &ret_orig));
390
391 Do_ADBG_EndSubCase(c, "TCP Socket ioctl");
392
393out_close_session:
394 TEEC_CloseSession(&session);
395out:
396 sock_server_uninit(&ts);
397}
398
399struct test_2002_barrier {
400 pthread_mutex_t mu;
401 pthread_barrier_t bar;
402};
403
404struct test_2002_arg {
405 bool success;
406 size_t tnum;
407 struct test_2002_barrier *bar;
408};
409
410static void xtest_2002_wait_barrier(struct test_2002_barrier *bar)
411{
412 /*
413 * Once the mutex is taken the barrier is initialized so the mutex
414 * can be released immediately.
415 */
416 xtest_mutex_lock(&bar->mu);
417 xtest_mutex_unlock(&bar->mu);
418 xtest_barrier_wait(&bar->bar);
419}
420
421static void *xtest_tee_test_2002_thread(void *arg)
422{
423 struct test_2002_arg *a = arg;
424 TEE_Result res;
425 struct sock_server ts;
426 TEEC_Session session = { 0 };
427 uint32_t ret_orig;
428 uint32_t proto_error;
429 struct socket_handle sh;
430 struct test_200x_io_state server_iostate;
431 struct test_200x_io_state local_iostate;
432 struct sock_io_cb cb = {
433 .accept = test_200x_tcp_accept_cb,
434 .read = test_200x_tcp_read_cb,
435 .write = test_200x_tcp_write_cb,
436 .ptr = &server_iostate,
437 };
438 int seed[2] = { 1 + a->tnum * 2, 2 + a->tnum * 2 };
439 size_t send_limit = 10000;
440 size_t recv_limit = 10000;
441 size_t sent_bytes = 0;
442 size_t recvd_bytes = 0;
443
444 test_200x_init_io_state(&server_iostate, seed[0], seed[1]);
445 test_200x_init_io_state(&local_iostate, seed[1], seed[0]);
446
447 if (!sock_server_init_tcp(&ts, &cb)) {
448 xtest_2002_wait_barrier(a->bar);
449 return NULL;
450 }
451
452 res = xtest_teec_open_session(&session, &socket_ta_uuid, NULL,
453 &ret_orig);
454
455 xtest_2002_wait_barrier(a->bar);
456 if (res != TEE_SUCCESS)
457 goto out;
458
459 res = socket_tcp_open(&session, TEE_IP_VERSION_DC, ts.bind->host,
460 ts.bind->port, &sh, &proto_error, &ret_orig);
461 if (res != TEE_SUCCESS)
462 goto out_close_session;
463
464 while (sent_bytes < send_limit && recvd_bytes < recv_limit) {
465 const void *peek;
466 uint8_t buf[64];
467 uint8_t buf2[64];
468 size_t blen;
469
470 blen = sizeof(buf);
471 peek = rand_stream_peek(local_iostate.write_rs, &blen);
472 res = socket_send(&session, &sh, peek, &blen,
473 TEE_TIMEOUT_INFINITE, &ret_orig);
474 if (res != TEE_SUCCESS)
475 goto out_close_session;
476 rand_stream_advance(local_iostate.write_rs, blen);
477 sent_bytes += blen;
478
479 blen = sizeof(buf);
480 res = socket_recv(&session, &sh, buf, &blen,
481 TEE_TIMEOUT_INFINITE, &ret_orig);
482 if (res != TEE_SUCCESS)
483 goto out_close_session;
484 rand_stream_read(local_iostate.read_rs, buf2, blen);
485 if (memcmp(buf2, buf, blen))
486 goto out_close_session;
487 recvd_bytes += blen;
488 }
489
490
491 res = socket_close(&session, &sh, &ret_orig);
492 if (res != TEE_SUCCESS)
493 goto out_close_session;
494
495 /*
496 * All written bytes above (with the TA) is quite likely to have
497 * hit the tcp server by now.
498 */
499 a->success = !server_iostate.rfail;
500
501out_close_session:
502 TEEC_CloseSession(&session);
503out:
504 sock_server_uninit(&ts);
505 return NULL;
506}
507
508#define NUM_THREADS 3
509
510static void xtest_tee_test_2002(ADBG_Case_t *c)
511{
512 pthread_t thr[NUM_THREADS];
513 struct test_2002_barrier bar = { .mu = PTHREAD_MUTEX_INITIALIZER };
514 struct test_2002_arg arg[NUM_THREADS];
515 size_t n;
516 size_t nt;
517
518 Do_ADBG_BeginSubCase(c, "Stressing with %d threads", NUM_THREADS);
519
520 xtest_mutex_lock(&bar.mu);
521
522 nt = NUM_THREADS;
523 for (n = 0; n < nt; n++) {
524 arg[n].success = false;
525 arg[n].tnum = n;
526 arg[n].bar = &bar;
527 if (!ADBG_EXPECT(c, 0, pthread_create(thr + n, NULL,
528 xtest_tee_test_2002_thread, arg + n)))
529 nt = n; /* break loop and start cleanup */
530 }
531
532 xtest_barrier_init(&bar.bar, nt + 1);
533 xtest_mutex_unlock(&bar.mu);
534 xtest_barrier_wait(&bar.bar);
535
536 for (n = 0; n < nt; n++) {
537 ADBG_EXPECT(c, 0, pthread_join(thr[n], NULL));
538 ADBG_EXPECT_TRUE(c, arg[n].success);
539 }
540
541 xtest_mutex_destroy(&bar.mu);
542 xtest_barrier_destroy(&bar.bar);
543
544 Do_ADBG_EndSubCase(c, "Stressing with %d threads", NUM_THREADS);
545}
546
547static bool test_2003_accept_cb(void *ptr, int fd, short *events)
548{
549 int val;
550
551 (void)ptr;
552 (void)events;
553
554 val = 4 * 1024;
555 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)))
556 warn("test_2003_accept_cb: setsockopt");
557 return true;
558}
559
560static void xtest_tee_test_2003(ADBG_Case_t *c)
561{
562 struct sock_server ts;
563 TEEC_Session session = { 0 };
564 uint32_t ret_orig;
565 uint32_t proto_error;
566 struct socket_handle sh;
567 void *buf;
568 const size_t blen0 = 16 * 1024;
569 size_t blen;
570 uint32_t val;
571 struct sock_io_cb cb = { .accept = test_2003_accept_cb };
572
573 Do_ADBG_BeginSubCase(c, "Start server");
574 if (!ADBG_EXPECT_TRUE(c, sock_server_init_tcp(&ts, &cb)))
575 return;
576 buf = calloc(1, blen0);
577 if (!ADBG_EXPECT_NOT_NULL(c, buf))
578 goto out;
579 Do_ADBG_EndSubCase(c, "Start server");
580
581 Do_ADBG_BeginSubCase(c, "TCP Socket open");
582 if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session(
583 &session, &socket_ta_uuid, NULL, &ret_orig)))
584 goto out;
585
586 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_tcp_open(&session,
587 TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port,
588 &sh, &proto_error, &ret_orig)))
589 goto out_close_session;
590
591 blen = sizeof(val);
592 val = 4 * 1024;
593 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh,
594 TEE_TCP_SET_RECVBUF, &val, &blen, &ret_orig)))
595 goto out_close_session;
596
597 blen = sizeof(val);
598 val = 4 * 1024;
599 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh,
600 TEE_TCP_SET_SENDBUF, &val, &blen, &ret_orig)))
601 goto out_close_session;
602
603 Do_ADBG_EndSubCase(c, "TCP Socket open");
604
605 Do_ADBG_BeginSubCase(c, "TCP Socket send (10 ms timeout)");
606 while (true) {
607 TEE_Result res;
608
609 blen = blen0;
610 memset(buf, 0, blen0);
611 res = socket_send(&session, &sh, buf, &blen, 10, &ret_orig);
612 if (res == TEE_ISOCKET_ERROR_TIMEOUT)
613 break;
614 if (!ADBG_EXPECT_TEEC_SUCCESS(c, res))
615 goto out_close_session;
616 ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, blen0);
617 }
618 Do_ADBG_EndSubCase(c, "TCP Socket send (10 ms timeout)");
619
620 Do_ADBG_BeginSubCase(c, "TCP Socket recv (10 ms timeout)");
621 blen = blen0;
622 ADBG_EXPECT_TEEC_RESULT(c, TEE_ISOCKET_ERROR_TIMEOUT,
623 socket_recv(&session, &sh, buf, &blen,
624 10, &ret_orig));
625 ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, blen0);
626 Do_ADBG_EndSubCase(c, "TCP Socket recv (10 ms timeout)");
627
628 Do_ADBG_BeginSubCase(c, "TCP Socket get error");
629 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_get_error(&session, &sh,
630 &proto_error, &ret_orig)))
631 goto out_close_session;
632 ADBG_EXPECT_TEEC_RESULT(c, TEE_ISOCKET_ERROR_TIMEOUT, proto_error);
633 Do_ADBG_EndSubCase(c, "TCP Socket get error");
634
635out_close_session:
636 TEEC_CloseSession(&session);
637out:
638 free(buf);
639 sock_server_uninit(&ts);
640}
641
642static bool test_200x_udp_accept_cb(void *ptr, int fd, short *events)
643{
644 struct test_200x_io_state *iostate = ptr;
645 struct sockaddr_storage sass;
646 struct sockaddr *sa = (struct sockaddr *)&sass;
647 socklen_t slen = sizeof(sass);
648 uint8_t buf[100];
649 uint8_t buf2[100];
650 ssize_t r;
651 size_t l;
652
653 (void)events;
654
655 r = recvfrom(fd, buf, sizeof(buf), 0, sa, &slen);
656 if (r == -1)
657 return false;
658
659 l = r;
660 rand_stream_read(iostate->read_rs, buf2, l);
661 if (memcmp(buf, buf2, l))
662 iostate->rfail = true;
663
664 rand_stream_read(iostate->write_rs, buf, l);
665 return sendto(fd, buf, l, 0, sa, slen) != -1;
666}
667
668static void xtest_tee_test_2004(ADBG_Case_t *c)
669{
670 struct sock_server ts;
671 struct sock_server ts2;
672 struct sock_server ts3;
673 bool ts_inited = false;
674 bool ts2_inited = false;
675 bool ts3_inited = false;
676 TEEC_Session session = { 0 };
677 uint32_t ret_orig;
678 uint32_t proto_error;
679 struct socket_handle sh;
680 uint8_t buf[64];
681 uint8_t buf2[64];
682 size_t blen;
683 uint16_t port;
684 struct test_200x_io_state server_iostate;
685 struct test_200x_io_state local_iostate;
686 struct sock_io_cb cb = {
687 .accept = test_200x_udp_accept_cb,
688 .ptr = &server_iostate,
689 };
690
691 test_200x_init_io_state(&server_iostate, 1, 2);
692 test_200x_init_io_state(&local_iostate, 2, 1);
693
694 Do_ADBG_BeginSubCase(c, "Start server");
695 if (!ADBG_EXPECT_TRUE(c, sock_server_init_udp(&ts, &cb)))
696 return;
697 ts_inited = true;
698 if (!ADBG_EXPECT_TRUE(c, sock_server_init_udp(&ts2, &cb)))
699 goto out;
700 ts2_inited = true;
701 if (!ADBG_EXPECT_TRUE(c, sock_server_init_udp(&ts3, &cb)))
702 goto out;
703 ts3_inited = true;
704 Do_ADBG_EndSubCase(c, "Start server");
705
706 Do_ADBG_BeginSubCase(c, "UDP Socket open");
707 if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session(
708 &session, &socket_ta_uuid, NULL, &ret_orig)))
709 goto out;
710
711 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_udp_open(&session,
712 TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port,
713 &sh, &proto_error, &ret_orig)))
714 goto out_close_session;
715
716 Do_ADBG_EndSubCase(c, "UDP Socket open");
717
718 Do_ADBG_BeginSubCase(c, "UDP Socket send");
719 blen = sizeof(buf);
720 rand_stream_read(local_iostate.write_rs, buf, blen);
721 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_send(&session, &sh,
722 buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig)))
723 goto out_close_session;
724 ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, sizeof(buf));
725 Do_ADBG_EndSubCase(c, "UDP Socket send");
726
727 Do_ADBG_BeginSubCase(c, "UDP Socket recv");
728 blen = sizeof(buf);
729 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_recv(&session, &sh,
730 buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig)))
731 goto out_close_session;
732 ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, sizeof(buf));
733 rand_stream_read(local_iostate.read_rs, buf2, blen);
734 ADBG_EXPECT_BUFFER(c, buf2, blen, buf, blen);
735 ADBG_EXPECT_TRUE(c, !server_iostate.rfail);
736 Do_ADBG_EndSubCase(c, "UDP Socket recv");
737
738 Do_ADBG_BeginSubCase(c, "UDP Socket get error");
739 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_get_error(&session, &sh,
740 &proto_error, &ret_orig)))
741 goto out_close_session;
742 if (!ADBG_EXPECT_TEEC_SUCCESS(c, proto_error))
743 goto out_close_session;
744 Do_ADBG_EndSubCase(c, "UDP Socket get error");
745
746 Do_ADBG_BeginSubCase(c, "UDP Socket close");
747 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_close(&session, &sh,
748 &ret_orig)))
749 goto out_close_session;
750 Do_ADBG_EndSubCase(c, "UDP Socket close");
751
752 Do_ADBG_BeginSubCase(c, "UDP Socket ioctl");
753
754 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_udp_open(&session,
755 TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port,
756 &sh, &proto_error, &ret_orig)))
757 goto out_close_session;
758
759 blen = sizeof(buf);
760 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh, 0x00F00000,
761 buf, &blen, &ret_orig)))
762 goto out_close_session;
763
764 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_close(&session, &sh,
765 &ret_orig)))
766 goto out_close_session;
767
768
769 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_udp_open(&session,
770 TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port,
771 &sh, &proto_error, &ret_orig)))
772 goto out_close_session;
773
774 blen = sizeof(buf);
775 ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD,
776 socket_ioctl(&session, &sh,
777 TEE_ISOCKET_PROTOCOLID_UDP << 24,
778 buf, &blen, &ret_orig));
779 TEEC_CloseSession(&session);
780
781 if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session(
782 &session, &socket_ta_uuid, NULL, &ret_orig)))
783 goto out;
784
785 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_udp_open(&session,
786 TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port,
787 &sh, &proto_error, &ret_orig)))
788 goto out_close_session;
789
790 blen = sizeof(buf);
791 ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD,
792 socket_ioctl(&session, &sh, 0x32 << 24,
793 buf, &blen, &ret_orig));
794
795 Do_ADBG_EndSubCase(c, "UDP Socket ioctl");
796
797 Do_ADBG_BeginSubCase(c, "UDP Socket change port");
798
799 if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session(
800 &session, &socket_ta_uuid, NULL, &ret_orig)))
801 goto out;
802
803 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_udp_open(&session,
804 TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port,
805 &sh, &proto_error, &ret_orig)))
806 goto out_close_session;
807 sock_server_uninit(&ts);
808 ts_inited = false;
809
810 port = ts2.bind->port;
811 blen = sizeof(port);
812 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh,
813 TEE_UDP_CHANGEPORT, &port, &blen, &ret_orig)))
814 goto out_close_session;
815
816 Do_ADBG_BeginSubCase(c, "UDP Socket send");
817 blen = sizeof(buf);
818 rand_stream_read(local_iostate.write_rs, buf, blen);
819 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_send(&session, &sh,
820 buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig)))
821 goto out_close_session;
822 ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, sizeof(buf));
823 Do_ADBG_EndSubCase(c, "UDP Socket send");
824
825 Do_ADBG_BeginSubCase(c, "UDP Socket recv");
826 blen = sizeof(buf);
827 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_recv(&session, &sh,
828 buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig)))
829 goto out_close_session;
830 ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, sizeof(buf));
831 rand_stream_read(local_iostate.read_rs, buf2, blen);
832 ADBG_EXPECT_BUFFER(c, buf2, blen, buf, blen);
833 ADBG_EXPECT_TRUE(c, !server_iostate.rfail);
834 Do_ADBG_EndSubCase(c, "UDP Socket recv");
835
836 Do_ADBG_EndSubCase(c, "UDP Socket change port");
837
838 Do_ADBG_BeginSubCase(c, "UDP Socket change addr");
839
840 if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session(
841 &session, &socket_ta_uuid, NULL, &ret_orig)))
842 goto out;
843
844 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_udp_open(&session,
845 TEE_IP_VERSION_DC, ts2.bind->host, ts2.bind->port,
846 &sh, &proto_error, &ret_orig)))
847 goto out_close_session;
848 sock_server_uninit(&ts2);
849 ts2_inited = false;
850
851 port = ts3.bind->port;
852 blen = sizeof(port);
853 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh,
854 TEE_UDP_CHANGEPORT, &port, &blen, &ret_orig)))
855 goto out_close_session;
856
857 blen = strlen(ts3.bind->host) + 1;
858 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh,
859 TEE_UDP_CHANGEADDR, ts3.bind->host, &blen, &ret_orig)))
860 goto out_close_session;
861
862 Do_ADBG_BeginSubCase(c, "UDP Socket send");
863 blen = sizeof(buf);
864 rand_stream_read(local_iostate.write_rs, buf, blen);
865 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_send(&session, &sh,
866 buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig)))
867 goto out_close_session;
868 ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, sizeof(buf));
869 Do_ADBG_EndSubCase(c, "UDP Socket send");
870
871 Do_ADBG_BeginSubCase(c, "UDP Socket recv");
872 blen = sizeof(buf);
873 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_recv(&session, &sh,
874 buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig)))
875 goto out_close_session;
876 ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, sizeof(buf));
877 rand_stream_read(local_iostate.read_rs, buf2, blen);
878 ADBG_EXPECT_BUFFER(c, buf2, blen, buf, blen);
879 ADBG_EXPECT_TRUE(c, !server_iostate.rfail);
880 Do_ADBG_EndSubCase(c, "UDP Socket recv");
881
882 Do_ADBG_EndSubCase(c, "UDP Socket change addr");
883
884
885out_close_session:
886 TEEC_CloseSession(&session);
887out:
888 if (ts_inited)
889 sock_server_uninit(&ts);
890 if (ts2_inited)
891 sock_server_uninit(&ts2);
892 if (ts3_inited)
893 sock_server_uninit(&ts3);
894}
895
896
897
898ADBG_CASE_DEFINE(regression, 2001, xtest_tee_test_2001,
899 "Trivial TCP iSocket API tests");
900
901ADBG_CASE_DEFINE(regression, 2002, xtest_tee_test_2002,
902 "Concurrent stressing TCP iSocket API tests");
903
904ADBG_CASE_DEFINE(regression, 2003, xtest_tee_test_2003,
905 "Timeout TCP iSocket API tests");
906
907ADBG_CASE_DEFINE(regression, 2004, xtest_tee_test_2004,
908 "UDP iSocket API tests");