xref: /optee_os/lib/libutee/tee_api.c (revision 30e5e0be8c4e663f68ba88716dde9cad2ae33f06)
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 
25 static void copy_param(struct utee_params *up, uint32_t param_types,
26 		       const TEE_Param params[TEE_NUM_PARAMS])
27 {
28 	size_t n = 0;
29 	uint64_t a = 0;
30 	uint64_t b = 0;
31 
32 	up->types = param_types;
33 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
34 		switch (TEE_PARAM_TYPE_GET(up->types, n)) {
35 		case TEE_PARAM_TYPE_VALUE_INPUT:
36 		case TEE_PARAM_TYPE_VALUE_INOUT:
37 			a = params[n].value.a;
38 			b = params[n].value.b;
39 			break;
40 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
41 		case TEE_PARAM_TYPE_MEMREF_INOUT:
42 		case TEE_PARAM_TYPE_MEMREF_INPUT:
43 			a = (vaddr_t)params[n].memref.buffer;
44 			b = params[n].memref.size;
45 			break;
46 		default:
47 			a = 0;
48 			b = 0;
49 		}
50 		up->vals[n * 2] = a;
51 		up->vals[n * 2 + 1] = b;
52 	}
53 }
54 
55 static void copy_gp11_param(struct utee_params *up, uint32_t param_types,
56 			    const __GP11_TEE_Param params[TEE_NUM_PARAMS])
57 {
58 	size_t n = 0;
59 	uint64_t a = 0;
60 	uint64_t b = 0;
61 
62 	up->types = param_types;
63 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
64 		switch (TEE_PARAM_TYPE_GET(up->types, n)) {
65 		case TEE_PARAM_TYPE_VALUE_INPUT:
66 		case TEE_PARAM_TYPE_VALUE_INOUT:
67 			a = params[n].value.a;
68 			b = params[n].value.b;
69 			break;
70 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
71 		case TEE_PARAM_TYPE_MEMREF_INOUT:
72 		case TEE_PARAM_TYPE_MEMREF_INPUT:
73 			a = (vaddr_t)params[n].memref.buffer;
74 			b = params[n].memref.size;
75 			break;
76 		default:
77 			a = 0;
78 			b = 0;
79 		}
80 		up->vals[n * 2] = a;
81 		up->vals[n * 2 + 1] = b;
82 	}
83 }
84 
85 static TEE_Result map_tmp_param(struct utee_params *up, void **tmp_buf,
86 				size_t *tmp_len, void *tmp_va[TEE_NUM_PARAMS])
87 {
88 	size_t n = 0;
89 	uint8_t *tb = NULL;
90 	size_t tbl = 0;
91 	size_t tmp_align = sizeof(vaddr_t) * 2;
92 	bool is_tmp_mem[TEE_NUM_PARAMS] = { false };
93 	void *b = NULL;
94 	size_t s = 0;
95 	const uint32_t flags = TEE_MEMORY_ACCESS_READ;
96 
97 	/*
98 	 * If a memory parameter points to TA private memory we need to
99 	 * allocate a temporary buffer to avoid exposing the memory
100 	 * directly to the called TA.
101 	 */
102 
103 	*tmp_buf = NULL;
104 	*tmp_len = 0;
105 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
106 		tmp_va[n] = NULL;
107 		switch (TEE_PARAM_TYPE_GET(up->types, n)) {
108 		case TEE_PARAM_TYPE_MEMREF_INPUT:
109 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
110 		case TEE_PARAM_TYPE_MEMREF_INOUT:
111 			b = (void *)(vaddr_t)up->vals[n * 2];
112 			s = up->vals[n * 2 + 1];
113 			/*
114 			 * We're only allocating temporary memory if the
115 			 * buffer is completely within TA memory. If it's
116 			 * NULL, empty, partially outside or completely
117 			 * outside TA memory there's nothing more we need
118 			 * to do here. If there's security/permissions
119 			 * problem we'll get an error in the
120 			 * invoke_command/open_session below.
121 			 */
122 			if (b && s &&
123 			    !TEE_CheckMemoryAccessRights(flags, b, s)) {
124 				is_tmp_mem[n] = true;
125 				tbl += ROUNDUP(s, tmp_align);
126 			}
127 			break;
128 		default:
129 			break;
130 		}
131 	}
132 
133 	if (tbl) {
134 		tb = tee_map_zi(tbl, TEE_MEMORY_ACCESS_ANY_OWNER);
135 		if (!tb)
136 			return TEE_ERROR_OUT_OF_MEMORY;
137 		*tmp_buf = tb;
138 		*tmp_len = tbl;
139 	}
140 
141 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
142 		switch (TEE_PARAM_TYPE_GET(up->types, n)) {
143 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
144 		case TEE_PARAM_TYPE_MEMREF_INOUT:
145 		case TEE_PARAM_TYPE_MEMREF_INPUT:
146 			if (!is_tmp_mem[n])
147 				break;
148 			s = up->vals[n * 2 + 1];
149 			b = (void *)(vaddr_t)up->vals[n * 2];
150 			tmp_va[n] = tb;
151 			tb += ROUNDUP(s, tmp_align);
152 			up->vals[n * 2] = (vaddr_t)tmp_va[n];
153 			if (TEE_PARAM_TYPE_GET(up->types, n) !=
154 			    TEE_PARAM_TYPE_MEMREF_OUTPUT)
155 				memcpy(tmp_va[n], b, s);
156 			break;
157 		default:
158 			break;
159 		}
160 	}
161 
162 	return TEE_SUCCESS;
163 
164 }
165 
166 static void update_out_param(TEE_Param params[TEE_NUM_PARAMS],
167 			     void *tmp_va[TEE_NUM_PARAMS],
168 			     const struct utee_params *up)
169 {
170 	size_t n;
171 	uint32_t types = up->types;
172 
173 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
174 		uintptr_t a = up->vals[n * 2];
175 		uintptr_t b = up->vals[n * 2 + 1];
176 
177 		switch (TEE_PARAM_TYPE_GET(types, n)) {
178 		case TEE_PARAM_TYPE_VALUE_OUTPUT:
179 		case TEE_PARAM_TYPE_VALUE_INOUT:
180 			params[n].value.a = a;
181 			params[n].value.b = b;
182 			break;
183 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
184 		case TEE_PARAM_TYPE_MEMREF_INOUT:
185 			if (tmp_va[n])
186 				memcpy(params[n].memref.buffer, tmp_va[n],
187 				       MIN(b, params[n].memref.size));
188 			params[n].memref.size = b;
189 			break;
190 		default:
191 			break;
192 		}
193 	}
194 }
195 
196 static void update_out_gp11_param(__GP11_TEE_Param params[TEE_NUM_PARAMS],
197 				  void *tmp_va[TEE_NUM_PARAMS],
198 				  const struct utee_params *up)
199 {
200 	size_t n = 0;
201 	uint32_t types = up->types;
202 
203 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
204 		uintptr_t a = up->vals[n * 2];
205 		uintptr_t b = up->vals[n * 2 + 1];
206 
207 		switch (TEE_PARAM_TYPE_GET(types, n)) {
208 		case TEE_PARAM_TYPE_VALUE_OUTPUT:
209 		case TEE_PARAM_TYPE_VALUE_INOUT:
210 			params[n].value.a = a;
211 			params[n].value.b = b;
212 			break;
213 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
214 		case TEE_PARAM_TYPE_MEMREF_INOUT:
215 			if (tmp_va[n])
216 				memcpy(params[n].memref.buffer, tmp_va[n],
217 				       MIN(b, params[n].memref.size));
218 			params[n].memref.size = b;
219 			break;
220 		default:
221 			break;
222 		}
223 	}
224 }
225 
226 static bool bufs_intersect(void *buf1, size_t sz1, void *buf2, size_t sz2)
227 {
228 	vaddr_t b1 = (vaddr_t)buf1;
229 	vaddr_t b2 = (vaddr_t)buf2;
230 	vaddr_t e1 = b1 + sz1 - 1;
231 	vaddr_t e2 = b2 + sz2 - 1;
232 
233 	if (!sz1 || !sz2)
234 		return false;
235 
236 	if (e1 < b2 || e2 < b1)
237 		return false;
238 
239 	return true;
240 }
241 
242 static TEE_Result check_mem_access_rights_params(uint32_t flags, void *buf,
243 						 size_t len)
244 {
245 	size_t n = 0;
246 
247 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
248 		uint32_t f = TEE_MEMORY_ACCESS_ANY_OWNER;
249 
250 		switch (TEE_PARAM_TYPE_GET(ta_param_types, n)) {
251 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
252 		case TEE_PARAM_TYPE_MEMREF_INOUT:
253 			f |= TEE_MEMORY_ACCESS_WRITE;
254 			fallthrough;
255 		case TEE_PARAM_TYPE_MEMREF_INPUT:
256 			f |= TEE_MEMORY_ACCESS_READ;
257 			if (bufs_intersect(buf, len,
258 					   ta_params[n].memref.buffer,
259 					   ta_params[n].memref.size)) {
260 				if ((flags & f) != flags)
261 					return TEE_ERROR_ACCESS_DENIED;
262 			}
263 			break;
264 		default:
265 			break;
266 		}
267 	}
268 
269 	return TEE_SUCCESS;
270 }
271 
272 static void check_invoke_param(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS])
273 {
274 	size_t n = 0;
275 
276 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
277 		uint32_t f = TEE_MEMORY_ACCESS_ANY_OWNER;
278 		void *buf = params[n].memref.buffer;
279 		size_t size = params[n].memref.size;
280 
281 		switch (TEE_PARAM_TYPE_GET(pt, n)) {
282 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
283 		case TEE_PARAM_TYPE_MEMREF_INOUT:
284 			f |= TEE_MEMORY_ACCESS_WRITE;
285 			fallthrough;
286 		case TEE_PARAM_TYPE_MEMREF_INPUT:
287 			f |= TEE_MEMORY_ACCESS_READ;
288 			if (check_mem_access_rights_params(f, buf, size))
289 				TEE_Panic(0);
290 			break;
291 		default:
292 			break;
293 		}
294 	}
295 }
296 
297 TEE_Result TEE_OpenTASession(const TEE_UUID *destination,
298 				uint32_t cancellationRequestTimeout,
299 				uint32_t paramTypes,
300 				TEE_Param params[TEE_NUM_PARAMS],
301 				TEE_TASessionHandle *session,
302 				uint32_t *returnOrigin)
303 {
304 	TEE_Result res = TEE_SUCCESS;
305 	struct utee_params up = { };
306 	uint32_t s = 0;
307 	void *tmp_buf = NULL;
308 	size_t tmp_len = 0;
309 	void *tmp_va[TEE_NUM_PARAMS] = { NULL };
310 
311 	if (paramTypes) {
312 		__utee_check_inout_annotation(params,
313 					      sizeof(TEE_Param) *
314 					      TEE_NUM_PARAMS);
315 		check_invoke_param(paramTypes, params);
316 	}
317 	__utee_check_out_annotation(session, sizeof(*session));
318 
319 	copy_param(&up, paramTypes, params);
320 	res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va);
321 	if (res)
322 		goto out;
323 	res = _utee_open_ta_session(destination, cancellationRequestTimeout,
324 				    &up, &s, returnOrigin);
325 	update_out_param(params, tmp_va, &up);
326 	if (tmp_buf) {
327 		TEE_Result res2 = tee_unmap(tmp_buf, tmp_len);
328 
329 		if (res2)
330 			TEE_Panic(res2);
331 	}
332 
333 out:
334 	/*
335 	 * Specification says that *session must hold TEE_HANDLE_NULL is
336 	 * TEE_SUCCESS isn't returned. Set it here explicitly in case
337 	 * the syscall fails before out parameters has been updated.
338 	 */
339 	if (res != TEE_SUCCESS)
340 		s = TEE_HANDLE_NULL;
341 
342 	*session = (TEE_TASessionHandle)(uintptr_t)s;
343 	return res;
344 }
345 
346 TEE_Result __GP11_TEE_OpenTASession(const TEE_UUID *destination,
347 				    uint32_t cancellationRequestTimeout,
348 				    uint32_t paramTypes,
349 				    __GP11_TEE_Param params[TEE_NUM_PARAMS],
350 				    TEE_TASessionHandle *session,
351 				    uint32_t *returnOrigin)
352 {
353 	TEE_Result res = TEE_SUCCESS;
354 	struct utee_params up = { };
355 	uint32_t s = 0;
356 	void *tmp_buf = NULL;
357 	size_t tmp_len = 0;
358 	void *tmp_va[TEE_NUM_PARAMS] = { NULL };
359 
360 	if (paramTypes)
361 		__utee_check_inout_annotation(params,
362 					      sizeof(__GP11_TEE_Param) *
363 					      TEE_NUM_PARAMS);
364 	__utee_check_out_annotation(session, sizeof(*session));
365 
366 	copy_gp11_param(&up, paramTypes, params);
367 	res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va);
368 	if (res)
369 		goto out;
370 	res = _utee_open_ta_session(destination, cancellationRequestTimeout,
371 				    &up, &s, returnOrigin);
372 	update_out_gp11_param(params, tmp_va, &up);
373 	if (tmp_buf) {
374 		TEE_Result res2 = tee_unmap(tmp_buf, tmp_len);
375 
376 		if (res2)
377 			TEE_Panic(res2);
378 	}
379 
380 out:
381 	/*
382 	 * Specification says that *session must hold TEE_HANDLE_NULL if
383 	 * TEE_SUCCESS isn't returned. Set it here explicitly in case
384 	 * the syscall fails before out parameters has been updated.
385 	 */
386 	if (res != TEE_SUCCESS)
387 		s = TEE_HANDLE_NULL;
388 
389 	*session = (TEE_TASessionHandle)(uintptr_t)s;
390 	return res;
391 }
392 
393 void TEE_CloseTASession(TEE_TASessionHandle session)
394 {
395 	if (session != TEE_HANDLE_NULL) {
396 		TEE_Result res = _utee_close_ta_session((uintptr_t)session);
397 
398 		if (res != TEE_SUCCESS)
399 			TEE_Panic(res);
400 	}
401 }
402 
403 TEE_Result TEE_InvokeTACommand(TEE_TASessionHandle session,
404 				uint32_t cancellationRequestTimeout,
405 				uint32_t commandID, uint32_t paramTypes,
406 				TEE_Param params[TEE_NUM_PARAMS],
407 				uint32_t *returnOrigin)
408 {
409 	TEE_Result res = TEE_SUCCESS;
410 	uint32_t ret_origin = TEE_ORIGIN_TEE;
411 	struct utee_params up = { };
412 	void *tmp_buf = NULL;
413 	size_t tmp_len = 0;
414 	void *tmp_va[TEE_NUM_PARAMS] = { NULL };
415 
416 	if (paramTypes) {
417 		__utee_check_inout_annotation(params,
418 					      sizeof(TEE_Param) *
419 					      TEE_NUM_PARAMS);
420 		check_invoke_param(paramTypes, params);
421 	}
422 	if (returnOrigin)
423 		__utee_check_out_annotation(returnOrigin,
424 					    sizeof(*returnOrigin));
425 
426 	copy_param(&up, paramTypes, params);
427 	res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va);
428 	if (res)
429 		goto out;
430 	res = _utee_invoke_ta_command((uintptr_t)session,
431 				      cancellationRequestTimeout,
432 				      commandID, &up, &ret_origin);
433 	update_out_param(params, tmp_va, &up);
434 	if (tmp_buf) {
435 		TEE_Result res2 = tee_unmap(tmp_buf, tmp_len);
436 
437 		if (res2)
438 			TEE_Panic(res2);
439 	}
440 
441 out:
442 	if (returnOrigin != NULL)
443 		*returnOrigin = ret_origin;
444 
445 	if (ret_origin == TEE_ORIGIN_TRUSTED_APP)
446 		return res;
447 
448 	if (res != TEE_SUCCESS &&
449 	    res != TEE_ERROR_OUT_OF_MEMORY &&
450 	    res != TEE_ERROR_TARGET_DEAD)
451 		TEE_Panic(res);
452 
453 	return res;
454 }
455 
456 TEE_Result __GP11_TEE_InvokeTACommand(TEE_TASessionHandle session,
457 				      uint32_t cancellationRequestTimeout,
458 				      uint32_t commandID, uint32_t paramTypes,
459 				      __GP11_TEE_Param params[TEE_NUM_PARAMS],
460 				      uint32_t *returnOrigin)
461 {
462 	TEE_Result res = TEE_SUCCESS;
463 	uint32_t ret_origin = TEE_ORIGIN_TEE;
464 	struct utee_params up = { };
465 	void *tmp_buf = NULL;
466 	size_t tmp_len = 0;
467 	void *tmp_va[TEE_NUM_PARAMS] = { NULL };
468 
469 	if (paramTypes)
470 		__utee_check_inout_annotation(params,
471 					      sizeof(__GP11_TEE_Param) *
472 					      TEE_NUM_PARAMS);
473 	if (returnOrigin)
474 		__utee_check_out_annotation(returnOrigin,
475 					    sizeof(*returnOrigin));
476 
477 	copy_gp11_param(&up, paramTypes, params);
478 	res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va);
479 	if (res)
480 		goto out;
481 	res = _utee_invoke_ta_command((uintptr_t)session,
482 				      cancellationRequestTimeout,
483 				      commandID, &up, &ret_origin);
484 	update_out_gp11_param(params, tmp_va, &up);
485 	if (tmp_buf) {
486 		TEE_Result res2 = tee_unmap(tmp_buf, tmp_len);
487 
488 		if (res2)
489 			TEE_Panic(res2);
490 	}
491 
492 out:
493 	if (returnOrigin)
494 		*returnOrigin = ret_origin;
495 
496 	if (ret_origin == TEE_ORIGIN_TRUSTED_APP)
497 		return res;
498 
499 	if (res != TEE_SUCCESS &&
500 	    res != TEE_ERROR_OUT_OF_MEMORY &&
501 	    res != TEE_ERROR_TARGET_DEAD)
502 		TEE_Panic(res);
503 
504 	return res;
505 }
506 
507 /* System API - Cancellations */
508 
509 bool TEE_GetCancellationFlag(void)
510 {
511 	uint32_t c;
512 	TEE_Result res = _utee_get_cancellation_flag(&c);
513 
514 	if (res != TEE_SUCCESS)
515 		c = 0;
516 	return !!c;
517 }
518 
519 bool TEE_UnmaskCancellation(void)
520 {
521 	uint32_t old_mask;
522 	TEE_Result res = _utee_unmask_cancellation(&old_mask);
523 
524 	if (res != TEE_SUCCESS)
525 		TEE_Panic(res);
526 	return !!old_mask;
527 }
528 
529 bool TEE_MaskCancellation(void)
530 {
531 	uint32_t old_mask;
532 	TEE_Result res = _utee_mask_cancellation(&old_mask);
533 
534 	if (res != TEE_SUCCESS)
535 		TEE_Panic(res);
536 	return !!old_mask;
537 }
538 
539 /* System API - Memory Management */
540 
541 TEE_Result TEE_CheckMemoryAccessRights(uint32_t accessFlags, void *buffer,
542 				       size_t size)
543 {
544 	uint32_t flags = accessFlags;
545 
546 	if (!size)
547 		return TEE_SUCCESS;
548 
549 	/*
550 	 * Check access rights against memory mapping. If this check is
551 	 * OK the size can't cause an overflow when added with buffer.
552 	 */
553 	if (_utee_check_access_rights(accessFlags, buffer, size))
554 		return TEE_ERROR_ACCESS_DENIED;
555 
556 	/*
557 	 * Check access rights against input parameters.
558 	 *
559 	 * Clear eventual extension flags like TEE_MEMORY_ACCESS_NONSECURE
560 	 * and TEE_MEMORY_ACCESS_SECURE.
561 	 */
562 	flags &= TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE |
563 		 TEE_MEMORY_ACCESS_ANY_OWNER;
564 	if (check_mem_access_rights_params(flags, buffer, size))
565 		return TEE_ERROR_ACCESS_DENIED;
566 
567 	if (malloc_buffer_overlaps_heap(buffer, size) &&
568 	    !malloc_buffer_is_within_alloced(buffer, size))
569 		return TEE_ERROR_ACCESS_DENIED;
570 
571 	return TEE_SUCCESS;
572 }
573 
574 TEE_Result __GP11_TEE_CheckMemoryAccessRights(uint32_t accessFlags,
575 					      void *buffer, uint32_t size)
576 {
577 	return TEE_CheckMemoryAccessRights(accessFlags, buffer, size);
578 }
579 
580 void TEE_SetInstanceData(const void *instanceData)
581 {
582 	tee_api_instance_data = instanceData;
583 }
584 
585 const void *TEE_GetInstanceData(void)
586 {
587 	return tee_api_instance_data;
588 }
589 
590 void *TEE_MemMove(void *dest, const void *src, size_t size)
591 {
592 	return memmove(dest, src, size);
593 }
594 
595 void *__GP11_TEE_MemMove(void *dest, const void *src, uint32_t size)
596 {
597 	return TEE_MemMove(dest, src, size);
598 }
599 
600 int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, size_t size)
601 {
602 	return consttime_memcmp(buffer1, buffer2, size);
603 }
604 
605 int32_t __GP11_TEE_MemCompare(const void *buffer1, const void *buffer2,
606 			      uint32_t size)
607 {
608 	return TEE_MemCompare(buffer1, buffer2, size);
609 }
610 
611 void TEE_MemFill(void *buff, uint32_t x, size_t size)
612 {
613 	memset(buff, x, size);
614 }
615 
616 void __GP11_TEE_MemFill(void *buff, uint32_t x, uint32_t size)
617 {
618 	TEE_MemFill(buff, x, size);
619 }
620 
621 /* Date & Time API */
622 
623 void TEE_GetSystemTime(TEE_Time *time)
624 {
625 	TEE_Result res = _utee_get_time(UTEE_TIME_CAT_SYSTEM, time);
626 
627 	if (res != TEE_SUCCESS)
628 		TEE_Panic(res);
629 }
630 
631 TEE_Result TEE_Wait(uint32_t timeout)
632 {
633 	TEE_Result res = _utee_wait(timeout);
634 
635 	if (res != TEE_SUCCESS && res != TEE_ERROR_CANCEL)
636 		TEE_Panic(res);
637 
638 	return res;
639 }
640 
641 TEE_Result TEE_GetTAPersistentTime(TEE_Time *time)
642 {
643 	TEE_Result res;
644 
645 	res = _utee_get_time(UTEE_TIME_CAT_TA_PERSISTENT, time);
646 
647 	if (res != TEE_SUCCESS && res != TEE_ERROR_OVERFLOW) {
648 		time->seconds = 0;
649 		time->millis = 0;
650 	}
651 
652 	if (res != TEE_SUCCESS &&
653 	    res != TEE_ERROR_TIME_NOT_SET &&
654 	    res != TEE_ERROR_TIME_NEEDS_RESET &&
655 	    res != TEE_ERROR_OVERFLOW &&
656 	    res != TEE_ERROR_OUT_OF_MEMORY)
657 		TEE_Panic(res);
658 
659 	return res;
660 }
661 
662 TEE_Result TEE_SetTAPersistentTime(const TEE_Time *time)
663 {
664 	TEE_Result res;
665 
666 	res = _utee_set_ta_time(time);
667 
668 	if (res != TEE_SUCCESS &&
669 	    res != TEE_ERROR_OUT_OF_MEMORY &&
670 	    res != TEE_ERROR_STORAGE_NO_SPACE)
671 		TEE_Panic(res);
672 
673 	return res;
674 }
675 
676 void TEE_GetREETime(TEE_Time *time)
677 {
678 	TEE_Result res = _utee_get_time(UTEE_TIME_CAT_REE, time);
679 
680 	if (res != TEE_SUCCESS)
681 		TEE_Panic(res);
682 }
683 
684 void *TEE_Malloc(size_t len, uint32_t hint)
685 {
686 	switch (hint) {
687 	case TEE_MALLOC_FILL_ZERO:
688 		if (!len)
689 			return TEE_NULL_SIZED_VA;
690 		return calloc(1, len);
691 
692 	case TEE_MALLOC_NO_FILL:
693 		TEE_Panic(0);
694 		break;
695 
696 	case TEE_MALLOC_NO_FILL | TEE_MALLOC_NO_SHARE:
697 		return NULL; /* TEE_MALLOC_NO_SHARE is not yet supported */
698 
699 	case TEE_USER_MEM_HINT_NO_FILL_ZERO:
700 		if (!len)
701 			return TEE_NULL_SIZED_VA;
702 		return malloc(len);
703 
704 	default:
705 		break;
706 	}
707 
708 	EMSG("Invalid hint %#" PRIx32, hint);
709 
710 	return NULL;
711 }
712 
713 void *__GP11_TEE_Malloc(uint32_t size, uint32_t hint)
714 {
715 	return TEE_Malloc(size, hint);
716 }
717 
718 void *TEE_Realloc(void *buffer, size_t newSize)
719 {
720 	if (!newSize) {
721 		TEE_Free(buffer);
722 		return TEE_NULL_SIZED_VA;
723 	}
724 
725 	if (buffer == TEE_NULL_SIZED_VA)
726 		return calloc(1, newSize);
727 
728 	return realloc(buffer, newSize);
729 }
730 
731 void *__GP11_TEE_Realloc(void *buffer, uint32_t newSize)
732 {
733 	return TEE_Realloc(buffer, newSize);
734 }
735 
736 void TEE_Free(void *buffer)
737 {
738 	if (buffer != TEE_NULL_SIZED_VA)
739 		free(buffer);
740 }
741 
742 /* Cache maintenance support (TA requires the CACHE_MAINTENANCE property) */
743 TEE_Result TEE_CacheClean(char *buf, size_t len)
744 {
745 	return _utee_cache_operation(buf, len, TEE_CACHECLEAN);
746 }
747 TEE_Result TEE_CacheFlush(char *buf, size_t len)
748 {
749 	return _utee_cache_operation(buf, len, TEE_CACHEFLUSH);
750 }
751 
752 TEE_Result TEE_CacheInvalidate(char *buf, size_t len)
753 {
754 	return _utee_cache_operation(buf, len, TEE_CACHEINVALIDATE);
755 }
756