1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2014, STMicroelectronics International N.V.
4 * All rights reserved.
5 * Copyright (c) 2022, Linaro Limited.
6 */
7 #include <compiler.h>
8 #include <dlfcn.h>
9 #include <link.h>
10 #include <memtag.h>
11 #include <setjmp.h>
12 #include <stdint.h>
13 #include <string.h>
14 #include <ta_crypt.h>
15 #include <ta_os_test.h>
16 #include <tee_internal_api_extensions.h>
17
18 #include "os_test.h"
19 #include "test_float_subj.h"
20 #include "os_test_lib.h"
21
22 enum p_type {
23 P_TYPE_BOOL,
24 P_TYPE_INT,
25 P_TYPE_UUID,
26 P_TYPE_IDENTITY,
27 P_TYPE_STRING,
28 P_TYPE_BINARY_BLOCK,
29 };
30
31 struct p_attr {
32 const char *str;
33 enum p_type type;
34 bool retrieved;
35 };
36
check_returned_prop(int line __maybe_unused,char * prop_name __maybe_unused,TEE_Result return_res,TEE_Result expected_res,uint32_t return_len,uint32_t expected_len)37 static TEE_Result check_returned_prop(
38 int line __maybe_unused, char *prop_name __maybe_unused,
39 TEE_Result return_res, TEE_Result expected_res,
40 uint32_t return_len, uint32_t expected_len)
41 {
42 if (return_res != expected_res) {
43 EMSG("From line %d (property name=%s): return_res=0x%x vs expected_res=0x%x",
44 line, (prop_name ? prop_name : "unknown"),
45 (unsigned int)return_res, (unsigned int)expected_res);
46 return TEE_ERROR_GENERIC;
47 }
48 if (return_len != expected_len) {
49 EMSG("From line %d (property name=%s): return_len=%u vs expected_res=%u",
50 line, (prop_name ? prop_name : "unknown"),
51 return_len, expected_len);
52 return TEE_ERROR_GENERIC;
53 }
54 return TEE_SUCCESS;
55 }
56
check_binprop_ones(size_t size,char * bbuf,size_t bblen)57 static TEE_Result check_binprop_ones(size_t size, char *bbuf, size_t bblen)
58 {
59 char ones[4] = { 0xff, 0xff, 0xff, 0xff };
60
61 if (size > 4 || bblen != size) {
62 EMSG("Size error (size=%zu, bblen=%zu)", size, bblen);
63 return TEE_ERROR_GENERIC;
64 }
65 if (strncmp(bbuf, ones, bblen)) {
66 EMSG("Unexpected content");
67 DHEXDUMP(bbuf, bblen);
68 return TEE_ERROR_GENERIC;
69 }
70 return TEE_SUCCESS;
71 }
72
get_binblock_property(TEE_PropSetHandle h,char * nbuf __unused,char ** bbuf,size_t * bblen)73 static TEE_Result get_binblock_property(TEE_PropSetHandle h,
74 char *nbuf __unused, char **bbuf, size_t *bblen)
75 {
76 TEE_Result res = TEE_ERROR_GENERIC;
77 uint32_t block_len = 0;
78
79 *bbuf = NULL;
80 *bblen = 0;
81 res = TEE_GetPropertyAsBinaryBlock(h, NULL, *bbuf, &block_len);
82
83 if (res == TEE_SUCCESS && !block_len)
84 return TEE_SUCCESS;
85
86 if (res != TEE_ERROR_SHORT_BUFFER) {
87 EMSG("TEE_GetPropertyAsBinaryBlock() size query returned 0x%x",
88 (unsigned int)res);
89 return res ? res : TEE_ERROR_GENERIC;
90 }
91
92 *bbuf = TEE_Malloc(block_len, TEE_MALLOC_FILL_ZERO);
93 if (!bbuf)
94 return TEE_ERROR_OUT_OF_MEMORY;
95
96 res = TEE_GetPropertyAsBinaryBlock(h, NULL, *bbuf, &block_len);
97 if (res != TEE_SUCCESS)
98 EMSG("TEE_GetPropertyAsBinaryBlock(\"%s\") returned 0x%x",
99 nbuf, (unsigned int)res);
100 else
101 *bblen = block_len;
102
103 return res;
104 }
105
print_properties(TEE_PropSetHandle h,TEE_PropSetHandle prop_set,struct p_attr * p_attrs,size_t num_p_attrs)106 static TEE_Result print_properties(TEE_PropSetHandle h,
107 TEE_PropSetHandle prop_set,
108 struct p_attr *p_attrs, size_t num_p_attrs)
109 {
110 TEE_Result res = TEE_ERROR_GENERIC;
111 size_t n = 0;
112
113 TEE_StartPropertyEnumerator(h, prop_set);
114
115 while (true) {
116 char nbuf[256] = { };
117 char nbuf_small[256] = { };
118 char vbuf[256] = { };
119 char vbuf2[256] = { };
120 uint32_t nblen = sizeof(nbuf);
121 uint32_t nblen_small = 0;
122 uint32_t vblen = sizeof(vbuf);
123 uint32_t vblen2 = sizeof(vbuf2);
124 char *bbuf = NULL;
125 size_t bblen = 0;
126
127 res = TEE_GetPropertyName(h, nbuf, &nblen);
128 if (res != TEE_SUCCESS) {
129 EMSG("TEE_GetPropertyName returned 0x%x\n",
130 (unsigned int)res);
131 return res;
132 }
133 if (nblen != strlen(nbuf) + 1) {
134 EMSG("Name has wrong size: %u vs %zu", nblen, strlen(nbuf) + 1);
135 return TEE_ERROR_GENERIC;
136 }
137
138
139 /* Get the property name with a very small buffer */
140 nblen_small = 2;
141 res = TEE_GetPropertyName(h, nbuf_small, &nblen_small);
142 res = check_returned_prop(__LINE__, nbuf, res, TEE_ERROR_SHORT_BUFFER,
143 nblen_small, nblen);
144 if (res != TEE_SUCCESS)
145 return res;
146
147 /* Get the property name with almost the correct buffer */
148 nblen_small = nblen - 1;
149 res = TEE_GetPropertyName(h, nbuf_small, &nblen_small);
150 res = check_returned_prop(__LINE__, nbuf, res, TEE_ERROR_SHORT_BUFFER,
151 nblen_small, nblen);
152 if (res != TEE_SUCCESS)
153 return res;
154
155 /* Get the property name with the exact buffer length */
156 nblen_small = nblen;
157 res = TEE_GetPropertyName(h, nbuf_small, &nblen_small);
158 res = check_returned_prop(__LINE__, nbuf, res, TEE_SUCCESS,
159 nblen_small, nblen);
160 if (res != TEE_SUCCESS)
161 return res;
162
163 /* Get the property value */
164 res = TEE_GetPropertyAsString(h, NULL, vbuf, &vblen);
165 res = check_returned_prop(__LINE__, nbuf, res, TEE_SUCCESS,
166 vblen, strlen(vbuf) + 1);
167 if (res != TEE_SUCCESS)
168 return res;
169
170 res = TEE_GetPropertyAsString(prop_set, nbuf, vbuf2, &vblen2);
171 res = check_returned_prop(__LINE__, nbuf, res, TEE_SUCCESS,
172 vblen2, strlen(vbuf2) + 1);
173 if (res != TEE_SUCCESS)
174 return res;
175
176 if (strcmp(vbuf, vbuf2) != 0) {
177 EMSG("String of \"%s\" differs\n", nbuf);
178 return TEE_ERROR_GENERIC;
179 }
180
181 /* Get the property with a very small buffer */
182 if (vblen > 1) {
183 vblen2 = 1;
184 res = TEE_GetPropertyAsString(prop_set, nbuf, vbuf2, &vblen2);
185 res = check_returned_prop(__LINE__, nbuf, res,
186 TEE_ERROR_SHORT_BUFFER,
187 vblen2, vblen);
188 if (res != TEE_SUCCESS)
189 return res;
190 }
191
192 /* Get the property with almost the correct buffer */
193 vblen2 = vblen - 1;
194 res = TEE_GetPropertyAsString(prop_set, nbuf, vbuf2, &vblen2);
195 res = check_returned_prop(__LINE__, nbuf, res, TEE_ERROR_SHORT_BUFFER,
196 vblen2, vblen);
197 if (res != TEE_SUCCESS)
198 return res;
199
200 /* Get the property name with the exact buffer length */
201 vblen2 = vblen;
202 res = TEE_GetPropertyAsString(prop_set, nbuf, vbuf2, &vblen2);
203 res = check_returned_prop(__LINE__, nbuf, res, TEE_SUCCESS, vblen2, vblen);
204 if (res != TEE_SUCCESS)
205 return res;
206
207 /* check specific myprop.hello property, which is larger than 80 */
208 if (!strcmp("myprop.hello", nbuf) &&
209 vblen2 != 1 + strlen("hello property, larger than 80 characters, so that it checks that it is not truncated by anything in the source code which may be wrong")) {
210 EMSG("TEE_GetPropertyAsString(\"%s\") is truncated - returned \"%s\"\n",
211 nbuf, vbuf);
212 return TEE_ERROR_GENERIC;
213 }
214
215 DMSG("Found \"%s\" value \"%s\"\n", nbuf, vbuf);
216
217 for (n = 0; n < num_p_attrs; n++) {
218 if (strcmp(nbuf, p_attrs[n].str) != 0)
219 continue;
220
221 if (p_attrs[n].retrieved) {
222 EMSG("Value \"%s\" already retrieved\n",
223 p_attrs[n].str);
224 return TEE_ERROR_GENERIC;
225 }
226 p_attrs[n].retrieved = true;
227
228 switch (p_attrs[n].type) {
229 case P_TYPE_BOOL:
230 {
231 bool v = false;
232
233 res =
234 TEE_GetPropertyAsBool(h, NULL, &v);
235 if (res != TEE_SUCCESS) {
236 EMSG(
237 "TEE_GetPropertyAsBool(\"%s\") returned 0x%x\n",
238 nbuf, (unsigned int)res);
239 return res;
240 }
241 }
242 break;
243
244 case P_TYPE_INT:
245 {
246 uint32_t v = 0;
247
248 res = TEE_GetPropertyAsU32(h, NULL, &v);
249 if (res != TEE_SUCCESS) {
250 EMSG(
251 "TEE_GetPropertyAsU32(\"%s\") returned 0x%x\n",
252 nbuf, (unsigned int)res);
253 return res;
254 }
255 }
256 break;
257
258 case P_TYPE_UUID:
259 {
260 TEE_UUID v = { };
261
262 res =
263 TEE_GetPropertyAsUUID(h, NULL, &v);
264 if (res != TEE_SUCCESS) {
265 EMSG(
266 "TEE_GetPropertyAsUUID(\"%s\") returned 0x%x\n",
267 nbuf, (unsigned int)res);
268 return res;
269 }
270 }
271 break;
272
273 case P_TYPE_IDENTITY:
274 {
275 TEE_Identity v = { };
276
277 res =
278 TEE_GetPropertyAsIdentity(h, NULL,
279 &v);
280 if (res != TEE_SUCCESS) {
281 EMSG(
282 "TEE_GetPropertyAsIdentity(\"%s\") returned 0x%x\n",
283 nbuf, (unsigned int)res);
284 return res;
285 }
286 }
287 break;
288
289 case P_TYPE_STRING:
290 /* Already read as string */
291 break;
292
293 case P_TYPE_BINARY_BLOCK:
294 res = get_binblock_property(h, nbuf, &bbuf, &bblen);
295 if (res)
296 return res;
297
298 if (!strcmp("myprop.binaryblock", nbuf)) {
299 const char exp_bin_value[] = "Hello world!";
300
301 if (bblen != strlen(exp_bin_value) ||
302 TEE_MemCompare(exp_bin_value, bbuf,
303 bblen)) {
304 EMSG("Binary buffer of \"%s\" differs from \"%s\"",
305 nbuf, exp_bin_value);
306 EMSG("Got \"%s\"", bbuf);
307 return TEE_ERROR_GENERIC;
308 }
309 } else if (!strcmp("myprop.binaryblock.1byte-ones",
310 nbuf)) {
311 res = check_binprop_ones(1, bbuf, bblen);
312 if (res)
313 return res;
314 } else if (!strcmp("myprop.binaryblock.2byte-ones",
315 nbuf)) {
316 res = check_binprop_ones(2, bbuf, bblen);
317 if (res)
318 return res;
319 } else if (!strcmp("myprop.binaryblock.3byte-ones",
320 nbuf)) {
321 res = check_binprop_ones(3, bbuf, bblen);
322 if (res)
323 return res;
324 } else if (!strcmp("myprop.binaryblock.4byte-ones",
325 nbuf)) {
326 res = check_binprop_ones(4, bbuf, bblen);
327 if (res)
328 return res;
329 } else if (!strcmp("myprop.binaryblock.empty1", nbuf) ||
330 !strcmp("myprop.binaryblock.empty2", nbuf) ||
331 !strcmp("myprop.binaryblock.empty3", nbuf)) {
332 if (bblen) {
333 EMSG("Property \"%s\": %zu byte(s)",
334 nbuf, bblen);
335 return TEE_ERROR_GENERIC;
336 }
337 } else {
338 EMSG("Unexpected property \"%s\"", nbuf);
339 TEE_Panic(0);
340 }
341
342 TEE_Free(bbuf);
343 break;
344
345 default:
346 EMSG("Unknown type (%d) for \"%s\"\n",
347 p_attrs[n].type, p_attrs[n].str);
348 return TEE_ERROR_GENERIC;
349 }
350 }
351
352 res = TEE_GetNextProperty(h);
353 if (res != TEE_SUCCESS) {
354 if (res == TEE_ERROR_ITEM_NOT_FOUND)
355 return TEE_SUCCESS;
356 return res;
357 }
358 }
359 }
360
test_malloc(void)361 static TEE_Result test_malloc(void)
362 {
363 void *p = TEE_Malloc(4, 0);
364
365 if (p == NULL) {
366 EMSG("TEE_Malloc failed\n");
367 return TEE_ERROR_OUT_OF_MEMORY;
368 }
369 TEE_Free(p);
370 TEE_Free(NULL);
371
372 return TEE_SUCCESS;
373 }
374
test_properties(void)375 static TEE_Result test_properties(void)
376 {
377 TEE_Result res = TEE_ERROR_GENERIC;
378 TEE_PropSetHandle h = TEE_HANDLE_NULL;
379 struct p_attr p_attrs[] = {
380 {"gpd.ta.appID", P_TYPE_UUID},
381 {"gpd.ta.singleInstance", P_TYPE_BOOL},
382 {"gpd.ta.multiSession", P_TYPE_BOOL},
383 {"gpd.ta.instanceKeepAlive", P_TYPE_BOOL},
384 {"gpd.ta.dataSize", P_TYPE_INT},
385 {"gpd.ta.stackSize", P_TYPE_INT},
386 {"gpd.ta.version", P_TYPE_STRING},
387 {"gpd.ta.description", P_TYPE_STRING},
388 {"gpd.client.identity", P_TYPE_IDENTITY},
389 {"gpd.tee.apiversion", P_TYPE_STRING},
390 {"gpd.tee.description", P_TYPE_STRING},
391 {"gpd.tee.deviceID", P_TYPE_UUID},
392 {"gpd.tee.systemTime.protectionLevel", P_TYPE_INT},
393 {"gpd.tee.TAPersistentTime.protectionLevel", P_TYPE_INT},
394 {"gpd.tee.arith.maxBigIntSize", P_TYPE_INT},
395 {"gpd.tee.cryptography.ecc", P_TYPE_BOOL},
396 {"gpd.tee.trustedStorage.antiRollback.protectionLevel", P_TYPE_INT},
397 {"gpd.tee.trustedos.implementation.version", P_TYPE_STRING},
398 {"gpd.tee.trustedos.implementation.binaryversion", P_TYPE_INT},
399 {"gpd.tee.trustedos.manufacturer", P_TYPE_STRING},
400 {"gpd.tee.firmware.implementation.version", P_TYPE_STRING},
401 {"gpd.tee.firmware.implementation.binaryversion", P_TYPE_INT},
402 {"gpd.tee.firmware.manufacturer", P_TYPE_STRING},
403 {"myprop.true", P_TYPE_BOOL},
404 {"myprop.42", P_TYPE_INT},
405 {"myprop.123", P_TYPE_UUID},
406 {"myprop.1234", P_TYPE_IDENTITY},
407 {"myprop.hello", P_TYPE_STRING},
408 {"myprop.binaryblock", P_TYPE_BINARY_BLOCK},
409 {"myprop.binaryblock.1byte-ones", P_TYPE_BINARY_BLOCK},
410 {"myprop.binaryblock.2byte-ones", P_TYPE_BINARY_BLOCK},
411 {"myprop.binaryblock.3byte-ones", P_TYPE_BINARY_BLOCK},
412 {"myprop.binaryblock.4byte-ones", P_TYPE_BINARY_BLOCK},
413 {"myprop.binaryblock.empty1", P_TYPE_BINARY_BLOCK},
414 {"myprop.binaryblock.empty2", P_TYPE_BINARY_BLOCK},
415 {"myprop.binaryblock.empty3", P_TYPE_BINARY_BLOCK},
416 };
417 const size_t num_p_attrs = sizeof(p_attrs) / sizeof(p_attrs[0]);
418 size_t n = 0;
419
420 res = TEE_AllocatePropertyEnumerator(&h);
421 if (res != TEE_SUCCESS) {
422 EMSG("TEE_AllocatePropertyEnumerator: returned 0x%x\n",
423 (unsigned int)res);
424 return TEE_ERROR_GENERIC;
425 }
426
427 printf("Getting properties for current TA\n");
428 res = print_properties(h, TEE_PROPSET_CURRENT_TA, p_attrs, num_p_attrs);
429 if (res != TEE_SUCCESS)
430 goto cleanup_return;
431
432 printf("Getting properties for current client\n");
433 res = print_properties(h, TEE_PROPSET_CURRENT_CLIENT, p_attrs,
434 num_p_attrs);
435 if (res != TEE_SUCCESS)
436 goto cleanup_return;
437
438 printf("Getting properties for implementation\n");
439 res = print_properties(h, TEE_PROPSET_TEE_IMPLEMENTATION, p_attrs,
440 num_p_attrs);
441 if (res != TEE_SUCCESS)
442 goto cleanup_return;
443
444 for (n = 0; n < num_p_attrs; n++) {
445 if (!p_attrs[n].retrieved) {
446 EMSG("\"%s\" not retrieved\n", p_attrs[n].str);
447 res = TEE_ERROR_GENERIC;
448 goto cleanup_return;
449 }
450 }
451
452 cleanup_return:
453 TEE_FreePropertyEnumerator(h);
454 return res;
455 }
456
test_mem_access_right(uint32_t param_types,TEE_Param params[4])457 static TEE_Result test_mem_access_right(uint32_t param_types,
458 TEE_Param params[4])
459 {
460 static const TEE_UUID test_uuid = TA_OS_TEST_UUID;
461 TEE_Result res = TEE_ERROR_GENERIC;
462 uint32_t ret_orig = 0;
463 uint32_t l_pts = 0;
464 TEE_Param l_params[4] = { };
465 uint8_t buf[32] = { };
466 TEE_TASessionHandle sess = TEE_HANDLE_NULL;
467 TEE_UUID *uuid = NULL;
468
469 if (param_types !=
470 TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0, 0))
471 return TEE_ERROR_GENERIC;
472
473 /* test access rights on memref parameter */
474 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ |
475 TEE_MEMORY_ACCESS_ANY_OWNER,
476 params[0].memref.buffer,
477 params[0].memref.size);
478 if (res != TEE_SUCCESS)
479 return res;
480
481 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ,
482 params[0].memref.buffer,
483 params[0].memref.size);
484 if (res != TEE_ERROR_ACCESS_DENIED)
485 return TEE_ERROR_GENERIC;
486
487 /* test access rights on private read-only and read-write memory */
488 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ,
489 (void *)&test_uuid, sizeof(test_uuid));
490 if (res != TEE_SUCCESS)
491 return res;
492
493 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_WRITE,
494 (void *)&test_uuid, sizeof(test_uuid));
495 if (res == TEE_SUCCESS)
496 return TEE_ERROR_GENERIC;
497
498 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ |
499 TEE_MEMORY_ACCESS_WRITE,
500 &ret_orig, sizeof(ret_orig));
501 if (res != TEE_SUCCESS)
502 return res;
503
504 uuid = TEE_Malloc(sizeof(*uuid), 0);
505 if (!uuid)
506 return TEE_ERROR_OUT_OF_MEMORY;
507
508 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ |
509 TEE_MEMORY_ACCESS_WRITE,
510 uuid, sizeof(*uuid));
511 TEE_Free(uuid);
512 if (res != TEE_SUCCESS)
513 return res;
514
515 /* test access rights on invalid memory (at least lower 256kB) */
516 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ,
517 NULL, 1);
518 if (res == TEE_SUCCESS)
519 return TEE_ERROR_GENERIC;
520
521 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ,
522 (void*)(256 * 1024), 1);
523 if (res == TEE_SUCCESS)
524 return TEE_ERROR_GENERIC;
525
526 res = TEE_OpenTASession(&test_uuid, TEE_TIMEOUT_INFINITE, 0, NULL,
527 &sess, &ret_orig);
528 if (res != TEE_SUCCESS) {
529 EMSG("test_mem_access_right: TEE_OpenTASession failed\n");
530 goto cleanup_return;
531 }
532
533 l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
534 TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0);
535 l_params[0].memref.buffer = buf;
536 l_params[0].memref.size = sizeof(buf);
537 l_params[1].memref.buffer = NULL;
538 l_params[1].memref.size = 0;
539 res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE,
540 TA_OS_TEST_CMD_PARAMS_ACCESS,
541 l_pts, l_params, &ret_orig);
542 if (res != TEE_SUCCESS) {
543 EMSG("test_mem_access_right: TEE_InvokeTACommand failed\n");
544 goto cleanup_return;
545 }
546
547 cleanup_return:
548 TEE_CloseTASession(sess);
549 return res;
550 }
551
test_time(void)552 static TEE_Result test_time(void)
553 {
554 TEE_Result res = TEE_ERROR_GENERIC;
555 TEE_Time t = { };
556 TEE_Time sys_t = { };
557 static const TEE_Time null_time = { 0, 0 };
558 static const TEE_Time wrap_time = { UINT32_MAX, 999 };
559
560 TEE_GetSystemTime(&sys_t);
561 printf("system time %u.%03u\n", (unsigned int)sys_t.seconds,
562 (unsigned int)sys_t.millis);
563
564 TEE_GetREETime(&t);
565 printf("REE time %u.%03u\n", (unsigned int)t.seconds,
566 (unsigned int)t.millis);
567
568 res = TEE_GetTAPersistentTime(&t);
569 switch (res) {
570 case TEE_SUCCESS:
571 printf("Stored TA time %u.%03u\n", (unsigned int)t.seconds,
572 (unsigned int)t.millis);
573 break;
574 case TEE_ERROR_OVERFLOW:
575 EMSG("Stored TA time overflowed %u.%03u\n",
576 (unsigned int)t.seconds, (unsigned int)t.millis);
577 break;
578 case TEE_ERROR_TIME_NOT_SET:
579 EMSG("TA time not stored\n");
580 break;
581 case TEE_ERROR_TIME_NEEDS_RESET:
582 EMSG("TA time needs reset\n");
583 break;
584 default:
585 return res;
586 }
587
588 res = TEE_SetTAPersistentTime(&null_time);
589 if (res != TEE_SUCCESS) {
590 EMSG("TEE_SetTAPersistentTime: failed\n");
591 return res;
592 }
593
594 res = TEE_GetTAPersistentTime(&t);
595 if (res != TEE_SUCCESS) {
596 EMSG("TEE_GetTAPersistentTime null: failed\n");
597 return res;
598 }
599 printf("TA time %u.%03u\n", (unsigned int)t.seconds,
600 (unsigned int)t.millis);
601 /*
602 * The time between TEE_SetTAPersistentTime() and
603 * TEE_GetTAPersistentTime() should be much less than 1 second, in fact
604 * it's not even a millisecond.
605 */
606 if (t.seconds > 1 || t.millis >= 1000) {
607 EMSG("Unexpected stored TA time %u.%03u\n",
608 (unsigned int)t.seconds, (unsigned int)t.millis);
609 return TEE_ERROR_BAD_STATE;
610 }
611
612 res = TEE_SetTAPersistentTime(&wrap_time);
613 if (res != TEE_SUCCESS) {
614 EMSG("TEE_SetTAPersistentTime wrap: failed\n");
615 return res;
616 }
617
618 res = TEE_Wait(1000);
619 if (res != TEE_SUCCESS)
620 EMSG("TEE_Wait wrap: failed\n");
621
622 res = TEE_GetTAPersistentTime(&t);
623 if (res != TEE_ERROR_OVERFLOW) {
624 EMSG("TEE_GetTAPersistentTime: failed\n");
625 return TEE_ERROR_BAD_STATE;
626 }
627 printf("TA time %u.%03u\n", (unsigned int)t.seconds,
628 (unsigned int)t.millis);
629
630 if (t.seconds > sys_t.seconds) {
631 EMSG("Unexpected wrapped time %u.%03u (sys_t %u.%03u)\n",
632 (unsigned int)t.seconds, (unsigned int)t.millis,
633 (unsigned int)sys_t.seconds, (unsigned int)sys_t.millis);
634 return TEE_ERROR_BAD_STATE;
635 }
636
637 return TEE_SUCCESS;
638 }
639
640 #ifdef CFG_TA_FLOAT_SUPPORT
my_dcmpeq(double v1,double v2,double prec)641 static bool my_dcmpeq(double v1, double v2, double prec)
642 {
643 return v1 > (v2 - prec) && v1 < (v2 + prec);
644 }
645
my_fcmpeq(float v1,float v2,float prec)646 static bool my_fcmpeq(float v1, float v2, float prec)
647 {
648 return v1 > (v2 - prec) && v1 < (v2 + prec);
649 }
650
651
test_float(void)652 static TEE_Result test_float(void)
653 {
654 #define VAL1 2.6
655 #define VAL1_INT 2
656 #define VAL2 5.3
657 #define DPREC 0.000000000000001
658 #define FPREC 0.000001
659 #define EXPECT(expr) do { \
660 if (!(expr)) { \
661 EMSG("Expression %s failed", #expr); \
662 return TEE_ERROR_GENERIC; \
663 } \
664 } while (0)
665
666 IMSG("Testing floating point operations");
667
668 EXPECT(my_dcmpeq(test_float_dadd(VAL1, VAL2), VAL1 + VAL2, DPREC));
669 EXPECT(my_dcmpeq(test_float_ddiv(VAL1, VAL2), VAL1 / VAL2, DPREC));
670 EXPECT(my_dcmpeq(test_float_dmul(VAL1, VAL2), VAL1 * VAL2, DPREC));
671 EXPECT(my_dcmpeq(test_float_drsub(VAL1, VAL2), VAL2 - VAL1, DPREC));
672 EXPECT(my_dcmpeq(test_float_dsub(VAL1, VAL2), VAL1 - VAL2, DPREC));
673
674 EXPECT(test_float_dcmpeq(VAL1, VAL1) == 1);
675 EXPECT(test_float_dcmplt(VAL1, VAL2) == 1);
676 EXPECT(test_float_dcmple(VAL1, VAL1) == 1);
677 EXPECT(test_float_dcmpge(VAL1, VAL1) == 1);
678 EXPECT(test_float_dcmpgt(VAL2, VAL1) == 1);
679
680 EXPECT(my_fcmpeq(test_float_fadd(VAL1, VAL2), VAL1 + VAL2, FPREC));
681 EXPECT(my_fcmpeq(test_float_fdiv(VAL1, VAL2), VAL1 / VAL2, FPREC));
682 EXPECT(my_fcmpeq(test_float_fmul(VAL1, VAL2), VAL1 * VAL2, FPREC));
683 EXPECT(my_fcmpeq(test_float_frsub(VAL1, VAL2), VAL2 - VAL1, FPREC));
684 EXPECT(my_fcmpeq(test_float_fsub(VAL1, VAL2), VAL1 - VAL2, FPREC));
685
686 EXPECT(test_float_fcmpeq(VAL1, VAL1) == 1);
687 EXPECT(test_float_fcmplt(VAL1, VAL2) == 1);
688 EXPECT(test_float_fcmple(VAL1, VAL1) == 1);
689 EXPECT(test_float_fcmpge(VAL1, VAL1) == 1);
690 EXPECT(test_float_fcmpgt(VAL2, VAL1) == 1);
691
692 EXPECT(test_float_d2iz(VAL1) == VAL1_INT);
693 EXPECT(test_float_d2uiz(VAL1) == VAL1_INT);
694 EXPECT(test_float_d2lz(VAL1) == VAL1_INT);
695 EXPECT(test_float_d2ulz(VAL1) == VAL1_INT);
696
697 EXPECT(test_float_f2iz(VAL1) == VAL1_INT);
698 EXPECT(test_float_f2uiz(VAL1) == VAL1_INT);
699 EXPECT(test_float_f2lz(VAL1) == VAL1_INT);
700 EXPECT(test_float_f2ulz(VAL1) == VAL1_INT);
701
702 EXPECT(my_fcmpeq(test_float_d2f(VAL1), VAL1, FPREC));
703 EXPECT(my_dcmpeq(test_float_f2d(VAL1), VAL1, FPREC));
704
705 EXPECT(my_dcmpeq(test_float_i2d(VAL1_INT), VAL1_INT, DPREC));
706 EXPECT(my_dcmpeq(test_float_ui2d(VAL1_INT), VAL1_INT, DPREC));
707 EXPECT(my_dcmpeq(test_float_l2d(VAL1_INT), VAL1_INT, DPREC));
708 EXPECT(my_dcmpeq(test_float_ul2d(VAL1_INT), VAL1_INT, DPREC));
709
710 EXPECT(my_fcmpeq(test_float_i2f(VAL1_INT), VAL1_INT, FPREC));
711 EXPECT(my_fcmpeq(test_float_ui2f(VAL1_INT), VAL1_INT, FPREC));
712 EXPECT(my_fcmpeq(test_float_l2f(VAL1_INT), VAL1_INT, FPREC));
713 EXPECT(my_fcmpeq(test_float_ul2f(VAL1_INT), VAL1_INT, FPREC));
714 return TEE_SUCCESS;
715 }
716 #else /*CFG_TA_FLOAT_SUPPORT*/
test_float(void)717 static TEE_Result test_float(void)
718 {
719 IMSG("Floating point disabled");
720 return TEE_SUCCESS;
721 }
722 #endif /*CFG_TA_FLOAT_SUPPORT*/
723
724 #if defined(CFG_TA_BGET_TEST)
725 /* From libutils */
726 int bget_main_test(void *(*malloc_func)(size_t), void (*free_func)(void *));
727
malloc_wrapper(size_t size)728 static void *malloc_wrapper(size_t size)
729 {
730 return tee_map_zi(size, 0);
731 }
732
free_wrapper(void * ptr __unused)733 static void free_wrapper(void *ptr __unused)
734 {
735 }
736
test_bget(void)737 static TEE_Result test_bget(void)
738 {
739 DMSG("Testing bget");
740 if (bget_main_test(malloc_wrapper, free_wrapper)) {
741 EMSG("bget_main_test failed");
742 return TEE_ERROR_GENERIC;
743 }
744 DMSG("Bget OK");
745 return TEE_SUCCESS;
746 }
747 #else
test_bget(void)748 static TEE_Result test_bget(void)
749 {
750 IMSG("Bget test disabled");
751 return TEE_SUCCESS;
752 }
753 #endif
754
755
call_longjmp(jmp_buf env)756 static __noinline __noreturn void call_longjmp(jmp_buf env)
757 {
758 DMSG("Calling longjmp");
759 longjmp(env, 1);
760 EMSG("error: longjmp returned to calling function");
761 }
762
test_setjmp(void)763 static TEE_Result test_setjmp(void)
764 {
765 jmp_buf env = { };
766
767 if (setjmp(env)) {
768 IMSG("Returned via longjmp");
769 return TEE_SUCCESS;
770 } else {
771 call_longjmp(env);
772 return TEE_ERROR_GENERIC;
773 }
774 }
775
ta_entry_basic(uint32_t param_types,TEE_Param params[4])776 TEE_Result ta_entry_basic(uint32_t param_types, TEE_Param params[4])
777 {
778 TEE_Result res = TEE_ERROR_GENERIC;
779
780 printf("ta_entry_basic: enter\n");
781
782 res = test_malloc();
783 if (res != TEE_SUCCESS)
784 return res;
785
786 res = test_properties();
787 if (res != TEE_SUCCESS)
788 return res;
789
790 res = test_mem_access_right(param_types, params);
791 if (res != TEE_SUCCESS)
792 return res;
793
794 res = test_time();
795 if (res != TEE_SUCCESS)
796 return res;
797
798 res = test_float();
799 if (res != TEE_SUCCESS)
800 return res;
801
802 res = test_setjmp();
803 if (res != TEE_SUCCESS)
804 return res;
805
806 res = test_bget();
807 if (res != TEE_SUCCESS)
808 return res;
809
810 return TEE_SUCCESS;
811 }
812
ta_entry_panic(uint32_t param_types,TEE_Param params[4])813 TEE_Result ta_entry_panic(uint32_t param_types, TEE_Param params[4])
814 {
815 volatile bool mytrue = true;
816 (void)param_types;
817 (void)params;
818
819 printf("ta_entry_panic: enter\n");
820 /*
821 * Somewhat clumsy way of avoiding compile errors if TEE_Panic() has
822 * the __noreturn attribute.
823 */
824 if (mytrue)
825 TEE_Panic(0xbeef);
826
827 /*
828 * Should not be reached, but if it is the testsuite can detect that
829 * TEE_Panic() returned instead of panicking the TA.
830 */
831 return TEE_SUCCESS;
832 }
833
ta_entry_client_with_timeout(uint32_t param_types,TEE_Param params[4])834 TEE_Result ta_entry_client_with_timeout(uint32_t param_types,
835 TEE_Param params[4])
836 {
837 static const TEE_UUID os_test_uuid = TA_OS_TEST_UUID;
838 TEE_Result res = TEE_ERROR_GENERIC;
839 TEE_TASessionHandle sess = TEE_HANDLE_NULL;
840 uint32_t ret_orig = 0;
841
842 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
843 TEE_PARAM_TYPE_NONE,
844 TEE_PARAM_TYPE_NONE,
845 TEE_PARAM_TYPE_NONE)) {
846 EMSG("ta_entry_client_with_timeout: bad parameters\n");
847 return TEE_ERROR_BAD_PARAMETERS;
848 }
849
850 res = TEE_OpenTASession(&os_test_uuid, TEE_TIMEOUT_INFINITE, 0, NULL,
851 &sess, &ret_orig);
852 if (res != TEE_SUCCESS) {
853 EMSG(
854 "ta_entry_client_with_timeout: TEE_OpenTASession failed\n");
855 return res;
856 }
857
858 res =
859 TEE_InvokeTACommand(sess, params[0].value.a / 2,
860 TA_OS_TEST_CMD_WAIT, param_types, params,
861 &ret_orig);
862
863 if (ret_orig != TEE_ORIGIN_TRUSTED_APP || res != TEE_ERROR_CANCEL) {
864 EMSG("ta_entry_client_with_timeout: TEE_InvokeTACommand: "
865 "res 0x%x ret_orig 0x%x\n", (unsigned int)res,
866 (unsigned int)ret_orig);
867 res = TEE_ERROR_GENERIC;
868 } else
869 res = TEE_SUCCESS;
870
871 TEE_CloseTASession(sess);
872 return res;
873
874 }
875
ta_entry_client(uint32_t param_types,TEE_Param params[4])876 TEE_Result ta_entry_client(uint32_t param_types, TEE_Param params[4])
877 {
878 static const TEE_UUID crypt_uuid = TA_CRYPT_UUID;
879 TEE_Result res = TEE_ERROR_GENERIC;
880 uint32_t l_pts = 0;
881 TEE_Param l_params[4] = { };
882 TEE_TASessionHandle sess = TEE_HANDLE_NULL;
883 uint32_t ret_orig = 0;
884 static const uint8_t sha256_in[] = { 'a', 'b', 'c' };
885 static const uint8_t sha256_out[] = {
886 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
887 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
888 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
889 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
890 };
891 uint8_t out[32] = { 0 };
892 void *in = NULL;
893
894 (void)param_types;
895 (void)params;
896
897 printf("ta_entry_client: enter\n");
898
899 in = TEE_Malloc(sizeof(sha256_in), 0);
900 if (in == NULL)
901 return TEE_ERROR_OUT_OF_MEMORY;
902 TEE_MemMove(in, sha256_in, sizeof(sha256_in));
903
904 res = TEE_OpenTASession(&crypt_uuid, TEE_TIMEOUT_INFINITE, 0, NULL,
905 &sess, &ret_orig);
906 if (res != TEE_SUCCESS) {
907 EMSG("ta_entry_client: TEE_OpenTASession failed\n");
908 goto cleanup_return;
909 }
910
911 l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
912 TEE_PARAM_TYPE_MEMREF_OUTPUT, 0, 0);
913 l_params[0].memref.buffer = in;
914 l_params[0].memref.size = sizeof(sha256_in);
915 l_params[1].memref.buffer = out;
916 l_params[1].memref.size = sizeof(out);
917
918 res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE,
919 TA_CRYPT_CMD_SHA256, l_pts, l_params,
920 &ret_orig);
921 if (res != TEE_SUCCESS) {
922 EMSG("ta_entry_client: TEE_InvokeTACommand failed\n");
923 goto cleanup_return;
924 }
925
926 if (TEE_MemCompare(sha256_out, out, sizeof(sha256_out)) != 0) {
927 EMSG("ta_entry_client: out parameter failed\n");
928 res = TEE_ERROR_GENERIC;
929 goto cleanup_return;
930 }
931
932 cleanup_return:
933 TEE_Free(in);
934 TEE_CloseTASession(sess);
935 return res;
936 }
937
ta_entry_params_access_rights(uint32_t param_types,TEE_Param params[4])938 TEE_Result ta_entry_params_access_rights(uint32_t param_types, TEE_Param params[4])
939 {
940 TEE_Result res = TEE_ERROR_GENERIC;
941
942 if (param_types !=
943 TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
944 TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0))
945 return TEE_ERROR_GENERIC;
946
947 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ |
948 TEE_MEMORY_ACCESS_ANY_OWNER,
949 params[0].memref.buffer,
950 params[0].memref.size);
951 if (res != TEE_SUCCESS)
952 return res;
953
954 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ,
955 params[0].memref.buffer,
956 params[0].memref.size);
957 if (res != TEE_ERROR_ACCESS_DENIED)
958 return TEE_ERROR_GENERIC;
959 if (params[1].memref.buffer || params[1].memref.size)
960 return TEE_ERROR_BAD_PARAMETERS;
961
962 return TEE_SUCCESS;
963 }
964
ta_entry_wait(uint32_t param_types,TEE_Param params[4])965 TEE_Result ta_entry_wait(uint32_t param_types, TEE_Param params[4])
966 {
967 TEE_Result res = TEE_SUCCESS;
968 (void)param_types;
969
970 printf("ta_entry_wait: waiting %d\n", (unsigned int)params[0].value.a);
971 /* Wait */
972 res = TEE_Wait(params[0].value.a);
973
974 return res;
975 }
976
undef_instr(void)977 static void undef_instr(void)
978 {
979 #if defined(ARM64)
980 __asm__(".word 0x0");
981 #elif defined(ARM32)
982 __asm__(".word 0xe7ffffff");
983 #else
984 #error "Unsupported architecture"
985 #endif
986 }
987
ta_entry_bad_mem_access(uint32_t param_types,TEE_Param params[4])988 TEE_Result ta_entry_bad_mem_access(uint32_t param_types, TEE_Param params[4])
989 {
990 long int stack = 0;
991 long int stack_addr = (long int)&stack;
992 void (*volatile null_fn_ptr)(void) = NULL;
993 char *zero_size_malloc = NULL;
994
995 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 0, 0, 0) &&
996 param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
997 TEE_PARAM_TYPE_MEMREF_INOUT, 0, 0))
998 return TEE_ERROR_GENERIC;
999
1000 switch (params[0].value.a) {
1001 case 1:
1002 *((volatile uint32_t *)0) = 0;
1003 break;
1004 case 2:
1005 *((uint32_t *)(stack_addr + 0x40000000)) = 0;
1006 break;
1007 case 3:
1008 null_fn_ptr();
1009 break;
1010 case 4:
1011 ((void (*)(void))(stack_addr + 0x40000000)) ();
1012 break;
1013 case 5:
1014 undef_instr();
1015 break;
1016 case 6:
1017 zero_size_malloc = TEE_Malloc(0, 0);
1018 if (!zero_size_malloc)
1019 return TEE_ERROR_GENERIC;
1020 if (*zero_size_malloc)
1021 return TEE_ERROR_GENERIC;
1022 break;
1023 case 7:
1024 zero_size_malloc = TEE_Malloc(0, 0);
1025 if (!zero_size_malloc)
1026 return TEE_ERROR_GENERIC;
1027 *zero_size_malloc = 0;
1028 break;
1029 default:
1030 break;
1031 }
1032
1033 return TEE_SUCCESS;
1034 }
1035
incr_values(size_t bufsize,uint8_t * a,uint8_t * b,uint8_t * c)1036 static void incr_values(size_t bufsize, uint8_t *a, uint8_t *b, uint8_t *c)
1037 {
1038 size_t i = 0;
1039
1040 for (i = 0; i < bufsize; i++) {
1041 a[i]++; b[i]++; c[i]++;
1042 }
1043 }
1044
1045 #define TA2TA_BUF_SIZE (2 * 1024)
ta_entry_ta2ta_memref(uint32_t param_types,TEE_Param params[4])1046 TEE_Result ta_entry_ta2ta_memref(uint32_t param_types, TEE_Param params[4])
1047 {
1048 static const TEE_UUID test_uuid = TA_OS_TEST_UUID;
1049 TEE_TASessionHandle sess = TEE_HANDLE_NULL;
1050 TEE_Param l_params[4] = { };
1051 uint8_t in[TA2TA_BUF_SIZE] = { };
1052 uint8_t inout[TA2TA_BUF_SIZE] = { };
1053 uint8_t out[TA2TA_BUF_SIZE] = { };
1054 TEE_Result res = TEE_ERROR_GENERIC;
1055 uint32_t ret_orig = 0;
1056 uint32_t l_pts = 0;
1057 size_t i = 0;
1058
1059 (void)params;
1060
1061 if (param_types != TEE_PARAM_TYPES(0, 0, 0, 0))
1062 return TEE_ERROR_GENERIC;
1063
1064 res = TEE_OpenTASession(&test_uuid, TEE_TIMEOUT_INFINITE, 0, NULL,
1065 &sess, &ret_orig);
1066 if (res != TEE_SUCCESS) {
1067 EMSG("TEE_OpenTASession failed");
1068 goto cleanup_return;
1069 }
1070
1071 l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
1072 TEE_PARAM_TYPE_MEMREF_INOUT,
1073 TEE_PARAM_TYPE_MEMREF_OUTPUT, 0);
1074 l_params[0].memref.buffer = in;
1075 l_params[0].memref.size = TA2TA_BUF_SIZE;
1076 l_params[1].memref.buffer = inout;
1077 l_params[1].memref.size = TA2TA_BUF_SIZE;
1078 l_params[2].memref.buffer = out;
1079 l_params[2].memref.size = TA2TA_BUF_SIZE;
1080
1081 /* Initialize buffers */
1082 for (i = 0; i < TA2TA_BUF_SIZE; i++) {
1083 in[i] = 5;
1084 inout[i] = 10;
1085 out[i] = 0;
1086 }
1087
1088 /*
1089 * TA will compute: out = ++inout + in
1090 * Expected values after this step: in: 5, inout: 11, out: 16
1091 */
1092 res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE,
1093 TA_OS_TEST_CMD_TA2TA_MEMREF_MIX,
1094 l_pts, l_params, &ret_orig);
1095 if (res != TEE_SUCCESS) {
1096 EMSG("TEE_InvokeTACommand failed");
1097 goto cleanup_return;
1098 }
1099
1100 /*
1101 * Increment all values by one.
1102 * Expected values after this step: in: 6, inout: 12, out: 17
1103 */
1104 incr_values(TA2TA_BUF_SIZE, in, inout, out);
1105
1106 /*
1107 * TA will compute: out = ++inout + in
1108 * Expected values after this step: in: 6, inout: 13, out: 19
1109 */
1110 res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE,
1111 TA_OS_TEST_CMD_TA2TA_MEMREF_MIX,
1112 l_pts, l_params, &ret_orig);
1113 if (res != TEE_SUCCESS) {
1114 EMSG("TEE_InvokeTACommand failed");
1115 goto cleanup_return;
1116 }
1117
1118 /* Check the actual values */
1119 for (i = 0; i < TA2TA_BUF_SIZE; i++) {
1120 if (in[i] != 6 || inout[i] != 13 || out[i] != 19) {
1121 EMSG("Unexpected value in buffer(s)");
1122 DHEXDUMP(in, TA2TA_BUF_SIZE);
1123 DHEXDUMP(inout, TA2TA_BUF_SIZE);
1124 DHEXDUMP(out, TA2TA_BUF_SIZE);
1125 return TEE_ERROR_GENERIC;
1126 }
1127 }
1128
1129 cleanup_return:
1130 TEE_CloseTASession(sess);
1131 return res;
1132 }
1133
ta_entry_ta2ta_memref_mix(uint32_t param_types,TEE_Param params[4])1134 TEE_Result ta_entry_ta2ta_memref_mix(uint32_t param_types, TEE_Param params[4])
1135 {
1136 uint8_t *in = NULL;
1137 uint8_t *inout = NULL;
1138 uint8_t *out = NULL;
1139 size_t bufsize = 0;
1140 size_t i = 0;
1141
1142 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
1143 TEE_PARAM_TYPE_MEMREF_INOUT,
1144 TEE_PARAM_TYPE_MEMREF_OUTPUT, 0))
1145 return TEE_ERROR_GENERIC;
1146
1147 bufsize = params[0].memref.size;
1148 if (params[1].memref.size != bufsize ||
1149 params[2].memref.size != bufsize)
1150 return TEE_ERROR_GENERIC;
1151
1152 in = params[0].memref.buffer;
1153 inout = params[1].memref.buffer;
1154 out = params[2].memref.buffer;
1155
1156 for (i = 0; i < bufsize; i++)
1157 out[i] = ++inout[i] + in[i];
1158
1159 return TEE_SUCCESS;
1160 }
1161
ta_entry_params(uint32_t param_types,TEE_Param params[4])1162 TEE_Result ta_entry_params(uint32_t param_types, TEE_Param params[4])
1163 {
1164 size_t n = 0;
1165
1166 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
1167 TEE_PARAM_TYPE_MEMREF_INPUT,
1168 TEE_PARAM_TYPE_MEMREF_OUTPUT,
1169 TEE_PARAM_TYPE_MEMREF_OUTPUT))
1170 return TEE_ERROR_BAD_PARAMETERS;
1171
1172 for (n = 0; n < TEE_NUM_PARAMS; n++)
1173 if (!params[n].memref.buffer || !params[n].memref.size)
1174 return TEE_ERROR_BAD_PARAMETERS;
1175
1176 return TEE_SUCCESS;
1177 }
1178
ta_entry_null_memref(uint32_t param_types,TEE_Param params[4])1179 TEE_Result ta_entry_null_memref(uint32_t param_types, TEE_Param params[4])
1180 {
1181 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
1182 TEE_PARAM_TYPE_MEMREF_INPUT,
1183 TEE_PARAM_TYPE_MEMREF_OUTPUT,
1184 TEE_PARAM_TYPE_MEMREF_OUTPUT))
1185 return TEE_ERROR_BAD_PARAMETERS;
1186
1187 /*
1188 * Tests how client can provide null or non-null memref parameters
1189 * param[0] expected as a 0 byte input mapped memeref.
1190 * param[1] expected as a 0 byte input not-mapped memeref.
1191 * param[2] expected as a 0 byte output mapped memeref.
1192 * param[3] expected as a 0 byte output not-mapped memeref.
1193 */
1194 if (!params[0].memref.buffer || params[0].memref.size ||
1195 params[1].memref.buffer || params[1].memref.size ||
1196 !params[2].memref.buffer || params[2].memref.size ||
1197 params[3].memref.buffer || params[3].memref.size)
1198 return TEE_ERROR_BAD_PARAMETERS;
1199
1200 return TEE_SUCCESS;
1201 }
1202
ta_entry_call_lib(uint32_t param_types,TEE_Param params[4]__unused)1203 TEE_Result ta_entry_call_lib(uint32_t param_types,
1204 TEE_Param params[4] __unused)
1205 {
1206 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
1207 TEE_PARAM_TYPE_NONE,
1208 TEE_PARAM_TYPE_NONE,
1209 TEE_PARAM_TYPE_NONE))
1210 return TEE_ERROR_BAD_PARAMETERS;
1211
1212 if (os_test_shlib_add(1, 2) != 3)
1213 return TEE_ERROR_GENERIC;
1214
1215 return TEE_SUCCESS;
1216 }
1217
ta_entry_call_lib_panic(uint32_t param_types,TEE_Param params[4]__unused)1218 TEE_Result ta_entry_call_lib_panic(uint32_t param_types,
1219 TEE_Param params[4] __unused)
1220 {
1221 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
1222 TEE_PARAM_TYPE_NONE,
1223 TEE_PARAM_TYPE_NONE,
1224 TEE_PARAM_TYPE_NONE))
1225 return TEE_ERROR_BAD_PARAMETERS;
1226
1227 os_test_shlib_panic();
1228
1229 return TEE_ERROR_GENERIC;
1230 }
1231
ta_entry_call_lib_dl(uint32_t param_types __maybe_unused,TEE_Param params[4]__unused)1232 TEE_Result ta_entry_call_lib_dl(uint32_t param_types __maybe_unused,
1233 TEE_Param params[4] __unused)
1234 {
1235 int (*add_func)(int a, int b) = NULL;
1236 TEE_Result res = TEE_ERROR_GENERIC;
1237 void *handle = NULL;
1238 void *hnull = NULL;
1239
1240 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
1241 TEE_PARAM_TYPE_NONE,
1242 TEE_PARAM_TYPE_NONE,
1243 TEE_PARAM_TYPE_NONE))
1244 return TEE_ERROR_BAD_PARAMETERS;
1245
1246 handle = dlopen("b3091a65-9751-4784-abf7-0298a7cc35ba",
1247 RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
1248 if (!handle)
1249 return TEE_ERROR_GENERIC;
1250
1251 add_func = dlsym(handle, "os_test_shlib_dl_add");
1252 if (!add_func)
1253 goto err;
1254 if (add_func(3, 4) != 7)
1255 goto err;
1256
1257 hnull = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
1258 if (!hnull)
1259 goto err;
1260
1261 add_func = dlsym(hnull, "os_test_shlib_dl_add");
1262 if (!add_func)
1263 goto err;
1264 if (add_func(5, 6) != 11)
1265 goto err;
1266
1267 res = TEE_SUCCESS;
1268 dlclose(hnull);
1269 err:
1270 dlclose(handle);
1271 return res;
1272 }
1273
ta_entry_call_lib_dl_panic(uint32_t param_types __maybe_unused,TEE_Param params[4]__unused)1274 TEE_Result ta_entry_call_lib_dl_panic(uint32_t param_types __maybe_unused,
1275 TEE_Param params[4] __unused)
1276 {
1277 int (*panic_func)(void) = NULL;
1278 void *handle = NULL;
1279 TEE_Result res = TEE_ERROR_GENERIC;
1280
1281 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
1282 TEE_PARAM_TYPE_NONE,
1283 TEE_PARAM_TYPE_NONE,
1284 TEE_PARAM_TYPE_NONE))
1285 return TEE_ERROR_BAD_PARAMETERS;
1286
1287 handle = dlopen("b3091a65-9751-4784-abf7-0298a7cc35ba",
1288 RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
1289 if (!handle)
1290 return res;
1291
1292 panic_func = dlsym(handle, "os_test_shlib_dl_panic");
1293 if (!panic_func)
1294 goto err;
1295 panic_func();
1296 return TEE_ERROR_GENERIC;
1297 err:
1298 dlclose(handle);
1299 return res;
1300 }
1301
1302 /* ELF initialization/finalization test */
1303
1304 volatile int os_test_global;
1305
os_test_init(void)1306 static void __attribute__((constructor)) os_test_init(void)
1307 {
1308 os_test_global *= 10;
1309 os_test_global += 1;
1310 DMSG("os_test_global=%d", os_test_global);
1311 }
1312
ta_entry_get_global_var(uint32_t param_types,TEE_Param params[4])1313 TEE_Result ta_entry_get_global_var(uint32_t param_types, TEE_Param params[4])
1314 {
1315 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
1316 TEE_PARAM_TYPE_NONE,
1317 TEE_PARAM_TYPE_NONE,
1318 TEE_PARAM_TYPE_NONE))
1319 return TEE_ERROR_BAD_PARAMETERS;
1320
1321 params[0].value.a = os_test_global;
1322
1323 return TEE_SUCCESS;
1324 }
1325
ta_entry_client_identity(uint32_t param_types,TEE_Param params[4])1326 TEE_Result ta_entry_client_identity(uint32_t param_types, TEE_Param params[4])
1327 {
1328 TEE_Result res = TEE_ERROR_GENERIC;
1329 TEE_Identity identity = { };
1330
1331 if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
1332 TEE_PARAM_TYPE_MEMREF_OUTPUT,
1333 TEE_PARAM_TYPE_NONE,
1334 TEE_PARAM_TYPE_NONE))
1335 return TEE_ERROR_BAD_PARAMETERS;
1336
1337 if (params[1].memref.size < sizeof(TEE_UUID)) {
1338 params[1].memref.size = sizeof(TEE_UUID);
1339 return TEE_ERROR_SHORT_BUFFER;
1340 }
1341
1342 res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT,
1343 "gpd.client.identity", &identity);
1344 if (res != TEE_SUCCESS) {
1345 EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, res);
1346 return res;
1347 }
1348
1349 params[0].value.a = identity.login;
1350 memcpy(params[1].memref.buffer, &identity.uuid, sizeof(TEE_UUID));
1351 params[1].memref.size = sizeof(TEE_UUID);
1352
1353 return res;
1354 }
1355
1356 #if defined(WITH_TLS_TESTS)
1357 __thread int os_test_tls_a;
1358 __thread int os_test_tls_b = 42;
1359
ta_entry_tls_test_main(void)1360 TEE_Result ta_entry_tls_test_main(void)
1361 {
1362 if (os_test_tls_a != 0) {
1363 EMSG("os_test_tls_a=%d, expected 0", os_test_tls_a);
1364 return TEE_ERROR_GENERIC;
1365 }
1366 if (os_test_tls_b != 42) {
1367 EMSG("os_test_tls_b=%d, expected 42", os_test_tls_b);
1368 return TEE_ERROR_GENERIC;
1369 }
1370
1371 return TEE_SUCCESS;
1372 }
1373
ta_entry_tls_test_shlib(void)1374 TEE_Result ta_entry_tls_test_shlib(void)
1375 {
1376 if (os_test_shlib_tls_a != 0) {
1377 EMSG("os_test_shlib_tls_a=%d, expected 0", os_test_shlib_tls_a);
1378 return TEE_ERROR_GENERIC;
1379 }
1380 if (os_test_shlib_tls_b != 123) {
1381 EMSG("os_test_shlib_tls_b=%d, expected 123",
1382 os_test_shlib_tls_b);
1383 return TEE_ERROR_GENERIC;
1384 }
1385
1386 return TEE_SUCCESS;
1387 }
1388 #else
ta_entry_tls_test_main(void)1389 TEE_Result ta_entry_tls_test_main(void)
1390 {
1391 return TEE_ERROR_NOT_SUPPORTED;
1392 }
1393
ta_entry_tls_test_shlib(void)1394 TEE_Result ta_entry_tls_test_shlib(void)
1395 {
1396 return TEE_ERROR_NOT_SUPPORTED;
1397 }
1398 #endif
1399
iterate_hdr_cb(struct dl_phdr_info * info __maybe_unused,size_t size __unused,void * data)1400 static int iterate_hdr_cb(struct dl_phdr_info *info __maybe_unused,
1401 size_t size __unused, void *data)
1402 {
1403 int *count = data;
1404
1405 (*count)++;
1406 IMSG("ELF module index: %d", *count);
1407 IMSG(" dlpi_addr=%p", (void *)info->dlpi_addr);
1408 IMSG(" dlpi_name='%s'", info->dlpi_name);
1409 IMSG(" dlpi_phdr=%p", (void *)info->dlpi_phdr);
1410 IMSG(" dlpi_phnum=%hu", info->dlpi_phnum);
1411 IMSG(" dlpi_adds=%llu", info->dlpi_adds);
1412 IMSG(" dlpi_subs=%llu", info->dlpi_subs);
1413 IMSG(" dlpi_tls_modid=%zu", info->dlpi_tls_modid);
1414 IMSG(" dlpi_tls_data=%p", info->dlpi_tls_data);
1415
1416 return 123;
1417 }
1418
expect_dl_count_ge(size_t exp_count)1419 static TEE_Result expect_dl_count_ge(size_t exp_count)
1420 {
1421 int st = 0;
1422 size_t count = 0;
1423
1424 st = dl_iterate_phdr(iterate_hdr_cb, (void *)&count);
1425 if (st != 123) {
1426 /*
1427 * dl_iterate_phdr() should return the last value returned by
1428 * the callback
1429 */
1430 EMSG("Expected return value 123, got %d", st);
1431 return TEE_ERROR_GENERIC;
1432 }
1433 if (count < exp_count) {
1434 /*
1435 * Expect >= and not == since there could be more shared
1436 * libraries (for instance, CFG_ULIBS_SHARED=y)
1437 */
1438 EMSG("Expected count > %zu, got: %zu", exp_count, count);
1439 return TEE_ERROR_GENERIC;
1440 }
1441
1442 return TEE_SUCCESS;
1443 }
1444
ta_entry_dl_phdr(void)1445 TEE_Result ta_entry_dl_phdr(void)
1446 {
1447 return expect_dl_count_ge(2);
1448 }
1449
ta_entry_dl_phdr_dl(void)1450 TEE_Result ta_entry_dl_phdr_dl(void)
1451 {
1452 TEE_Result res = TEE_ERROR_GENERIC;
1453 void *handle = NULL;
1454
1455 handle = dlopen("b3091a65-9751-4784-abf7-0298a7cc35ba",
1456 RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
1457 if (!handle)
1458 return TEE_ERROR_GENERIC;
1459
1460 res = expect_dl_count_ge(3);
1461 dlclose(handle);
1462
1463 return res;
1464 }
1465
ta_entry_memtag_use_after_free(void)1466 TEE_Result ta_entry_memtag_use_after_free(void)
1467 {
1468 uint32_t *p = NULL;
1469
1470 if (!memtag_is_enabled())
1471 return TEE_ERROR_NOT_SUPPORTED;
1472
1473 p = TEE_Malloc(sizeof(*p), TEE_MALLOC_FILL_ZERO);
1474 *p = 43;
1475 TEE_Free(p);
1476 (*p) += 2;
1477 return TEE_ERROR_GENERIC;
1478 }
1479
ta_entry_memtag_invalid_tag(void)1480 TEE_Result ta_entry_memtag_invalid_tag(void)
1481 {
1482 uint32_t *p = NULL;
1483 uint32_t *p2 = NULL;
1484
1485 if (!memtag_is_enabled())
1486 return TEE_ERROR_NOT_SUPPORTED;
1487
1488 p = TEE_Malloc(sizeof(*p), TEE_MALLOC_FILL_ZERO);
1489
1490 if (!memtag_get_tag(p)) {
1491 EMSG("missing tag in %p", (void *)p);
1492 goto err;
1493 }
1494 *p = 32;
1495
1496 p2 = memtag_insert_tag(p, (memtag_get_tag(p) + 1) & 0xf);
1497 *p2 = 42;
1498 EMSG("Expected to crash when writing to %p which was allocated as %p",
1499 (void *)p2, (void *)p);
1500 err:
1501 TEE_Free(p);
1502 return TEE_ERROR_GENERIC;
1503 }
1504
ta_entry_memtag_double_free(void)1505 TEE_Result ta_entry_memtag_double_free(void)
1506 {
1507 uint32_t *p = NULL;
1508
1509 if (!memtag_is_enabled())
1510 return TEE_ERROR_NOT_SUPPORTED;
1511
1512 p = TEE_Malloc(sizeof(*p), TEE_MALLOC_FILL_ZERO);
1513 *p = 43;
1514 TEE_Free(p);
1515 TEE_Free(p);
1516 return TEE_ERROR_GENERIC;
1517 }
1518
ta_entry_memtag_buffer_overrun(void)1519 TEE_Result ta_entry_memtag_buffer_overrun(void)
1520 {
1521 uint64_t *p = NULL;
1522
1523 if (!memtag_is_enabled())
1524 return TEE_ERROR_NOT_SUPPORTED;
1525
1526 p = TEE_Malloc(sizeof(*p) * 2, TEE_MALLOC_FILL_ZERO);
1527 p[2] += 44;
1528 TEE_Free(p);
1529 return TEE_ERROR_GENERIC;
1530 }
1531
1532
1533