xref: /optee_os/lib/libutee/tee_api_objects.c (revision 7583c59eb7d76afc7c36830b3b7034d44d43bb9e)
1 /*
2  * Copyright (c) 2014, STMicroelectronics International N.V.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include <tee_api.h>
31 #include <utee_syscalls.h>
32 
33 #include <assert.h>
34 
35 #define TEE_USAGE_DEFAULT   0xffffffff
36 
37 #define TEE_ATTR_BIT_VALUE                  (1 << 29)
38 #define TEE_ATTR_BIT_PROTECTED              (1 << 28)
39 
40 /* Data and Key Storage API  - Generic Object Functions */
41 /*
42  * Use of this function is deprecated
43  * new code SHOULD use the TEE_GetObjectInfo1 function instead
44  * These functions will be removed at some future major revision of
45  * this specification
46  */
47 void TEE_GetObjectInfo(TEE_ObjectHandle object, TEE_ObjectInfo *objectInfo)
48 {
49 	TEE_Result res;
50 
51 	res = utee_cryp_obj_get_info((uint32_t)object, objectInfo);
52 
53 	if (res != TEE_SUCCESS)
54 		TEE_Panic(res);
55 
56 	if (objectInfo->objectType == TEE_TYPE_CORRUPTED_OBJECT) {
57 		objectInfo->keySize = 0;
58 		objectInfo->maxKeySize = 0;
59 		objectInfo->objectUsage = 0;
60 		objectInfo->dataSize = 0;
61 		objectInfo->dataPosition = 0;
62 		objectInfo->handleFlags = 0;
63 	}
64 }
65 
66 TEE_Result TEE_GetObjectInfo1(TEE_ObjectHandle object, TEE_ObjectInfo *objectInfo)
67 {
68 	TEE_Result res;
69 
70 	res = utee_cryp_obj_get_info((uint32_t)object, objectInfo);
71 
72 	if (res == TEE_ERROR_CORRUPT_OBJECT) {
73 		res = utee_storage_obj_del(object);
74 		if (res != TEE_SUCCESS)
75 			TEE_Panic(0);
76 		return TEE_ERROR_CORRUPT_OBJECT;
77 	}
78 
79 	if (res != TEE_SUCCESS && res != TEE_ERROR_STORAGE_NOT_AVAILABLE)
80 		TEE_Panic(res);
81 
82 	return res;
83 }
84 
85 /*
86  * Use of this function is deprecated
87  * new code SHOULD use the TEE_RestrictObjectUsage1 function instead
88  * These functions will be removed at some future major revision of
89  * this specification
90  */
91 void TEE_RestrictObjectUsage(TEE_ObjectHandle object, uint32_t objectUsage)
92 {
93 	TEE_Result res;
94 	TEE_ObjectInfo objectInfo;
95 
96 	res = utee_cryp_obj_get_info((uint32_t)object, &objectInfo);
97 	if (objectInfo.objectType == TEE_TYPE_CORRUPTED_OBJECT)
98 		return;
99 
100 	res = TEE_RestrictObjectUsage1(object, objectUsage);
101 
102 	if (res != TEE_SUCCESS)
103 		TEE_Panic(0);
104 }
105 
106 TEE_Result TEE_RestrictObjectUsage1(TEE_ObjectHandle object, uint32_t objectUsage)
107 {
108 	TEE_Result res;
109 
110 	res = utee_cryp_obj_restrict_usage((uint32_t)object, objectUsage);
111 
112 	if (res == TEE_ERROR_CORRUPT_OBJECT) {
113 		res = utee_storage_obj_del(object);
114 		if (res != TEE_SUCCESS)
115 			TEE_Panic(0);
116 		return TEE_ERROR_CORRUPT_OBJECT;
117 	}
118 
119 	if (res != TEE_SUCCESS && res != TEE_ERROR_STORAGE_NOT_AVAILABLE)
120 		TEE_Panic(0);
121 
122 	return res;
123 }
124 
125 TEE_Result TEE_GetObjectBufferAttribute(TEE_ObjectHandle object,
126 					uint32_t attributeID, void *buffer,
127 					uint32_t *size)
128 {
129 	TEE_Result res;
130 	TEE_ObjectInfo info;
131 
132 	res = utee_cryp_obj_get_info((uint32_t)object, &info);
133 	if (res != TEE_SUCCESS)
134 		TEE_Panic(0);
135 
136 	if ((info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0)
137 		TEE_Panic(0);
138 
139 	/* This function only supports reference attributes */
140 	if ((attributeID & TEE_ATTR_BIT_VALUE) != 0)
141 		TEE_Panic(0);
142 
143 	res =
144 	    utee_cryp_obj_get_attr((uint32_t)object, attributeID, buffer,
145 				   size);
146 
147 	if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND &&
148 	    res != TEE_ERROR_SHORT_BUFFER)
149 		TEE_Panic(0);
150 
151 	return res;
152 }
153 
154 TEE_Result TEE_GetObjectValueAttribute(TEE_ObjectHandle object,
155 				       uint32_t attributeID, uint32_t *a,
156 				       uint32_t *b)
157 {
158 	TEE_Result res;
159 	TEE_ObjectInfo info;
160 	uint32_t buf[2];
161 	uint32_t size = sizeof(buf);
162 
163 	res = utee_cryp_obj_get_info((uint32_t)object, &info);
164 	if (res != TEE_SUCCESS)
165 		TEE_Panic(0);
166 
167 	if ((info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0)
168 		TEE_Panic(0);
169 
170 	/* This function only supports value attributes */
171 	if ((attributeID & TEE_ATTR_BIT_VALUE) == 0)
172 		TEE_Panic(0);
173 
174 	res =
175 	    utee_cryp_obj_get_attr((uint32_t)object, attributeID, buf, &size);
176 
177 	if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND &&
178 	    res != TEE_ERROR_ACCESS_DENIED)
179 		TEE_Panic(0);
180 
181 	if (size != sizeof(buf))
182 		TEE_Panic(0);
183 
184 	*a = buf[0];
185 	*b = buf[1];
186 
187 	return res;
188 }
189 
190 void TEE_CloseObject(TEE_ObjectHandle object)
191 {
192 	TEE_Result res;
193 
194 	if (object == TEE_HANDLE_NULL)
195 		return;
196 
197 	res = utee_cryp_obj_close((uint32_t)object);
198 	if (res != TEE_SUCCESS)
199 		TEE_Panic(0);
200 }
201 
202 /* Data and Key Storage API  - Transient Object Functions */
203 
204 TEE_Result TEE_AllocateTransientObject(TEE_ObjectType objectType,
205 				       uint32_t maxKeySize,
206 				       TEE_ObjectHandle *object)
207 {
208 	TEE_Result res;
209 	uint32_t obj;
210 
211 	res = utee_cryp_obj_alloc(objectType, maxKeySize, &obj);
212 	if (res == TEE_SUCCESS)
213 		*object = (TEE_ObjectHandle) obj;
214 	return res;
215 }
216 
217 void TEE_FreeTransientObject(TEE_ObjectHandle object)
218 {
219 	TEE_Result res;
220 	TEE_ObjectInfo info;
221 
222 	if (object == TEE_HANDLE_NULL)
223 		return;
224 
225 	res = utee_cryp_obj_get_info((uint32_t)object, &info);
226 	if (res != TEE_SUCCESS)
227 		TEE_Panic(0);
228 
229 	if ((info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) != 0)
230 		TEE_Panic(0);
231 
232 	res = utee_cryp_obj_close((uint32_t)object);
233 	if (res != TEE_SUCCESS)
234 		TEE_Panic(0);
235 }
236 
237 void TEE_ResetTransientObject(TEE_ObjectHandle object)
238 {
239 	TEE_Result res;
240 	TEE_ObjectInfo info;
241 
242 	if (object == TEE_HANDLE_NULL)
243 		return;
244 
245 	res = utee_cryp_obj_get_info((uint32_t)object, &info);
246 	if (res != TEE_SUCCESS)
247 		TEE_Panic(0);
248 
249 	if ((info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) != 0)
250 		TEE_Panic(0);
251 
252 	res = utee_cryp_obj_reset((uint32_t)object);
253 	if (res != TEE_SUCCESS)
254 		TEE_Panic(0);
255 }
256 
257 TEE_Result TEE_PopulateTransientObject(TEE_ObjectHandle object,
258 				       TEE_Attribute *attrs,
259 				       uint32_t attrCount)
260 {
261 	TEE_Result res;
262 	TEE_ObjectInfo info;
263 
264 	res = utee_cryp_obj_get_info((uint32_t)object, &info);
265 	if (res != TEE_SUCCESS)
266 		TEE_Panic(0);
267 
268 	/* Must be a transient object */
269 	if ((info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) != 0)
270 		TEE_Panic(0);
271 
272 	/* Must not be initialized already */
273 	if ((info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0)
274 		TEE_Panic(0);
275 
276 	res = utee_cryp_obj_populate((uint32_t)object, attrs, attrCount);
277 	if (res != TEE_SUCCESS && res != TEE_ERROR_BAD_PARAMETERS)
278 		TEE_Panic(res);
279 	return res;
280 }
281 
282 void TEE_InitRefAttribute(TEE_Attribute *attr, uint32_t attributeID,
283 			  void *buffer, uint32_t length)
284 {
285 	if (attr == NULL)
286 		TEE_Panic(0);
287 	if ((attributeID & TEE_ATTR_BIT_VALUE) != 0)
288 		TEE_Panic(0);
289 	attr->attributeID = attributeID;
290 	attr->content.ref.buffer = buffer;
291 	attr->content.ref.length = length;
292 }
293 
294 void TEE_InitValueAttribute(TEE_Attribute *attr, uint32_t attributeID,
295 			    uint32_t a, uint32_t b)
296 {
297 	if (attr == NULL)
298 		TEE_Panic(0);
299 	if ((attributeID & TEE_ATTR_BIT_VALUE) == 0)
300 		TEE_Panic(0);
301 	attr->attributeID = attributeID;
302 	attr->content.value.a = a;
303 	attr->content.value.b = b;
304 }
305 
306 /*
307  * Use of this function is deprecated
308  * new code SHOULD use the TEE_CopyObjectAttributes1 function instead
309  * These functions will be removed at some future major revision of
310  * this specification
311  */
312 void TEE_CopyObjectAttributes(TEE_ObjectHandle destObject,
313 			      TEE_ObjectHandle srcObject)
314 {
315 	TEE_Result res;
316 	TEE_ObjectInfo src_info;
317 
318 	res = utee_cryp_obj_get_info((uint32_t)srcObject, &src_info);
319 	if (src_info.objectType == TEE_TYPE_CORRUPTED_OBJECT)
320 		return;
321 
322 	res = TEE_CopyObjectAttributes1(destObject, srcObject);
323 	if (res != TEE_SUCCESS)
324 		TEE_Panic(0);
325 }
326 
327 TEE_Result TEE_CopyObjectAttributes1(TEE_ObjectHandle destObject,
328 			      TEE_ObjectHandle srcObject)
329 {
330 	TEE_Result res;
331 	TEE_ObjectInfo dst_info;
332 	TEE_ObjectInfo src_info;
333 
334 	res = utee_cryp_obj_get_info((uint32_t)destObject, &dst_info);
335 	if (res != TEE_SUCCESS)
336 		goto err;
337 
338 	res = utee_cryp_obj_get_info((uint32_t)srcObject, &src_info);
339 	if (res != TEE_SUCCESS)
340 		goto err;
341 
342 	if ((src_info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0)
343 		TEE_Panic(0);
344 	if ((dst_info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) != 0)
345 		TEE_Panic(0);
346 	if ((dst_info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0)
347 		TEE_Panic(0);
348 
349 	res = utee_cryp_obj_copy((uint32_t)destObject, (uint32_t)srcObject);
350 	if (res != TEE_SUCCESS)
351 		TEE_Panic(0);
352 
353 	goto out;
354 
355 err:
356 	if (res == TEE_ERROR_CORRUPT_OBJECT) {
357 		res = utee_storage_obj_del(srcObject);
358 		if (res != TEE_SUCCESS)
359 			TEE_Panic(0);
360 		return TEE_ERROR_CORRUPT_OBJECT;
361 	}
362 	if (res == TEE_ERROR_STORAGE_NOT_AVAILABLE)
363 		return res;
364 	TEE_Panic(0);
365 out:
366 	return TEE_SUCCESS;
367 }
368 
369 TEE_Result TEE_GenerateKey(TEE_ObjectHandle object, uint32_t keySize,
370 			   TEE_Attribute *params, uint32_t paramCount)
371 {
372 	TEE_Result res;
373 
374 	res = utee_cryp_obj_generate_key((uint32_t)object, keySize,
375 					 params, paramCount);
376 
377 	if (res != TEE_SUCCESS)
378 		TEE_Panic(0);
379 
380 	return res;
381 }
382 
383 /* Data and Key Storage API  - Persistent Object Functions */
384 
385 TEE_Result TEE_OpenPersistentObject(uint32_t storageID, void *objectID,
386 				    uint32_t objectIDLen, uint32_t flags,
387 				    TEE_ObjectHandle *object)
388 {
389 	if (storageID != TEE_STORAGE_PRIVATE)
390 		return TEE_ERROR_ITEM_NOT_FOUND;
391 
392 	if (objectID == NULL)
393 		return TEE_ERROR_ITEM_NOT_FOUND;
394 
395 	if (objectIDLen > TEE_OBJECT_ID_MAX_LEN)
396 		TEE_Panic(0);
397 
398 	if (object == NULL)
399 		return TEE_ERROR_BAD_PARAMETERS;
400 
401 	return utee_storage_obj_open(storageID, objectID, objectIDLen, flags,
402 				     object);
403 }
404 
405 TEE_Result TEE_CreatePersistentObject(uint32_t storageID, void *objectID,
406 				      uint32_t objectIDLen, uint32_t flags,
407 				      TEE_ObjectHandle attributes,
408 				      const void *initialData,
409 				      uint32_t initialDataLen,
410 				      TEE_ObjectHandle *object)
411 {
412 	if (storageID != TEE_STORAGE_PRIVATE)
413 		return TEE_ERROR_ITEM_NOT_FOUND;
414 
415 	if (objectID == NULL)
416 		return TEE_ERROR_ITEM_NOT_FOUND;
417 
418 	if (objectIDLen > TEE_OBJECT_ID_MAX_LEN)
419 		TEE_Panic(0);
420 
421 	if (object == NULL)
422 		return TEE_ERROR_BAD_PARAMETERS;
423 
424 	return utee_storage_obj_create(storageID, objectID, objectIDLen, flags,
425 				       attributes, initialData, initialDataLen,
426 				       object);
427 }
428 
429 /*
430  * Use of this function is deprecated
431  * new code SHOULD use the TEE_CloseAndDeletePersistentObject1 function instead
432  * These functions will be removed at some future major revision of
433  * this specification
434  */
435 void TEE_CloseAndDeletePersistentObject(TEE_ObjectHandle object)
436 {
437 	TEE_Result res;
438 
439 	if (object == TEE_HANDLE_NULL)
440 		return;
441 
442 	res = TEE_CloseAndDeletePersistentObject1(object);
443 
444 	if (res != TEE_SUCCESS)
445 		TEE_Panic(0);
446 }
447 
448 TEE_Result TEE_CloseAndDeletePersistentObject1(TEE_ObjectHandle object)
449 {
450 	TEE_Result res;
451 
452 	if (object == TEE_HANDLE_NULL)
453 		return TEE_ERROR_STORAGE_NOT_AVAILABLE;
454 
455 	res = utee_storage_obj_del(object);
456 
457 	if (res != TEE_SUCCESS && res != TEE_ERROR_STORAGE_NOT_AVAILABLE)
458 		TEE_Panic(0);
459 
460 	return res;
461 }
462 
463 
464 TEE_Result TEE_RenamePersistentObject(TEE_ObjectHandle object,
465 				      const void *newObjectID,
466 				      uint32_t newObjectIDLen)
467 {
468 	TEE_Result res;
469 
470 	if (object == TEE_HANDLE_NULL)
471 		return TEE_ERROR_ITEM_NOT_FOUND;
472 
473 	if (newObjectID == NULL)
474 		return TEE_ERROR_BAD_PARAMETERS;
475 
476 	if (newObjectIDLen > TEE_OBJECT_ID_MAX_LEN)
477 		TEE_Panic(0);
478 
479 	res = utee_storage_obj_rename(object, newObjectID, newObjectIDLen);
480 
481 	if (res != TEE_SUCCESS && res != TEE_ERROR_ACCESS_CONFLICT)
482 		TEE_Panic(0);
483 
484 	return res;
485 }
486 
487 TEE_Result TEE_AllocatePersistentObjectEnumerator(TEE_ObjectEnumHandle *
488 						  objectEnumerator)
489 {
490 	TEE_Result res;
491 
492 	if (objectEnumerator == NULL)
493 		return TEE_ERROR_BAD_PARAMETERS;
494 
495 	res = utee_storage_alloc_enum(objectEnumerator);
496 
497 	if (res != TEE_SUCCESS)
498 		*objectEnumerator = TEE_HANDLE_NULL;
499 
500 	return res;
501 }
502 
503 void TEE_FreePersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator)
504 {
505 	TEE_Result res;
506 
507 	if (objectEnumerator == TEE_HANDLE_NULL)
508 		return;
509 
510 	res = utee_storage_free_enum(objectEnumerator);
511 
512 	if (res != TEE_SUCCESS)
513 		TEE_Panic(0);
514 }
515 
516 void TEE_ResetPersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator)
517 {
518 	TEE_Result res;
519 
520 	if (objectEnumerator == TEE_HANDLE_NULL)
521 		return;
522 
523 	res = utee_storage_reset_enum(objectEnumerator);
524 
525 	if (res != TEE_SUCCESS)
526 		TEE_Panic(0);
527 }
528 
529 TEE_Result TEE_StartPersistentObjectEnumerator(TEE_ObjectEnumHandle
530 					       objectEnumerator,
531 					       uint32_t storageID)
532 {
533 	TEE_Result res;
534 
535 	if (storageID != TEE_STORAGE_PRIVATE)
536 		return TEE_ERROR_ITEM_NOT_FOUND;
537 
538 	res = utee_storage_start_enum(objectEnumerator, storageID);
539 
540 	if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND)
541 		TEE_Panic(0);
542 
543 	return res;
544 }
545 
546 TEE_Result TEE_GetNextPersistentObject(TEE_ObjectEnumHandle objectEnumerator,
547 				       TEE_ObjectInfo *objectInfo,
548 				       void *objectID, uint32_t *objectIDLen)
549 {
550 	TEE_Result res;
551 
552 	res =
553 	    utee_storage_next_enum(objectEnumerator, objectInfo, objectID,
554 				   objectIDLen);
555 
556 	if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND)
557 		TEE_Panic(0);
558 
559 	return res;
560 }
561 
562 /* Data and Key Storage API  - Data Stream Access Functions */
563 
564 TEE_Result TEE_ReadObjectData(TEE_ObjectHandle object, void *buffer,
565 			      uint32_t size, uint32_t *count)
566 {
567 	TEE_Result res;
568 
569 	if (object == TEE_HANDLE_NULL)
570 		TEE_Panic(0);
571 
572 	res = utee_storage_obj_read(object, buffer, size, count);
573 
574 	if (res != TEE_SUCCESS)
575 		TEE_Panic(0);
576 
577 	return res;
578 }
579 
580 TEE_Result TEE_WriteObjectData(TEE_ObjectHandle object, void *buffer,
581 			       uint32_t size)
582 {
583 	TEE_Result res;
584 
585 	if (object == TEE_HANDLE_NULL)
586 		TEE_Panic(0);
587 
588 	res = utee_storage_obj_write(object, buffer, size);
589 
590 	if (res != TEE_SUCCESS && res != TEE_ERROR_STORAGE_NO_SPACE)
591 		TEE_Panic(0);
592 
593 	return res;
594 }
595 
596 TEE_Result TEE_TruncateObjectData(TEE_ObjectHandle object, uint32_t size)
597 {
598 	TEE_Result res;
599 
600 	if (object == TEE_HANDLE_NULL)
601 		TEE_Panic(0);
602 
603 	res = utee_storage_obj_trunc(object, size);
604 
605 	if (res != TEE_SUCCESS && res != TEE_ERROR_STORAGE_NO_SPACE)
606 		TEE_Panic(0);
607 
608 	return res;
609 }
610 
611 TEE_Result TEE_SeekObjectData(TEE_ObjectHandle object, int32_t offset,
612 			      TEE_Whence whence)
613 {
614 	TEE_Result res;
615 	TEE_ObjectInfo info;
616 
617 	if (object == TEE_HANDLE_NULL)
618 		TEE_Panic(0);
619 
620 	res = utee_cryp_obj_get_info((uint32_t)object, &info);
621 	if (res != TEE_SUCCESS)
622 		TEE_Panic(0);
623 
624 	switch (whence) {
625 	case TEE_DATA_SEEK_SET:
626 		if (offset > 0 && (uint32_t)offset > TEE_DATA_MAX_POSITION)
627 			return TEE_ERROR_OVERFLOW;
628 		break;
629 	case TEE_DATA_SEEK_CUR:
630 		if (offset > 0 &&
631 		    ((uint32_t)offset + info.dataPosition >
632 		     TEE_DATA_MAX_POSITION ||
633 		     (uint32_t)offset + info.dataPosition <
634 		     info.dataPosition))
635 			return TEE_ERROR_OVERFLOW;
636 		break;
637 	case TEE_DATA_SEEK_END:
638 		if (offset > 0 &&
639 		    ((uint32_t)offset + info.dataSize > TEE_DATA_MAX_POSITION ||
640 		     (uint32_t)offset + info.dataSize < info.dataSize))
641 			return TEE_ERROR_OVERFLOW;
642 		break;
643 	default:
644 		TEE_Panic(0);
645 	}
646 
647 	res = utee_storage_obj_seek(object, offset, whence);
648 
649 	if (res != TEE_SUCCESS && res != TEE_ERROR_OVERFLOW)
650 		TEE_Panic(0);
651 
652 	return res;
653 }
654