blob: 2dc1072578c707bd3eff737694e89dd7665591e3 [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{
Etienne Carrieree4ec9e42019-03-28 13:30:21 +010045 TEE_Result res = TEE_ERROR_GENERIC;
Jens Wiklander02389a92016-12-16 11:13:38 +010046 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{
Etienne Carrieree4ec9e42019-03-28 13:30:21 +010075 TEE_Result res = TEE_ERROR_GENERIC;
Jens Wiklander02389a92016-12-16 11:13:38 +010076 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{
Etienne Carrieree4ec9e42019-03-28 13:30:21 +0100105 TEE_Result res = TEE_ERROR_GENERIC;
Jens Wiklander02389a92016-12-16 11:13:38 +0100106 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{
Etienne Carrieree4ec9e42019-03-28 13:30:21 +0100129 TEE_Result res = TEE_ERROR_GENERIC;
Jens Wiklander02389a92016-12-16 11:13:38 +0100130 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{
Etienne Carrieree4ec9e42019-03-28 13:30:21 +0100152 TEE_Result res = TEE_ERROR_GENERIC;
Jens Wiklander02389a92016-12-16 11:13:38 +0100153 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{
Etienne Carrieree4ec9e42019-03-28 13:30:21 +0100186 TEE_Result res = TEE_ERROR_GENERIC;
Jens Wiklander02389a92016-12-16 11:13:38 +0100187 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;
Etienne Carrieree4ec9e42019-03-28 13:30:21 +0100233 ssize_t r = 0;
234 uint8_t buf[100] = { };
235 uint8_t buf2[100] = { };
Jens Wiklander02389a92016-12-16 11:13:38 +0100236
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;
Etienne Carrieree4ec9e42019-03-28 13:30:21 +0100255 const void *bytes = NULL;
256 ssize_t r = 0;
Jens Wiklander02389a92016-12-16 11:13:38 +0100257
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{
Etienne Carrieree4ec9e42019-03-28 13:30:21 +0100271 struct sock_server ts = { };
272 TEEC_Session session = { };
273 uint32_t ret_orig = 0;
274 uint32_t proto_error = 9;
275 struct socket_handle sh = { };
276 uint8_t buf[64] = { };
277 uint8_t buf2[64] = { };
278 size_t blen = 0;
279 struct test_200x_io_state server_iostate = { };
280 struct test_200x_io_state local_iostate = { };
Jens Wiklander02389a92016-12-16 11:13:38 +0100281 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}
Jens Wiklander14f48872018-06-29 15:30:13 +0200398ADBG_CASE_DEFINE(regression, 2001, xtest_tee_test_2001,
399 "Trivial TCP iSocket API tests");
Jens Wiklander02389a92016-12-16 11:13:38 +0100400
401struct test_2002_barrier {
402 pthread_mutex_t mu;
403 pthread_barrier_t bar;
404};
405
406struct test_2002_arg {
407 bool success;
408 size_t tnum;
409 struct test_2002_barrier *bar;
410};
411
412static void xtest_2002_wait_barrier(struct test_2002_barrier *bar)
413{
414 /*
415 * Once the mutex is taken the barrier is initialized so the mutex
416 * can be released immediately.
417 */
418 xtest_mutex_lock(&bar->mu);
419 xtest_mutex_unlock(&bar->mu);
420 xtest_barrier_wait(&bar->bar);
421}
422
423static void *xtest_tee_test_2002_thread(void *arg)
424{
425 struct test_2002_arg *a = arg;
Etienne Carrieree4ec9e42019-03-28 13:30:21 +0100426 TEE_Result res = TEE_ERROR_GENERIC;
427 struct sock_server ts = { };
428 TEEC_Session session = { };
429 uint32_t ret_orig = 0;
430 uint32_t proto_error = 0;
431 struct socket_handle sh = { };
432 struct test_200x_io_state server_iostate = { };
433 struct test_200x_io_state local_iostate = { };
Jens Wiklander02389a92016-12-16 11:13:38 +0100434 struct sock_io_cb cb = {
435 .accept = test_200x_tcp_accept_cb,
436 .read = test_200x_tcp_read_cb,
437 .write = test_200x_tcp_write_cb,
438 .ptr = &server_iostate,
439 };
440 int seed[2] = { 1 + a->tnum * 2, 2 + a->tnum * 2 };
441 size_t send_limit = 10000;
442 size_t recv_limit = 10000;
443 size_t sent_bytes = 0;
444 size_t recvd_bytes = 0;
445
446 test_200x_init_io_state(&server_iostate, seed[0], seed[1]);
447 test_200x_init_io_state(&local_iostate, seed[1], seed[0]);
448
449 if (!sock_server_init_tcp(&ts, &cb)) {
450 xtest_2002_wait_barrier(a->bar);
451 return NULL;
452 }
453
454 res = xtest_teec_open_session(&session, &socket_ta_uuid, NULL,
455 &ret_orig);
456
457 xtest_2002_wait_barrier(a->bar);
458 if (res != TEE_SUCCESS)
459 goto out;
460
461 res = socket_tcp_open(&session, TEE_IP_VERSION_DC, ts.bind->host,
462 ts.bind->port, &sh, &proto_error, &ret_orig);
463 if (res != TEE_SUCCESS)
464 goto out_close_session;
465
466 while (sent_bytes < send_limit && recvd_bytes < recv_limit) {
Etienne Carrieree4ec9e42019-03-28 13:30:21 +0100467 const void *peek = NULL;
468 uint8_t buf[64] = { };
469 uint8_t buf2[64] = { };
470 size_t blen = 0;
Jens Wiklander02389a92016-12-16 11:13:38 +0100471
472 blen = sizeof(buf);
473 peek = rand_stream_peek(local_iostate.write_rs, &blen);
474 res = socket_send(&session, &sh, peek, &blen,
475 TEE_TIMEOUT_INFINITE, &ret_orig);
476 if (res != TEE_SUCCESS)
477 goto out_close_session;
478 rand_stream_advance(local_iostate.write_rs, blen);
479 sent_bytes += blen;
480
481 blen = sizeof(buf);
482 res = socket_recv(&session, &sh, buf, &blen,
483 TEE_TIMEOUT_INFINITE, &ret_orig);
484 if (res != TEE_SUCCESS)
485 goto out_close_session;
486 rand_stream_read(local_iostate.read_rs, buf2, blen);
487 if (memcmp(buf2, buf, blen))
488 goto out_close_session;
489 recvd_bytes += blen;
490 }
491
492
493 res = socket_close(&session, &sh, &ret_orig);
494 if (res != TEE_SUCCESS)
495 goto out_close_session;
496
497 /*
498 * All written bytes above (with the TA) is quite likely to have
499 * hit the tcp server by now.
500 */
501 a->success = !server_iostate.rfail;
502
503out_close_session:
504 TEEC_CloseSession(&session);
505out:
506 sock_server_uninit(&ts);
507 return NULL;
508}
509
510#define NUM_THREADS 3
511
512static void xtest_tee_test_2002(ADBG_Case_t *c)
513{
Jens Wiklander02389a92016-12-16 11:13:38 +0100514 struct test_2002_barrier bar = { .mu = PTHREAD_MUTEX_INITIALIZER };
Etienne Carrieree4ec9e42019-03-28 13:30:21 +0100515 struct test_2002_arg arg[NUM_THREADS] = { };
516 size_t n = 0;
517 size_t nt = 0;
518 pthread_t thr[NUM_THREADS] = { };
Jens Wiklander02389a92016-12-16 11:13:38 +0100519
520 Do_ADBG_BeginSubCase(c, "Stressing with %d threads", NUM_THREADS);
521
522 xtest_mutex_lock(&bar.mu);
523
524 nt = NUM_THREADS;
525 for (n = 0; n < nt; n++) {
526 arg[n].success = false;
527 arg[n].tnum = n;
528 arg[n].bar = &bar;
529 if (!ADBG_EXPECT(c, 0, pthread_create(thr + n, NULL,
530 xtest_tee_test_2002_thread, arg + n)))
531 nt = n; /* break loop and start cleanup */
532 }
533
534 xtest_barrier_init(&bar.bar, nt + 1);
535 xtest_mutex_unlock(&bar.mu);
536 xtest_barrier_wait(&bar.bar);
537
538 for (n = 0; n < nt; n++) {
539 ADBG_EXPECT(c, 0, pthread_join(thr[n], NULL));
540 ADBG_EXPECT_TRUE(c, arg[n].success);
541 }
542
543 xtest_mutex_destroy(&bar.mu);
544 xtest_barrier_destroy(&bar.bar);
545
546 Do_ADBG_EndSubCase(c, "Stressing with %d threads", NUM_THREADS);
547}
Jens Wiklander14f48872018-06-29 15:30:13 +0200548ADBG_CASE_DEFINE(regression, 2002, xtest_tee_test_2002,
549 "Concurrent stressing TCP iSocket API tests");
Jens Wiklander02389a92016-12-16 11:13:38 +0100550
551static bool test_2003_accept_cb(void *ptr, int fd, short *events)
552{
Etienne Carrieree4ec9e42019-03-28 13:30:21 +0100553 int val = 0;
Jens Wiklander02389a92016-12-16 11:13:38 +0100554
555 (void)ptr;
556 (void)events;
557
558 val = 4 * 1024;
559 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)))
560 warn("test_2003_accept_cb: setsockopt");
561 return true;
562}
563
564static void xtest_tee_test_2003(ADBG_Case_t *c)
565{
Etienne Carrieree4ec9e42019-03-28 13:30:21 +0100566 struct sock_server ts = { };
567 TEEC_Session session = { };
568 uint32_t ret_orig = 0;
569 uint32_t proto_error = 0;
570 struct socket_handle sh = { };
571 void *buf = NULL;
Jens Wiklander02389a92016-12-16 11:13:38 +0100572 const size_t blen0 = 16 * 1024;
Etienne Carrieree4ec9e42019-03-28 13:30:21 +0100573 size_t blen = 0;
574 uint32_t val = 0;
Jens Wiklander02389a92016-12-16 11:13:38 +0100575 struct sock_io_cb cb = { .accept = test_2003_accept_cb };
576
577 Do_ADBG_BeginSubCase(c, "Start server");
578 if (!ADBG_EXPECT_TRUE(c, sock_server_init_tcp(&ts, &cb)))
579 return;
580 buf = calloc(1, blen0);
581 if (!ADBG_EXPECT_NOT_NULL(c, buf))
582 goto out;
583 Do_ADBG_EndSubCase(c, "Start server");
584
585 Do_ADBG_BeginSubCase(c, "TCP Socket open");
586 if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session(
587 &session, &socket_ta_uuid, NULL, &ret_orig)))
588 goto out;
589
590 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_tcp_open(&session,
591 TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port,
592 &sh, &proto_error, &ret_orig)))
593 goto out_close_session;
594
595 blen = sizeof(val);
596 val = 4 * 1024;
597 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh,
598 TEE_TCP_SET_RECVBUF, &val, &blen, &ret_orig)))
599 goto out_close_session;
600
601 blen = sizeof(val);
602 val = 4 * 1024;
603 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh,
604 TEE_TCP_SET_SENDBUF, &val, &blen, &ret_orig)))
605 goto out_close_session;
606
607 Do_ADBG_EndSubCase(c, "TCP Socket open");
608
609 Do_ADBG_BeginSubCase(c, "TCP Socket send (10 ms timeout)");
610 while (true) {
Etienne Carrieree4ec9e42019-03-28 13:30:21 +0100611 TEE_Result res = TEE_ERROR_GENERIC;
Jens Wiklander02389a92016-12-16 11:13:38 +0100612
613 blen = blen0;
614 memset(buf, 0, blen0);
615 res = socket_send(&session, &sh, buf, &blen, 10, &ret_orig);
616 if (res == TEE_ISOCKET_ERROR_TIMEOUT)
617 break;
618 if (!ADBG_EXPECT_TEEC_SUCCESS(c, res))
619 goto out_close_session;
620 ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, blen0);
621 }
622 Do_ADBG_EndSubCase(c, "TCP Socket send (10 ms timeout)");
623
624 Do_ADBG_BeginSubCase(c, "TCP Socket recv (10 ms timeout)");
625 blen = blen0;
626 ADBG_EXPECT_TEEC_RESULT(c, TEE_ISOCKET_ERROR_TIMEOUT,
627 socket_recv(&session, &sh, buf, &blen,
628 10, &ret_orig));
629 ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, blen0);
630 Do_ADBG_EndSubCase(c, "TCP Socket recv (10 ms timeout)");
631
632 Do_ADBG_BeginSubCase(c, "TCP Socket get error");
633 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_get_error(&session, &sh,
634 &proto_error, &ret_orig)))
635 goto out_close_session;
636 ADBG_EXPECT_TEEC_RESULT(c, TEE_ISOCKET_ERROR_TIMEOUT, proto_error);
637 Do_ADBG_EndSubCase(c, "TCP Socket get error");
638
639out_close_session:
640 TEEC_CloseSession(&session);
641out:
642 free(buf);
643 sock_server_uninit(&ts);
644}
Jens Wiklander14f48872018-06-29 15:30:13 +0200645ADBG_CASE_DEFINE(regression, 2003, xtest_tee_test_2003,
646 "Timeout TCP iSocket API tests");
Jens Wiklander02389a92016-12-16 11:13:38 +0100647
648static bool test_200x_udp_accept_cb(void *ptr, int fd, short *events)
649{
650 struct test_200x_io_state *iostate = ptr;
Etienne Carrieree4ec9e42019-03-28 13:30:21 +0100651 struct sockaddr_storage sass = { };
Jens Wiklander02389a92016-12-16 11:13:38 +0100652 struct sockaddr *sa = (struct sockaddr *)&sass;
653 socklen_t slen = sizeof(sass);
Etienne Carrieree4ec9e42019-03-28 13:30:21 +0100654 uint8_t buf[100] = { };
655 uint8_t buf2[100] = { };
656 ssize_t r = 0;
657 size_t l = 0;
Jens Wiklander02389a92016-12-16 11:13:38 +0100658
659 (void)events;
660
661 r = recvfrom(fd, buf, sizeof(buf), 0, sa, &slen);
662 if (r == -1)
663 return false;
664
665 l = r;
666 rand_stream_read(iostate->read_rs, buf2, l);
667 if (memcmp(buf, buf2, l))
668 iostate->rfail = true;
669
670 rand_stream_read(iostate->write_rs, buf, l);
671 return sendto(fd, buf, l, 0, sa, slen) != -1;
672}
673
674static void xtest_tee_test_2004(ADBG_Case_t *c)
675{
Etienne Carrieree4ec9e42019-03-28 13:30:21 +0100676 struct sock_server ts = { };
677 struct sock_server ts2 = { };
678 struct sock_server ts3 = { };
Jens Wiklander02389a92016-12-16 11:13:38 +0100679 bool ts_inited = false;
680 bool ts2_inited = false;
681 bool ts3_inited = false;
Etienne Carrieree4ec9e42019-03-28 13:30:21 +0100682 TEEC_Session session = { };
683 uint32_t ret_orig = 0;
684 uint32_t proto_error = 0;
685 struct socket_handle sh = { };
686 uint8_t buf[64] = { };
687 uint8_t buf2[64] = { };
688 size_t blen = 0;
689 uint16_t port = 0;
690 struct test_200x_io_state server_iostate = { };
691 struct test_200x_io_state local_iostate = { };
Jens Wiklander02389a92016-12-16 11:13:38 +0100692 struct sock_io_cb cb = {
693 .accept = test_200x_udp_accept_cb,
694 .ptr = &server_iostate,
695 };
696
697 test_200x_init_io_state(&server_iostate, 1, 2);
698 test_200x_init_io_state(&local_iostate, 2, 1);
699
700 Do_ADBG_BeginSubCase(c, "Start server");
701 if (!ADBG_EXPECT_TRUE(c, sock_server_init_udp(&ts, &cb)))
702 return;
703 ts_inited = true;
704 if (!ADBG_EXPECT_TRUE(c, sock_server_init_udp(&ts2, &cb)))
705 goto out;
706 ts2_inited = true;
707 if (!ADBG_EXPECT_TRUE(c, sock_server_init_udp(&ts3, &cb)))
708 goto out;
709 ts3_inited = true;
710 Do_ADBG_EndSubCase(c, "Start server");
711
712 Do_ADBG_BeginSubCase(c, "UDP Socket open");
713 if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session(
714 &session, &socket_ta_uuid, NULL, &ret_orig)))
715 goto out;
716
717 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_udp_open(&session,
718 TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port,
719 &sh, &proto_error, &ret_orig)))
720 goto out_close_session;
721
722 Do_ADBG_EndSubCase(c, "UDP Socket open");
723
724 Do_ADBG_BeginSubCase(c, "UDP Socket send");
725 blen = sizeof(buf);
726 rand_stream_read(local_iostate.write_rs, buf, blen);
727 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_send(&session, &sh,
728 buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig)))
729 goto out_close_session;
730 ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, sizeof(buf));
731 Do_ADBG_EndSubCase(c, "UDP Socket send");
732
733 Do_ADBG_BeginSubCase(c, "UDP Socket recv");
734 blen = sizeof(buf);
735 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_recv(&session, &sh,
736 buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig)))
737 goto out_close_session;
738 ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, sizeof(buf));
739 rand_stream_read(local_iostate.read_rs, buf2, blen);
740 ADBG_EXPECT_BUFFER(c, buf2, blen, buf, blen);
741 ADBG_EXPECT_TRUE(c, !server_iostate.rfail);
742 Do_ADBG_EndSubCase(c, "UDP Socket recv");
743
744 Do_ADBG_BeginSubCase(c, "UDP Socket get error");
745 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_get_error(&session, &sh,
746 &proto_error, &ret_orig)))
747 goto out_close_session;
748 if (!ADBG_EXPECT_TEEC_SUCCESS(c, proto_error))
749 goto out_close_session;
750 Do_ADBG_EndSubCase(c, "UDP Socket get error");
751
752 Do_ADBG_BeginSubCase(c, "UDP Socket close");
753 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_close(&session, &sh,
754 &ret_orig)))
755 goto out_close_session;
756 Do_ADBG_EndSubCase(c, "UDP Socket close");
757
758 Do_ADBG_BeginSubCase(c, "UDP Socket ioctl");
759
760 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_udp_open(&session,
761 TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port,
762 &sh, &proto_error, &ret_orig)))
763 goto out_close_session;
764
765 blen = sizeof(buf);
766 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh, 0x00F00000,
767 buf, &blen, &ret_orig)))
768 goto out_close_session;
769
770 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_close(&session, &sh,
771 &ret_orig)))
772 goto out_close_session;
773
774
775 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_udp_open(&session,
776 TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port,
777 &sh, &proto_error, &ret_orig)))
778 goto out_close_session;
779
780 blen = sizeof(buf);
781 ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD,
782 socket_ioctl(&session, &sh,
783 TEE_ISOCKET_PROTOCOLID_UDP << 24,
784 buf, &blen, &ret_orig));
785 TEEC_CloseSession(&session);
786
787 if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session(
788 &session, &socket_ta_uuid, NULL, &ret_orig)))
789 goto out;
790
791 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_udp_open(&session,
792 TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port,
793 &sh, &proto_error, &ret_orig)))
794 goto out_close_session;
795
796 blen = sizeof(buf);
797 ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD,
798 socket_ioctl(&session, &sh, 0x32 << 24,
799 buf, &blen, &ret_orig));
800
801 Do_ADBG_EndSubCase(c, "UDP Socket ioctl");
802
803 Do_ADBG_BeginSubCase(c, "UDP Socket change port");
804
805 if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session(
806 &session, &socket_ta_uuid, NULL, &ret_orig)))
807 goto out;
808
809 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_udp_open(&session,
810 TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port,
811 &sh, &proto_error, &ret_orig)))
812 goto out_close_session;
813 sock_server_uninit(&ts);
814 ts_inited = false;
815
816 port = ts2.bind->port;
817 blen = sizeof(port);
818 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh,
819 TEE_UDP_CHANGEPORT, &port, &blen, &ret_orig)))
820 goto out_close_session;
821
822 Do_ADBG_BeginSubCase(c, "UDP Socket send");
823 blen = sizeof(buf);
824 rand_stream_read(local_iostate.write_rs, buf, blen);
825 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_send(&session, &sh,
826 buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig)))
827 goto out_close_session;
828 ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, sizeof(buf));
829 Do_ADBG_EndSubCase(c, "UDP Socket send");
830
831 Do_ADBG_BeginSubCase(c, "UDP Socket recv");
832 blen = sizeof(buf);
833 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_recv(&session, &sh,
834 buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig)))
835 goto out_close_session;
836 ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, sizeof(buf));
837 rand_stream_read(local_iostate.read_rs, buf2, blen);
838 ADBG_EXPECT_BUFFER(c, buf2, blen, buf, blen);
839 ADBG_EXPECT_TRUE(c, !server_iostate.rfail);
840 Do_ADBG_EndSubCase(c, "UDP Socket recv");
841
842 Do_ADBG_EndSubCase(c, "UDP Socket change port");
843
844 Do_ADBG_BeginSubCase(c, "UDP Socket change addr");
845
846 if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session(
847 &session, &socket_ta_uuid, NULL, &ret_orig)))
848 goto out;
849
850 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_udp_open(&session,
851 TEE_IP_VERSION_DC, ts2.bind->host, ts2.bind->port,
852 &sh, &proto_error, &ret_orig)))
853 goto out_close_session;
854 sock_server_uninit(&ts2);
855 ts2_inited = false;
856
857 port = ts3.bind->port;
858 blen = sizeof(port);
859 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh,
860 TEE_UDP_CHANGEPORT, &port, &blen, &ret_orig)))
861 goto out_close_session;
862
863 blen = strlen(ts3.bind->host) + 1;
864 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh,
865 TEE_UDP_CHANGEADDR, ts3.bind->host, &blen, &ret_orig)))
866 goto out_close_session;
867
868 Do_ADBG_BeginSubCase(c, "UDP Socket send");
869 blen = sizeof(buf);
870 rand_stream_read(local_iostate.write_rs, buf, blen);
871 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_send(&session, &sh,
872 buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig)))
873 goto out_close_session;
874 ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, sizeof(buf));
875 Do_ADBG_EndSubCase(c, "UDP Socket send");
876
877 Do_ADBG_BeginSubCase(c, "UDP Socket recv");
878 blen = sizeof(buf);
879 if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_recv(&session, &sh,
880 buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig)))
881 goto out_close_session;
882 ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, sizeof(buf));
883 rand_stream_read(local_iostate.read_rs, buf2, blen);
884 ADBG_EXPECT_BUFFER(c, buf2, blen, buf, blen);
885 ADBG_EXPECT_TRUE(c, !server_iostate.rfail);
886 Do_ADBG_EndSubCase(c, "UDP Socket recv");
887
888 Do_ADBG_EndSubCase(c, "UDP Socket change addr");
889
890
891out_close_session:
892 TEEC_CloseSession(&session);
893out:
894 if (ts_inited)
895 sock_server_uninit(&ts);
896 if (ts2_inited)
897 sock_server_uninit(&ts2);
898 if (ts3_inited)
899 sock_server_uninit(&ts3);
900}
Jens Wiklander02389a92016-12-16 11:13:38 +0100901ADBG_CASE_DEFINE(regression, 2004, xtest_tee_test_2004,
902 "UDP iSocket API tests");