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