xref: /optee_os/lib/libutee/tee_api.c (revision 93b037ac2dee6e31ada8256ad21ecc3348c5edaa)
11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2b0104773SPascal Brand /*
3b0104773SPascal Brand  * Copyright (c) 2014, STMicroelectronics International N.V.
4b0104773SPascal Brand  */
5b0104773SPascal Brand #include <stdlib.h>
6b0104773SPascal Brand #include <string.h>
765551e69SJerome Forissier #include <string_ext.h>
8b0104773SPascal Brand #include <tee_api.h>
996c1d8c5SJens Wiklander #include <tee_internal_api_extensions.h>
10ef305e54SJens Wiklander #include <types_ext.h>
11b0104773SPascal Brand #include <user_ta_header.h>
1296c1d8c5SJens Wiklander #include <utee_syscalls.h>
13e86f1266SJens Wiklander #include "tee_api_private.h"
14b0104773SPascal Brand 
15a83ee50aSSadiq Hussain /*
16a83ee50aSSadiq Hussain  * return a known non-NULL invalid pointer when the
17a83ee50aSSadiq Hussain  * requested size is zero
18a83ee50aSSadiq Hussain  */
19a83ee50aSSadiq Hussain #define TEE_NULL_SIZED_VA		((void *)1)
20e64b7b2eSJens Wiklander #define TEE_NULL_SIZED_NO_SHARE_VA	((void *)2)
21e64b7b2eSJens Wiklander 
22e64b7b2eSJens Wiklander /*
23e64b7b2eSJens Wiklander  * Workaround build error in Teaclave TrustZone SDK
24e64b7b2eSJens Wiklander  *
25e64b7b2eSJens Wiklander  * These are supposed to be provided by ta/arch/arm/user_ta_header.c, but
26e64b7b2eSJens Wiklander  * Teaclave TrustZone SDK seems to roll their own in Rust.
27e64b7b2eSJens Wiklander  */
28e64b7b2eSJens Wiklander uint8_t __ta_no_share_heap[0] __weak;
29e64b7b2eSJens Wiklander const size_t __ta_no_share_heap_size __weak;
30e64b7b2eSJens Wiklander struct malloc_ctx *__ta_no_share_malloc_ctx __weak;
31a83ee50aSSadiq Hussain 
328f07fe6fSJerome Forissier static const void *tee_api_instance_data;
33b0104773SPascal Brand 
34b0104773SPascal Brand /* System API - Internal Client API */
35b0104773SPascal Brand 
copy_param(struct utee_params * up,uint32_t param_types,const TEE_Param params[TEE_NUM_PARAMS])367509620bSJens Wiklander static void copy_param(struct utee_params *up, uint32_t param_types,
377509620bSJens Wiklander 		       const TEE_Param params[TEE_NUM_PARAMS])
387509620bSJens Wiklander {
397509620bSJens Wiklander 	size_t n = 0;
407509620bSJens Wiklander 	uint64_t a = 0;
417509620bSJens Wiklander 	uint64_t b = 0;
427509620bSJens Wiklander 
437509620bSJens Wiklander 	up->types = param_types;
447509620bSJens Wiklander 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
457509620bSJens Wiklander 		switch (TEE_PARAM_TYPE_GET(up->types, n)) {
467509620bSJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INPUT:
477509620bSJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INOUT:
487509620bSJens Wiklander 			a = params[n].value.a;
497509620bSJens Wiklander 			b = params[n].value.b;
507509620bSJens Wiklander 			break;
517509620bSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
527509620bSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
537509620bSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INPUT:
547509620bSJens Wiklander 			a = (vaddr_t)params[n].memref.buffer;
557509620bSJens Wiklander 			b = params[n].memref.size;
567509620bSJens Wiklander 			break;
577509620bSJens Wiklander 		default:
587509620bSJens Wiklander 			a = 0;
597509620bSJens Wiklander 			b = 0;
607509620bSJens Wiklander 		}
617509620bSJens Wiklander 		up->vals[n * 2] = a;
627509620bSJens Wiklander 		up->vals[n * 2 + 1] = b;
637509620bSJens Wiklander 	}
647509620bSJens Wiklander }
657509620bSJens Wiklander 
copy_gp11_param(struct utee_params * up,uint32_t param_types,const __GP11_TEE_Param params[TEE_NUM_PARAMS])667509620bSJens Wiklander static void copy_gp11_param(struct utee_params *up, uint32_t param_types,
677509620bSJens Wiklander 			    const __GP11_TEE_Param params[TEE_NUM_PARAMS])
687509620bSJens Wiklander {
697509620bSJens Wiklander 	size_t n = 0;
707509620bSJens Wiklander 	uint64_t a = 0;
717509620bSJens Wiklander 	uint64_t b = 0;
727509620bSJens Wiklander 
737509620bSJens Wiklander 	up->types = param_types;
747509620bSJens Wiklander 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
757509620bSJens Wiklander 		switch (TEE_PARAM_TYPE_GET(up->types, n)) {
767509620bSJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INPUT:
777509620bSJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INOUT:
787509620bSJens Wiklander 			a = params[n].value.a;
797509620bSJens Wiklander 			b = params[n].value.b;
807509620bSJens Wiklander 			break;
817509620bSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
827509620bSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
837509620bSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INPUT:
847509620bSJens Wiklander 			a = (vaddr_t)params[n].memref.buffer;
857509620bSJens Wiklander 			b = params[n].memref.size;
867509620bSJens Wiklander 			break;
877509620bSJens Wiklander 		default:
887509620bSJens Wiklander 			a = 0;
897509620bSJens Wiklander 			b = 0;
907509620bSJens Wiklander 		}
917509620bSJens Wiklander 		up->vals[n * 2] = a;
927509620bSJens Wiklander 		up->vals[n * 2 + 1] = b;
937509620bSJens Wiklander 	}
947509620bSJens Wiklander }
957509620bSJens Wiklander 
map_tmp_param(struct utee_params * up,void ** tmp_buf,size_t * tmp_len,void * tmp_va[TEE_NUM_PARAMS])967509620bSJens Wiklander static TEE_Result map_tmp_param(struct utee_params *up, void **tmp_buf,
977509620bSJens Wiklander 				size_t *tmp_len, void *tmp_va[TEE_NUM_PARAMS])
98e86f1266SJens Wiklander {
99ef305e54SJens Wiklander 	size_t n = 0;
100ef305e54SJens Wiklander 	uint8_t *tb = NULL;
101ef305e54SJens Wiklander 	size_t tbl = 0;
102ef305e54SJens Wiklander 	size_t tmp_align = sizeof(vaddr_t) * 2;
103ef305e54SJens Wiklander 	bool is_tmp_mem[TEE_NUM_PARAMS] = { false };
104ef305e54SJens Wiklander 	void *b = NULL;
105ef305e54SJens Wiklander 	size_t s = 0;
106ef305e54SJens Wiklander 	const uint32_t flags = TEE_MEMORY_ACCESS_READ;
107ef305e54SJens Wiklander 
108ef305e54SJens Wiklander 	/*
109ef305e54SJens Wiklander 	 * If a memory parameter points to TA private memory we need to
110ef305e54SJens Wiklander 	 * allocate a temporary buffer to avoid exposing the memory
111ef305e54SJens Wiklander 	 * directly to the called TA.
112ef305e54SJens Wiklander 	 */
113ef305e54SJens Wiklander 
114ef305e54SJens Wiklander 	*tmp_buf = NULL;
115ef305e54SJens Wiklander 	*tmp_len = 0;
116ef305e54SJens Wiklander 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
117ef305e54SJens Wiklander 		tmp_va[n] = NULL;
1187509620bSJens Wiklander 		switch (TEE_PARAM_TYPE_GET(up->types, n)) {
119ef305e54SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INPUT:
120ef305e54SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
121ef305e54SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
1227509620bSJens Wiklander 			b = (void *)(vaddr_t)up->vals[n * 2];
1237509620bSJens Wiklander 			s = up->vals[n * 2 + 1];
124ef305e54SJens Wiklander 			/*
125ef305e54SJens Wiklander 			 * We're only allocating temporary memory if the
126ef305e54SJens Wiklander 			 * buffer is completely within TA memory. If it's
127ef305e54SJens Wiklander 			 * NULL, empty, partially outside or completely
128ef305e54SJens Wiklander 			 * outside TA memory there's nothing more we need
129ef305e54SJens Wiklander 			 * to do here. If there's security/permissions
130ef305e54SJens Wiklander 			 * problem we'll get an error in the
131ef305e54SJens Wiklander 			 * invoke_command/open_session below.
132ef305e54SJens Wiklander 			 */
133ef305e54SJens Wiklander 			if (b && s &&
134ef305e54SJens Wiklander 			    !TEE_CheckMemoryAccessRights(flags, b, s)) {
135ef305e54SJens Wiklander 				is_tmp_mem[n] = true;
13676d6685eSEtienne Carriere 				tbl += ROUNDUP2(s, tmp_align);
137ef305e54SJens Wiklander 			}
138ef305e54SJens Wiklander 			break;
139ef305e54SJens Wiklander 		default:
140ef305e54SJens Wiklander 			break;
141ef305e54SJens Wiklander 		}
142ef305e54SJens Wiklander 	}
143ef305e54SJens Wiklander 
144ef305e54SJens Wiklander 	if (tbl) {
145ef305e54SJens Wiklander 		tb = tee_map_zi(tbl, TEE_MEMORY_ACCESS_ANY_OWNER);
146ef305e54SJens Wiklander 		if (!tb)
147ef305e54SJens Wiklander 			return TEE_ERROR_OUT_OF_MEMORY;
148ef305e54SJens Wiklander 		*tmp_buf = tb;
149ef305e54SJens Wiklander 		*tmp_len = tbl;
150ef305e54SJens Wiklander 	}
151e86f1266SJens Wiklander 
152e86f1266SJens Wiklander 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
1537509620bSJens Wiklander 		switch (TEE_PARAM_TYPE_GET(up->types, n)) {
154e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
155e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
156ef305e54SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INPUT:
1577509620bSJens Wiklander 			if (!is_tmp_mem[n])
1587509620bSJens Wiklander 				break;
1597509620bSJens Wiklander 			s = up->vals[n * 2 + 1];
1607509620bSJens Wiklander 			b = (void *)(vaddr_t)up->vals[n * 2];
161ef305e54SJens Wiklander 			tmp_va[n] = tb;
16276d6685eSEtienne Carriere 			tb += ROUNDUP2(s, tmp_align);
1637509620bSJens Wiklander 			up->vals[n * 2] = (vaddr_t)tmp_va[n];
1647509620bSJens Wiklander 			if (TEE_PARAM_TYPE_GET(up->types, n) !=
165ef305e54SJens Wiklander 			    TEE_PARAM_TYPE_MEMREF_OUTPUT)
1667509620bSJens Wiklander 				memcpy(tmp_va[n], b, s);
167e86f1266SJens Wiklander 			break;
168e86f1266SJens Wiklander 		default:
169e86f1266SJens Wiklander 			break;
170e86f1266SJens Wiklander 		}
171e86f1266SJens Wiklander 	}
172ef305e54SJens Wiklander 
173ef305e54SJens Wiklander 	return TEE_SUCCESS;
1747509620bSJens Wiklander 
175e86f1266SJens Wiklander }
176e86f1266SJens Wiklander 
update_out_param(TEE_Param params[TEE_NUM_PARAMS],void * tmp_va[TEE_NUM_PARAMS],const struct utee_params * up)177ef305e54SJens Wiklander static void update_out_param(TEE_Param params[TEE_NUM_PARAMS],
178ef305e54SJens Wiklander 			     void *tmp_va[TEE_NUM_PARAMS],
179ef305e54SJens Wiklander 			     const struct utee_params *up)
180e86f1266SJens Wiklander {
181e86f1266SJens Wiklander 	size_t n;
182e86f1266SJens Wiklander 	uint32_t types = up->types;
183e86f1266SJens Wiklander 
184e86f1266SJens Wiklander 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
185e86f1266SJens Wiklander 		uintptr_t a = up->vals[n * 2];
186e86f1266SJens Wiklander 		uintptr_t b = up->vals[n * 2 + 1];
187e86f1266SJens Wiklander 
188e86f1266SJens Wiklander 		switch (TEE_PARAM_TYPE_GET(types, n)) {
189e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_VALUE_OUTPUT:
190e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INOUT:
191e86f1266SJens Wiklander 			params[n].value.a = a;
192e86f1266SJens Wiklander 			params[n].value.b = b;
193e86f1266SJens Wiklander 			break;
194e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
195e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
196ef305e54SJens Wiklander 			if (tmp_va[n])
197ef305e54SJens Wiklander 				memcpy(params[n].memref.buffer, tmp_va[n],
198ef305e54SJens Wiklander 				       MIN(b, params[n].memref.size));
199e86f1266SJens Wiklander 			params[n].memref.size = b;
200e86f1266SJens Wiklander 			break;
201e86f1266SJens Wiklander 		default:
202e86f1266SJens Wiklander 			break;
203e86f1266SJens Wiklander 		}
204e86f1266SJens Wiklander 	}
205e86f1266SJens Wiklander }
206e86f1266SJens Wiklander 
update_out_gp11_param(__GP11_TEE_Param params[TEE_NUM_PARAMS],void * tmp_va[TEE_NUM_PARAMS],const struct utee_params * up)2077509620bSJens Wiklander static void update_out_gp11_param(__GP11_TEE_Param params[TEE_NUM_PARAMS],
2087509620bSJens Wiklander 				  void *tmp_va[TEE_NUM_PARAMS],
2097509620bSJens Wiklander 				  const struct utee_params *up)
2107509620bSJens Wiklander {
2117509620bSJens Wiklander 	size_t n = 0;
2127509620bSJens Wiklander 	uint32_t types = up->types;
2137509620bSJens Wiklander 
2147509620bSJens Wiklander 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
2157509620bSJens Wiklander 		uintptr_t a = up->vals[n * 2];
2167509620bSJens Wiklander 		uintptr_t b = up->vals[n * 2 + 1];
2177509620bSJens Wiklander 
2187509620bSJens Wiklander 		switch (TEE_PARAM_TYPE_GET(types, n)) {
2197509620bSJens Wiklander 		case TEE_PARAM_TYPE_VALUE_OUTPUT:
2207509620bSJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INOUT:
2217509620bSJens Wiklander 			params[n].value.a = a;
2227509620bSJens Wiklander 			params[n].value.b = b;
2237509620bSJens Wiklander 			break;
2247509620bSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
2257509620bSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
2267509620bSJens Wiklander 			if (tmp_va[n])
2277509620bSJens Wiklander 				memcpy(params[n].memref.buffer, tmp_va[n],
2287509620bSJens Wiklander 				       MIN(b, params[n].memref.size));
2297509620bSJens Wiklander 			params[n].memref.size = b;
2307509620bSJens Wiklander 			break;
2317509620bSJens Wiklander 		default:
2327509620bSJens Wiklander 			break;
2337509620bSJens Wiklander 		}
2347509620bSJens Wiklander 	}
2357509620bSJens Wiklander }
2367509620bSJens Wiklander 
bufs_intersect(void * buf1,size_t sz1,void * buf2,size_t sz2)237c8bf6a25SJens Wiklander static bool bufs_intersect(void *buf1, size_t sz1, void *buf2, size_t sz2)
238c8bf6a25SJens Wiklander {
239c8bf6a25SJens Wiklander 	vaddr_t b1 = (vaddr_t)buf1;
240c8bf6a25SJens Wiklander 	vaddr_t b2 = (vaddr_t)buf2;
241c8bf6a25SJens Wiklander 	vaddr_t e1 = b1 + sz1 - 1;
242c8bf6a25SJens Wiklander 	vaddr_t e2 = b2 + sz2 - 1;
243c8bf6a25SJens Wiklander 
244c8bf6a25SJens Wiklander 	if (!sz1 || !sz2)
245c8bf6a25SJens Wiklander 		return false;
246c8bf6a25SJens Wiklander 
247c8bf6a25SJens Wiklander 	if (e1 < b2 || e2 < b1)
248c8bf6a25SJens Wiklander 		return false;
249c8bf6a25SJens Wiklander 
250c8bf6a25SJens Wiklander 	return true;
251c8bf6a25SJens Wiklander }
252c8bf6a25SJens Wiklander 
check_mem_access_rights_params(uint32_t flags,void * buf,size_t len)253c8bf6a25SJens Wiklander static TEE_Result check_mem_access_rights_params(uint32_t flags, void *buf,
254c8bf6a25SJens Wiklander 						 size_t len)
255c8bf6a25SJens Wiklander {
256c8bf6a25SJens Wiklander 	size_t n = 0;
257c8bf6a25SJens Wiklander 
258c8bf6a25SJens Wiklander 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
259c8bf6a25SJens Wiklander 		uint32_t f = TEE_MEMORY_ACCESS_ANY_OWNER;
260c8bf6a25SJens Wiklander 
261c8bf6a25SJens Wiklander 		switch (TEE_PARAM_TYPE_GET(ta_param_types, n)) {
262c8bf6a25SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
263c8bf6a25SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
264c8bf6a25SJens Wiklander 			f |= TEE_MEMORY_ACCESS_WRITE;
265c8bf6a25SJens Wiklander 			fallthrough;
266c8bf6a25SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INPUT:
267c8bf6a25SJens Wiklander 			f |= TEE_MEMORY_ACCESS_READ;
268c8bf6a25SJens Wiklander 			if (bufs_intersect(buf, len,
269c8bf6a25SJens Wiklander 					   ta_params[n].memref.buffer,
270c8bf6a25SJens Wiklander 					   ta_params[n].memref.size)) {
271c8bf6a25SJens Wiklander 				if ((flags & f) != flags)
272c8bf6a25SJens Wiklander 					return TEE_ERROR_ACCESS_DENIED;
273c8bf6a25SJens Wiklander 			}
274c8bf6a25SJens Wiklander 			break;
275c8bf6a25SJens Wiklander 		default:
276c8bf6a25SJens Wiklander 			break;
277c8bf6a25SJens Wiklander 		}
278c8bf6a25SJens Wiklander 	}
279c8bf6a25SJens Wiklander 
280c8bf6a25SJens Wiklander 	return TEE_SUCCESS;
281c8bf6a25SJens Wiklander }
282c8bf6a25SJens Wiklander 
buf_overlaps_no_share_heap(void * buf,size_t size)283e64b7b2eSJens Wiklander static bool buf_overlaps_no_share_heap(void *buf, size_t size)
284e64b7b2eSJens Wiklander {
285e64b7b2eSJens Wiklander 	struct malloc_ctx *ctx = __ta_no_share_malloc_ctx;
286e64b7b2eSJens Wiklander 
287e64b7b2eSJens Wiklander 	return ctx && raw_malloc_buffer_overlaps_heap(ctx, buf, size);
288e64b7b2eSJens Wiklander }
289e64b7b2eSJens Wiklander 
check_invoke_param(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])29030e5e0beSJens Wiklander static void check_invoke_param(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS])
29130e5e0beSJens Wiklander {
29230e5e0beSJens Wiklander 	size_t n = 0;
29330e5e0beSJens Wiklander 
29430e5e0beSJens Wiklander 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
29530e5e0beSJens Wiklander 		uint32_t f = TEE_MEMORY_ACCESS_ANY_OWNER;
29630e5e0beSJens Wiklander 		void *buf = params[n].memref.buffer;
29730e5e0beSJens Wiklander 		size_t size = params[n].memref.size;
29830e5e0beSJens Wiklander 
29930e5e0beSJens Wiklander 		switch (TEE_PARAM_TYPE_GET(pt, n)) {
30030e5e0beSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
30130e5e0beSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
30230e5e0beSJens Wiklander 			f |= TEE_MEMORY_ACCESS_WRITE;
30330e5e0beSJens Wiklander 			fallthrough;
30430e5e0beSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INPUT:
30530e5e0beSJens Wiklander 			f |= TEE_MEMORY_ACCESS_READ;
30630e5e0beSJens Wiklander 			if (check_mem_access_rights_params(f, buf, size))
30730e5e0beSJens Wiklander 				TEE_Panic(0);
308e64b7b2eSJens Wiklander 			if (buf_overlaps_no_share_heap(buf, size))
309e64b7b2eSJens Wiklander 				TEE_Panic(0);
31030e5e0beSJens Wiklander 			break;
31130e5e0beSJens Wiklander 		default:
31230e5e0beSJens Wiklander 			break;
31330e5e0beSJens Wiklander 		}
31430e5e0beSJens Wiklander 	}
31530e5e0beSJens Wiklander }
31630e5e0beSJens Wiklander 
TEE_OpenTASession(const TEE_UUID * destination,uint32_t cancellationRequestTimeout,uint32_t paramTypes,TEE_Param params[TEE_NUM_PARAMS],TEE_TASessionHandle * session,uint32_t * returnOrigin)317b0104773SPascal Brand TEE_Result TEE_OpenTASession(const TEE_UUID *destination,
318b0104773SPascal Brand 				uint32_t cancellationRequestTimeout,
31968540524SIgor Opaniuk 				uint32_t paramTypes,
32068540524SIgor Opaniuk 				TEE_Param params[TEE_NUM_PARAMS],
321b0104773SPascal Brand 				TEE_TASessionHandle *session,
322b0104773SPascal Brand 				uint32_t *returnOrigin)
323b0104773SPascal Brand {
324ef305e54SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
3257509620bSJens Wiklander 	struct utee_params up = { };
326ef305e54SJens Wiklander 	uint32_t s = 0;
327ef305e54SJens Wiklander 	void *tmp_buf = NULL;
328ef305e54SJens Wiklander 	size_t tmp_len = 0;
329ef305e54SJens Wiklander 	void *tmp_va[TEE_NUM_PARAMS] = { NULL };
330b0104773SPascal Brand 
33130e5e0beSJens Wiklander 	if (paramTypes) {
3326915bbbbSJens Wiklander 		__utee_check_inout_annotation(params,
3336915bbbbSJens Wiklander 					      sizeof(TEE_Param) *
3346915bbbbSJens Wiklander 					      TEE_NUM_PARAMS);
33530e5e0beSJens Wiklander 		check_invoke_param(paramTypes, params);
33630e5e0beSJens Wiklander 	}
3376915bbbbSJens Wiklander 	__utee_check_out_annotation(session, sizeof(*session));
3386915bbbbSJens Wiklander 
3397509620bSJens Wiklander 	copy_param(&up, paramTypes, params);
3407509620bSJens Wiklander 	res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va);
341ef305e54SJens Wiklander 	if (res)
342ef305e54SJens Wiklander 		goto out;
3432c028fdeSJerome Forissier 	res = _utee_open_ta_session(destination, cancellationRequestTimeout,
344e86f1266SJens Wiklander 				    &up, &s, returnOrigin);
345ef305e54SJens Wiklander 	update_out_param(params, tmp_va, &up);
346ef305e54SJens Wiklander 	if (tmp_buf) {
347ef305e54SJens Wiklander 		TEE_Result res2 = tee_unmap(tmp_buf, tmp_len);
348ef305e54SJens Wiklander 
349ef305e54SJens Wiklander 		if (res2)
350ef305e54SJens Wiklander 			TEE_Panic(res2);
351ef305e54SJens Wiklander 	}
352ef305e54SJens Wiklander 
353ef305e54SJens Wiklander out:
354b0104773SPascal Brand 	/*
355b0104773SPascal Brand 	 * Specification says that *session must hold TEE_HANDLE_NULL is
356b0104773SPascal Brand 	 * TEE_SUCCESS isn't returned. Set it here explicitly in case
357b0104773SPascal Brand 	 * the syscall fails before out parameters has been updated.
358b0104773SPascal Brand 	 */
359b0104773SPascal Brand 	if (res != TEE_SUCCESS)
360e86f1266SJens Wiklander 		s = TEE_HANDLE_NULL;
361b0104773SPascal Brand 
362e86f1266SJens Wiklander 	*session = (TEE_TASessionHandle)(uintptr_t)s;
363b0104773SPascal Brand 	return res;
364b0104773SPascal Brand }
365b0104773SPascal Brand 
__GP11_TEE_OpenTASession(const TEE_UUID * destination,uint32_t cancellationRequestTimeout,uint32_t paramTypes,__GP11_TEE_Param params[TEE_NUM_PARAMS],TEE_TASessionHandle * session,uint32_t * returnOrigin)3667509620bSJens Wiklander TEE_Result __GP11_TEE_OpenTASession(const TEE_UUID *destination,
3677509620bSJens Wiklander 				    uint32_t cancellationRequestTimeout,
3687509620bSJens Wiklander 				    uint32_t paramTypes,
3697509620bSJens Wiklander 				    __GP11_TEE_Param params[TEE_NUM_PARAMS],
3707509620bSJens Wiklander 				    TEE_TASessionHandle *session,
3717509620bSJens Wiklander 				    uint32_t *returnOrigin)
3727509620bSJens Wiklander {
3737509620bSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
3747509620bSJens Wiklander 	struct utee_params up = { };
3757509620bSJens Wiklander 	uint32_t s = 0;
3767509620bSJens Wiklander 	void *tmp_buf = NULL;
3777509620bSJens Wiklander 	size_t tmp_len = 0;
3787509620bSJens Wiklander 	void *tmp_va[TEE_NUM_PARAMS] = { NULL };
3797509620bSJens Wiklander 
3807509620bSJens Wiklander 	if (paramTypes)
3817509620bSJens Wiklander 		__utee_check_inout_annotation(params,
3827509620bSJens Wiklander 					      sizeof(__GP11_TEE_Param) *
3837509620bSJens Wiklander 					      TEE_NUM_PARAMS);
3847509620bSJens Wiklander 	__utee_check_out_annotation(session, sizeof(*session));
3857509620bSJens Wiklander 
3867509620bSJens Wiklander 	copy_gp11_param(&up, paramTypes, params);
3877509620bSJens Wiklander 	res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va);
3887509620bSJens Wiklander 	if (res)
3897509620bSJens Wiklander 		goto out;
3907509620bSJens Wiklander 	res = _utee_open_ta_session(destination, cancellationRequestTimeout,
3917509620bSJens Wiklander 				    &up, &s, returnOrigin);
3927509620bSJens Wiklander 	update_out_gp11_param(params, tmp_va, &up);
3937509620bSJens Wiklander 	if (tmp_buf) {
3947509620bSJens Wiklander 		TEE_Result res2 = tee_unmap(tmp_buf, tmp_len);
3957509620bSJens Wiklander 
3967509620bSJens Wiklander 		if (res2)
3977509620bSJens Wiklander 			TEE_Panic(res2);
3987509620bSJens Wiklander 	}
3997509620bSJens Wiklander 
4007509620bSJens Wiklander out:
4017509620bSJens Wiklander 	/*
4027509620bSJens Wiklander 	 * Specification says that *session must hold TEE_HANDLE_NULL if
4037509620bSJens Wiklander 	 * TEE_SUCCESS isn't returned. Set it here explicitly in case
4047509620bSJens Wiklander 	 * the syscall fails before out parameters has been updated.
4057509620bSJens Wiklander 	 */
4067509620bSJens Wiklander 	if (res != TEE_SUCCESS)
4077509620bSJens Wiklander 		s = TEE_HANDLE_NULL;
4087509620bSJens Wiklander 
4097509620bSJens Wiklander 	*session = (TEE_TASessionHandle)(uintptr_t)s;
4107509620bSJens Wiklander 	return res;
4117509620bSJens Wiklander }
4127509620bSJens Wiklander 
TEE_CloseTASession(TEE_TASessionHandle session)413b0104773SPascal Brand void TEE_CloseTASession(TEE_TASessionHandle session)
414b0104773SPascal Brand {
415b0104773SPascal Brand 	if (session != TEE_HANDLE_NULL) {
4162c028fdeSJerome Forissier 		TEE_Result res = _utee_close_ta_session((uintptr_t)session);
417e86f1266SJens Wiklander 
418b0104773SPascal Brand 		if (res != TEE_SUCCESS)
419b0104773SPascal Brand 			TEE_Panic(res);
420b0104773SPascal Brand 	}
421b0104773SPascal Brand }
422b0104773SPascal Brand 
TEE_InvokeTACommand(TEE_TASessionHandle session,uint32_t cancellationRequestTimeout,uint32_t commandID,uint32_t paramTypes,TEE_Param params[TEE_NUM_PARAMS],uint32_t * returnOrigin)423b0104773SPascal Brand TEE_Result TEE_InvokeTACommand(TEE_TASessionHandle session,
424b0104773SPascal Brand 				uint32_t cancellationRequestTimeout,
425b0104773SPascal Brand 				uint32_t commandID, uint32_t paramTypes,
42668540524SIgor Opaniuk 				TEE_Param params[TEE_NUM_PARAMS],
42768540524SIgor Opaniuk 				uint32_t *returnOrigin)
428b0104773SPascal Brand {
429ef305e54SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
430ef305e54SJens Wiklander 	uint32_t ret_origin = TEE_ORIGIN_TEE;
4317509620bSJens Wiklander 	struct utee_params up = { };
432ef305e54SJens Wiklander 	void *tmp_buf = NULL;
433ef305e54SJens Wiklander 	size_t tmp_len = 0;
434ef305e54SJens Wiklander 	void *tmp_va[TEE_NUM_PARAMS] = { NULL };
435c15e5835SCedric Chaumont 
43630e5e0beSJens Wiklander 	if (paramTypes) {
4376915bbbbSJens Wiklander 		__utee_check_inout_annotation(params,
4386915bbbbSJens Wiklander 					      sizeof(TEE_Param) *
4396915bbbbSJens Wiklander 					      TEE_NUM_PARAMS);
44030e5e0beSJens Wiklander 		check_invoke_param(paramTypes, params);
44130e5e0beSJens Wiklander 	}
4426915bbbbSJens Wiklander 	if (returnOrigin)
4436915bbbbSJens Wiklander 		__utee_check_out_annotation(returnOrigin,
4446915bbbbSJens Wiklander 					    sizeof(*returnOrigin));
4456915bbbbSJens Wiklander 
4467509620bSJens Wiklander 	copy_param(&up, paramTypes, params);
4477509620bSJens Wiklander 	res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va);
448ef305e54SJens Wiklander 	if (res)
449ef305e54SJens Wiklander 		goto out;
4502c028fdeSJerome Forissier 	res = _utee_invoke_ta_command((uintptr_t)session,
451e86f1266SJens Wiklander 				      cancellationRequestTimeout,
452e86f1266SJens Wiklander 				      commandID, &up, &ret_origin);
453ef305e54SJens Wiklander 	update_out_param(params, tmp_va, &up);
454ef305e54SJens Wiklander 	if (tmp_buf) {
455ef305e54SJens Wiklander 		TEE_Result res2 = tee_unmap(tmp_buf, tmp_len);
4566709c3eaSCedric Chaumont 
457ef305e54SJens Wiklander 		if (res2)
458ef305e54SJens Wiklander 			TEE_Panic(res2);
459ef305e54SJens Wiklander 	}
460ef305e54SJens Wiklander 
461ef305e54SJens Wiklander out:
4626709c3eaSCedric Chaumont 	if (returnOrigin != NULL)
4636709c3eaSCedric Chaumont 		*returnOrigin = ret_origin;
4646709c3eaSCedric Chaumont 
4656709c3eaSCedric Chaumont 	if (ret_origin == TEE_ORIGIN_TRUSTED_APP)
4666709c3eaSCedric Chaumont 		return res;
4676709c3eaSCedric Chaumont 
468c15e5835SCedric Chaumont 	if (res != TEE_SUCCESS &&
469c15e5835SCedric Chaumont 	    res != TEE_ERROR_OUT_OF_MEMORY &&
470c15e5835SCedric Chaumont 	    res != TEE_ERROR_TARGET_DEAD)
471c15e5835SCedric Chaumont 		TEE_Panic(res);
472c15e5835SCedric Chaumont 
473c15e5835SCedric Chaumont 	return res;
474b0104773SPascal Brand }
475b0104773SPascal Brand 
__GP11_TEE_InvokeTACommand(TEE_TASessionHandle session,uint32_t cancellationRequestTimeout,uint32_t commandID,uint32_t paramTypes,__GP11_TEE_Param params[TEE_NUM_PARAMS],uint32_t * returnOrigin)4767509620bSJens Wiklander TEE_Result __GP11_TEE_InvokeTACommand(TEE_TASessionHandle session,
4777509620bSJens Wiklander 				      uint32_t cancellationRequestTimeout,
4787509620bSJens Wiklander 				      uint32_t commandID, uint32_t paramTypes,
4797509620bSJens Wiklander 				      __GP11_TEE_Param params[TEE_NUM_PARAMS],
4807509620bSJens Wiklander 				      uint32_t *returnOrigin)
4817509620bSJens Wiklander {
4827509620bSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
4837509620bSJens Wiklander 	uint32_t ret_origin = TEE_ORIGIN_TEE;
4847509620bSJens Wiklander 	struct utee_params up = { };
4857509620bSJens Wiklander 	void *tmp_buf = NULL;
4867509620bSJens Wiklander 	size_t tmp_len = 0;
4877509620bSJens Wiklander 	void *tmp_va[TEE_NUM_PARAMS] = { NULL };
4887509620bSJens Wiklander 
4897509620bSJens Wiklander 	if (paramTypes)
4907509620bSJens Wiklander 		__utee_check_inout_annotation(params,
4917509620bSJens Wiklander 					      sizeof(__GP11_TEE_Param) *
4927509620bSJens Wiklander 					      TEE_NUM_PARAMS);
4937509620bSJens Wiklander 	if (returnOrigin)
4947509620bSJens Wiklander 		__utee_check_out_annotation(returnOrigin,
4957509620bSJens Wiklander 					    sizeof(*returnOrigin));
4967509620bSJens Wiklander 
4977509620bSJens Wiklander 	copy_gp11_param(&up, paramTypes, params);
4987509620bSJens Wiklander 	res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va);
4997509620bSJens Wiklander 	if (res)
5007509620bSJens Wiklander 		goto out;
5017509620bSJens Wiklander 	res = _utee_invoke_ta_command((uintptr_t)session,
5027509620bSJens Wiklander 				      cancellationRequestTimeout,
5037509620bSJens Wiklander 				      commandID, &up, &ret_origin);
5047509620bSJens Wiklander 	update_out_gp11_param(params, tmp_va, &up);
5057509620bSJens Wiklander 	if (tmp_buf) {
5067509620bSJens Wiklander 		TEE_Result res2 = tee_unmap(tmp_buf, tmp_len);
5077509620bSJens Wiklander 
5087509620bSJens Wiklander 		if (res2)
5097509620bSJens Wiklander 			TEE_Panic(res2);
5107509620bSJens Wiklander 	}
5117509620bSJens Wiklander 
5127509620bSJens Wiklander out:
5137509620bSJens Wiklander 	if (returnOrigin)
5147509620bSJens Wiklander 		*returnOrigin = ret_origin;
5157509620bSJens Wiklander 
5167509620bSJens Wiklander 	if (ret_origin == TEE_ORIGIN_TRUSTED_APP)
5177509620bSJens Wiklander 		return res;
5187509620bSJens Wiklander 
5197509620bSJens Wiklander 	if (res != TEE_SUCCESS &&
5207509620bSJens Wiklander 	    res != TEE_ERROR_OUT_OF_MEMORY &&
5217509620bSJens Wiklander 	    res != TEE_ERROR_TARGET_DEAD)
5227509620bSJens Wiklander 		TEE_Panic(res);
5237509620bSJens Wiklander 
5247509620bSJens Wiklander 	return res;
5257509620bSJens Wiklander }
5267509620bSJens Wiklander 
527b0104773SPascal Brand /* System API - Cancellations */
528b0104773SPascal Brand 
TEE_GetCancellationFlag(void)529b0104773SPascal Brand bool TEE_GetCancellationFlag(void)
530b0104773SPascal Brand {
531e86f1266SJens Wiklander 	uint32_t c;
5322c028fdeSJerome Forissier 	TEE_Result res = _utee_get_cancellation_flag(&c);
533e86f1266SJens Wiklander 
534b0104773SPascal Brand 	if (res != TEE_SUCCESS)
535e86f1266SJens Wiklander 		c = 0;
536e86f1266SJens Wiklander 	return !!c;
537b0104773SPascal Brand }
538b0104773SPascal Brand 
TEE_UnmaskCancellation(void)539b0104773SPascal Brand bool TEE_UnmaskCancellation(void)
540b0104773SPascal Brand {
541e86f1266SJens Wiklander 	uint32_t old_mask;
5422c028fdeSJerome Forissier 	TEE_Result res = _utee_unmask_cancellation(&old_mask);
543b0104773SPascal Brand 
544b0104773SPascal Brand 	if (res != TEE_SUCCESS)
545b0104773SPascal Brand 		TEE_Panic(res);
546e86f1266SJens Wiklander 	return !!old_mask;
547b0104773SPascal Brand }
548b0104773SPascal Brand 
TEE_MaskCancellation(void)549b0104773SPascal Brand bool TEE_MaskCancellation(void)
550b0104773SPascal Brand {
551e86f1266SJens Wiklander 	uint32_t old_mask;
5522c028fdeSJerome Forissier 	TEE_Result res = _utee_mask_cancellation(&old_mask);
553b0104773SPascal Brand 
554b0104773SPascal Brand 	if (res != TEE_SUCCESS)
555b0104773SPascal Brand 		TEE_Panic(res);
556e86f1266SJens Wiklander 	return !!old_mask;
557b0104773SPascal Brand }
558b0104773SPascal Brand 
559b0104773SPascal Brand /* System API - Memory Management */
560b0104773SPascal Brand 
TEE_CheckMemoryAccessRights(uint32_t accessFlags,void * buffer,size_t size)561b0104773SPascal Brand TEE_Result TEE_CheckMemoryAccessRights(uint32_t accessFlags, void *buffer,
562cd3a8caeSJens Wiklander 				       size_t size)
563b0104773SPascal Brand {
564c8bf6a25SJens Wiklander 	uint32_t flags = accessFlags;
565b0104773SPascal Brand 
566c8bf6a25SJens Wiklander 	if (!size)
567b0104773SPascal Brand 		return TEE_SUCCESS;
568b0104773SPascal Brand 
569c8bf6a25SJens Wiklander 	/*
570c8bf6a25SJens Wiklander 	 * Check access rights against memory mapping. If this check is
571c8bf6a25SJens Wiklander 	 * OK the size can't cause an overflow when added with buffer.
572c8bf6a25SJens Wiklander 	 */
573c8bf6a25SJens Wiklander 	if (_utee_check_access_rights(accessFlags, buffer, size))
574c8bf6a25SJens Wiklander 		return TEE_ERROR_ACCESS_DENIED;
575b0104773SPascal Brand 
576b0104773SPascal Brand 	/*
577c8bf6a25SJens Wiklander 	 * Check access rights against input parameters.
578c8bf6a25SJens Wiklander 	 *
579c8bf6a25SJens Wiklander 	 * Clear eventual extension flags like TEE_MEMORY_ACCESS_NONSECURE
580c8bf6a25SJens Wiklander 	 * and TEE_MEMORY_ACCESS_SECURE.
581b0104773SPascal Brand 	 */
582c8bf6a25SJens Wiklander 	flags &= TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE |
583c8bf6a25SJens Wiklander 		 TEE_MEMORY_ACCESS_ANY_OWNER;
584c8bf6a25SJens Wiklander 	if (check_mem_access_rights_params(flags, buffer, size))
585c8bf6a25SJens Wiklander 		return TEE_ERROR_ACCESS_DENIED;
586b0104773SPascal Brand 
587c8bf6a25SJens Wiklander 	if (malloc_buffer_overlaps_heap(buffer, size) &&
588c8bf6a25SJens Wiklander 	    !malloc_buffer_is_within_alloced(buffer, size))
589c8bf6a25SJens Wiklander 		return TEE_ERROR_ACCESS_DENIED;
590c8bf6a25SJens Wiklander 
591c8bf6a25SJens Wiklander 	return TEE_SUCCESS;
592b0104773SPascal Brand }
593b0104773SPascal Brand 
__GP11_TEE_CheckMemoryAccessRights(uint32_t accessFlags,void * buffer,uint32_t size)594cd3a8caeSJens Wiklander TEE_Result __GP11_TEE_CheckMemoryAccessRights(uint32_t accessFlags,
595cd3a8caeSJens Wiklander 					      void *buffer, uint32_t size)
596cd3a8caeSJens Wiklander {
597cd3a8caeSJens Wiklander 	return TEE_CheckMemoryAccessRights(accessFlags, buffer, size);
598cd3a8caeSJens Wiklander }
599cd3a8caeSJens Wiklander 
TEE_SetInstanceData(const void * instanceData)6008f07fe6fSJerome Forissier void TEE_SetInstanceData(const void *instanceData)
601b0104773SPascal Brand {
602b0104773SPascal Brand 	tee_api_instance_data = instanceData;
603b0104773SPascal Brand }
604b0104773SPascal Brand 
TEE_GetInstanceData(void)6058f07fe6fSJerome Forissier const void *TEE_GetInstanceData(void)
606b0104773SPascal Brand {
607b0104773SPascal Brand 	return tee_api_instance_data;
608b0104773SPascal Brand }
609b0104773SPascal Brand 
TEE_MemMove(void * dest,const void * src,size_t size)610da603884SVincent Mailhol void TEE_MemMove(void *dest, const void *src, size_t size)
611b0104773SPascal Brand {
612da603884SVincent Mailhol 	memmove(dest, src, size);
613b0104773SPascal Brand }
614b0104773SPascal Brand 
__GP11_TEE_MemMove(void * dest,const void * src,uint32_t size)615da603884SVincent Mailhol void __GP11_TEE_MemMove(void *dest, const void *src, uint32_t size)
6161d0ed95aSJens Wiklander {
617da603884SVincent Mailhol 	TEE_MemMove(dest, src, size);
6181d0ed95aSJens Wiklander }
6191d0ed95aSJens Wiklander 
TEE_MemCompare(const void * buffer1,const void * buffer2,size_t size)6201d0ed95aSJens Wiklander int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, size_t size)
621b0104773SPascal Brand {
62265551e69SJerome Forissier 	return consttime_memcmp(buffer1, buffer2, size);
623b0104773SPascal Brand }
624b0104773SPascal Brand 
__GP11_TEE_MemCompare(const void * buffer1,const void * buffer2,uint32_t size)6251d0ed95aSJens Wiklander int32_t __GP11_TEE_MemCompare(const void *buffer1, const void *buffer2,
6261d0ed95aSJens Wiklander 			      uint32_t size)
6271d0ed95aSJens Wiklander {
6281d0ed95aSJens Wiklander 	return TEE_MemCompare(buffer1, buffer2, size);
6291d0ed95aSJens Wiklander }
6301d0ed95aSJens Wiklander 
TEE_MemFill(void * buff,uint32_t x,size_t size)6311d0ed95aSJens Wiklander void TEE_MemFill(void *buff, uint32_t x, size_t size)
632b0104773SPascal Brand {
63332c75600SJens Wiklander 	memset(buff, x, size);
634b0104773SPascal Brand }
635b0104773SPascal Brand 
__GP11_TEE_MemFill(void * buff,uint32_t x,uint32_t size)6361d0ed95aSJens Wiklander void __GP11_TEE_MemFill(void *buff, uint32_t x, uint32_t size)
6371d0ed95aSJens Wiklander {
6381d0ed95aSJens Wiklander 	TEE_MemFill(buff, x, size);
6391d0ed95aSJens Wiklander }
6401d0ed95aSJens Wiklander 
641b0104773SPascal Brand /* Date & Time API */
642b0104773SPascal Brand 
TEE_GetSystemTime(TEE_Time * time)643b0104773SPascal Brand void TEE_GetSystemTime(TEE_Time *time)
644b0104773SPascal Brand {
6452c028fdeSJerome Forissier 	TEE_Result res = _utee_get_time(UTEE_TIME_CAT_SYSTEM, time);
646b0104773SPascal Brand 
647b0104773SPascal Brand 	if (res != TEE_SUCCESS)
648b36311adSJerome Forissier 		TEE_Panic(res);
649b0104773SPascal Brand }
650b0104773SPascal Brand 
TEE_Wait(uint32_t timeout)651b0104773SPascal Brand TEE_Result TEE_Wait(uint32_t timeout)
652b0104773SPascal Brand {
6532c028fdeSJerome Forissier 	TEE_Result res = _utee_wait(timeout);
654b0104773SPascal Brand 
655b0104773SPascal Brand 	if (res != TEE_SUCCESS && res != TEE_ERROR_CANCEL)
656b0104773SPascal Brand 		TEE_Panic(res);
657b0104773SPascal Brand 
658b0104773SPascal Brand 	return res;
659b0104773SPascal Brand }
660b0104773SPascal Brand 
TEE_GetTAPersistentTime(TEE_Time * time)661b0104773SPascal Brand TEE_Result TEE_GetTAPersistentTime(TEE_Time *time)
662b0104773SPascal Brand {
663b64d6909SCedric Chaumont 	TEE_Result res;
664b64d6909SCedric Chaumont 
6652c028fdeSJerome Forissier 	res = _utee_get_time(UTEE_TIME_CAT_TA_PERSISTENT, time);
666b64d6909SCedric Chaumont 
667b64d6909SCedric Chaumont 	if (res != TEE_SUCCESS && res != TEE_ERROR_OVERFLOW) {
668b64d6909SCedric Chaumont 		time->seconds = 0;
669b64d6909SCedric Chaumont 		time->millis = 0;
670b64d6909SCedric Chaumont 	}
671b64d6909SCedric Chaumont 
672b64d6909SCedric Chaumont 	if (res != TEE_SUCCESS &&
673b64d6909SCedric Chaumont 	    res != TEE_ERROR_TIME_NOT_SET &&
674b64d6909SCedric Chaumont 	    res != TEE_ERROR_TIME_NEEDS_RESET &&
675b64d6909SCedric Chaumont 	    res != TEE_ERROR_OVERFLOW &&
676b64d6909SCedric Chaumont 	    res != TEE_ERROR_OUT_OF_MEMORY)
677b64d6909SCedric Chaumont 		TEE_Panic(res);
678b64d6909SCedric Chaumont 
679b64d6909SCedric Chaumont 	return res;
680b0104773SPascal Brand }
681b0104773SPascal Brand 
TEE_SetTAPersistentTime(const TEE_Time * time)682b0104773SPascal Brand TEE_Result TEE_SetTAPersistentTime(const TEE_Time *time)
683b0104773SPascal Brand {
684b64d6909SCedric Chaumont 	TEE_Result res;
685b64d6909SCedric Chaumont 
6862c028fdeSJerome Forissier 	res = _utee_set_ta_time(time);
687b64d6909SCedric Chaumont 
688b64d6909SCedric Chaumont 	if (res != TEE_SUCCESS &&
689b64d6909SCedric Chaumont 	    res != TEE_ERROR_OUT_OF_MEMORY &&
690b64d6909SCedric Chaumont 	    res != TEE_ERROR_STORAGE_NO_SPACE)
691b64d6909SCedric Chaumont 		TEE_Panic(res);
692b64d6909SCedric Chaumont 
693b64d6909SCedric Chaumont 	return res;
694b0104773SPascal Brand }
695b0104773SPascal Brand 
TEE_GetREETime(TEE_Time * time)696b0104773SPascal Brand void TEE_GetREETime(TEE_Time *time)
697b0104773SPascal Brand {
6982c028fdeSJerome Forissier 	TEE_Result res = _utee_get_time(UTEE_TIME_CAT_REE, time);
699b0104773SPascal Brand 
700b0104773SPascal Brand 	if (res != TEE_SUCCESS)
701b36311adSJerome Forissier 		TEE_Panic(res);
702b0104773SPascal Brand }
703b0104773SPascal Brand 
TEE_Malloc(size_t len,uint32_t hint)70411285ebcSJens Wiklander void *TEE_Malloc(size_t len, uint32_t hint)
705b0104773SPascal Brand {
70611285ebcSJens Wiklander 	switch (hint) {
70711285ebcSJens Wiklander 	case TEE_MALLOC_FILL_ZERO:
708a83ee50aSSadiq Hussain 		if (!len)
709a83ee50aSSadiq Hussain 			return TEE_NULL_SIZED_VA;
71096c1d8c5SJens Wiklander 		return calloc(1, len);
71111285ebcSJens Wiklander 
71211285ebcSJens Wiklander 	case TEE_MALLOC_NO_FILL:
71311285ebcSJens Wiklander 		TEE_Panic(0);
71411285ebcSJens Wiklander 		break;
71511285ebcSJens Wiklander 
716e64b7b2eSJens Wiklander 	case TEE_MALLOC_NO_SHARE:
717e64b7b2eSJens Wiklander 		if (!len)
718e64b7b2eSJens Wiklander 			return TEE_NULL_SIZED_NO_SHARE_VA;
719e64b7b2eSJens Wiklander 		if (!__ta_no_share_malloc_ctx)
720e64b7b2eSJens Wiklander 			return NULL;
721e64b7b2eSJens Wiklander 		return raw_calloc(0, 0, 1, len, __ta_no_share_malloc_ctx);
722e64b7b2eSJens Wiklander 
72311285ebcSJens Wiklander 	case TEE_MALLOC_NO_FILL | TEE_MALLOC_NO_SHARE:
724e64b7b2eSJens Wiklander 		if (!len)
725e64b7b2eSJens Wiklander 			return TEE_NULL_SIZED_NO_SHARE_VA;
726e64b7b2eSJens Wiklander 		if (!__ta_no_share_malloc_ctx)
727e64b7b2eSJens Wiklander 			return NULL;
728e64b7b2eSJens Wiklander 		return raw_malloc(0, 0, len, __ta_no_share_malloc_ctx);
72911285ebcSJens Wiklander 
73011285ebcSJens Wiklander 	case TEE_USER_MEM_HINT_NO_FILL_ZERO:
73111285ebcSJens Wiklander 		if (!len)
73211285ebcSJens Wiklander 			return TEE_NULL_SIZED_VA;
73396c1d8c5SJens Wiklander 		return malloc(len);
73496c1d8c5SJens Wiklander 
73511285ebcSJens Wiklander 	default:
73611285ebcSJens Wiklander 		break;
73711285ebcSJens Wiklander 	}
73811285ebcSJens Wiklander 
73996c1d8c5SJens Wiklander 	EMSG("Invalid hint %#" PRIx32, hint);
74096c1d8c5SJens Wiklander 
74196c1d8c5SJens Wiklander 	return NULL;
742b0104773SPascal Brand }
743b0104773SPascal Brand 
__GP11_TEE_Malloc(uint32_t size,uint32_t hint)74411285ebcSJens Wiklander void *__GP11_TEE_Malloc(uint32_t size, uint32_t hint)
74511285ebcSJens Wiklander {
74611285ebcSJens Wiklander 	return TEE_Malloc(size, hint);
74711285ebcSJens Wiklander }
74811285ebcSJens Wiklander 
addr_is_in_no_share_heap(void * p)749e64b7b2eSJens Wiklander static bool addr_is_in_no_share_heap(void *p)
750e64b7b2eSJens Wiklander {
751e64b7b2eSJens Wiklander 	return buf_overlaps_no_share_heap(p, 1);
752e64b7b2eSJens Wiklander }
753e64b7b2eSJens Wiklander 
TEE_Realloc(void * buffer,size_t newSize)75411285ebcSJens Wiklander void *TEE_Realloc(void *buffer, size_t newSize)
755b0104773SPascal Brand {
756*93b037acSJens Wiklander 	bool no_share = (buffer == TEE_NULL_SIZED_NO_SHARE_VA ||
757*93b037acSJens Wiklander 			 addr_is_in_no_share_heap(buffer));
758*93b037acSJens Wiklander 	void *p = NULL;
759*93b037acSJens Wiklander 
760*93b037acSJens Wiklander 	if (buffer != TEE_NULL_SIZED_NO_SHARE_VA && buffer != TEE_NULL_SIZED_VA)
761*93b037acSJens Wiklander 		p = buffer;
762*93b037acSJens Wiklander 
763a83ee50aSSadiq Hussain 	if (!newSize) {
764*93b037acSJens Wiklander 		TEE_Free(p);
765*93b037acSJens Wiklander 		if (no_share)
766*93b037acSJens Wiklander 			return TEE_NULL_SIZED_NO_SHARE_VA;
767e64b7b2eSJens Wiklander 		else
768*93b037acSJens Wiklander 			return TEE_NULL_SIZED_VA;
769a83ee50aSSadiq Hussain 	}
770a83ee50aSSadiq Hussain 
771*93b037acSJens Wiklander 	if (no_share) {
772e64b7b2eSJens Wiklander 		if (!__ta_no_share_malloc_ctx)
773e64b7b2eSJens Wiklander 			return NULL;
774*93b037acSJens Wiklander 		return raw_malloc_flags(MAF_ZERO_INIT, p, 0, 0,
775*93b037acSJens Wiklander 					MALLOC_DEFAULT_ALIGNMENT, 1, newSize,
776*93b037acSJens Wiklander 					__ta_no_share_malloc_ctx);
777e64b7b2eSJens Wiklander 	}
778a83ee50aSSadiq Hussain 
779*93b037acSJens Wiklander 	return malloc_flags(MAF_ZERO_INIT, p, 1, newSize);
780b0104773SPascal Brand }
781b0104773SPascal Brand 
__GP11_TEE_Realloc(void * buffer,uint32_t newSize)78211285ebcSJens Wiklander void *__GP11_TEE_Realloc(void *buffer, uint32_t newSize)
78311285ebcSJens Wiklander {
78411285ebcSJens Wiklander 	return TEE_Realloc(buffer, newSize);
78511285ebcSJens Wiklander }
78611285ebcSJens Wiklander 
TEE_Free(void * buffer)787b0104773SPascal Brand void TEE_Free(void *buffer)
788b0104773SPascal Brand {
789e64b7b2eSJens Wiklander 	if (buffer != TEE_NULL_SIZED_VA &&
790e64b7b2eSJens Wiklander 	    buffer != TEE_NULL_SIZED_NO_SHARE_VA) {
791e64b7b2eSJens Wiklander 		if (addr_is_in_no_share_heap(buffer))
792e64b7b2eSJens Wiklander 			raw_free(buffer, __ta_no_share_malloc_ctx, false);
793e64b7b2eSJens Wiklander 		else
79496c1d8c5SJens Wiklander 			free(buffer);
795b0104773SPascal Brand 	}
796e64b7b2eSJens Wiklander }
797fa530828SPascal Brand 
798fa530828SPascal Brand /* Cache maintenance support (TA requires the CACHE_MAINTENANCE property) */
TEE_CacheClean(char * buf,size_t len)799fa530828SPascal Brand TEE_Result TEE_CacheClean(char *buf, size_t len)
800fa530828SPascal Brand {
8012c028fdeSJerome Forissier 	return _utee_cache_operation(buf, len, TEE_CACHECLEAN);
802fa530828SPascal Brand }
TEE_CacheFlush(char * buf,size_t len)803fa530828SPascal Brand TEE_Result TEE_CacheFlush(char *buf, size_t len)
804fa530828SPascal Brand {
8052c028fdeSJerome Forissier 	return _utee_cache_operation(buf, len, TEE_CACHEFLUSH);
806fa530828SPascal Brand }
807fa530828SPascal Brand 
TEE_CacheInvalidate(char * buf,size_t len)808fa530828SPascal Brand TEE_Result TEE_CacheInvalidate(char *buf, size_t len)
809fa530828SPascal Brand {
8102c028fdeSJerome Forissier 	return _utee_cache_operation(buf, len, TEE_CACHEINVALIDATE);
811fa530828SPascal Brand }
812