blob: e2f611e23f1d5da9cf81b8badecd515e77c6aa34 [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
Etienne Carriere3a34b982017-10-24 15:31:34 +020044#include "include/uapi/linux/ion_old.h"
45
Etienne Carriere41343db2017-03-17 15:38:52 +010046/*
47 * SDP basic test setup overview.
48 *
49 * - A dedicated trusted application (SDP basic TA) supports 3 commands:
50 * - 'inject' data from a nonsecure buffer into a secure buffer
51 * - 'transform' data inside a secure buffer (bitwise invert + unsigned incr)
52 * - 'dump' data from a secure buffer into a nonsecure buffer
53
54 * - This test client application (CA) invokes the TA for these 3 operations,
55 * inject random value, trasforming them then dump them.
56 *
57 * To do so, CA allocates a 'SDP secure buffer' and invoke the TA for these 3
58 * operations (inject then transform then dump) over the allocate buffer.
59 *
60 * The secure buffer is currently allocation through ION support adn
61 * registered to OP-TEE and as shared memory.
62 *
63 * To enhance test coverage against buffer alignement usecase, the CA invokes
64 * the TA with a variable offset inside the buffer. As CA injects random data
65 * into the buffer, the CA uses one of the random bytes to set the value of the
66 * offset in the accessed secure buffer.
67 *
68 * For debugging support, the CA may map (in nonsecure world) the secure
69 * buffer to read its content. As this is unsafe on a hardened platform, this
70 * operation is default disable. When enable, error only print out a warning
71 * trace but does not actually fail the test. This also give an easy way to
72 * check that some HW complains on access violation when nonsecure accesses
73 * secure data.
74 */
75
Etienne Carriere41343db2017-03-17 15:38:52 +010076struct tee_ctx {
77 TEEC_Context ctx;
78 TEEC_Session sess;
79};
80
Etienne Carriere3a34b982017-10-24 15:31:34 +020081/*
82 * Old ION API to allocate and export a buffer
83 */
84static int allocate_ion_buffer_old_api(size_t size, int heap_type_id, int ion)
85{
86 struct ion0_allocation_data alloc_data;
87 struct ion0_handle_data hdl_data;
88 struct ion0_fd_data fd_data;
89 int fd = -1;
90
91 alloc_data.len = size;
92 alloc_data.align = 0;
93 alloc_data.flags = 0;
94 alloc_data.heap_id_mask = 1 << heap_type_id;
95 if (ioctl(ion, ION0_IOC_ALLOC, &alloc_data) == -1) {
96 fprintf(stderr, "Error: old ION allocate API failed\n");
97 return fd;
98 }
99
100 fd_data.handle = alloc_data.handle;
101 if (ioctl(ion, ION0_IOC_SHARE, &fd_data) != -1)
102 fd = fd_data.fd;
103 else
104 fprintf(stderr, "Error: old ION share API failed\n");
105
106 hdl_data.handle = alloc_data.handle;
107 (void)ioctl(ion, ION0_IOC_FREE, &hdl_data);
108
109 return fd;
110}
111
Etienne Carriere8bc31422017-08-24 14:48:30 +0200112int allocate_ion_buffer(size_t size, int heap_type_id, int verbosity)
Etienne Carriere41343db2017-03-17 15:38:52 +0100113{
Etienne Carriere8bc31422017-08-24 14:48:30 +0200114 struct ion_heap_query query_data;
115 struct ion_heap_data heap_data[32];
Etienne Carriere41343db2017-03-17 15:38:52 +0100116 struct ion_allocation_data alloc_data;
Etienne Carriere41343db2017-03-17 15:38:52 +0100117 int ion;
118 int fd = -1;
Etienne Carriere8bc31422017-08-24 14:48:30 +0200119 unsigned int idx;
Etienne Carriere41343db2017-03-17 15:38:52 +0100120
121 ion = open("/dev/ion", O_RDWR);
122 if (ion < 0) {
Etienne Carriere8bc31422017-08-24 14:48:30 +0200123 fprintf(stderr, "Error: failed to open /dev/ion\n");
Etienne Carriere41343db2017-03-17 15:38:52 +0100124 verbose("Seems no ION heap is available.\n");
125 verbose("To test ION allocation you can enable\n");
126 verbose("CONFIG_ION and CONFIG_ION_DUMMY in your\n");
127 verbose("linux kernel configuration.\n");
128 return fd;
129 }
130
Etienne Carriere8bc31422017-08-24 14:48:30 +0200131 if (heap_type_id < 0)
132 heap_type_id = DEFAULT_ION_HEAP_TYPE;
Etienne Carriere41343db2017-03-17 15:38:52 +0100133
Etienne Carriere8bc31422017-08-24 14:48:30 +0200134 memset(&query_data, 0, sizeof(query_data));
135 if (ioctl(ion, ION_IOC_HEAP_QUERY, &query_data) < 0) {
136 fprintf(stderr, "Error: failed to query the number of heaps\n");
137 goto out;
138 }
139
140 query_data.heaps = (__u64)(unsigned long)&heap_data;
141 if (ioctl(ion, ION_IOC_HEAP_QUERY, &query_data) < 0) {
Etienne Carriere3a34b982017-10-24 15:31:34 +0200142 fprintf(stderr, "Info: can't query heaps data, try old API\n");
143 fd = allocate_ion_buffer_old_api(size, heap_type_id, ion);
Etienne Carriere8bc31422017-08-24 14:48:30 +0200144 goto out;
145 }
146
147 for (idx = 0; idx < query_data.cnt; idx++)
148 if (heap_data[idx].type == (unsigned int)heap_type_id)
149 break;
150 if (idx == query_data.cnt) {
151 fprintf(stderr, "Error: target heap type %d not found\n",
152 heap_type_id);
153 goto out;
154 }
155
156 verbose("Allocate in ION heap '%s' (type=%u, id=%u)\n",
157 heap_data[idx].name, heap_data[idx].type,
158 heap_data[idx].heap_id);
Etienne Carriere41343db2017-03-17 15:38:52 +0100159
160 alloc_data.len = size;
Etienne Carriere41343db2017-03-17 15:38:52 +0100161 alloc_data.flags = 0;
Etienne Carriere8bc31422017-08-24 14:48:30 +0200162 alloc_data.heap_id_mask = 1 << heap_data[idx].heap_id;
163 if (ioctl(ion, ION_IOC_ALLOC, &alloc_data) < 0) {
164 fprintf(stderr, "Error: failed to allocate in target heap\n");
Etienne Carriere41343db2017-03-17 15:38:52 +0100165 goto out;
Etienne Carriere8bc31422017-08-24 14:48:30 +0200166 }
Etienne Carriere41343db2017-03-17 15:38:52 +0100167
Etienne Carriere8bc31422017-08-24 14:48:30 +0200168 fd = alloc_data.fd;
Etienne Carriere41343db2017-03-17 15:38:52 +0100169out:
170 close(ion);
171 return fd;
172}
173
174static void finalize_tee_ctx(struct tee_ctx *ctx)
175{
176 if (!ctx)
177 return;
178
179 TEEC_CloseSession(&ctx->sess);
180 TEEC_FinalizeContext(&ctx->ctx);
181}
182
Etienne Carrierec45d9762017-03-21 15:45:13 +0100183static int create_tee_ctx(struct tee_ctx *ctx, enum test_target_ta target_ta)
Etienne Carriere41343db2017-03-17 15:38:52 +0100184{
185 TEEC_Result teerc;
Etienne Carriereb296a642017-03-29 15:23:56 +0200186 const TEEC_UUID *uuid;
Etienne Carriere41343db2017-03-17 15:38:52 +0100187 uint32_t err_origin;
188
Etienne Carrierec45d9762017-03-21 15:45:13 +0100189 switch (target_ta) {
190 case TEST_NS_TO_TA:
191 case TEST_TA_TO_TA:
192 case TEST_TA_TO_PTA:
Etienne Carriere50abf9a2017-03-24 11:33:50 +0100193 uuid = &sdp_basic_ta_uuid;
Etienne Carrierec45d9762017-03-21 15:45:13 +0100194 break;
195 case TEST_NS_TO_PTA:
Etienne Carriere50abf9a2017-03-24 11:33:50 +0100196 uuid = &pta_invoke_tests_ta_uuid;
Etienne Carrierec45d9762017-03-21 15:45:13 +0100197 break;
198 default:
199 return -1;
200 }
201
Etienne Carriere41343db2017-03-17 15:38:52 +0100202 teerc = TEEC_InitializeContext(NULL, &ctx->ctx);
203 if (teerc != TEEC_SUCCESS)
204 return -1;
205
Etienne Carrierec45d9762017-03-21 15:45:13 +0100206 teerc = TEEC_OpenSession(&ctx->ctx, &ctx->sess, uuid,
Etienne Carriere41343db2017-03-17 15:38:52 +0100207 TEEC_LOGIN_PUBLIC, NULL, NULL, &err_origin);
Etienne Carrierecc72dd22017-10-18 11:55:05 +0200208 if (teerc != TEEC_SUCCESS) {
Etienne Carrierec45d9762017-03-21 15:45:13 +0100209 fprintf(stderr, "Error: open session to target test %s failed %x %d\n",
210 (target_ta == TEST_NS_TO_PTA) ? "pTA" : "TA",
Etienne Carriere41343db2017-03-17 15:38:52 +0100211 teerc, err_origin);
212
Etienne Carrierecc72dd22017-10-18 11:55:05 +0200213 TEEC_FinalizeContext(&ctx->ctx);
214 }
Etienne Carriere41343db2017-03-17 15:38:52 +0100215 return (teerc == TEEC_SUCCESS) ? 0 : -1;
216}
217
218static int tee_register_buffer(struct tee_ctx *ctx, void **shm_ref, int fd)
219{
220 TEEC_Result teerc;
221 TEEC_SharedMemory *shm;
222
223 shm = malloc(sizeof(*shm));
224 if (!shm)
225 return 1;
226
227 shm->flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
228 teerc = TEEC_RegisterSharedMemoryFileDescriptor(&ctx->ctx, shm, fd);
229 if (teerc != TEEC_SUCCESS) {
230 fprintf(stderr, "Error: TEEC_RegisterMemoryFileDescriptor() failed %x\n",
231 teerc);
232 return 1;
233 }
234
235 *shm_ref = shm;
236 return 0;
237}
238
239static void tee_deregister_buffer(struct tee_ctx *ctx, void *shm_ref)
240{
241 (void)ctx;
242
243 if (!shm_ref)
244 return;
245
246 TEEC_ReleaseSharedMemory((TEEC_SharedMemory *)shm_ref);
247 free(shm_ref);
248}
249
250static int inject_sdp_data(struct tee_ctx *ctx,
Etienne Carrieref690b912017-03-21 15:44:13 +0100251 void *in, size_t offset, size_t len, void *shm_ref, int ind)
Etienne Carriere41343db2017-03-17 15:38:52 +0100252{
253 TEEC_SharedMemory *shm = (TEEC_SharedMemory *)shm_ref;
254 TEEC_Result teerc;
255 TEEC_Operation op;
256 uint32_t err_origin;
Etienne Carrierec45d9762017-03-21 15:45:13 +0100257 unsigned cmd;
258
259 switch (ind) {
260 case TEST_NS_TO_TA:
261 cmd = TA_SDP_BASIC_CMD_INJECT;
262 break;
263 case TEST_TA_TO_TA:
264 cmd = TA_SDP_BASIC_CMD_INVOKE_INJECT;
265 break;
266 case TEST_TA_TO_PTA:
267 cmd = TA_SDP_BASIC_CMD_PTA_INJECT;
268 break;
269 case TEST_NS_TO_PTA:
270 cmd = PTA_INVOKE_TESTS_CMD_COPY_NSEC_TO_SEC;
271 break;
272 default:
273 return -1;
274 }
Etienne Carriere41343db2017-03-17 15:38:52 +0100275
276 memset(&op, 0, sizeof(op));
277 op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
278 TEEC_MEMREF_PARTIAL_OUTPUT,
279 TEEC_NONE, TEEC_NONE);
280
281 op.params[0].tmpref.buffer = in;
282 op.params[0].tmpref.size = len;
283
284 op.params[1].memref.parent = shm;
285 op.params[1].memref.size = len;
286 op.params[1].memref.offset = offset;
287
Etienne Carrieref690b912017-03-21 15:44:13 +0100288 teerc = TEEC_InvokeCommand(&ctx->sess, cmd, &op, &err_origin);
Etienne Carriere41343db2017-03-17 15:38:52 +0100289 if (teerc != TEEC_SUCCESS)
290 fprintf(stderr, "Error: invoke SDP test TA (inject) failed %x %d\n",
291 teerc, err_origin);
292
293 return (teerc == TEEC_SUCCESS) ? 0 : -1;
294}
295
296static int transform_sdp_data(struct tee_ctx *ctx,
Etienne Carrieref690b912017-03-21 15:44:13 +0100297 size_t offset, size_t len, void *shm_ref, int ind)
Etienne Carriere41343db2017-03-17 15:38:52 +0100298{
299 TEEC_SharedMemory *shm = (TEEC_SharedMemory *)shm_ref;
300 TEEC_Result teerc;
301 TEEC_Operation op;
302 uint32_t err_origin;
Etienne Carrierec45d9762017-03-21 15:45:13 +0100303 unsigned cmd;
304
305 switch (ind) {
306 case TEST_NS_TO_TA:
307 cmd = TA_SDP_BASIC_CMD_TRANSFORM;
308 break;
309 case TEST_TA_TO_TA:
310 cmd = TA_SDP_BASIC_CMD_INVOKE_TRANSFORM;
311 break;
312 case TEST_TA_TO_PTA:
313 cmd = TA_SDP_BASIC_CMD_PTA_TRANSFORM;
314 break;
315 case TEST_NS_TO_PTA:
316 cmd = PTA_INVOKE_TESTS_CMD_READ_MODIFY_SEC;
317 break;
318 default:
319 return -1;
320 }
Etienne Carriere41343db2017-03-17 15:38:52 +0100321
322 memset(&op, 0, sizeof(op));
323 op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INOUT,
324 TEEC_NONE, TEEC_NONE, TEEC_NONE);
325 op.params[0].memref.parent = shm;
326 op.params[0].memref.size = len;
327 op.params[0].memref.offset = offset;
328
Etienne Carrieref690b912017-03-21 15:44:13 +0100329 teerc = TEEC_InvokeCommand(&ctx->sess, cmd, &op, &err_origin);
Etienne Carriere41343db2017-03-17 15:38:52 +0100330 if (teerc != TEEC_SUCCESS)
331 fprintf(stderr, "Error: invoke SDP test TA (transform) failed %x %d\n",
332 teerc, err_origin);
333
334 return (teerc == TEEC_SUCCESS) ? 0 : -1;
335}
336
337static int dump_sdp_data(struct tee_ctx *ctx,
Etienne Carrieref690b912017-03-21 15:44:13 +0100338 void *out, size_t offset, size_t len, void *shm_ref, int ind)
Etienne Carriere41343db2017-03-17 15:38:52 +0100339{
340 TEEC_SharedMemory *shm = (TEEC_SharedMemory *)shm_ref;
341 TEEC_Result teerc;
342 TEEC_Operation op;
343 uint32_t err_origin;
Etienne Carrierec45d9762017-03-21 15:45:13 +0100344 unsigned cmd;
345
346 switch (ind) {
347 case TEST_NS_TO_TA:
348 cmd = TA_SDP_BASIC_CMD_DUMP;
349 break;
350 case TEST_TA_TO_TA:
351 cmd = TA_SDP_BASIC_CMD_INVOKE_DUMP;
352 break;
353 case TEST_TA_TO_PTA:
354 cmd = TA_SDP_BASIC_CMD_PTA_DUMP;
355 break;
356 case TEST_NS_TO_PTA:
357 cmd = PTA_INVOKE_TESTS_CMD_COPY_SEC_TO_NSEC;
358 break;
359 default:
360 return -1;
361 }
Etienne Carriere41343db2017-03-17 15:38:52 +0100362
363 memset(&op, 0, sizeof(op));
364 op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INPUT,
365 TEEC_MEMREF_TEMP_OUTPUT,
366 TEEC_NONE, TEEC_NONE);
367 op.params[0].memref.parent = shm;
368 op.params[0].memref.size = len;
369 op.params[0].memref.offset = offset;
370
371 op.params[1].tmpref.buffer = out;
372 op.params[1].tmpref.size = len;
373
Etienne Carrieref690b912017-03-21 15:44:13 +0100374 teerc = TEEC_InvokeCommand(&ctx->sess, cmd, &op, &err_origin);
Etienne Carriere41343db2017-03-17 15:38:52 +0100375 if (teerc != TEEC_SUCCESS)
376 fprintf(stderr, "Error: invoke SDP test TA (dump) failed %x %d\n",
377 teerc, err_origin);
378
379 return (teerc == TEEC_SUCCESS) ? 0 : -1;
380}
381
382static int check_sdp_dumped(struct tee_ctx *ctx, void *ref, size_t len,
383 void *out)
384{
385 char *bref = (char *)ref;
386 char *data = (char *)out;
387 int err = 0;
388
389 (void)ctx;
390
391 while(len--)
392 if (*data++ != (unsigned char)(~(*bref++) + 1))
393 err++;
394
395 return err;
396}
397
398/*
399 * Consider 32kByte + 1 of random data is sufficient for an accurate test
400 * whatever the test buffer size is. Random buffer is read as a ring buffer.
401 */
402#define RANDOM_BUFFER_SIZE (32 * 1024 + 1)
403static int get_random_bytes(char *out, size_t len)
404{
405 static char *rand_buf = NULL;
406 static size_t rand_idx = 0;
407 int rc;
408
409 if (!rand_buf) {
410 const char rand_dev[] = "/dev/urandom";
411 int fd;
412
413 rand_buf = malloc(RANDOM_BUFFER_SIZE);
414 if (!rand_buf) {
415 fprintf(stderr, "failed to random buffer memory (%d bytes)\n",
416 RANDOM_BUFFER_SIZE);
417 return -1;
418 }
419
420 fd = open(rand_dev, O_RDONLY);
421 if (fd < 0) {
422 fprintf(stderr, "failed to open %s\n", rand_dev);
423 return -1;
424 }
425
426 rc = read(fd, rand_buf, RANDOM_BUFFER_SIZE);
427 if (rc != RANDOM_BUFFER_SIZE) {
428 fprintf(stderr, "failed to read %d bytes from %s\n",
429 RANDOM_BUFFER_SIZE, rand_dev);
430 return -1;
431 }
432 close(fd);
433 }
434
435 while (len) {
436 size_t t_len = (RANDOM_BUFFER_SIZE < len) ? RANDOM_BUFFER_SIZE : len;
437
438 if ((rand_idx + t_len) > RANDOM_BUFFER_SIZE) {
439 int sz_end = RANDOM_BUFFER_SIZE - rand_idx;
440 int sz_beg = t_len - sz_end;
441
442 memcpy(out, rand_buf + rand_idx, sz_end);
443 memcpy(out + sz_end, rand_buf , sz_beg);
444 rand_idx = sz_beg;
445 } else {
446 memcpy(out, rand_buf + rand_idx, t_len);
447 rand_idx += t_len;
448 }
449 len -= t_len;
450 }
451 return 0;
452}
453
454
Etienne Carriere50abf9a2017-03-24 11:33:50 +0100455int sdp_basic_test(enum test_target_ta ta, size_t size, size_t loop,
Etienne Carriereb9a95822017-04-26 15:03:53 +0200456 int ion_heap, int rnd_offset, int verbosity)
Etienne Carriere41343db2017-03-17 15:38:52 +0100457{
458 struct tee_ctx *ctx = NULL;
459 unsigned char *test_buf = NULL;
460 unsigned char *ref_buf = NULL;
461 void *shm_ref = NULL;
462 unsigned int err = 1;
463 int fd = -1;
464 size_t sdp_size = size;
465 size_t offset;
Etienne Carrieref690b912017-03-21 15:44:13 +0100466 size_t loop_cnt;
Etienne Carriere41343db2017-03-17 15:38:52 +0100467
468 if (!loop) {
469 fprintf(stderr, "Error: null loop value\n");
470 return 1;
471 }
472
473 /* reduce size to enable offset tests (max offset is 255 bytes) */
474 if (rnd_offset)
475 size -= 255;
476
477 test_buf = malloc(size);
478 ref_buf = malloc(size);
479 if (!test_buf || !ref_buf) {
480 verbose("failed to allocate memory\n");
Etienne Carrierecc72dd22017-10-18 11:55:05 +0200481 goto bail1;
Etienne Carriere41343db2017-03-17 15:38:52 +0100482 }
483
Etienne Carriereb9a95822017-04-26 15:03:53 +0200484 fd = allocate_ion_buffer(sdp_size, ion_heap, verbosity);
Etienne Carriere41343db2017-03-17 15:38:52 +0100485 if (fd < 0) {
Etienne Carriere5fdf6352017-03-24 11:49:50 +0100486 verbose("Failed to allocate SDP buffer (%zu bytes) in ION heap %d: %d\n",
Etienne Carriere41343db2017-03-17 15:38:52 +0100487 sdp_size, ion_heap, fd);
Etienne Carrierecc72dd22017-10-18 11:55:05 +0200488 goto bail1;
Etienne Carriere41343db2017-03-17 15:38:52 +0100489 }
490
491 /* register secure buffer to TEE */
492 ctx = malloc(sizeof(*ctx));
493 if (!ctx)
Etienne Carrierecc72dd22017-10-18 11:55:05 +0200494 goto bail1;
Etienne Carrierec45d9762017-03-21 15:45:13 +0100495 if (create_tee_ctx(ctx, ta))
Etienne Carrierecc72dd22017-10-18 11:55:05 +0200496 goto bail1;
Etienne Carriere41343db2017-03-17 15:38:52 +0100497 if (tee_register_buffer(ctx, &shm_ref, fd))
Etienne Carrierecc72dd22017-10-18 11:55:05 +0200498 goto bail2;
Etienne Carriere41343db2017-03-17 15:38:52 +0100499
500 /* release registered fd: tee should still hold refcount on resource */
501 close(fd);
502 fd = -1;
503
504 /* invoke trusted application with secure buffer as memref parameter */
Etienne Carrieref690b912017-03-21 15:44:13 +0100505 for (loop_cnt = loop; loop_cnt; loop_cnt--) {
Etienne Carriere41343db2017-03-17 15:38:52 +0100506 /* get an buffer of random-like values */
507 if (get_random_bytes((char *)ref_buf, size))
Etienne Carrierecc72dd22017-10-18 11:55:05 +0200508 goto bail2;
Etienne Carriere41343db2017-03-17 15:38:52 +0100509 memcpy(test_buf, ref_buf, size);
510 /* random offset [0 255] */
511 offset = (unsigned int)*ref_buf;
512
513 /* TA writes into SDP buffer */
Etienne Carrierec45d9762017-03-21 15:45:13 +0100514 if (inject_sdp_data(ctx, test_buf, offset, size, shm_ref, ta))
Etienne Carrierecc72dd22017-10-18 11:55:05 +0200515 goto bail2;
Etienne Carriere41343db2017-03-17 15:38:52 +0100516
517 /* TA reads/writes into SDP buffer */
Etienne Carrierec45d9762017-03-21 15:45:13 +0100518 if (transform_sdp_data(ctx, offset, size, shm_ref, ta))
Etienne Carrierecc72dd22017-10-18 11:55:05 +0200519 goto bail2;
Etienne Carriere41343db2017-03-17 15:38:52 +0100520
521 /* TA reads into SDP buffer */
Etienne Carrierec45d9762017-03-21 15:45:13 +0100522 if (dump_sdp_data(ctx, test_buf, offset, size, shm_ref, ta))
Etienne Carrierecc72dd22017-10-18 11:55:05 +0200523 goto bail2;
Etienne Carrieref690b912017-03-21 15:44:13 +0100524
525 /* check dumped data are the expected ones */
526 if (check_sdp_dumped(ctx, ref_buf, size, test_buf)) {
527 fprintf(stderr, "check SDP data: %d errors\n", err);
Etienne Carrierecc72dd22017-10-18 11:55:05 +0200528 goto bail2;
Etienne Carrieref690b912017-03-21 15:44:13 +0100529 }
530 }
531
Etienne Carriere41343db2017-03-17 15:38:52 +0100532 err = 0;
Etienne Carrierecc72dd22017-10-18 11:55:05 +0200533bail2:
Etienne Carriere41343db2017-03-17 15:38:52 +0100534 if (fd >= 0)
535 close(fd);
536 if (shm_ref)
537 tee_deregister_buffer(ctx, shm_ref);
538 finalize_tee_ctx(ctx);
Etienne Carrierecc72dd22017-10-18 11:55:05 +0200539bail1:
Etienne Carriere41343db2017-03-17 15:38:52 +0100540 free(ctx);
541 free(ref_buf);
542 free(test_buf);
543 return err;
544}
545
546#define _TO_STR(x) #x
547#define TO_STR(x) _TO_STR(x)
548
549static void usage(const char *progname, size_t size, int loop, int ion_heap)
550{
551 fprintf(stderr, "Usage: %s [OPTION]\n", progname);
552 fprintf(stderr,
553 "Testing basic accesses to secure buffer (SDP) on OP-TEE.\n"
554 "Allocates a secure buffer and invoke a TA to access it.\n"
555 "TA is used to init/transform/dump the secure buffer.\n"
556 "CA check dumped content.\n\n");
557
558 fprintf(stderr, "Options:\n");
559 fprintf(stderr, " -h|--help Print this help and exit\n");
560 fprintf(stderr, " -v Be verbose\n");
561 fprintf(stderr, " -s SIZE SDP buffer byte size [%zu]\n", size);
562 fprintf(stderr, " -n LOOP Test loop iterations [%u]\n", loop);
563 fprintf(stderr, " --ion-heap ID Target ION heap ID [%d]\n", ion_heap);
564 fprintf(stderr, " --no-offset No random offset [0 255] in buffer\n");
565}
566
567#define NEXT_ARG(i) \
568 do { \
569 if (++i == argc) { \
570 fprintf(stderr, "%s: %s: missing argument\n", \
571 argv[0], argv[i-1]); \
572 return 1; \
573 } \
574 } while (0);
575
Jerome Forissiere1342522017-05-19 09:25:53 +0200576#define CHECK_RESULT(_res, _exp, _action) \
577 if ((_res) == (_exp)) { \
578 verbose("Test passed\n"); \
579 } else { \
580 verbose("Test failed!\n"); \
581 _action; \
582 }
583
Etienne Carriere41343db2017-03-17 15:38:52 +0100584int sdp_basic_runner_cmd_parser(int argc, char *argv[])
585{
586 size_t test_size = 5000;
587 size_t test_loop = 1000;
588 int ion_heap = DEFAULT_ION_HEAP_TYPE;
589 int rnd_offset = 1;
Etienne Carriereb9a95822017-04-26 15:03:53 +0200590 int verbosity = 1;
Jerome Forissiere1342522017-05-19 09:25:53 +0200591 int err;
Etienne Carriere41343db2017-03-17 15:38:52 +0100592 int i;
593
594 /* Parse command line */
595 for (i = 1; i < argc; i++) {
596 if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
597 usage(argv[0], test_size, test_loop, ion_heap);
598 return 0;
599 }
600 }
601 for (i = 1; i < argc; i++) {
602 if (!strcmp(argv[i], "-v")) {
603 verbosity++;
604 } else if (!strcmp(argv[i], "-s")) {
605 NEXT_ARG(i);
606 test_size = atoi(argv[i]);
607 } else if (!strcmp(argv[i], "-n")) {
608 NEXT_ARG(i);
609 test_loop = atoi(argv[i]);
610 } else if (!strcmp(argv[i], "--ion-heap")) {
611 NEXT_ARG(i);
612 ion_heap = atoi(argv[i]);
613 } else if (!strcmp(argv[i], "--no-offset")) {
614 rnd_offset = 0;
615 } else {
616 fprintf(stderr, "%s: invalid argument: %s\n",
617 argv[0], argv[i]);
618 usage(argv[0], test_size, test_loop, ion_heap);
619 return 1;
620 }
621 }
622
Jerome Forissiere1342522017-05-19 09:25:53 +0200623 verbose("\nSecure Data Path basic access: "
624 "NS invokes SDP TA\n");
625 err = sdp_basic_test(TEST_NS_TO_TA, test_size, test_loop, ion_heap,
626 rnd_offset, verbosity);
627 CHECK_RESULT(err, 0, return 1);
Etienne Carriere41343db2017-03-17 15:38:52 +0100628
Jerome Forissiere1342522017-05-19 09:25:53 +0200629 verbose("\nSecure Data Path basic access: "
630 "SDP TA invokes SDP TA\n");
631 err = sdp_basic_test(TEST_TA_TO_TA, test_size, test_loop, ion_heap,
632 rnd_offset, verbosity);
633 CHECK_RESULT(err, 0, return 1);
Etienne Carrierec45d9762017-03-21 15:45:13 +0100634
Jerome Forissiere1342522017-05-19 09:25:53 +0200635 verbose("\nSecure Data Path basic access: "
636 "SDP TA invokes SDP pTA\n");
637 err = sdp_basic_test(TEST_TA_TO_PTA, test_size, test_loop, ion_heap,
638 rnd_offset, verbosity);
639 CHECK_RESULT(err, 0, return 1);
Etienne Carriere41343db2017-03-17 15:38:52 +0100640
Jerome Forissiere1342522017-05-19 09:25:53 +0200641 verbose("\nSecure Data Path basic access: "
642 "NS invokes SDP pTA (shall fail)\n");
643 err = sdp_basic_test(TEST_NS_TO_PTA, test_size, test_loop, ion_heap,
644 rnd_offset, verbosity);
645 CHECK_RESULT(err, 1, return 1);
Etienne Carriered1655822017-03-21 15:45:24 +0100646
Etienne Carriere41343db2017-03-17 15:38:52 +0100647 return 0;
648}