blob: 84de4b1d7527c535245b3ff860412931e8b76766 [file] [log] [blame]
Etienne Carriere41343db2017-03-17 15:38:52 +01001/*
2 * Copyright (c) 2016, Linaro Limited
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <err.h>
29#include <fcntl.h>
Etienne Carrierec45d9762017-03-21 15:45:13 +010030#include <pta_invoke_tests.h>
Etienne Carriere41343db2017-03-17 15:38:52 +010031#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <sys/ioctl.h>
35#include <sys/mman.h>
36#include <tee_client_api.h>
37#include <tee_client_api_extensions.h>
38#include <unistd.h>
39
Etienne Carriere41343db2017-03-17 15:38:52 +010040#include "crypto_common.h"
Etienne Carriere50abf9a2017-03-24 11:33:50 +010041#include "sdp_basic.h"
42#include "xtest_test.h"
Etienne Carriere41343db2017-03-17 15:38:52 +010043
44/*
45 * SDP basic test setup overview.
46 *
47 * - A dedicated trusted application (SDP basic TA) supports 3 commands:
48 * - 'inject' data from a nonsecure buffer into a secure buffer
49 * - 'transform' data inside a secure buffer (bitwise invert + unsigned incr)
50 * - 'dump' data from a secure buffer into a nonsecure buffer
51
52 * - This test client application (CA) invokes the TA for these 3 operations,
53 * inject random value, trasforming them then dump them.
54 *
55 * To do so, CA allocates a 'SDP secure buffer' and invoke the TA for these 3
56 * operations (inject then transform then dump) over the allocate buffer.
57 *
58 * The secure buffer is currently allocation through ION support adn
59 * registered to OP-TEE and as shared memory.
60 *
61 * To enhance test coverage against buffer alignement usecase, the CA invokes
62 * the TA with a variable offset inside the buffer. As CA injects random data
63 * into the buffer, the CA uses one of the random bytes to set the value of the
64 * offset in the accessed secure buffer.
65 *
66 * For debugging support, the CA may map (in nonsecure world) the secure
67 * buffer to read its content. As this is unsafe on a hardened platform, this
68 * operation is default disable. When enable, error only print out a warning
69 * trace but does not actually fail the test. This also give an easy way to
70 * check that some HW complains on access violation when nonsecure accesses
71 * secure data.
72 */
73
Etienne Carriere41343db2017-03-17 15:38:52 +010074struct tee_ctx {
75 TEEC_Context ctx;
76 TEEC_Session sess;
77};
78
Etienne Carriere8bc31422017-08-24 14:48:30 +020079int allocate_ion_buffer(size_t size, int heap_type_id, int verbosity)
Etienne Carriere41343db2017-03-17 15:38:52 +010080{
Etienne Carriere8bc31422017-08-24 14:48:30 +020081 struct ion_heap_query query_data;
82 struct ion_heap_data heap_data[32];
Etienne Carriere41343db2017-03-17 15:38:52 +010083 struct ion_allocation_data alloc_data;
Etienne Carriere41343db2017-03-17 15:38:52 +010084 int ion;
85 int fd = -1;
Etienne Carriere8bc31422017-08-24 14:48:30 +020086 unsigned int idx;
Etienne Carriere41343db2017-03-17 15:38:52 +010087
88 ion = open("/dev/ion", O_RDWR);
89 if (ion < 0) {
Etienne Carriere8bc31422017-08-24 14:48:30 +020090 fprintf(stderr, "Error: failed to open /dev/ion\n");
Etienne Carriere41343db2017-03-17 15:38:52 +010091 verbose("Seems no ION heap is available.\n");
92 verbose("To test ION allocation you can enable\n");
93 verbose("CONFIG_ION and CONFIG_ION_DUMMY in your\n");
94 verbose("linux kernel configuration.\n");
95 return fd;
96 }
97
Etienne Carriere8bc31422017-08-24 14:48:30 +020098 if (heap_type_id < 0)
99 heap_type_id = DEFAULT_ION_HEAP_TYPE;
Etienne Carriere41343db2017-03-17 15:38:52 +0100100
Etienne Carriere8bc31422017-08-24 14:48:30 +0200101 memset(&query_data, 0, sizeof(query_data));
102 if (ioctl(ion, ION_IOC_HEAP_QUERY, &query_data) < 0) {
103 fprintf(stderr, "Error: failed to query the number of heaps\n");
104 goto out;
105 }
106
107 query_data.heaps = (__u64)(unsigned long)&heap_data;
108 if (ioctl(ion, ION_IOC_HEAP_QUERY, &query_data) < 0) {
109 fprintf(stderr, "Error: failed to query heaps data\n");
110 goto out;
111 }
112
113 for (idx = 0; idx < query_data.cnt; idx++)
114 if (heap_data[idx].type == (unsigned int)heap_type_id)
115 break;
116 if (idx == query_data.cnt) {
117 fprintf(stderr, "Error: target heap type %d not found\n",
118 heap_type_id);
119 goto out;
120 }
121
122 verbose("Allocate in ION heap '%s' (type=%u, id=%u)\n",
123 heap_data[idx].name, heap_data[idx].type,
124 heap_data[idx].heap_id);
Etienne Carriere41343db2017-03-17 15:38:52 +0100125
126 alloc_data.len = size;
Etienne Carriere41343db2017-03-17 15:38:52 +0100127 alloc_data.flags = 0;
Etienne Carriere8bc31422017-08-24 14:48:30 +0200128 alloc_data.heap_id_mask = 1 << heap_data[idx].heap_id;
129 if (ioctl(ion, ION_IOC_ALLOC, &alloc_data) < 0) {
130 fprintf(stderr, "Error: failed to allocate in target heap\n");
Etienne Carriere41343db2017-03-17 15:38:52 +0100131 goto out;
Etienne Carriere8bc31422017-08-24 14:48:30 +0200132 }
Etienne Carriere41343db2017-03-17 15:38:52 +0100133
Etienne Carriere8bc31422017-08-24 14:48:30 +0200134 fd = alloc_data.fd;
Etienne Carriere41343db2017-03-17 15:38:52 +0100135out:
136 close(ion);
137 return fd;
138}
139
140static void finalize_tee_ctx(struct tee_ctx *ctx)
141{
142 if (!ctx)
143 return;
144
145 TEEC_CloseSession(&ctx->sess);
146 TEEC_FinalizeContext(&ctx->ctx);
147}
148
Etienne Carrierec45d9762017-03-21 15:45:13 +0100149static int create_tee_ctx(struct tee_ctx *ctx, enum test_target_ta target_ta)
Etienne Carriere41343db2017-03-17 15:38:52 +0100150{
151 TEEC_Result teerc;
Etienne Carriereb296a642017-03-29 15:23:56 +0200152 const TEEC_UUID *uuid;
Etienne Carriere41343db2017-03-17 15:38:52 +0100153 uint32_t err_origin;
154
Etienne Carrierec45d9762017-03-21 15:45:13 +0100155 switch (target_ta) {
156 case TEST_NS_TO_TA:
157 case TEST_TA_TO_TA:
158 case TEST_TA_TO_PTA:
Etienne Carriere50abf9a2017-03-24 11:33:50 +0100159 uuid = &sdp_basic_ta_uuid;
Etienne Carrierec45d9762017-03-21 15:45:13 +0100160 break;
161 case TEST_NS_TO_PTA:
Etienne Carriere50abf9a2017-03-24 11:33:50 +0100162 uuid = &pta_invoke_tests_ta_uuid;
Etienne Carrierec45d9762017-03-21 15:45:13 +0100163 break;
164 default:
165 return -1;
166 }
167
Etienne Carriere41343db2017-03-17 15:38:52 +0100168 teerc = TEEC_InitializeContext(NULL, &ctx->ctx);
169 if (teerc != TEEC_SUCCESS)
170 return -1;
171
Etienne Carrierec45d9762017-03-21 15:45:13 +0100172 teerc = TEEC_OpenSession(&ctx->ctx, &ctx->sess, uuid,
Etienne Carriere41343db2017-03-17 15:38:52 +0100173 TEEC_LOGIN_PUBLIC, NULL, NULL, &err_origin);
174 if (teerc != TEEC_SUCCESS)
Etienne Carrierec45d9762017-03-21 15:45:13 +0100175 fprintf(stderr, "Error: open session to target test %s failed %x %d\n",
176 (target_ta == TEST_NS_TO_PTA) ? "pTA" : "TA",
Etienne Carriere41343db2017-03-17 15:38:52 +0100177 teerc, err_origin);
178
179 return (teerc == TEEC_SUCCESS) ? 0 : -1;
180}
181
182static int tee_register_buffer(struct tee_ctx *ctx, void **shm_ref, int fd)
183{
184 TEEC_Result teerc;
185 TEEC_SharedMemory *shm;
186
187 shm = malloc(sizeof(*shm));
188 if (!shm)
189 return 1;
190
191 shm->flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
192 teerc = TEEC_RegisterSharedMemoryFileDescriptor(&ctx->ctx, shm, fd);
193 if (teerc != TEEC_SUCCESS) {
194 fprintf(stderr, "Error: TEEC_RegisterMemoryFileDescriptor() failed %x\n",
195 teerc);
196 return 1;
197 }
198
199 *shm_ref = shm;
200 return 0;
201}
202
203static void tee_deregister_buffer(struct tee_ctx *ctx, void *shm_ref)
204{
205 (void)ctx;
206
207 if (!shm_ref)
208 return;
209
210 TEEC_ReleaseSharedMemory((TEEC_SharedMemory *)shm_ref);
211 free(shm_ref);
212}
213
214static int inject_sdp_data(struct tee_ctx *ctx,
Etienne Carrieref690b912017-03-21 15:44:13 +0100215 void *in, size_t offset, size_t len, void *shm_ref, int ind)
Etienne Carriere41343db2017-03-17 15:38:52 +0100216{
217 TEEC_SharedMemory *shm = (TEEC_SharedMemory *)shm_ref;
218 TEEC_Result teerc;
219 TEEC_Operation op;
220 uint32_t err_origin;
Etienne Carrierec45d9762017-03-21 15:45:13 +0100221 unsigned cmd;
222
223 switch (ind) {
224 case TEST_NS_TO_TA:
225 cmd = TA_SDP_BASIC_CMD_INJECT;
226 break;
227 case TEST_TA_TO_TA:
228 cmd = TA_SDP_BASIC_CMD_INVOKE_INJECT;
229 break;
230 case TEST_TA_TO_PTA:
231 cmd = TA_SDP_BASIC_CMD_PTA_INJECT;
232 break;
233 case TEST_NS_TO_PTA:
234 cmd = PTA_INVOKE_TESTS_CMD_COPY_NSEC_TO_SEC;
235 break;
236 default:
237 return -1;
238 }
Etienne Carriere41343db2017-03-17 15:38:52 +0100239
240 memset(&op, 0, sizeof(op));
241 op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
242 TEEC_MEMREF_PARTIAL_OUTPUT,
243 TEEC_NONE, TEEC_NONE);
244
245 op.params[0].tmpref.buffer = in;
246 op.params[0].tmpref.size = len;
247
248 op.params[1].memref.parent = shm;
249 op.params[1].memref.size = len;
250 op.params[1].memref.offset = offset;
251
Etienne Carrieref690b912017-03-21 15:44:13 +0100252 teerc = TEEC_InvokeCommand(&ctx->sess, cmd, &op, &err_origin);
Etienne Carriere41343db2017-03-17 15:38:52 +0100253 if (teerc != TEEC_SUCCESS)
254 fprintf(stderr, "Error: invoke SDP test TA (inject) failed %x %d\n",
255 teerc, err_origin);
256
257 return (teerc == TEEC_SUCCESS) ? 0 : -1;
258}
259
260static int transform_sdp_data(struct tee_ctx *ctx,
Etienne Carrieref690b912017-03-21 15:44:13 +0100261 size_t offset, size_t len, void *shm_ref, int ind)
Etienne Carriere41343db2017-03-17 15:38:52 +0100262{
263 TEEC_SharedMemory *shm = (TEEC_SharedMemory *)shm_ref;
264 TEEC_Result teerc;
265 TEEC_Operation op;
266 uint32_t err_origin;
Etienne Carrierec45d9762017-03-21 15:45:13 +0100267 unsigned cmd;
268
269 switch (ind) {
270 case TEST_NS_TO_TA:
271 cmd = TA_SDP_BASIC_CMD_TRANSFORM;
272 break;
273 case TEST_TA_TO_TA:
274 cmd = TA_SDP_BASIC_CMD_INVOKE_TRANSFORM;
275 break;
276 case TEST_TA_TO_PTA:
277 cmd = TA_SDP_BASIC_CMD_PTA_TRANSFORM;
278 break;
279 case TEST_NS_TO_PTA:
280 cmd = PTA_INVOKE_TESTS_CMD_READ_MODIFY_SEC;
281 break;
282 default:
283 return -1;
284 }
Etienne Carriere41343db2017-03-17 15:38:52 +0100285
286 memset(&op, 0, sizeof(op));
287 op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INOUT,
288 TEEC_NONE, TEEC_NONE, TEEC_NONE);
289 op.params[0].memref.parent = shm;
290 op.params[0].memref.size = len;
291 op.params[0].memref.offset = offset;
292
Etienne Carrieref690b912017-03-21 15:44:13 +0100293 teerc = TEEC_InvokeCommand(&ctx->sess, cmd, &op, &err_origin);
Etienne Carriere41343db2017-03-17 15:38:52 +0100294 if (teerc != TEEC_SUCCESS)
295 fprintf(stderr, "Error: invoke SDP test TA (transform) failed %x %d\n",
296 teerc, err_origin);
297
298 return (teerc == TEEC_SUCCESS) ? 0 : -1;
299}
300
301static int dump_sdp_data(struct tee_ctx *ctx,
Etienne Carrieref690b912017-03-21 15:44:13 +0100302 void *out, size_t offset, size_t len, void *shm_ref, int ind)
Etienne Carriere41343db2017-03-17 15:38:52 +0100303{
304 TEEC_SharedMemory *shm = (TEEC_SharedMemory *)shm_ref;
305 TEEC_Result teerc;
306 TEEC_Operation op;
307 uint32_t err_origin;
Etienne Carrierec45d9762017-03-21 15:45:13 +0100308 unsigned cmd;
309
310 switch (ind) {
311 case TEST_NS_TO_TA:
312 cmd = TA_SDP_BASIC_CMD_DUMP;
313 break;
314 case TEST_TA_TO_TA:
315 cmd = TA_SDP_BASIC_CMD_INVOKE_DUMP;
316 break;
317 case TEST_TA_TO_PTA:
318 cmd = TA_SDP_BASIC_CMD_PTA_DUMP;
319 break;
320 case TEST_NS_TO_PTA:
321 cmd = PTA_INVOKE_TESTS_CMD_COPY_SEC_TO_NSEC;
322 break;
323 default:
324 return -1;
325 }
Etienne Carriere41343db2017-03-17 15:38:52 +0100326
327 memset(&op, 0, sizeof(op));
328 op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INPUT,
329 TEEC_MEMREF_TEMP_OUTPUT,
330 TEEC_NONE, TEEC_NONE);
331 op.params[0].memref.parent = shm;
332 op.params[0].memref.size = len;
333 op.params[0].memref.offset = offset;
334
335 op.params[1].tmpref.buffer = out;
336 op.params[1].tmpref.size = len;
337
Etienne Carrieref690b912017-03-21 15:44:13 +0100338 teerc = TEEC_InvokeCommand(&ctx->sess, cmd, &op, &err_origin);
Etienne Carriere41343db2017-03-17 15:38:52 +0100339 if (teerc != TEEC_SUCCESS)
340 fprintf(stderr, "Error: invoke SDP test TA (dump) failed %x %d\n",
341 teerc, err_origin);
342
343 return (teerc == TEEC_SUCCESS) ? 0 : -1;
344}
345
346static int check_sdp_dumped(struct tee_ctx *ctx, void *ref, size_t len,
347 void *out)
348{
349 char *bref = (char *)ref;
350 char *data = (char *)out;
351 int err = 0;
352
353 (void)ctx;
354
355 while(len--)
356 if (*data++ != (unsigned char)(~(*bref++) + 1))
357 err++;
358
359 return err;
360}
361
362/*
363 * Consider 32kByte + 1 of random data is sufficient for an accurate test
364 * whatever the test buffer size is. Random buffer is read as a ring buffer.
365 */
366#define RANDOM_BUFFER_SIZE (32 * 1024 + 1)
367static int get_random_bytes(char *out, size_t len)
368{
369 static char *rand_buf = NULL;
370 static size_t rand_idx = 0;
371 int rc;
372
373 if (!rand_buf) {
374 const char rand_dev[] = "/dev/urandom";
375 int fd;
376
377 rand_buf = malloc(RANDOM_BUFFER_SIZE);
378 if (!rand_buf) {
379 fprintf(stderr, "failed to random buffer memory (%d bytes)\n",
380 RANDOM_BUFFER_SIZE);
381 return -1;
382 }
383
384 fd = open(rand_dev, O_RDONLY);
385 if (fd < 0) {
386 fprintf(stderr, "failed to open %s\n", rand_dev);
387 return -1;
388 }
389
390 rc = read(fd, rand_buf, RANDOM_BUFFER_SIZE);
391 if (rc != RANDOM_BUFFER_SIZE) {
392 fprintf(stderr, "failed to read %d bytes from %s\n",
393 RANDOM_BUFFER_SIZE, rand_dev);
394 return -1;
395 }
396 close(fd);
397 }
398
399 while (len) {
400 size_t t_len = (RANDOM_BUFFER_SIZE < len) ? RANDOM_BUFFER_SIZE : len;
401
402 if ((rand_idx + t_len) > RANDOM_BUFFER_SIZE) {
403 int sz_end = RANDOM_BUFFER_SIZE - rand_idx;
404 int sz_beg = t_len - sz_end;
405
406 memcpy(out, rand_buf + rand_idx, sz_end);
407 memcpy(out + sz_end, rand_buf , sz_beg);
408 rand_idx = sz_beg;
409 } else {
410 memcpy(out, rand_buf + rand_idx, t_len);
411 rand_idx += t_len;
412 }
413 len -= t_len;
414 }
415 return 0;
416}
417
418
Etienne Carriere50abf9a2017-03-24 11:33:50 +0100419int sdp_basic_test(enum test_target_ta ta, size_t size, size_t loop,
Etienne Carriereb9a95822017-04-26 15:03:53 +0200420 int ion_heap, int rnd_offset, int verbosity)
Etienne Carriere41343db2017-03-17 15:38:52 +0100421{
422 struct tee_ctx *ctx = NULL;
423 unsigned char *test_buf = NULL;
424 unsigned char *ref_buf = NULL;
425 void *shm_ref = NULL;
426 unsigned int err = 1;
427 int fd = -1;
428 size_t sdp_size = size;
429 size_t offset;
Etienne Carrieref690b912017-03-21 15:44:13 +0100430 size_t loop_cnt;
Etienne Carriere41343db2017-03-17 15:38:52 +0100431
432 if (!loop) {
433 fprintf(stderr, "Error: null loop value\n");
434 return 1;
435 }
436
437 /* reduce size to enable offset tests (max offset is 255 bytes) */
438 if (rnd_offset)
439 size -= 255;
440
441 test_buf = malloc(size);
442 ref_buf = malloc(size);
443 if (!test_buf || !ref_buf) {
444 verbose("failed to allocate memory\n");
445 goto out;
446 }
447
Etienne Carriereb9a95822017-04-26 15:03:53 +0200448 fd = allocate_ion_buffer(sdp_size, ion_heap, verbosity);
Etienne Carriere41343db2017-03-17 15:38:52 +0100449 if (fd < 0) {
Etienne Carriere5fdf6352017-03-24 11:49:50 +0100450 verbose("Failed to allocate SDP buffer (%zu bytes) in ION heap %d: %d\n",
Etienne Carriere41343db2017-03-17 15:38:52 +0100451 sdp_size, ion_heap, fd);
452 goto out;
453 }
454
455 /* register secure buffer to TEE */
456 ctx = malloc(sizeof(*ctx));
457 if (!ctx)
458 goto out;
Etienne Carrierec45d9762017-03-21 15:45:13 +0100459 if (create_tee_ctx(ctx, ta))
Etienne Carriere41343db2017-03-17 15:38:52 +0100460 goto out;
461 if (tee_register_buffer(ctx, &shm_ref, fd))
462 goto out;
463
464 /* release registered fd: tee should still hold refcount on resource */
465 close(fd);
466 fd = -1;
467
468 /* invoke trusted application with secure buffer as memref parameter */
Etienne Carrieref690b912017-03-21 15:44:13 +0100469 for (loop_cnt = loop; loop_cnt; loop_cnt--) {
Etienne Carriere41343db2017-03-17 15:38:52 +0100470 /* get an buffer of random-like values */
471 if (get_random_bytes((char *)ref_buf, size))
472 goto out;
473 memcpy(test_buf, ref_buf, size);
474 /* random offset [0 255] */
475 offset = (unsigned int)*ref_buf;
476
477 /* TA writes into SDP buffer */
Etienne Carrierec45d9762017-03-21 15:45:13 +0100478 if (inject_sdp_data(ctx, test_buf, offset, size, shm_ref, ta))
Etienne Carriere41343db2017-03-17 15:38:52 +0100479 goto out;
480
481 /* TA reads/writes into SDP buffer */
Etienne Carrierec45d9762017-03-21 15:45:13 +0100482 if (transform_sdp_data(ctx, offset, size, shm_ref, ta))
Etienne Carriere41343db2017-03-17 15:38:52 +0100483 goto out;
484
485 /* TA reads into SDP buffer */
Etienne Carrierec45d9762017-03-21 15:45:13 +0100486 if (dump_sdp_data(ctx, test_buf, offset, size, shm_ref, ta))
Etienne Carrieref690b912017-03-21 15:44:13 +0100487 goto out;
488
489 /* check dumped data are the expected ones */
490 if (check_sdp_dumped(ctx, ref_buf, size, test_buf)) {
491 fprintf(stderr, "check SDP data: %d errors\n", err);
492 goto out;
493 }
494 }
495
Etienne Carriere41343db2017-03-17 15:38:52 +0100496 err = 0;
Etienne Carriere41343db2017-03-17 15:38:52 +0100497out:
Etienne Carriere41343db2017-03-17 15:38:52 +0100498 if (fd >= 0)
499 close(fd);
500 if (shm_ref)
501 tee_deregister_buffer(ctx, shm_ref);
502 finalize_tee_ctx(ctx);
503 free(ctx);
504 free(ref_buf);
505 free(test_buf);
506 return err;
507}
508
509#define _TO_STR(x) #x
510#define TO_STR(x) _TO_STR(x)
511
512static void usage(const char *progname, size_t size, int loop, int ion_heap)
513{
514 fprintf(stderr, "Usage: %s [OPTION]\n", progname);
515 fprintf(stderr,
516 "Testing basic accesses to secure buffer (SDP) on OP-TEE.\n"
517 "Allocates a secure buffer and invoke a TA to access it.\n"
518 "TA is used to init/transform/dump the secure buffer.\n"
519 "CA check dumped content.\n\n");
520
521 fprintf(stderr, "Options:\n");
522 fprintf(stderr, " -h|--help Print this help and exit\n");
523 fprintf(stderr, " -v Be verbose\n");
524 fprintf(stderr, " -s SIZE SDP buffer byte size [%zu]\n", size);
525 fprintf(stderr, " -n LOOP Test loop iterations [%u]\n", loop);
526 fprintf(stderr, " --ion-heap ID Target ION heap ID [%d]\n", ion_heap);
527 fprintf(stderr, " --no-offset No random offset [0 255] in buffer\n");
528}
529
530#define NEXT_ARG(i) \
531 do { \
532 if (++i == argc) { \
533 fprintf(stderr, "%s: %s: missing argument\n", \
534 argv[0], argv[i-1]); \
535 return 1; \
536 } \
537 } while (0);
538
Jerome Forissiere1342522017-05-19 09:25:53 +0200539#define CHECK_RESULT(_res, _exp, _action) \
540 if ((_res) == (_exp)) { \
541 verbose("Test passed\n"); \
542 } else { \
543 verbose("Test failed!\n"); \
544 _action; \
545 }
546
Etienne Carriere41343db2017-03-17 15:38:52 +0100547int sdp_basic_runner_cmd_parser(int argc, char *argv[])
548{
549 size_t test_size = 5000;
550 size_t test_loop = 1000;
551 int ion_heap = DEFAULT_ION_HEAP_TYPE;
552 int rnd_offset = 1;
Etienne Carriereb9a95822017-04-26 15:03:53 +0200553 int verbosity = 1;
Jerome Forissiere1342522017-05-19 09:25:53 +0200554 int err;
Etienne Carriere41343db2017-03-17 15:38:52 +0100555 int i;
556
557 /* Parse command line */
558 for (i = 1; i < argc; i++) {
559 if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
560 usage(argv[0], test_size, test_loop, ion_heap);
561 return 0;
562 }
563 }
564 for (i = 1; i < argc; i++) {
565 if (!strcmp(argv[i], "-v")) {
566 verbosity++;
567 } else if (!strcmp(argv[i], "-s")) {
568 NEXT_ARG(i);
569 test_size = atoi(argv[i]);
570 } else if (!strcmp(argv[i], "-n")) {
571 NEXT_ARG(i);
572 test_loop = atoi(argv[i]);
573 } else if (!strcmp(argv[i], "--ion-heap")) {
574 NEXT_ARG(i);
575 ion_heap = atoi(argv[i]);
576 } else if (!strcmp(argv[i], "--no-offset")) {
577 rnd_offset = 0;
578 } else {
579 fprintf(stderr, "%s: invalid argument: %s\n",
580 argv[0], argv[i]);
581 usage(argv[0], test_size, test_loop, ion_heap);
582 return 1;
583 }
584 }
585
Jerome Forissiere1342522017-05-19 09:25:53 +0200586 verbose("\nSecure Data Path basic access: "
587 "NS invokes SDP TA\n");
588 err = sdp_basic_test(TEST_NS_TO_TA, test_size, test_loop, ion_heap,
589 rnd_offset, verbosity);
590 CHECK_RESULT(err, 0, return 1);
Etienne Carriere41343db2017-03-17 15:38:52 +0100591
Jerome Forissiere1342522017-05-19 09:25:53 +0200592 verbose("\nSecure Data Path basic access: "
593 "SDP TA invokes SDP TA\n");
594 err = sdp_basic_test(TEST_TA_TO_TA, test_size, test_loop, ion_heap,
595 rnd_offset, verbosity);
596 CHECK_RESULT(err, 0, return 1);
Etienne Carrierec45d9762017-03-21 15:45:13 +0100597
Jerome Forissiere1342522017-05-19 09:25:53 +0200598 verbose("\nSecure Data Path basic access: "
599 "SDP TA invokes SDP pTA\n");
600 err = sdp_basic_test(TEST_TA_TO_PTA, test_size, test_loop, ion_heap,
601 rnd_offset, verbosity);
602 CHECK_RESULT(err, 0, return 1);
Etienne Carriere41343db2017-03-17 15:38:52 +0100603
Jerome Forissiere1342522017-05-19 09:25:53 +0200604 verbose("\nSecure Data Path basic access: "
605 "NS invokes SDP pTA (shall fail)\n");
606 err = sdp_basic_test(TEST_NS_TO_PTA, test_size, test_loop, ion_heap,
607 rnd_offset, verbosity);
608 CHECK_RESULT(err, 1, return 1);
Etienne Carriered1655822017-03-21 15:45:24 +0100609
Etienne Carriere41343db2017-03-17 15:38:52 +0100610 return 0;
611}