xref: /optee_os/lib/libutee/tee_api.c (revision 7509620b8b95fa57f9c786c15b216cdd3b5ddc7c)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2014, STMicroelectronics International N.V.
4  */
5 #include <stdlib.h>
6 #include <string.h>
7 #include <string_ext.h>
8 #include <tee_api.h>
9 #include <tee_internal_api_extensions.h>
10 #include <types_ext.h>
11 #include <user_ta_header.h>
12 #include <utee_syscalls.h>
13 #include "tee_api_private.h"
14 
15 /*
16  * return a known non-NULL invalid pointer when the
17  * requested size is zero
18  */
19 #define TEE_NULL_SIZED_VA	((void *)1)
20 
21 static const void *tee_api_instance_data;
22 
23 /* System API - Internal Client API */
24 
25 static void copy_param(struct utee_params *up, uint32_t param_types,
26 		       const TEE_Param params[TEE_NUM_PARAMS])
27 {
28 	size_t n = 0;
29 	uint64_t a = 0;
30 	uint64_t b = 0;
31 
32 	up->types = param_types;
33 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
34 		switch (TEE_PARAM_TYPE_GET(up->types, n)) {
35 		case TEE_PARAM_TYPE_VALUE_INPUT:
36 		case TEE_PARAM_TYPE_VALUE_INOUT:
37 			a = params[n].value.a;
38 			b = params[n].value.b;
39 			break;
40 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
41 		case TEE_PARAM_TYPE_MEMREF_INOUT:
42 		case TEE_PARAM_TYPE_MEMREF_INPUT:
43 			a = (vaddr_t)params[n].memref.buffer;
44 			b = params[n].memref.size;
45 			break;
46 		default:
47 			a = 0;
48 			b = 0;
49 		}
50 		up->vals[n * 2] = a;
51 		up->vals[n * 2 + 1] = b;
52 	}
53 }
54 
55 static void copy_gp11_param(struct utee_params *up, uint32_t param_types,
56 			    const __GP11_TEE_Param params[TEE_NUM_PARAMS])
57 {
58 	size_t n = 0;
59 	uint64_t a = 0;
60 	uint64_t b = 0;
61 
62 	up->types = param_types;
63 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
64 		switch (TEE_PARAM_TYPE_GET(up->types, n)) {
65 		case TEE_PARAM_TYPE_VALUE_INPUT:
66 		case TEE_PARAM_TYPE_VALUE_INOUT:
67 			a = params[n].value.a;
68 			b = params[n].value.b;
69 			break;
70 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
71 		case TEE_PARAM_TYPE_MEMREF_INOUT:
72 		case TEE_PARAM_TYPE_MEMREF_INPUT:
73 			a = (vaddr_t)params[n].memref.buffer;
74 			b = params[n].memref.size;
75 			break;
76 		default:
77 			a = 0;
78 			b = 0;
79 		}
80 		up->vals[n * 2] = a;
81 		up->vals[n * 2 + 1] = b;
82 	}
83 }
84 
85 static TEE_Result map_tmp_param(struct utee_params *up, void **tmp_buf,
86 				size_t *tmp_len, void *tmp_va[TEE_NUM_PARAMS])
87 {
88 	size_t n = 0;
89 	uint8_t *tb = NULL;
90 	size_t tbl = 0;
91 	size_t tmp_align = sizeof(vaddr_t) * 2;
92 	bool is_tmp_mem[TEE_NUM_PARAMS] = { false };
93 	void *b = NULL;
94 	size_t s = 0;
95 	const uint32_t flags = TEE_MEMORY_ACCESS_READ;
96 
97 	/*
98 	 * If a memory parameter points to TA private memory we need to
99 	 * allocate a temporary buffer to avoid exposing the memory
100 	 * directly to the called TA.
101 	 */
102 
103 	*tmp_buf = NULL;
104 	*tmp_len = 0;
105 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
106 		tmp_va[n] = NULL;
107 		switch (TEE_PARAM_TYPE_GET(up->types, n)) {
108 		case TEE_PARAM_TYPE_MEMREF_INPUT:
109 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
110 		case TEE_PARAM_TYPE_MEMREF_INOUT:
111 			b = (void *)(vaddr_t)up->vals[n * 2];
112 			s = up->vals[n * 2 + 1];
113 			/*
114 			 * We're only allocating temporary memory if the
115 			 * buffer is completely within TA memory. If it's
116 			 * NULL, empty, partially outside or completely
117 			 * outside TA memory there's nothing more we need
118 			 * to do here. If there's security/permissions
119 			 * problem we'll get an error in the
120 			 * invoke_command/open_session below.
121 			 */
122 			if (b && s &&
123 			    !TEE_CheckMemoryAccessRights(flags, b, s)) {
124 				is_tmp_mem[n] = true;
125 				tbl += ROUNDUP(s, tmp_align);
126 			}
127 			break;
128 		default:
129 			break;
130 		}
131 	}
132 
133 	if (tbl) {
134 		tb = tee_map_zi(tbl, TEE_MEMORY_ACCESS_ANY_OWNER);
135 		if (!tb)
136 			return TEE_ERROR_OUT_OF_MEMORY;
137 		*tmp_buf = tb;
138 		*tmp_len = tbl;
139 	}
140 
141 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
142 		switch (TEE_PARAM_TYPE_GET(up->types, n)) {
143 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
144 		case TEE_PARAM_TYPE_MEMREF_INOUT:
145 		case TEE_PARAM_TYPE_MEMREF_INPUT:
146 			if (!is_tmp_mem[n])
147 				break;
148 			s = up->vals[n * 2 + 1];
149 			b = (void *)(vaddr_t)up->vals[n * 2];
150 			tmp_va[n] = tb;
151 			tb += ROUNDUP(s, tmp_align);
152 			up->vals[n * 2] = (vaddr_t)tmp_va[n];
153 			if (TEE_PARAM_TYPE_GET(up->types, n) !=
154 			    TEE_PARAM_TYPE_MEMREF_OUTPUT)
155 				memcpy(tmp_va[n], b, s);
156 			break;
157 		default:
158 			break;
159 		}
160 	}
161 
162 	return TEE_SUCCESS;
163 
164 }
165 
166 static void update_out_param(TEE_Param params[TEE_NUM_PARAMS],
167 			     void *tmp_va[TEE_NUM_PARAMS],
168 			     const struct utee_params *up)
169 {
170 	size_t n;
171 	uint32_t types = up->types;
172 
173 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
174 		uintptr_t a = up->vals[n * 2];
175 		uintptr_t b = up->vals[n * 2 + 1];
176 
177 		switch (TEE_PARAM_TYPE_GET(types, n)) {
178 		case TEE_PARAM_TYPE_VALUE_OUTPUT:
179 		case TEE_PARAM_TYPE_VALUE_INOUT:
180 			params[n].value.a = a;
181 			params[n].value.b = b;
182 			break;
183 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
184 		case TEE_PARAM_TYPE_MEMREF_INOUT:
185 			if (tmp_va[n])
186 				memcpy(params[n].memref.buffer, tmp_va[n],
187 				       MIN(b, params[n].memref.size));
188 			params[n].memref.size = b;
189 			break;
190 		default:
191 			break;
192 		}
193 	}
194 }
195 
196 static void update_out_gp11_param(__GP11_TEE_Param params[TEE_NUM_PARAMS],
197 				  void *tmp_va[TEE_NUM_PARAMS],
198 				  const struct utee_params *up)
199 {
200 	size_t n = 0;
201 	uint32_t types = up->types;
202 
203 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
204 		uintptr_t a = up->vals[n * 2];
205 		uintptr_t b = up->vals[n * 2 + 1];
206 
207 		switch (TEE_PARAM_TYPE_GET(types, n)) {
208 		case TEE_PARAM_TYPE_VALUE_OUTPUT:
209 		case TEE_PARAM_TYPE_VALUE_INOUT:
210 			params[n].value.a = a;
211 			params[n].value.b = b;
212 			break;
213 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
214 		case TEE_PARAM_TYPE_MEMREF_INOUT:
215 			if (tmp_va[n])
216 				memcpy(params[n].memref.buffer, tmp_va[n],
217 				       MIN(b, params[n].memref.size));
218 			params[n].memref.size = b;
219 			break;
220 		default:
221 			break;
222 		}
223 	}
224 }
225 
226 TEE_Result TEE_OpenTASession(const TEE_UUID *destination,
227 				uint32_t cancellationRequestTimeout,
228 				uint32_t paramTypes,
229 				TEE_Param params[TEE_NUM_PARAMS],
230 				TEE_TASessionHandle *session,
231 				uint32_t *returnOrigin)
232 {
233 	TEE_Result res = TEE_SUCCESS;
234 	struct utee_params up = { };
235 	uint32_t s = 0;
236 	void *tmp_buf = NULL;
237 	size_t tmp_len = 0;
238 	void *tmp_va[TEE_NUM_PARAMS] = { NULL };
239 
240 	if (paramTypes)
241 		__utee_check_inout_annotation(params,
242 					      sizeof(TEE_Param) *
243 					      TEE_NUM_PARAMS);
244 	__utee_check_out_annotation(session, sizeof(*session));
245 
246 	copy_param(&up, paramTypes, params);
247 	res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va);
248 	if (res)
249 		goto out;
250 	res = _utee_open_ta_session(destination, cancellationRequestTimeout,
251 				    &up, &s, returnOrigin);
252 	update_out_param(params, tmp_va, &up);
253 	if (tmp_buf) {
254 		TEE_Result res2 = tee_unmap(tmp_buf, tmp_len);
255 
256 		if (res2)
257 			TEE_Panic(res2);
258 	}
259 
260 out:
261 	/*
262 	 * Specification says that *session must hold TEE_HANDLE_NULL is
263 	 * TEE_SUCCESS isn't returned. Set it here explicitly in case
264 	 * the syscall fails before out parameters has been updated.
265 	 */
266 	if (res != TEE_SUCCESS)
267 		s = TEE_HANDLE_NULL;
268 
269 	*session = (TEE_TASessionHandle)(uintptr_t)s;
270 	return res;
271 }
272 
273 TEE_Result __GP11_TEE_OpenTASession(const TEE_UUID *destination,
274 				    uint32_t cancellationRequestTimeout,
275 				    uint32_t paramTypes,
276 				    __GP11_TEE_Param params[TEE_NUM_PARAMS],
277 				    TEE_TASessionHandle *session,
278 				    uint32_t *returnOrigin)
279 {
280 	TEE_Result res = TEE_SUCCESS;
281 	struct utee_params up = { };
282 	uint32_t s = 0;
283 	void *tmp_buf = NULL;
284 	size_t tmp_len = 0;
285 	void *tmp_va[TEE_NUM_PARAMS] = { NULL };
286 
287 	if (paramTypes)
288 		__utee_check_inout_annotation(params,
289 					      sizeof(__GP11_TEE_Param) *
290 					      TEE_NUM_PARAMS);
291 	__utee_check_out_annotation(session, sizeof(*session));
292 
293 	copy_gp11_param(&up, paramTypes, params);
294 	res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va);
295 	if (res)
296 		goto out;
297 	res = _utee_open_ta_session(destination, cancellationRequestTimeout,
298 				    &up, &s, returnOrigin);
299 	update_out_gp11_param(params, tmp_va, &up);
300 	if (tmp_buf) {
301 		TEE_Result res2 = tee_unmap(tmp_buf, tmp_len);
302 
303 		if (res2)
304 			TEE_Panic(res2);
305 	}
306 
307 out:
308 	/*
309 	 * Specification says that *session must hold TEE_HANDLE_NULL if
310 	 * TEE_SUCCESS isn't returned. Set it here explicitly in case
311 	 * the syscall fails before out parameters has been updated.
312 	 */
313 	if (res != TEE_SUCCESS)
314 		s = TEE_HANDLE_NULL;
315 
316 	*session = (TEE_TASessionHandle)(uintptr_t)s;
317 	return res;
318 }
319 
320 void TEE_CloseTASession(TEE_TASessionHandle session)
321 {
322 	if (session != TEE_HANDLE_NULL) {
323 		TEE_Result res = _utee_close_ta_session((uintptr_t)session);
324 
325 		if (res != TEE_SUCCESS)
326 			TEE_Panic(res);
327 	}
328 }
329 
330 TEE_Result TEE_InvokeTACommand(TEE_TASessionHandle session,
331 				uint32_t cancellationRequestTimeout,
332 				uint32_t commandID, uint32_t paramTypes,
333 				TEE_Param params[TEE_NUM_PARAMS],
334 				uint32_t *returnOrigin)
335 {
336 	TEE_Result res = TEE_SUCCESS;
337 	uint32_t ret_origin = TEE_ORIGIN_TEE;
338 	struct utee_params up = { };
339 	void *tmp_buf = NULL;
340 	size_t tmp_len = 0;
341 	void *tmp_va[TEE_NUM_PARAMS] = { NULL };
342 
343 	if (paramTypes)
344 		__utee_check_inout_annotation(params,
345 					      sizeof(TEE_Param) *
346 					      TEE_NUM_PARAMS);
347 	if (returnOrigin)
348 		__utee_check_out_annotation(returnOrigin,
349 					    sizeof(*returnOrigin));
350 
351 	copy_param(&up, paramTypes, params);
352 	res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va);
353 	if (res)
354 		goto out;
355 	res = _utee_invoke_ta_command((uintptr_t)session,
356 				      cancellationRequestTimeout,
357 				      commandID, &up, &ret_origin);
358 	update_out_param(params, tmp_va, &up);
359 	if (tmp_buf) {
360 		TEE_Result res2 = tee_unmap(tmp_buf, tmp_len);
361 
362 		if (res2)
363 			TEE_Panic(res2);
364 	}
365 
366 out:
367 	if (returnOrigin != NULL)
368 		*returnOrigin = ret_origin;
369 
370 	if (ret_origin == TEE_ORIGIN_TRUSTED_APP)
371 		return res;
372 
373 	if (res != TEE_SUCCESS &&
374 	    res != TEE_ERROR_OUT_OF_MEMORY &&
375 	    res != TEE_ERROR_TARGET_DEAD)
376 		TEE_Panic(res);
377 
378 	return res;
379 }
380 
381 TEE_Result __GP11_TEE_InvokeTACommand(TEE_TASessionHandle session,
382 				      uint32_t cancellationRequestTimeout,
383 				      uint32_t commandID, uint32_t paramTypes,
384 				      __GP11_TEE_Param params[TEE_NUM_PARAMS],
385 				      uint32_t *returnOrigin)
386 {
387 	TEE_Result res = TEE_SUCCESS;
388 	uint32_t ret_origin = TEE_ORIGIN_TEE;
389 	struct utee_params up = { };
390 	void *tmp_buf = NULL;
391 	size_t tmp_len = 0;
392 	void *tmp_va[TEE_NUM_PARAMS] = { NULL };
393 
394 	if (paramTypes)
395 		__utee_check_inout_annotation(params,
396 					      sizeof(__GP11_TEE_Param) *
397 					      TEE_NUM_PARAMS);
398 	if (returnOrigin)
399 		__utee_check_out_annotation(returnOrigin,
400 					    sizeof(*returnOrigin));
401 
402 	copy_gp11_param(&up, paramTypes, params);
403 	res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va);
404 	if (res)
405 		goto out;
406 	res = _utee_invoke_ta_command((uintptr_t)session,
407 				      cancellationRequestTimeout,
408 				      commandID, &up, &ret_origin);
409 	update_out_gp11_param(params, tmp_va, &up);
410 	if (tmp_buf) {
411 		TEE_Result res2 = tee_unmap(tmp_buf, tmp_len);
412 
413 		if (res2)
414 			TEE_Panic(res2);
415 	}
416 
417 out:
418 	if (returnOrigin)
419 		*returnOrigin = ret_origin;
420 
421 	if (ret_origin == TEE_ORIGIN_TRUSTED_APP)
422 		return res;
423 
424 	if (res != TEE_SUCCESS &&
425 	    res != TEE_ERROR_OUT_OF_MEMORY &&
426 	    res != TEE_ERROR_TARGET_DEAD)
427 		TEE_Panic(res);
428 
429 	return res;
430 }
431 
432 /* System API - Cancellations */
433 
434 bool TEE_GetCancellationFlag(void)
435 {
436 	uint32_t c;
437 	TEE_Result res = _utee_get_cancellation_flag(&c);
438 
439 	if (res != TEE_SUCCESS)
440 		c = 0;
441 	return !!c;
442 }
443 
444 bool TEE_UnmaskCancellation(void)
445 {
446 	uint32_t old_mask;
447 	TEE_Result res = _utee_unmask_cancellation(&old_mask);
448 
449 	if (res != TEE_SUCCESS)
450 		TEE_Panic(res);
451 	return !!old_mask;
452 }
453 
454 bool TEE_MaskCancellation(void)
455 {
456 	uint32_t old_mask;
457 	TEE_Result res = _utee_mask_cancellation(&old_mask);
458 
459 	if (res != TEE_SUCCESS)
460 		TEE_Panic(res);
461 	return !!old_mask;
462 }
463 
464 /* System API - Memory Management */
465 
466 TEE_Result TEE_CheckMemoryAccessRights(uint32_t accessFlags, void *buffer,
467 				       uint32_t size)
468 {
469 	TEE_Result res;
470 
471 	if (size == 0)
472 		return TEE_SUCCESS;
473 
474 	/* Check access rights against memory mapping */
475 	res = _utee_check_access_rights(accessFlags, buffer, size);
476 	if (res != TEE_SUCCESS)
477 		goto out;
478 
479 	/*
480 	* Check access rights against input parameters
481 	* Previous legacy code was removed and will need to be restored
482 	*/
483 
484 	res = TEE_SUCCESS;
485 out:
486 	return res;
487 }
488 
489 void TEE_SetInstanceData(const void *instanceData)
490 {
491 	tee_api_instance_data = instanceData;
492 }
493 
494 const void *TEE_GetInstanceData(void)
495 {
496 	return tee_api_instance_data;
497 }
498 
499 void *TEE_MemMove(void *dest, const void *src, uint32_t size)
500 {
501 	return memmove(dest, src, size);
502 }
503 
504 int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, uint32_t size)
505 {
506 	return consttime_memcmp(buffer1, buffer2, size);
507 }
508 
509 void TEE_MemFill(void *buff, uint32_t x, uint32_t size)
510 {
511 	memset(buff, x, size);
512 }
513 
514 /* Date & Time API */
515 
516 void TEE_GetSystemTime(TEE_Time *time)
517 {
518 	TEE_Result res = _utee_get_time(UTEE_TIME_CAT_SYSTEM, time);
519 
520 	if (res != TEE_SUCCESS)
521 		TEE_Panic(res);
522 }
523 
524 TEE_Result TEE_Wait(uint32_t timeout)
525 {
526 	TEE_Result res = _utee_wait(timeout);
527 
528 	if (res != TEE_SUCCESS && res != TEE_ERROR_CANCEL)
529 		TEE_Panic(res);
530 
531 	return res;
532 }
533 
534 TEE_Result TEE_GetTAPersistentTime(TEE_Time *time)
535 {
536 	TEE_Result res;
537 
538 	res = _utee_get_time(UTEE_TIME_CAT_TA_PERSISTENT, time);
539 
540 	if (res != TEE_SUCCESS && res != TEE_ERROR_OVERFLOW) {
541 		time->seconds = 0;
542 		time->millis = 0;
543 	}
544 
545 	if (res != TEE_SUCCESS &&
546 	    res != TEE_ERROR_TIME_NOT_SET &&
547 	    res != TEE_ERROR_TIME_NEEDS_RESET &&
548 	    res != TEE_ERROR_OVERFLOW &&
549 	    res != TEE_ERROR_OUT_OF_MEMORY)
550 		TEE_Panic(res);
551 
552 	return res;
553 }
554 
555 TEE_Result TEE_SetTAPersistentTime(const TEE_Time *time)
556 {
557 	TEE_Result res;
558 
559 	res = _utee_set_ta_time(time);
560 
561 	if (res != TEE_SUCCESS &&
562 	    res != TEE_ERROR_OUT_OF_MEMORY &&
563 	    res != TEE_ERROR_STORAGE_NO_SPACE)
564 		TEE_Panic(res);
565 
566 	return res;
567 }
568 
569 void TEE_GetREETime(TEE_Time *time)
570 {
571 	TEE_Result res = _utee_get_time(UTEE_TIME_CAT_REE, time);
572 
573 	if (res != TEE_SUCCESS)
574 		TEE_Panic(res);
575 }
576 
577 void *TEE_Malloc(uint32_t len, uint32_t hint)
578 {
579 	if (!len)
580 		return TEE_NULL_SIZED_VA;
581 
582 	if (hint == TEE_MALLOC_FILL_ZERO)
583 		return calloc(1, len);
584 	else if (hint == TEE_USER_MEM_HINT_NO_FILL_ZERO)
585 		return malloc(len);
586 
587 	EMSG("Invalid hint %#" PRIx32, hint);
588 
589 	return NULL;
590 }
591 
592 void *TEE_Realloc(void *buffer, uint32_t newSize)
593 {
594 	if (!newSize) {
595 		TEE_Free(buffer);
596 		return TEE_NULL_SIZED_VA;
597 	}
598 
599 	if (buffer == TEE_NULL_SIZED_VA)
600 		return calloc(1, newSize);
601 
602 	return realloc(buffer, newSize);
603 }
604 
605 void TEE_Free(void *buffer)
606 {
607 	if (buffer != TEE_NULL_SIZED_VA)
608 		free(buffer);
609 }
610 
611 /* Cache maintenance support (TA requires the CACHE_MAINTENANCE property) */
612 TEE_Result TEE_CacheClean(char *buf, size_t len)
613 {
614 	return _utee_cache_operation(buf, len, TEE_CACHECLEAN);
615 }
616 TEE_Result TEE_CacheFlush(char *buf, size_t len)
617 {
618 	return _utee_cache_operation(buf, len, TEE_CACHEFLUSH);
619 }
620 
621 TEE_Result TEE_CacheInvalidate(char *buf, size_t len)
622 {
623 	return _utee_cache_operation(buf, len, TEE_CACHEINVALIDATE);
624 }
625