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