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