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