xref: /optee_os/lib/libutee/tee_api.c (revision 65551e69a006c496fb18d8374389b7b3617c2076)
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>
7*65551e69SJerome Forissier #include <string_ext.h>
8b0104773SPascal Brand 
9b0104773SPascal Brand #include <tee_api.h>
1096c1d8c5SJens Wiklander #include <tee_internal_api_extensions.h>
11b0104773SPascal Brand #include <user_ta_header.h>
1296c1d8c5SJens Wiklander #include <utee_syscalls.h>
13e86f1266SJens Wiklander #include "tee_api_private.h"
14b0104773SPascal Brand 
158f07fe6fSJerome Forissier static const void *tee_api_instance_data;
16b0104773SPascal Brand 
17b0104773SPascal Brand /* System API - Internal Client API */
18b0104773SPascal Brand 
19e86f1266SJens Wiklander void __utee_from_param(struct utee_params *up, uint32_t param_types,
20e86f1266SJens Wiklander 			const TEE_Param params[TEE_NUM_PARAMS])
21e86f1266SJens Wiklander {
22e86f1266SJens Wiklander 	size_t n;
23e86f1266SJens Wiklander 
24e86f1266SJens Wiklander 	up->types = param_types;
25e86f1266SJens Wiklander 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
26e86f1266SJens Wiklander 		switch (TEE_PARAM_TYPE_GET(param_types, n)) {
27e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INPUT:
28e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_VALUE_OUTPUT:
29e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INOUT:
30e86f1266SJens Wiklander 			up->vals[n * 2] = params[n].value.a;
31e86f1266SJens Wiklander 			up->vals[n * 2 + 1] = params[n].value.b;
32e86f1266SJens Wiklander 			break;
33e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INPUT:
34e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
35e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
36e86f1266SJens Wiklander 			up->vals[n * 2] = (uintptr_t)params[n].memref.buffer;
37e86f1266SJens Wiklander 			up->vals[n * 2 + 1] = params[n].memref.size;
38e86f1266SJens Wiklander 			break;
39e86f1266SJens Wiklander 		default:
40e86f1266SJens Wiklander 			up->vals[n * 2] = 0;
41e86f1266SJens Wiklander 			up->vals[n * 2 + 1] = 0;
42e86f1266SJens Wiklander 			break;
43e86f1266SJens Wiklander 		}
44e86f1266SJens Wiklander 	}
45e86f1266SJens Wiklander }
46e86f1266SJens Wiklander 
47e86f1266SJens Wiklander void __utee_to_param(TEE_Param params[TEE_NUM_PARAMS],
48e86f1266SJens Wiklander 			uint32_t *param_types, const struct utee_params *up)
49e86f1266SJens Wiklander {
50e86f1266SJens Wiklander 	size_t n;
51e86f1266SJens Wiklander 	uint32_t types = up->types;
52e86f1266SJens Wiklander 
53e86f1266SJens Wiklander 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
54e86f1266SJens Wiklander 		uintptr_t a = up->vals[n * 2];
55e86f1266SJens Wiklander 		uintptr_t b = up->vals[n * 2 + 1];
56e86f1266SJens Wiklander 
57e86f1266SJens Wiklander 		switch (TEE_PARAM_TYPE_GET(types, n)) {
58e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INPUT:
59e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_VALUE_OUTPUT:
60e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INOUT:
61e86f1266SJens Wiklander 			params[n].value.a = a;
62e86f1266SJens Wiklander 			params[n].value.b = b;
63e86f1266SJens Wiklander 			break;
64e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INPUT:
65e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
66e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
67e86f1266SJens Wiklander 			params[n].memref.buffer = (void *)a;
68e86f1266SJens Wiklander 			params[n].memref.size = b;
69e86f1266SJens Wiklander 			break;
70e86f1266SJens Wiklander 		default:
71e86f1266SJens Wiklander 			break;
72e86f1266SJens Wiklander 		}
73e86f1266SJens Wiklander 	}
74e86f1266SJens Wiklander 
75e86f1266SJens Wiklander 	if (param_types)
76e86f1266SJens Wiklander 		*param_types = types;
77e86f1266SJens Wiklander }
78e86f1266SJens Wiklander 
79b0104773SPascal Brand TEE_Result TEE_OpenTASession(const TEE_UUID *destination,
80b0104773SPascal Brand 				uint32_t cancellationRequestTimeout,
8168540524SIgor Opaniuk 				uint32_t paramTypes,
8268540524SIgor Opaniuk 				TEE_Param params[TEE_NUM_PARAMS],
83b0104773SPascal Brand 				TEE_TASessionHandle *session,
84b0104773SPascal Brand 				uint32_t *returnOrigin)
85b0104773SPascal Brand {
86b0104773SPascal Brand 	TEE_Result res;
87e86f1266SJens Wiklander 	struct utee_params up;
88e86f1266SJens Wiklander 	uint32_t s;
89b0104773SPascal Brand 
90e86f1266SJens Wiklander 	__utee_from_param(&up, paramTypes, params);
91b0104773SPascal Brand 	res = utee_open_ta_session(destination, cancellationRequestTimeout,
92e86f1266SJens Wiklander 				   &up, &s, returnOrigin);
93e86f1266SJens Wiklander 	__utee_to_param(params, NULL, &up);
94b0104773SPascal Brand 	/*
95b0104773SPascal Brand 	 * Specification says that *session must hold TEE_HANDLE_NULL is
96b0104773SPascal Brand 	 * TEE_SUCCESS isn't returned. Set it here explicitly in case
97b0104773SPascal Brand 	 * the syscall fails before out parameters has been updated.
98b0104773SPascal Brand 	 */
99b0104773SPascal Brand 	if (res != TEE_SUCCESS)
100e86f1266SJens Wiklander 		s = TEE_HANDLE_NULL;
101b0104773SPascal Brand 
102e86f1266SJens Wiklander 	*session = (TEE_TASessionHandle)(uintptr_t)s;
103b0104773SPascal Brand 	return res;
104b0104773SPascal Brand }
105b0104773SPascal Brand 
106b0104773SPascal Brand void TEE_CloseTASession(TEE_TASessionHandle session)
107b0104773SPascal Brand {
108b0104773SPascal Brand 	if (session != TEE_HANDLE_NULL) {
109e86f1266SJens Wiklander 		TEE_Result res = utee_close_ta_session((uintptr_t)session);
110e86f1266SJens Wiklander 
111b0104773SPascal Brand 		if (res != TEE_SUCCESS)
112b0104773SPascal Brand 			TEE_Panic(res);
113b0104773SPascal Brand 	}
114b0104773SPascal Brand }
115b0104773SPascal Brand 
116b0104773SPascal Brand TEE_Result TEE_InvokeTACommand(TEE_TASessionHandle session,
117b0104773SPascal Brand 				uint32_t cancellationRequestTimeout,
118b0104773SPascal Brand 				uint32_t commandID, uint32_t paramTypes,
11968540524SIgor Opaniuk 				TEE_Param params[TEE_NUM_PARAMS],
12068540524SIgor Opaniuk 				uint32_t *returnOrigin)
121b0104773SPascal Brand {
122c15e5835SCedric Chaumont 	TEE_Result res;
1236709c3eaSCedric Chaumont 	uint32_t ret_origin;
124e86f1266SJens Wiklander 	struct utee_params up;
125c15e5835SCedric Chaumont 
126e86f1266SJens Wiklander 	__utee_from_param(&up, paramTypes, params);
127e86f1266SJens Wiklander 	res = utee_invoke_ta_command((uintptr_t)session,
128e86f1266SJens Wiklander 				      cancellationRequestTimeout,
129e86f1266SJens Wiklander 				      commandID, &up, &ret_origin);
130e86f1266SJens Wiklander 	__utee_to_param(params, NULL, &up);
1316709c3eaSCedric Chaumont 
1326709c3eaSCedric Chaumont 	if (returnOrigin != NULL)
1336709c3eaSCedric Chaumont 		*returnOrigin = ret_origin;
1346709c3eaSCedric Chaumont 
1356709c3eaSCedric Chaumont 	if (ret_origin == TEE_ORIGIN_TRUSTED_APP)
1366709c3eaSCedric Chaumont 		return res;
1376709c3eaSCedric Chaumont 
138c15e5835SCedric Chaumont 	if (res != TEE_SUCCESS &&
139c15e5835SCedric Chaumont 	    res != TEE_ERROR_OUT_OF_MEMORY &&
140c15e5835SCedric Chaumont 	    res != TEE_ERROR_TARGET_DEAD)
141c15e5835SCedric Chaumont 		TEE_Panic(res);
142c15e5835SCedric Chaumont 
143c15e5835SCedric Chaumont 	return res;
144b0104773SPascal Brand }
145b0104773SPascal Brand 
146b0104773SPascal Brand /* System API - Cancellations */
147b0104773SPascal Brand 
148b0104773SPascal Brand bool TEE_GetCancellationFlag(void)
149b0104773SPascal Brand {
150e86f1266SJens Wiklander 	uint32_t c;
151b0104773SPascal Brand 	TEE_Result res = utee_get_cancellation_flag(&c);
152e86f1266SJens Wiklander 
153b0104773SPascal Brand 	if (res != TEE_SUCCESS)
154e86f1266SJens Wiklander 		c = 0;
155e86f1266SJens Wiklander 	return !!c;
156b0104773SPascal Brand }
157b0104773SPascal Brand 
158b0104773SPascal Brand bool TEE_UnmaskCancellation(void)
159b0104773SPascal Brand {
160e86f1266SJens Wiklander 	uint32_t old_mask;
161b0104773SPascal Brand 	TEE_Result res = utee_unmask_cancellation(&old_mask);
162b0104773SPascal Brand 
163b0104773SPascal Brand 	if (res != TEE_SUCCESS)
164b0104773SPascal Brand 		TEE_Panic(res);
165e86f1266SJens Wiklander 	return !!old_mask;
166b0104773SPascal Brand }
167b0104773SPascal Brand 
168b0104773SPascal Brand bool TEE_MaskCancellation(void)
169b0104773SPascal Brand {
170e86f1266SJens Wiklander 	uint32_t old_mask;
171b0104773SPascal Brand 	TEE_Result res = utee_mask_cancellation(&old_mask);
172b0104773SPascal Brand 
173b0104773SPascal Brand 	if (res != TEE_SUCCESS)
174b0104773SPascal Brand 		TEE_Panic(res);
175e86f1266SJens Wiklander 	return !!old_mask;
176b0104773SPascal Brand }
177b0104773SPascal Brand 
178b0104773SPascal Brand /* System API - Memory Management */
179b0104773SPascal Brand 
180b0104773SPascal Brand TEE_Result TEE_CheckMemoryAccessRights(uint32_t accessFlags, void *buffer,
18179a3c601SCedric Chaumont 				       uint32_t size)
182b0104773SPascal Brand {
183b0104773SPascal Brand 	TEE_Result res;
184b0104773SPascal Brand 
185b0104773SPascal Brand 	if (size == 0)
186b0104773SPascal Brand 		return TEE_SUCCESS;
187b0104773SPascal Brand 
188b0104773SPascal Brand 	/* Check access rights against memory mapping */
189b0104773SPascal Brand 	res = utee_check_access_rights(accessFlags, buffer, size);
190b0104773SPascal Brand 	if (res != TEE_SUCCESS)
191b0104773SPascal Brand 		goto out;
192b0104773SPascal Brand 
193b0104773SPascal Brand 	/*
194b0104773SPascal Brand 	* Check access rights against input parameters
195b0104773SPascal Brand 	* Previous legacy code was removed and will need to be restored
196b0104773SPascal Brand 	*/
197b0104773SPascal Brand 
198b0104773SPascal Brand 	res = TEE_SUCCESS;
199b0104773SPascal Brand out:
200b0104773SPascal Brand 	return res;
201b0104773SPascal Brand }
202b0104773SPascal Brand 
2038f07fe6fSJerome Forissier void TEE_SetInstanceData(const void *instanceData)
204b0104773SPascal Brand {
205b0104773SPascal Brand 	tee_api_instance_data = instanceData;
206b0104773SPascal Brand }
207b0104773SPascal Brand 
2088f07fe6fSJerome Forissier const void *TEE_GetInstanceData(void)
209b0104773SPascal Brand {
210b0104773SPascal Brand 	return tee_api_instance_data;
211b0104773SPascal Brand }
212b0104773SPascal Brand 
213b0104773SPascal Brand void *TEE_MemMove(void *dest, const void *src, uint32_t size)
214b0104773SPascal Brand {
215b0104773SPascal Brand 	return memmove(dest, src, size);
216b0104773SPascal Brand }
217b0104773SPascal Brand 
218b0104773SPascal Brand int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, uint32_t size)
219b0104773SPascal Brand {
220*65551e69SJerome Forissier 	return consttime_memcmp(buffer1, buffer2, size);
221b0104773SPascal Brand }
222b0104773SPascal Brand 
223b0104773SPascal Brand void *TEE_MemFill(void *buff, uint32_t x, uint32_t size)
224b0104773SPascal Brand {
225b0104773SPascal Brand 	return memset(buff, x, size);
226b0104773SPascal Brand }
227b0104773SPascal Brand 
228b0104773SPascal Brand /* Date & Time API */
229b0104773SPascal Brand 
230b0104773SPascal Brand void TEE_GetSystemTime(TEE_Time *time)
231b0104773SPascal Brand {
232b0104773SPascal Brand 	TEE_Result res = utee_get_time(UTEE_TIME_CAT_SYSTEM, time);
233b0104773SPascal Brand 
234b0104773SPascal Brand 	if (res != TEE_SUCCESS)
235b36311adSJerome Forissier 		TEE_Panic(res);
236b0104773SPascal Brand }
237b0104773SPascal Brand 
238b0104773SPascal Brand TEE_Result TEE_Wait(uint32_t timeout)
239b0104773SPascal Brand {
240b0104773SPascal Brand 	TEE_Result res = utee_wait(timeout);
241b0104773SPascal Brand 
242b0104773SPascal Brand 	if (res != TEE_SUCCESS && res != TEE_ERROR_CANCEL)
243b0104773SPascal Brand 		TEE_Panic(res);
244b0104773SPascal Brand 
245b0104773SPascal Brand 	return res;
246b0104773SPascal Brand }
247b0104773SPascal Brand 
248b0104773SPascal Brand TEE_Result TEE_GetTAPersistentTime(TEE_Time *time)
249b0104773SPascal Brand {
250b64d6909SCedric Chaumont 	TEE_Result res;
251b64d6909SCedric Chaumont 
252b64d6909SCedric Chaumont 	res = utee_get_time(UTEE_TIME_CAT_TA_PERSISTENT, time);
253b64d6909SCedric Chaumont 
254b64d6909SCedric Chaumont 	if (res != TEE_SUCCESS && res != TEE_ERROR_OVERFLOW) {
255b64d6909SCedric Chaumont 		time->seconds = 0;
256b64d6909SCedric Chaumont 		time->millis = 0;
257b64d6909SCedric Chaumont 	}
258b64d6909SCedric Chaumont 
259b64d6909SCedric Chaumont 	if (res != TEE_SUCCESS &&
260b64d6909SCedric Chaumont 	    res != TEE_ERROR_TIME_NOT_SET &&
261b64d6909SCedric Chaumont 	    res != TEE_ERROR_TIME_NEEDS_RESET &&
262b64d6909SCedric Chaumont 	    res != TEE_ERROR_OVERFLOW &&
263b64d6909SCedric Chaumont 	    res != TEE_ERROR_OUT_OF_MEMORY)
264b64d6909SCedric Chaumont 		TEE_Panic(res);
265b64d6909SCedric Chaumont 
266b64d6909SCedric Chaumont 	return res;
267b0104773SPascal Brand }
268b0104773SPascal Brand 
269b0104773SPascal Brand TEE_Result TEE_SetTAPersistentTime(const TEE_Time *time)
270b0104773SPascal Brand {
271b64d6909SCedric Chaumont 	TEE_Result res;
272b64d6909SCedric Chaumont 
273b64d6909SCedric Chaumont 	res = utee_set_ta_time(time);
274b64d6909SCedric Chaumont 
275b64d6909SCedric Chaumont 	if (res != TEE_SUCCESS &&
276b64d6909SCedric Chaumont 	    res != TEE_ERROR_OUT_OF_MEMORY &&
277b64d6909SCedric Chaumont 	    res != TEE_ERROR_STORAGE_NO_SPACE)
278b64d6909SCedric Chaumont 		TEE_Panic(res);
279b64d6909SCedric Chaumont 
280b64d6909SCedric Chaumont 	return res;
281b0104773SPascal Brand }
282b0104773SPascal Brand 
283b0104773SPascal Brand void TEE_GetREETime(TEE_Time *time)
284b0104773SPascal Brand {
285b0104773SPascal Brand 	TEE_Result res = utee_get_time(UTEE_TIME_CAT_REE, time);
286b0104773SPascal Brand 
287b0104773SPascal Brand 	if (res != TEE_SUCCESS)
288b36311adSJerome Forissier 		TEE_Panic(res);
289b0104773SPascal Brand }
290b0104773SPascal Brand 
29179a3c601SCedric Chaumont void *TEE_Malloc(uint32_t len, uint32_t hint)
292b0104773SPascal Brand {
29396c1d8c5SJens Wiklander 	if (hint == TEE_MALLOC_FILL_ZERO)
29496c1d8c5SJens Wiklander 		return calloc(1, len);
29596c1d8c5SJens Wiklander 	else if (hint == TEE_USER_MEM_HINT_NO_FILL_ZERO)
29696c1d8c5SJens Wiklander 		return malloc(len);
29796c1d8c5SJens Wiklander 
29896c1d8c5SJens Wiklander 	EMSG("Invalid hint %#" PRIx32, hint);
29996c1d8c5SJens Wiklander 
30096c1d8c5SJens Wiklander 	return NULL;
301b0104773SPascal Brand }
302b0104773SPascal Brand 
303c0ce02edSJens Wiklander void *TEE_Realloc(void *buffer, uint32_t newSize)
304b0104773SPascal Brand {
30596c1d8c5SJens Wiklander 	return realloc(buffer, newSize);
306b0104773SPascal Brand }
307b0104773SPascal Brand 
308b0104773SPascal Brand void TEE_Free(void *buffer)
309b0104773SPascal Brand {
31096c1d8c5SJens Wiklander 	free(buffer);
311b0104773SPascal Brand }
312fa530828SPascal Brand 
313fa530828SPascal Brand /* Cache maintenance support (TA requires the CACHE_MAINTENANCE property) */
314fa530828SPascal Brand TEE_Result TEE_CacheClean(char *buf, size_t len)
315fa530828SPascal Brand {
316fa530828SPascal Brand 	return utee_cache_operation(buf, len, TEE_CACHECLEAN);
317fa530828SPascal Brand }
318fa530828SPascal Brand TEE_Result TEE_CacheFlush(char *buf, size_t len)
319fa530828SPascal Brand {
320fa530828SPascal Brand 	return utee_cache_operation(buf, len, TEE_CACHEFLUSH);
321fa530828SPascal Brand }
322fa530828SPascal Brand 
323fa530828SPascal Brand TEE_Result TEE_CacheInvalidate(char *buf, size_t len)
324fa530828SPascal Brand {
325fa530828SPascal Brand 	return utee_cache_operation(buf, len, TEE_CACHEINVALIDATE);
326fa530828SPascal Brand }
327