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