xref: /optee_os/lib/libutee/tee_api.c (revision c0ce02ed1cb00f59a8cdd66b4228b9798b560887)
11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2b0104773SPascal Brand /*
3b0104773SPascal Brand  * Copyright (c) 2014, STMicroelectronics International N.V.
4b0104773SPascal Brand  * All rights reserved.
5b0104773SPascal Brand  *
6b0104773SPascal Brand  * Redistribution and use in source and binary forms, with or without
7b0104773SPascal Brand  * modification, are permitted provided that the following conditions are met:
8b0104773SPascal Brand  *
9b0104773SPascal Brand  * 1. Redistributions of source code must retain the above copyright notice,
10b0104773SPascal Brand  * this list of conditions and the following disclaimer.
11b0104773SPascal Brand  *
12b0104773SPascal Brand  * 2. Redistributions in binary form must reproduce the above copyright notice,
13b0104773SPascal Brand  * this list of conditions and the following disclaimer in the documentation
14b0104773SPascal Brand  * and/or other materials provided with the distribution.
15b0104773SPascal Brand  *
16b0104773SPascal Brand  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17b0104773SPascal Brand  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18b0104773SPascal Brand  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19b0104773SPascal Brand  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20b0104773SPascal Brand  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21b0104773SPascal Brand  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22b0104773SPascal Brand  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23b0104773SPascal Brand  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24b0104773SPascal Brand  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25b0104773SPascal Brand  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26b0104773SPascal Brand  * POSSIBILITY OF SUCH DAMAGE.
27b0104773SPascal Brand  */
28b0104773SPascal Brand #include <stdlib.h>
29b0104773SPascal Brand #include <string.h>
30b0104773SPascal Brand 
31b0104773SPascal Brand #include <tee_api.h>
32b0104773SPascal Brand #include <utee_syscalls.h>
33b0104773SPascal Brand #include <user_ta_header.h>
34b0104773SPascal Brand #include "tee_user_mem.h"
35e86f1266SJens Wiklander #include "tee_api_private.h"
36b0104773SPascal Brand 
378f07fe6fSJerome Forissier static const void *tee_api_instance_data;
38b0104773SPascal Brand 
39b0104773SPascal Brand /* System API - Internal Client API */
40b0104773SPascal Brand 
41e86f1266SJens Wiklander void __utee_from_param(struct utee_params *up, uint32_t param_types,
42e86f1266SJens Wiklander 			const TEE_Param params[TEE_NUM_PARAMS])
43e86f1266SJens Wiklander {
44e86f1266SJens Wiklander 	size_t n;
45e86f1266SJens Wiklander 
46e86f1266SJens Wiklander 	up->types = param_types;
47e86f1266SJens Wiklander 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
48e86f1266SJens Wiklander 		switch (TEE_PARAM_TYPE_GET(param_types, n)) {
49e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INPUT:
50e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_VALUE_OUTPUT:
51e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INOUT:
52e86f1266SJens Wiklander 			up->vals[n * 2] = params[n].value.a;
53e86f1266SJens Wiklander 			up->vals[n * 2 + 1] = params[n].value.b;
54e86f1266SJens Wiklander 			break;
55e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INPUT:
56e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
57e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
58e86f1266SJens Wiklander 			up->vals[n * 2] = (uintptr_t)params[n].memref.buffer;
59e86f1266SJens Wiklander 			up->vals[n * 2 + 1] = params[n].memref.size;
60e86f1266SJens Wiklander 			break;
61e86f1266SJens Wiklander 		default:
62e86f1266SJens Wiklander 			up->vals[n * 2] = 0;
63e86f1266SJens Wiklander 			up->vals[n * 2 + 1] = 0;
64e86f1266SJens Wiklander 			break;
65e86f1266SJens Wiklander 		}
66e86f1266SJens Wiklander 	}
67e86f1266SJens Wiklander }
68e86f1266SJens Wiklander 
69e86f1266SJens Wiklander void __utee_to_param(TEE_Param params[TEE_NUM_PARAMS],
70e86f1266SJens Wiklander 			uint32_t *param_types, const struct utee_params *up)
71e86f1266SJens Wiklander {
72e86f1266SJens Wiklander 	size_t n;
73e86f1266SJens Wiklander 	uint32_t types = up->types;
74e86f1266SJens Wiklander 
75e86f1266SJens Wiklander 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
76e86f1266SJens Wiklander 		uintptr_t a = up->vals[n * 2];
77e86f1266SJens Wiklander 		uintptr_t b = up->vals[n * 2 + 1];
78e86f1266SJens Wiklander 
79e86f1266SJens Wiklander 		switch (TEE_PARAM_TYPE_GET(types, n)) {
80e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INPUT:
81e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_VALUE_OUTPUT:
82e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INOUT:
83e86f1266SJens Wiklander 			params[n].value.a = a;
84e86f1266SJens Wiklander 			params[n].value.b = b;
85e86f1266SJens Wiklander 			break;
86e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INPUT:
87e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
88e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
89e86f1266SJens Wiklander 			params[n].memref.buffer = (void *)a;
90e86f1266SJens Wiklander 			params[n].memref.size = b;
91e86f1266SJens Wiklander 			break;
92e86f1266SJens Wiklander 		default:
93e86f1266SJens Wiklander 			break;
94e86f1266SJens Wiklander 		}
95e86f1266SJens Wiklander 	}
96e86f1266SJens Wiklander 
97e86f1266SJens Wiklander 	if (param_types)
98e86f1266SJens Wiklander 		*param_types = types;
99e86f1266SJens Wiklander }
100e86f1266SJens Wiklander 
101b0104773SPascal Brand TEE_Result TEE_OpenTASession(const TEE_UUID *destination,
102b0104773SPascal Brand 				uint32_t cancellationRequestTimeout,
10368540524SIgor Opaniuk 				uint32_t paramTypes,
10468540524SIgor Opaniuk 				TEE_Param params[TEE_NUM_PARAMS],
105b0104773SPascal Brand 				TEE_TASessionHandle *session,
106b0104773SPascal Brand 				uint32_t *returnOrigin)
107b0104773SPascal Brand {
108b0104773SPascal Brand 	TEE_Result res;
109e86f1266SJens Wiklander 	struct utee_params up;
110e86f1266SJens Wiklander 	uint32_t s;
111b0104773SPascal Brand 
112e86f1266SJens Wiklander 	__utee_from_param(&up, paramTypes, params);
113b0104773SPascal Brand 	res = utee_open_ta_session(destination, cancellationRequestTimeout,
114e86f1266SJens Wiklander 				   &up, &s, returnOrigin);
115e86f1266SJens Wiklander 	__utee_to_param(params, NULL, &up);
116b0104773SPascal Brand 	/*
117b0104773SPascal Brand 	 * Specification says that *session must hold TEE_HANDLE_NULL is
118b0104773SPascal Brand 	 * TEE_SUCCESS isn't returned. Set it here explicitly in case
119b0104773SPascal Brand 	 * the syscall fails before out parameters has been updated.
120b0104773SPascal Brand 	 */
121b0104773SPascal Brand 	if (res != TEE_SUCCESS)
122e86f1266SJens Wiklander 		s = TEE_HANDLE_NULL;
123b0104773SPascal Brand 
124e86f1266SJens Wiklander 	*session = (TEE_TASessionHandle)(uintptr_t)s;
125b0104773SPascal Brand 	return res;
126b0104773SPascal Brand }
127b0104773SPascal Brand 
128b0104773SPascal Brand void TEE_CloseTASession(TEE_TASessionHandle session)
129b0104773SPascal Brand {
130b0104773SPascal Brand 	if (session != TEE_HANDLE_NULL) {
131e86f1266SJens Wiklander 		TEE_Result res = utee_close_ta_session((uintptr_t)session);
132e86f1266SJens Wiklander 
133b0104773SPascal Brand 		if (res != TEE_SUCCESS)
134b0104773SPascal Brand 			TEE_Panic(res);
135b0104773SPascal Brand 	}
136b0104773SPascal Brand }
137b0104773SPascal Brand 
138b0104773SPascal Brand TEE_Result TEE_InvokeTACommand(TEE_TASessionHandle session,
139b0104773SPascal Brand 				uint32_t cancellationRequestTimeout,
140b0104773SPascal Brand 				uint32_t commandID, uint32_t paramTypes,
14168540524SIgor Opaniuk 				TEE_Param params[TEE_NUM_PARAMS],
14268540524SIgor Opaniuk 				uint32_t *returnOrigin)
143b0104773SPascal Brand {
144c15e5835SCedric Chaumont 	TEE_Result res;
1456709c3eaSCedric Chaumont 	uint32_t ret_origin;
146e86f1266SJens Wiklander 	struct utee_params up;
147c15e5835SCedric Chaumont 
148e86f1266SJens Wiklander 	__utee_from_param(&up, paramTypes, params);
149e86f1266SJens Wiklander 	res = utee_invoke_ta_command((uintptr_t)session,
150e86f1266SJens Wiklander 				      cancellationRequestTimeout,
151e86f1266SJens Wiklander 				      commandID, &up, &ret_origin);
152e86f1266SJens Wiklander 	__utee_to_param(params, NULL, &up);
1536709c3eaSCedric Chaumont 
1546709c3eaSCedric Chaumont 	if (returnOrigin != NULL)
1556709c3eaSCedric Chaumont 		*returnOrigin = ret_origin;
1566709c3eaSCedric Chaumont 
1576709c3eaSCedric Chaumont 	if (ret_origin == TEE_ORIGIN_TRUSTED_APP)
1586709c3eaSCedric Chaumont 		return res;
1596709c3eaSCedric Chaumont 
160c15e5835SCedric Chaumont 	if (res != TEE_SUCCESS &&
161c15e5835SCedric Chaumont 	    res != TEE_ERROR_OUT_OF_MEMORY &&
162c15e5835SCedric Chaumont 	    res != TEE_ERROR_TARGET_DEAD)
163c15e5835SCedric Chaumont 		TEE_Panic(res);
164c15e5835SCedric Chaumont 
165c15e5835SCedric Chaumont 	return res;
166b0104773SPascal Brand }
167b0104773SPascal Brand 
168b0104773SPascal Brand /* System API - Cancellations */
169b0104773SPascal Brand 
170b0104773SPascal Brand bool TEE_GetCancellationFlag(void)
171b0104773SPascal Brand {
172e86f1266SJens Wiklander 	uint32_t c;
173b0104773SPascal Brand 	TEE_Result res = utee_get_cancellation_flag(&c);
174e86f1266SJens Wiklander 
175b0104773SPascal Brand 	if (res != TEE_SUCCESS)
176e86f1266SJens Wiklander 		c = 0;
177e86f1266SJens Wiklander 	return !!c;
178b0104773SPascal Brand }
179b0104773SPascal Brand 
180b0104773SPascal Brand bool TEE_UnmaskCancellation(void)
181b0104773SPascal Brand {
182e86f1266SJens Wiklander 	uint32_t old_mask;
183b0104773SPascal Brand 	TEE_Result res = utee_unmask_cancellation(&old_mask);
184b0104773SPascal Brand 
185b0104773SPascal Brand 	if (res != TEE_SUCCESS)
186b0104773SPascal Brand 		TEE_Panic(res);
187e86f1266SJens Wiklander 	return !!old_mask;
188b0104773SPascal Brand }
189b0104773SPascal Brand 
190b0104773SPascal Brand bool TEE_MaskCancellation(void)
191b0104773SPascal Brand {
192e86f1266SJens Wiklander 	uint32_t old_mask;
193b0104773SPascal Brand 	TEE_Result res = utee_mask_cancellation(&old_mask);
194b0104773SPascal Brand 
195b0104773SPascal Brand 	if (res != TEE_SUCCESS)
196b0104773SPascal Brand 		TEE_Panic(res);
197e86f1266SJens Wiklander 	return !!old_mask;
198b0104773SPascal Brand }
199b0104773SPascal Brand 
200b0104773SPascal Brand /* System API - Memory Management */
201b0104773SPascal Brand 
202b0104773SPascal Brand TEE_Result TEE_CheckMemoryAccessRights(uint32_t accessFlags, void *buffer,
20379a3c601SCedric Chaumont 				       uint32_t size)
204b0104773SPascal Brand {
205b0104773SPascal Brand 	TEE_Result res;
206b0104773SPascal Brand 
207b0104773SPascal Brand 	if (size == 0)
208b0104773SPascal Brand 		return TEE_SUCCESS;
209b0104773SPascal Brand 
210b0104773SPascal Brand 	/* Check access rights against memory mapping */
211b0104773SPascal Brand 	res = utee_check_access_rights(accessFlags, buffer, size);
212b0104773SPascal Brand 	if (res != TEE_SUCCESS)
213b0104773SPascal Brand 		goto out;
214b0104773SPascal Brand 
215b0104773SPascal Brand 	/*
216b0104773SPascal Brand 	* Check access rights against input parameters
217b0104773SPascal Brand 	* Previous legacy code was removed and will need to be restored
218b0104773SPascal Brand 	*/
219b0104773SPascal Brand 
220b0104773SPascal Brand 	res = TEE_SUCCESS;
221b0104773SPascal Brand out:
222b0104773SPascal Brand 	return res;
223b0104773SPascal Brand }
224b0104773SPascal Brand 
2258f07fe6fSJerome Forissier void TEE_SetInstanceData(const void *instanceData)
226b0104773SPascal Brand {
227b0104773SPascal Brand 	tee_api_instance_data = instanceData;
228b0104773SPascal Brand }
229b0104773SPascal Brand 
2308f07fe6fSJerome Forissier const void *TEE_GetInstanceData(void)
231b0104773SPascal Brand {
232b0104773SPascal Brand 	return tee_api_instance_data;
233b0104773SPascal Brand }
234b0104773SPascal Brand 
235b0104773SPascal Brand void *TEE_MemMove(void *dest, const void *src, uint32_t size)
236b0104773SPascal Brand {
237b0104773SPascal Brand 	return memmove(dest, src, size);
238b0104773SPascal Brand }
239b0104773SPascal Brand 
240b0104773SPascal Brand int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, uint32_t size)
241b0104773SPascal Brand {
242b0104773SPascal Brand 	return memcmp(buffer1, buffer2, size);
243b0104773SPascal Brand }
244b0104773SPascal Brand 
245b0104773SPascal Brand void *TEE_MemFill(void *buff, uint32_t x, uint32_t size)
246b0104773SPascal Brand {
247b0104773SPascal Brand 	return memset(buff, x, size);
248b0104773SPascal Brand }
249b0104773SPascal Brand 
250b0104773SPascal Brand /* Date & Time API */
251b0104773SPascal Brand 
252b0104773SPascal Brand void TEE_GetSystemTime(TEE_Time *time)
253b0104773SPascal Brand {
254b0104773SPascal Brand 	TEE_Result res = utee_get_time(UTEE_TIME_CAT_SYSTEM, time);
255b0104773SPascal Brand 
256b0104773SPascal Brand 	if (res != TEE_SUCCESS)
257b36311adSJerome Forissier 		TEE_Panic(res);
258b0104773SPascal Brand }
259b0104773SPascal Brand 
260b0104773SPascal Brand TEE_Result TEE_Wait(uint32_t timeout)
261b0104773SPascal Brand {
262b0104773SPascal Brand 	TEE_Result res = utee_wait(timeout);
263b0104773SPascal Brand 
264b0104773SPascal Brand 	if (res != TEE_SUCCESS && res != TEE_ERROR_CANCEL)
265b0104773SPascal Brand 		TEE_Panic(res);
266b0104773SPascal Brand 
267b0104773SPascal Brand 	return res;
268b0104773SPascal Brand }
269b0104773SPascal Brand 
270b0104773SPascal Brand TEE_Result TEE_GetTAPersistentTime(TEE_Time *time)
271b0104773SPascal Brand {
272b64d6909SCedric Chaumont 	TEE_Result res;
273b64d6909SCedric Chaumont 
274b64d6909SCedric Chaumont 	res = utee_get_time(UTEE_TIME_CAT_TA_PERSISTENT, time);
275b64d6909SCedric Chaumont 
276b64d6909SCedric Chaumont 	if (res != TEE_SUCCESS && res != TEE_ERROR_OVERFLOW) {
277b64d6909SCedric Chaumont 		time->seconds = 0;
278b64d6909SCedric Chaumont 		time->millis = 0;
279b64d6909SCedric Chaumont 	}
280b64d6909SCedric Chaumont 
281b64d6909SCedric Chaumont 	if (res != TEE_SUCCESS &&
282b64d6909SCedric Chaumont 	    res != TEE_ERROR_TIME_NOT_SET &&
283b64d6909SCedric Chaumont 	    res != TEE_ERROR_TIME_NEEDS_RESET &&
284b64d6909SCedric Chaumont 	    res != TEE_ERROR_OVERFLOW &&
285b64d6909SCedric Chaumont 	    res != TEE_ERROR_OUT_OF_MEMORY)
286b64d6909SCedric Chaumont 		TEE_Panic(res);
287b64d6909SCedric Chaumont 
288b64d6909SCedric Chaumont 	return res;
289b0104773SPascal Brand }
290b0104773SPascal Brand 
291b0104773SPascal Brand TEE_Result TEE_SetTAPersistentTime(const TEE_Time *time)
292b0104773SPascal Brand {
293b64d6909SCedric Chaumont 	TEE_Result res;
294b64d6909SCedric Chaumont 
295b64d6909SCedric Chaumont 	res = utee_set_ta_time(time);
296b64d6909SCedric Chaumont 
297b64d6909SCedric Chaumont 	if (res != TEE_SUCCESS &&
298b64d6909SCedric Chaumont 	    res != TEE_ERROR_OUT_OF_MEMORY &&
299b64d6909SCedric Chaumont 	    res != TEE_ERROR_STORAGE_NO_SPACE)
300b64d6909SCedric Chaumont 		TEE_Panic(res);
301b64d6909SCedric Chaumont 
302b64d6909SCedric Chaumont 	return res;
303b0104773SPascal Brand }
304b0104773SPascal Brand 
305b0104773SPascal Brand void TEE_GetREETime(TEE_Time *time)
306b0104773SPascal Brand {
307b0104773SPascal Brand 	TEE_Result res = utee_get_time(UTEE_TIME_CAT_REE, time);
308b0104773SPascal Brand 
309b0104773SPascal Brand 	if (res != TEE_SUCCESS)
310b36311adSJerome Forissier 		TEE_Panic(res);
311b0104773SPascal Brand }
312b0104773SPascal Brand 
31379a3c601SCedric Chaumont void *TEE_Malloc(uint32_t len, uint32_t hint)
314b0104773SPascal Brand {
315b0104773SPascal Brand 	return tee_user_mem_alloc(len, hint);
316b0104773SPascal Brand }
317b0104773SPascal Brand 
318*c0ce02edSJens Wiklander void *TEE_Realloc(void *buffer, uint32_t newSize)
319b0104773SPascal Brand {
320b0104773SPascal Brand 	/*
321b0104773SPascal Brand 	 * GP TEE Internal API specifies newSize as 'uint32_t'.
322b0104773SPascal Brand 	 * use unsigned 'size_t' type. it is at least 32bit!
323b0104773SPascal Brand 	 */
3248f07fe6fSJerome Forissier 	return tee_user_mem_realloc((void *)buffer, (size_t) newSize);
325b0104773SPascal Brand }
326b0104773SPascal Brand 
327b0104773SPascal Brand void TEE_Free(void *buffer)
328b0104773SPascal Brand {
329b0104773SPascal Brand 	tee_user_mem_free(buffer);
330b0104773SPascal Brand }
331fa530828SPascal Brand 
332fa530828SPascal Brand /* Cache maintenance support (TA requires the CACHE_MAINTENANCE property) */
333fa530828SPascal Brand TEE_Result TEE_CacheClean(char *buf, size_t len)
334fa530828SPascal Brand {
335fa530828SPascal Brand 	return utee_cache_operation(buf, len, TEE_CACHECLEAN);
336fa530828SPascal Brand }
337fa530828SPascal Brand TEE_Result TEE_CacheFlush(char *buf, size_t len)
338fa530828SPascal Brand {
339fa530828SPascal Brand 	return utee_cache_operation(buf, len, TEE_CACHEFLUSH);
340fa530828SPascal Brand }
341fa530828SPascal Brand 
342fa530828SPascal Brand TEE_Result TEE_CacheInvalidate(char *buf, size_t len)
343fa530828SPascal Brand {
344fa530828SPascal Brand 	return utee_cache_operation(buf, len, TEE_CACHEINVALIDATE);
345fa530828SPascal Brand }
346