1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2014, STMicroelectronics International N.V.
4  */
5 #include <stdlib.h>
6 #include <string.h>
7 #include <string_ext.h>
8 #include <tee_api.h>
9 #include <tee_internal_api_extensions.h>
10 #include <types_ext.h>
11 #include <user_ta_header.h>
12 #include <utee_syscalls.h>
13 #include "tee_api_private.h"
14 
15 /*
16  * return a known non-NULL invalid pointer when the
17  * requested size is zero
18  */
19 #define TEE_NULL_SIZED_VA	((void *)1)
20 
21 static const void *tee_api_instance_data;
22 
23 /* System API - Internal Client API */
24 
copy_param(struct utee_params * up,uint32_t param_types,const TEE_Param params[TEE_NUM_PARAMS],void ** tmp_buf,size_t * tmp_len,void * tmp_va[TEE_NUM_PARAMS])25 static TEE_Result copy_param(struct utee_params *up, uint32_t param_types,
26 			     const TEE_Param params[TEE_NUM_PARAMS],
27 			     void **tmp_buf, size_t *tmp_len,
28 			     void *tmp_va[TEE_NUM_PARAMS])
29 {
30 	size_t n = 0;
31 	uint8_t *tb = NULL;
32 	size_t tbl = 0;
33 	size_t tmp_align = sizeof(vaddr_t) * 2;
34 	bool is_tmp_mem[TEE_NUM_PARAMS] = { false };
35 	void *b = NULL;
36 	size_t s = 0;
37 	const uint32_t flags = TEE_MEMORY_ACCESS_READ;
38 
39 	/*
40 	 * If a memory parameter points to TA private memory we need to
41 	 * allocate a temporary buffer to avoid exposing the memory
42 	 * directly to the called TA.
43 	 */
44 
45 	*tmp_buf = NULL;
46 	*tmp_len = 0;
47 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
48 		tmp_va[n] = NULL;
49 		switch (TEE_PARAM_TYPE_GET(param_types, n)) {
50 		case TEE_PARAM_TYPE_MEMREF_INPUT:
51 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
52 		case TEE_PARAM_TYPE_MEMREF_INOUT:
53 			b = params[n].memref.buffer;
54 			s = params[n].memref.size;
55 			/*
56 			 * We're only allocating temporary memory if the
57 			 * buffer is completely within TA memory. If it's
58 			 * NULL, empty, partially outside or completely
59 			 * outside TA memory there's nothing more we need
60 			 * to do here. If there's security/permissions
61 			 * problem we'll get an error in the
62 			 * invoke_command/open_session below.
63 			 */
64 			if (b && s &&
65 			    !TEE_CheckMemoryAccessRights(flags, b, s)) {
66 				is_tmp_mem[n] = true;
67 				tbl += ROUNDUP(s, tmp_align);
68 			}
69 			break;
70 		default:
71 			break;
72 		}
73 	}
74 
75 	if (tbl) {
76 		tb = tee_map_zi(tbl, TEE_MEMORY_ACCESS_ANY_OWNER);
77 		if (!tb)
78 			return TEE_ERROR_OUT_OF_MEMORY;
79 		*tmp_buf = tb;
80 		*tmp_len = tbl;
81 	}
82 
83 	up->types = param_types;
84 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
85 		switch (TEE_PARAM_TYPE_GET(param_types, n)) {
86 		case TEE_PARAM_TYPE_VALUE_INPUT:
87 		case TEE_PARAM_TYPE_VALUE_INOUT:
88 			up->vals[n * 2] = params[n].value.a;
89 			up->vals[n * 2 + 1] = params[n].value.b;
90 			break;
91 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
92 		case TEE_PARAM_TYPE_MEMREF_INOUT:
93 		case TEE_PARAM_TYPE_MEMREF_INPUT:
94 			s = params[n].memref.size;
95 			if (is_tmp_mem[n]) {
96 				b = tb;
97 				tmp_va[n] = tb;
98 				tb += ROUNDUP(s, tmp_align);
99 				if (TEE_PARAM_TYPE_GET(param_types, n) !=
100 				    TEE_PARAM_TYPE_MEMREF_OUTPUT)
101 					memcpy(b, params[n].memref.buffer, s);
102 			} else {
103 				b = params[n].memref.buffer;
104 			}
105 			up->vals[n * 2] = (vaddr_t)b;
106 			up->vals[n * 2 + 1] = s;
107 			break;
108 		default:
109 			up->vals[n * 2] = 0;
110 			up->vals[n * 2 + 1] = 0;
111 			break;
112 		}
113 	}
114 
115 	return TEE_SUCCESS;
116 }
117 
update_out_param(TEE_Param params[TEE_NUM_PARAMS],void * tmp_va[TEE_NUM_PARAMS],const struct utee_params * up)118 static void update_out_param(TEE_Param params[TEE_NUM_PARAMS],
119 			     void *tmp_va[TEE_NUM_PARAMS],
120 			     const struct utee_params *up)
121 {
122 	size_t n;
123 	uint32_t types = up->types;
124 
125 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
126 		uintptr_t a = up->vals[n * 2];
127 		uintptr_t b = up->vals[n * 2 + 1];
128 
129 		switch (TEE_PARAM_TYPE_GET(types, n)) {
130 		case TEE_PARAM_TYPE_VALUE_OUTPUT:
131 		case TEE_PARAM_TYPE_VALUE_INOUT:
132 			params[n].value.a = a;
133 			params[n].value.b = b;
134 			break;
135 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
136 		case TEE_PARAM_TYPE_MEMREF_INOUT:
137 			if (tmp_va[n])
138 				memcpy(params[n].memref.buffer, tmp_va[n],
139 				       MIN(b, params[n].memref.size));
140 			params[n].memref.size = b;
141 			break;
142 		default:
143 			break;
144 		}
145 	}
146 }
147 
TEE_OpenTASession(const TEE_UUID * destination,uint32_t cancellationRequestTimeout,uint32_t paramTypes,TEE_Param params[TEE_NUM_PARAMS],TEE_TASessionHandle * session,uint32_t * returnOrigin)148 TEE_Result TEE_OpenTASession(const TEE_UUID *destination,
149 				uint32_t cancellationRequestTimeout,
150 				uint32_t paramTypes,
151 				TEE_Param params[TEE_NUM_PARAMS],
152 				TEE_TASessionHandle *session,
153 				uint32_t *returnOrigin)
154 {
155 	TEE_Result res = TEE_SUCCESS;
156 	struct utee_params up;
157 	uint32_t s = 0;
158 	void *tmp_buf = NULL;
159 	size_t tmp_len = 0;
160 	void *tmp_va[TEE_NUM_PARAMS] = { NULL };
161 
162 	if (paramTypes)
163 		__utee_check_inout_annotation(params,
164 					      sizeof(TEE_Param) *
165 					      TEE_NUM_PARAMS);
166 	__utee_check_out_annotation(session, sizeof(*session));
167 
168 	res = copy_param(&up, paramTypes, params, &tmp_buf, &tmp_len, tmp_va);
169 	if (res)
170 		goto out;
171 	res = _utee_open_ta_session(destination, cancellationRequestTimeout,
172 				    &up, &s, returnOrigin);
173 	update_out_param(params, tmp_va, &up);
174 	if (tmp_buf) {
175 		TEE_Result res2 = tee_unmap(tmp_buf, tmp_len);
176 
177 		if (res2)
178 			TEE_Panic(res2);
179 	}
180 
181 out:
182 	/*
183 	 * Specification says that *session must hold TEE_HANDLE_NULL is
184 	 * TEE_SUCCESS isn't returned. Set it here explicitly in case
185 	 * the syscall fails before out parameters has been updated.
186 	 */
187 	if (res != TEE_SUCCESS)
188 		s = TEE_HANDLE_NULL;
189 
190 	*session = (TEE_TASessionHandle)(uintptr_t)s;
191 	return res;
192 }
193 
TEE_CloseTASession(TEE_TASessionHandle session)194 void TEE_CloseTASession(TEE_TASessionHandle session)
195 {
196 	if (session != TEE_HANDLE_NULL) {
197 		TEE_Result res = _utee_close_ta_session((uintptr_t)session);
198 
199 		if (res != TEE_SUCCESS)
200 			TEE_Panic(res);
201 	}
202 }
203 
TEE_InvokeTACommand(TEE_TASessionHandle session,uint32_t cancellationRequestTimeout,uint32_t commandID,uint32_t paramTypes,TEE_Param params[TEE_NUM_PARAMS],uint32_t * returnOrigin)204 TEE_Result TEE_InvokeTACommand(TEE_TASessionHandle session,
205 				uint32_t cancellationRequestTimeout,
206 				uint32_t commandID, uint32_t paramTypes,
207 				TEE_Param params[TEE_NUM_PARAMS],
208 				uint32_t *returnOrigin)
209 {
210 	TEE_Result res = TEE_SUCCESS;
211 	uint32_t ret_origin = TEE_ORIGIN_TEE;
212 	struct utee_params up;
213 	void *tmp_buf = NULL;
214 	size_t tmp_len = 0;
215 	void *tmp_va[TEE_NUM_PARAMS] = { NULL };
216 
217 	if (paramTypes)
218 		__utee_check_inout_annotation(params,
219 					      sizeof(TEE_Param) *
220 					      TEE_NUM_PARAMS);
221 	if (returnOrigin)
222 		__utee_check_out_annotation(returnOrigin,
223 					    sizeof(*returnOrigin));
224 
225 	res = copy_param(&up, paramTypes, params, &tmp_buf, &tmp_len, tmp_va);
226 	if (res)
227 		goto out;
228 	res = _utee_invoke_ta_command((uintptr_t)session,
229 				      cancellationRequestTimeout,
230 				      commandID, &up, &ret_origin);
231 	update_out_param(params, tmp_va, &up);
232 	if (tmp_buf) {
233 		TEE_Result res2 = tee_unmap(tmp_buf, tmp_len);
234 
235 		if (res2)
236 			TEE_Panic(res2);
237 	}
238 
239 out:
240 	if (returnOrigin != NULL)
241 		*returnOrigin = ret_origin;
242 
243 	if (ret_origin == TEE_ORIGIN_TRUSTED_APP)
244 		return res;
245 
246 	if (res != TEE_SUCCESS &&
247 	    res != TEE_ERROR_OUT_OF_MEMORY &&
248 	    res != TEE_ERROR_TARGET_DEAD)
249 		TEE_Panic(res);
250 
251 	return res;
252 }
253 
254 /* System API - Cancellations */
255 
TEE_GetCancellationFlag(void)256 bool TEE_GetCancellationFlag(void)
257 {
258 	uint32_t c;
259 	TEE_Result res = _utee_get_cancellation_flag(&c);
260 
261 	if (res != TEE_SUCCESS)
262 		c = 0;
263 	return !!c;
264 }
265 
TEE_UnmaskCancellation(void)266 bool TEE_UnmaskCancellation(void)
267 {
268 	uint32_t old_mask;
269 	TEE_Result res = _utee_unmask_cancellation(&old_mask);
270 
271 	if (res != TEE_SUCCESS)
272 		TEE_Panic(res);
273 	return !!old_mask;
274 }
275 
TEE_MaskCancellation(void)276 bool TEE_MaskCancellation(void)
277 {
278 	uint32_t old_mask;
279 	TEE_Result res = _utee_mask_cancellation(&old_mask);
280 
281 	if (res != TEE_SUCCESS)
282 		TEE_Panic(res);
283 	return !!old_mask;
284 }
285 
286 /* System API - Memory Management */
287 
TEE_CheckMemoryAccessRights(uint32_t accessFlags,void * buffer,uint32_t size)288 TEE_Result TEE_CheckMemoryAccessRights(uint32_t accessFlags, void *buffer,
289 				       uint32_t size)
290 {
291 	TEE_Result res;
292 
293 	if (size == 0)
294 		return TEE_SUCCESS;
295 
296 	/* Check access rights against memory mapping */
297 	res = _utee_check_access_rights(accessFlags, buffer, size);
298 	if (res != TEE_SUCCESS)
299 		goto out;
300 
301 	/*
302 	* Check access rights against input parameters
303 	* Previous legacy code was removed and will need to be restored
304 	*/
305 
306 	res = TEE_SUCCESS;
307 out:
308 	return res;
309 }
310 
TEE_SetInstanceData(const void * instanceData)311 void TEE_SetInstanceData(const void *instanceData)
312 {
313 	tee_api_instance_data = instanceData;
314 }
315 
TEE_GetInstanceData(void)316 const void *TEE_GetInstanceData(void)
317 {
318 	return tee_api_instance_data;
319 }
320 
TEE_MemMove(void * dest,const void * src,uint32_t size)321 void *TEE_MemMove(void *dest, const void *src, uint32_t size)
322 {
323 	return memmove(dest, src, size);
324 }
325 
TEE_MemCompare(const void * buffer1,const void * buffer2,uint32_t size)326 int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, uint32_t size)
327 {
328 	return consttime_memcmp(buffer1, buffer2, size);
329 }
330 
TEE_MemFill(void * buff,uint32_t x,uint32_t size)331 void *TEE_MemFill(void *buff, uint32_t x, uint32_t size)
332 {
333 	return memset(buff, x, size);
334 }
335 
336 /* Date & Time API */
337 
TEE_GetSystemTime(TEE_Time * time)338 void TEE_GetSystemTime(TEE_Time *time)
339 {
340 	TEE_Result res = _utee_get_time(UTEE_TIME_CAT_SYSTEM, time);
341 
342 	if (res != TEE_SUCCESS)
343 		TEE_Panic(res);
344 }
345 
TEE_Wait(uint32_t timeout)346 TEE_Result TEE_Wait(uint32_t timeout)
347 {
348 	TEE_Result res = _utee_wait(timeout);
349 
350 	if (res != TEE_SUCCESS && res != TEE_ERROR_CANCEL)
351 		TEE_Panic(res);
352 
353 	return res;
354 }
355 
TEE_GetTAPersistentTime(TEE_Time * time)356 TEE_Result TEE_GetTAPersistentTime(TEE_Time *time)
357 {
358 	TEE_Result res;
359 
360 	res = _utee_get_time(UTEE_TIME_CAT_TA_PERSISTENT, time);
361 
362 	if (res != TEE_SUCCESS && res != TEE_ERROR_OVERFLOW) {
363 		time->seconds = 0;
364 		time->millis = 0;
365 	}
366 
367 	if (res != TEE_SUCCESS &&
368 	    res != TEE_ERROR_TIME_NOT_SET &&
369 	    res != TEE_ERROR_TIME_NEEDS_RESET &&
370 	    res != TEE_ERROR_OVERFLOW &&
371 	    res != TEE_ERROR_OUT_OF_MEMORY)
372 		TEE_Panic(res);
373 
374 	return res;
375 }
376 
TEE_SetTAPersistentTime(const TEE_Time * time)377 TEE_Result TEE_SetTAPersistentTime(const TEE_Time *time)
378 {
379 	TEE_Result res;
380 
381 	res = _utee_set_ta_time(time);
382 
383 	if (res != TEE_SUCCESS &&
384 	    res != TEE_ERROR_OUT_OF_MEMORY &&
385 	    res != TEE_ERROR_STORAGE_NO_SPACE)
386 		TEE_Panic(res);
387 
388 	return res;
389 }
390 
TEE_GetREETime(TEE_Time * time)391 void TEE_GetREETime(TEE_Time *time)
392 {
393 	TEE_Result res = _utee_get_time(UTEE_TIME_CAT_REE, time);
394 
395 	if (res != TEE_SUCCESS)
396 		TEE_Panic(res);
397 }
398 
TEE_Malloc(uint32_t len,uint32_t hint)399 void *TEE_Malloc(uint32_t len, uint32_t hint)
400 {
401 	if (!len)
402 		return TEE_NULL_SIZED_VA;
403 
404 	if (hint == TEE_MALLOC_FILL_ZERO)
405 		return calloc(1, len);
406 	else if (hint == TEE_USER_MEM_HINT_NO_FILL_ZERO)
407 		return malloc(len);
408 
409 	EMSG("Invalid hint %#" PRIx32, hint);
410 
411 	return NULL;
412 }
413 
TEE_Realloc(void * buffer,uint32_t newSize)414 void *TEE_Realloc(void *buffer, uint32_t newSize)
415 {
416 	if (!newSize) {
417 		TEE_Free(buffer);
418 		return TEE_NULL_SIZED_VA;
419 	}
420 
421 	if (buffer == TEE_NULL_SIZED_VA)
422 		return calloc(1, newSize);
423 
424 	return realloc(buffer, newSize);
425 }
426 
TEE_Free(void * buffer)427 void TEE_Free(void *buffer)
428 {
429 	if (buffer != TEE_NULL_SIZED_VA)
430 		free(buffer);
431 }
432 
433 /* Cache maintenance support (TA requires the CACHE_MAINTENANCE property) */
TEE_CacheClean(char * buf,size_t len)434 TEE_Result TEE_CacheClean(char *buf, size_t len)
435 {
436 	return _utee_cache_operation(buf, len, TEE_CACHECLEAN);
437 }
TEE_CacheFlush(char * buf,size_t len)438 TEE_Result TEE_CacheFlush(char *buf, size_t len)
439 {
440 	return _utee_cache_operation(buf, len, TEE_CACHEFLUSH);
441 }
442 
TEE_CacheInvalidate(char * buf,size_t len)443 TEE_Result TEE_CacheInvalidate(char *buf, size_t len)
444 {
445 	return _utee_cache_operation(buf, len, TEE_CACHEINVALIDATE);
446 }
447