xref: /OK3568_Linux_fs/external/security/rk_tee_user/v2/ta/os_test/os_test.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 
992 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 0, 0, 0) &&
993 	    param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
994 					   TEE_PARAM_TYPE_MEMREF_INOUT, 0, 0))
995 		return TEE_ERROR_GENERIC;
996 
997 	switch (params[0].value.a) {
998 	case 1:
999 		*((volatile uint32_t *)0) = 0;
1000 		break;
1001 	case 2:
1002 		*((uint32_t *)(stack_addr + 0x40000000)) = 0;
1003 		break;
1004 	case 3:
1005 		null_fn_ptr();
1006 		break;
1007 	case 4:
1008 		((void (*)(void))(stack_addr + 0x40000000)) ();
1009 		break;
1010 	case 5:
1011 		undef_instr();
1012 		break;
1013 	default:
1014 		break;
1015 	}
1016 
1017 	return TEE_SUCCESS;
1018 }
1019 
incr_values(size_t bufsize,uint8_t * a,uint8_t * b,uint8_t * c)1020 static void incr_values(size_t bufsize, uint8_t *a, uint8_t *b, uint8_t *c)
1021 {
1022 	size_t i = 0;
1023 
1024 	for (i = 0; i < bufsize; i++) {
1025 		a[i]++; b[i]++; c[i]++;
1026 	}
1027 }
1028 
1029 #define TA2TA_BUF_SIZE		(2 * 1024)
ta_entry_ta2ta_memref(uint32_t param_types,TEE_Param params[4])1030 TEE_Result ta_entry_ta2ta_memref(uint32_t param_types, TEE_Param params[4])
1031 {
1032 	static const TEE_UUID test_uuid = TA_OS_TEST_UUID;
1033 	TEE_TASessionHandle sess = TEE_HANDLE_NULL;
1034 	TEE_Param l_params[4] = { };
1035 	uint8_t in[TA2TA_BUF_SIZE] = { };
1036 	uint8_t inout[TA2TA_BUF_SIZE] = { };
1037 	uint8_t out[TA2TA_BUF_SIZE] = { };
1038 	TEE_Result res = TEE_ERROR_GENERIC;
1039 	uint32_t ret_orig = 0;
1040 	uint32_t l_pts = 0;
1041 	size_t i = 0;
1042 
1043 	(void)params;
1044 
1045 	if (param_types != TEE_PARAM_TYPES(0, 0, 0, 0))
1046 		return TEE_ERROR_GENERIC;
1047 
1048 	res = TEE_OpenTASession(&test_uuid, TEE_TIMEOUT_INFINITE, 0, NULL,
1049 				&sess, &ret_orig);
1050 	if (res != TEE_SUCCESS) {
1051 		EMSG("TEE_OpenTASession failed");
1052 		goto cleanup_return;
1053 	}
1054 
1055 	l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
1056 				TEE_PARAM_TYPE_MEMREF_INOUT,
1057 				TEE_PARAM_TYPE_MEMREF_OUTPUT, 0);
1058 	l_params[0].memref.buffer = in;
1059 	l_params[0].memref.size = TA2TA_BUF_SIZE;
1060 	l_params[1].memref.buffer = inout;
1061 	l_params[1].memref.size = TA2TA_BUF_SIZE;
1062 	l_params[2].memref.buffer = out;
1063 	l_params[2].memref.size = TA2TA_BUF_SIZE;
1064 
1065 	/* Initialize buffers */
1066 	for (i = 0; i < TA2TA_BUF_SIZE; i++) {
1067 		in[i] = 5;
1068 		inout[i] = 10;
1069 		out[i] = 0;
1070 	}
1071 
1072 	/*
1073 	 * TA will compute: out = ++inout + in
1074 	 * Expected values after this step: in: 5, inout: 11, out: 16
1075 	 */
1076 	res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE,
1077 				  TA_OS_TEST_CMD_TA2TA_MEMREF_MIX,
1078 				  l_pts, l_params, &ret_orig);
1079 	if (res != TEE_SUCCESS) {
1080 		EMSG("TEE_InvokeTACommand failed");
1081 		goto cleanup_return;
1082 	}
1083 
1084 	/*
1085 	 * Increment all values by one.
1086 	 * Expected values after this step: in: 6, inout: 12, out: 17
1087 	 */
1088 	incr_values(TA2TA_BUF_SIZE, in, inout, out);
1089 
1090 	/*
1091 	 * TA will compute: out = ++inout + in
1092 	 * Expected values after this step: in: 6, inout: 13, out: 19
1093 	 */
1094 	res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE,
1095 				  TA_OS_TEST_CMD_TA2TA_MEMREF_MIX,
1096 				  l_pts, l_params, &ret_orig);
1097 	if (res != TEE_SUCCESS) {
1098 		EMSG("TEE_InvokeTACommand failed");
1099 		goto cleanup_return;
1100 	}
1101 
1102 	/* Check the actual values */
1103 	for (i = 0; i < TA2TA_BUF_SIZE; i++) {
1104 		if (in[i] != 6 || inout[i] != 13 || out[i] != 19) {
1105 			EMSG("Unexpected value in buffer(s)");
1106 			DHEXDUMP(in, TA2TA_BUF_SIZE);
1107 			DHEXDUMP(inout, TA2TA_BUF_SIZE);
1108 			DHEXDUMP(out, TA2TA_BUF_SIZE);
1109 			return TEE_ERROR_GENERIC;
1110 		}
1111 	}
1112 
1113 cleanup_return:
1114 	TEE_CloseTASession(sess);
1115 	return res;
1116 }
1117 
ta_entry_ta2ta_memref_mix(uint32_t param_types,TEE_Param params[4])1118 TEE_Result ta_entry_ta2ta_memref_mix(uint32_t param_types, TEE_Param params[4])
1119 {
1120 	uint8_t *in = NULL;
1121 	uint8_t *inout = NULL;
1122 	uint8_t *out = NULL;
1123 	size_t bufsize = 0;
1124 	size_t i = 0;
1125 
1126 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
1127 					   TEE_PARAM_TYPE_MEMREF_INOUT,
1128 					   TEE_PARAM_TYPE_MEMREF_OUTPUT, 0))
1129 		return TEE_ERROR_GENERIC;
1130 
1131 	bufsize = params[0].memref.size;
1132 	if (params[1].memref.size != bufsize ||
1133 	    params[2].memref.size != bufsize)
1134 		return TEE_ERROR_GENERIC;
1135 
1136 	in = params[0].memref.buffer;
1137 	inout = params[1].memref.buffer;
1138 	out = params[2].memref.buffer;
1139 
1140 	for (i = 0; i < bufsize; i++)
1141 		out[i] = ++inout[i] + in[i];
1142 
1143 	return TEE_SUCCESS;
1144 }
1145 
ta_entry_params(uint32_t param_types,TEE_Param params[4])1146 TEE_Result ta_entry_params(uint32_t param_types, TEE_Param params[4])
1147 {
1148 	size_t n = 0;
1149 
1150 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
1151 					   TEE_PARAM_TYPE_MEMREF_INPUT,
1152 					   TEE_PARAM_TYPE_MEMREF_OUTPUT,
1153 					   TEE_PARAM_TYPE_MEMREF_OUTPUT))
1154 		return TEE_ERROR_BAD_PARAMETERS;
1155 
1156 	for (n = 0; n < TEE_NUM_PARAMS; n++)
1157 		if (!params[n].memref.buffer || !params[n].memref.size)
1158 			return TEE_ERROR_BAD_PARAMETERS;
1159 
1160 	return TEE_SUCCESS;
1161 }
1162 
ta_entry_null_memref(uint32_t param_types,TEE_Param params[4])1163 TEE_Result ta_entry_null_memref(uint32_t param_types, TEE_Param params[4])
1164 {
1165 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
1166 					   TEE_PARAM_TYPE_MEMREF_INPUT,
1167 					   TEE_PARAM_TYPE_MEMREF_OUTPUT,
1168 					   TEE_PARAM_TYPE_MEMREF_OUTPUT))
1169 		return TEE_ERROR_BAD_PARAMETERS;
1170 
1171 	/*
1172 	 * Tests how client can provide null or non-null memref parameters
1173 	 * param[0] expected as a 0 byte input mapped memeref.
1174 	 * param[1] expected as a 0 byte input not-mapped memeref.
1175 	 * param[2] expected as a 0 byte output mapped memeref.
1176 	 * param[3] expected as a 0 byte output not-mapped memeref.
1177 	 */
1178 	if (!params[0].memref.buffer || params[0].memref.size ||
1179 	    params[1].memref.buffer || params[1].memref.size ||
1180 	    !params[2].memref.buffer || params[2].memref.size ||
1181 	    params[3].memref.buffer || params[3].memref.size)
1182 		return TEE_ERROR_BAD_PARAMETERS;
1183 
1184 	return TEE_SUCCESS;
1185 }
1186 
ta_entry_call_lib(uint32_t param_types,TEE_Param params[4]__unused)1187 TEE_Result ta_entry_call_lib(uint32_t param_types,
1188 			     TEE_Param params[4] __unused)
1189 {
1190 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
1191 					   TEE_PARAM_TYPE_NONE,
1192 					   TEE_PARAM_TYPE_NONE,
1193 					   TEE_PARAM_TYPE_NONE))
1194 		return TEE_ERROR_BAD_PARAMETERS;
1195 
1196 	if (os_test_shlib_add(1, 2) != 3)
1197 		return TEE_ERROR_GENERIC;
1198 
1199 	return TEE_SUCCESS;
1200 }
1201 
ta_entry_call_lib_panic(uint32_t param_types,TEE_Param params[4]__unused)1202 TEE_Result ta_entry_call_lib_panic(uint32_t param_types,
1203 				   TEE_Param params[4] __unused)
1204 {
1205 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
1206 					   TEE_PARAM_TYPE_NONE,
1207 					   TEE_PARAM_TYPE_NONE,
1208 					   TEE_PARAM_TYPE_NONE))
1209 		return TEE_ERROR_BAD_PARAMETERS;
1210 
1211 	os_test_shlib_panic();
1212 
1213 	return TEE_ERROR_GENERIC;
1214 }
1215 
ta_entry_call_lib_dl(uint32_t param_types __maybe_unused,TEE_Param params[4]__unused)1216 TEE_Result ta_entry_call_lib_dl(uint32_t param_types __maybe_unused,
1217 				TEE_Param params[4] __unused)
1218 {
1219 	int (*add_func)(int a, int b) = NULL;
1220 	TEE_Result res = TEE_ERROR_GENERIC;
1221 	void *handle = NULL;
1222 	void *hnull = NULL;
1223 
1224 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
1225 					   TEE_PARAM_TYPE_NONE,
1226 					   TEE_PARAM_TYPE_NONE,
1227 					   TEE_PARAM_TYPE_NONE))
1228 		return TEE_ERROR_BAD_PARAMETERS;
1229 
1230 	handle = dlopen("b3091a65-9751-4784-abf7-0298a7cc35ba",
1231 			RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
1232 	if (!handle)
1233 		return TEE_ERROR_GENERIC;
1234 
1235 	add_func = dlsym(handle, "os_test_shlib_dl_add");
1236 	if (!add_func)
1237 		goto err;
1238 	if (add_func(3, 4) != 7)
1239 		goto err;
1240 
1241 	hnull = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
1242 	if (!hnull)
1243 		goto err;
1244 
1245 	add_func = dlsym(hnull, "os_test_shlib_dl_add");
1246 	if (!add_func)
1247 		goto err;
1248 	if (add_func(5, 6) != 11)
1249 		goto err;
1250 
1251 	res = TEE_SUCCESS;
1252 	dlclose(hnull);
1253 err:
1254 	dlclose(handle);
1255 	return res;
1256 }
1257 
ta_entry_call_lib_dl_panic(uint32_t param_types __maybe_unused,TEE_Param params[4]__unused)1258 TEE_Result ta_entry_call_lib_dl_panic(uint32_t param_types __maybe_unused,
1259 				      TEE_Param params[4] __unused)
1260 {
1261 	int (*panic_func)(void) = NULL;
1262 	void *handle = NULL;
1263 	TEE_Result res = TEE_ERROR_GENERIC;
1264 
1265 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
1266 					   TEE_PARAM_TYPE_NONE,
1267 					   TEE_PARAM_TYPE_NONE,
1268 					   TEE_PARAM_TYPE_NONE))
1269 		return TEE_ERROR_BAD_PARAMETERS;
1270 
1271 	handle = dlopen("b3091a65-9751-4784-abf7-0298a7cc35ba",
1272 			RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
1273 	if (!handle)
1274 		return res;
1275 
1276 	panic_func = dlsym(handle, "os_test_shlib_dl_panic");
1277 	if (!panic_func)
1278 		goto err;
1279 	panic_func();
1280 	return TEE_ERROR_GENERIC;
1281 err:
1282 	dlclose(handle);
1283 	return res;
1284 }
1285 
1286 /* ELF initialization/finalization test */
1287 
1288 volatile int os_test_global;
1289 
os_test_init(void)1290 static void __attribute__((constructor)) os_test_init(void)
1291 {
1292 	os_test_global *= 10;
1293 	os_test_global += 1;
1294 	DMSG("os_test_global=%d", os_test_global);
1295 }
1296 
ta_entry_get_global_var(uint32_t param_types,TEE_Param params[4])1297 TEE_Result ta_entry_get_global_var(uint32_t param_types, TEE_Param params[4])
1298 {
1299 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
1300 					   TEE_PARAM_TYPE_NONE,
1301 					   TEE_PARAM_TYPE_NONE,
1302 					   TEE_PARAM_TYPE_NONE))
1303 		return TEE_ERROR_BAD_PARAMETERS;
1304 
1305 	params[0].value.a = os_test_global;
1306 
1307 	return TEE_SUCCESS;
1308 }
1309 
ta_entry_client_identity(uint32_t param_types,TEE_Param params[4])1310 TEE_Result ta_entry_client_identity(uint32_t param_types, TEE_Param params[4])
1311 {
1312 	TEE_Result res = TEE_ERROR_GENERIC;
1313 	TEE_Identity identity = { };
1314 
1315 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
1316 					   TEE_PARAM_TYPE_MEMREF_OUTPUT,
1317 					   TEE_PARAM_TYPE_NONE,
1318 					   TEE_PARAM_TYPE_NONE))
1319 		return TEE_ERROR_BAD_PARAMETERS;
1320 
1321 	if (params[1].memref.size < sizeof(TEE_UUID)) {
1322 		params[1].memref.size = sizeof(TEE_UUID);
1323 		return TEE_ERROR_SHORT_BUFFER;
1324 	}
1325 
1326 	res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT,
1327 					"gpd.client.identity", &identity);
1328 	if (res != TEE_SUCCESS) {
1329 		EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, res);
1330 		return res;
1331 	}
1332 
1333 	params[0].value.a = identity.login;
1334 	memcpy(params[1].memref.buffer, &identity.uuid, sizeof(TEE_UUID));
1335 	params[1].memref.size = sizeof(TEE_UUID);
1336 
1337 	return res;
1338 }
1339 
1340 #if defined(WITH_TLS_TESTS)
1341 __thread int os_test_tls_a;
1342 __thread int os_test_tls_b = 42;
1343 
ta_entry_tls_test_main(void)1344 TEE_Result ta_entry_tls_test_main(void)
1345 {
1346 	if (os_test_tls_a != 0) {
1347 		EMSG("os_test_tls_a=%d, expected 0", os_test_tls_a);
1348 		return TEE_ERROR_GENERIC;
1349 	}
1350 	if (os_test_tls_b != 42) {
1351 		EMSG("os_test_tls_b=%d, expected 42", os_test_tls_b);
1352 		return TEE_ERROR_GENERIC;
1353 	}
1354 
1355 	return TEE_SUCCESS;
1356 }
1357 
ta_entry_tls_test_shlib(void)1358 TEE_Result ta_entry_tls_test_shlib(void)
1359 {
1360 	if (os_test_shlib_tls_a != 0) {
1361 		EMSG("os_test_shlib_tls_a=%d, expected 0", os_test_shlib_tls_a);
1362 		return TEE_ERROR_GENERIC;
1363 	}
1364 	if (os_test_shlib_tls_b != 123) {
1365 		EMSG("os_test_shlib_tls_b=%d, expected 123",
1366 		     os_test_shlib_tls_b);
1367 		return TEE_ERROR_GENERIC;
1368 	}
1369 
1370 	return TEE_SUCCESS;
1371 }
1372 #else
ta_entry_tls_test_main(void)1373 TEE_Result ta_entry_tls_test_main(void)
1374 {
1375 	return TEE_ERROR_NOT_SUPPORTED;
1376 }
1377 
ta_entry_tls_test_shlib(void)1378 TEE_Result ta_entry_tls_test_shlib(void)
1379 {
1380 	return TEE_ERROR_NOT_SUPPORTED;
1381 }
1382 #endif
1383 
iterate_hdr_cb(struct dl_phdr_info * info __maybe_unused,size_t size __unused,void * data)1384 static int iterate_hdr_cb(struct dl_phdr_info *info __maybe_unused,
1385 			  size_t size __unused, void *data)
1386 {
1387 	int *count = data;
1388 
1389 	(*count)++;
1390 	IMSG("ELF module index: %d", *count);
1391 	IMSG(" dlpi_addr=%p", (void *)info->dlpi_addr);
1392 	IMSG(" dlpi_name='%s'", info->dlpi_name);
1393 	IMSG(" dlpi_phdr=%p", (void *)info->dlpi_phdr);
1394 	IMSG(" dlpi_phnum=%hu", info->dlpi_phnum);
1395 	IMSG(" dlpi_adds=%llu", info->dlpi_adds);
1396 	IMSG(" dlpi_subs=%llu", info->dlpi_subs);
1397 	IMSG(" dlpi_tls_modid=%zu", info->dlpi_tls_modid);
1398 	IMSG(" dlpi_tls_data=%p", info->dlpi_tls_data);
1399 
1400 	return 123;
1401 }
1402 
expect_dl_count_ge(size_t exp_count)1403 static TEE_Result expect_dl_count_ge(size_t exp_count)
1404 {
1405 	int st = 0;
1406 	size_t count = 0;
1407 
1408 	st = dl_iterate_phdr(iterate_hdr_cb, (void *)&count);
1409 	if (st != 123) {
1410 		/*
1411 		 * dl_iterate_phdr() should return the last value returned by
1412 		 * the callback
1413 		 */
1414 		EMSG("Expected return value 123, got %d", st);
1415 		return TEE_ERROR_GENERIC;
1416 	}
1417 	if (count < exp_count) {
1418 		/*
1419 		 * Expect >= and not == since there could be more shared
1420 		 * libraries (for instance, CFG_ULIBS_SHARED=y)
1421 		 */
1422 		EMSG("Expected count > %zu, got: %zu", exp_count, count);
1423 		return TEE_ERROR_GENERIC;
1424 	}
1425 
1426 	return TEE_SUCCESS;
1427 }
1428 
ta_entry_dl_phdr(void)1429 TEE_Result ta_entry_dl_phdr(void)
1430 {
1431 	return expect_dl_count_ge(2);
1432 }
1433 
ta_entry_dl_phdr_dl(void)1434 TEE_Result ta_entry_dl_phdr_dl(void)
1435 {
1436 	TEE_Result res = TEE_ERROR_GENERIC;
1437 	void *handle = NULL;
1438 
1439 	handle = dlopen("b3091a65-9751-4784-abf7-0298a7cc35ba",
1440 			RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
1441 	if (!handle)
1442 		return TEE_ERROR_GENERIC;
1443 
1444 	res = expect_dl_count_ge(3);
1445 	dlclose(handle);
1446 
1447 	return res;
1448 }
1449