1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2014, STMicroelectronics International N.V.
4 * Copyright (c) 2017-2020, Linaro Limited
5 */
6 #include <base64.h>
7 #include <printk.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <string_ext.h>
12 #include <tee_api.h>
13 #include <tee_api_defines.h>
14 #include <tee_api_types.h>
15 #include <tee_arith_internal.h>
16 #include <tee_internal_api_extensions.h>
17 #include <tee_isocket.h>
18 #include <user_ta_header.h>
19 #include <utee_syscalls.h>
20 #include <util.h>
21
22 #include "tee_api_private.h"
23
24 #define PROP_STR_MAX 80
25
26 #define PROP_ENUMERATOR_NOT_STARTED 0xffffffff
27
28 struct prop_enumerator {
29 uint32_t idx; /* current index */
30 TEE_PropSetHandle prop_set; /* part of TEE_PROPSET_xxx */
31 };
32
33 const struct user_ta_property tee_props[] = {
34 {
35 "gpd.tee.arith.maxBigIntSize",
36 USER_TA_PROP_TYPE_U32,
37 &(const uint32_t){CFG_TA_BIGNUM_MAX_BITS}
38 },
39 {
40 "gpd.tee.sockets.version",
41 USER_TA_PROP_TYPE_U32,
42 &(const uint32_t){TEE_ISOCKET_VERSION}
43 },
44 {
45 "gpd.tee.sockets.tcp.version",
46 USER_TA_PROP_TYPE_U32,
47 &(const uint32_t){TEE_ISOCKET_VERSION}
48 },
49 {
50 "gpd.tee.internalCore.version",
51 USER_TA_PROP_TYPE_U32,
52 &(const uint32_t){TEE_CORE_API_VERSION}
53 },
54 };
55
propset_get(TEE_PropSetHandle h,const struct user_ta_property ** eps,size_t * eps_len)56 static TEE_Result propset_get(TEE_PropSetHandle h,
57 const struct user_ta_property **eps,
58 size_t *eps_len)
59 {
60 if (h == TEE_PROPSET_CURRENT_TA) {
61 *eps = ta_props;
62 *eps_len = ta_num_props;
63 } else if (h == TEE_PROPSET_CURRENT_CLIENT) {
64 *eps = NULL;
65 *eps_len = 0;
66 } else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) {
67 *eps = tee_props;
68 *eps_len = ARRAY_SIZE(tee_props);
69 } else {
70 return TEE_ERROR_ITEM_NOT_FOUND;
71 }
72
73 return TEE_SUCCESS;
74 }
75
propget_get_ext_prop(const struct user_ta_property * ep,enum user_ta_prop_type * type,void * buf,uint32_t * len)76 static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep,
77 enum user_ta_prop_type *type,
78 void *buf, uint32_t *len)
79 {
80 size_t l;
81
82 *type = ep->type;
83 switch (*type) {
84 case USER_TA_PROP_TYPE_BOOL:
85 l = sizeof(bool);
86 break;
87 case USER_TA_PROP_TYPE_U32:
88 l = sizeof(uint32_t);
89 break;
90 case USER_TA_PROP_TYPE_U64:
91 l = sizeof(uint64_t);
92 break;
93 case USER_TA_PROP_TYPE_UUID:
94 l = sizeof(TEE_UUID);
95 break;
96 case USER_TA_PROP_TYPE_IDENTITY:
97 l = sizeof(TEE_Identity);
98 break;
99 case USER_TA_PROP_TYPE_STRING:
100 /* take the leading 0 into account */
101 l = strlen(ep->value) + 1;
102 break;
103 case USER_TA_PROP_TYPE_BINARY_BLOCK:
104 /*
105 * in case of TA property, a binary block is provided as a
106 * string, which is base64 encoded. We must first decode it,
107 * without taking into account the zero termination of the
108 * string
109 */
110 l = *len;
111 if (!base64_dec(ep->value, strlen(ep->value), buf, &l) &&
112 l <= *len)
113 return TEE_ERROR_GENERIC;
114 if (*len < l) {
115 *len = l;
116 return TEE_ERROR_SHORT_BUFFER;
117 }
118
119 *len = l;
120 return TEE_SUCCESS;
121 default:
122 return TEE_ERROR_GENERIC;
123 }
124
125 if (*len < l) {
126 *len = l;
127 return TEE_ERROR_SHORT_BUFFER;
128 }
129
130 *len = l;
131 memcpy(buf, ep->value, l);
132 return TEE_SUCCESS;
133 }
134
is_propset_pseudo_handle(TEE_PropSetHandle h)135 static bool is_propset_pseudo_handle(TEE_PropSetHandle h)
136 {
137 return h == TEE_PROPSET_CURRENT_TA ||
138 h == TEE_PROPSET_CURRENT_CLIENT ||
139 h == TEE_PROPSET_TEE_IMPLEMENTATION;
140 }
141
propget_get_property(TEE_PropSetHandle h,const char * name,enum user_ta_prop_type * type,void * buf,uint32_t * len)142 static TEE_Result propget_get_property(TEE_PropSetHandle h, const char *name,
143 enum user_ta_prop_type *type,
144 void *buf, uint32_t *len)
145 {
146 TEE_Result res;
147 const struct user_ta_property *eps;
148 size_t eps_len;
149 uint32_t prop_type;
150 uint32_t index;
151
152 if (is_propset_pseudo_handle(h)) {
153 size_t n;
154
155 res = propset_get(h, &eps, &eps_len);
156 if (res != TEE_SUCCESS)
157 return res;
158
159 for (n = 0; n < eps_len; n++) {
160 if (!strcmp(name, eps[n].name))
161 return propget_get_ext_prop(eps + n, type,
162 buf, len);
163 }
164
165 /* get the index from the name */
166 res = _utee_get_property_name_to_index((unsigned long)h, name,
167 strlen(name) + 1,
168 &index);
169 if (res != TEE_SUCCESS)
170 return res;
171 res = _utee_get_property((unsigned long)h, index, NULL, NULL,
172 buf, len, &prop_type);
173 } else {
174 struct prop_enumerator *pe = (struct prop_enumerator *)h;
175 uint32_t idx = pe->idx;
176
177 if (idx == PROP_ENUMERATOR_NOT_STARTED)
178 return TEE_ERROR_ITEM_NOT_FOUND;
179
180 res = propset_get(pe->prop_set, &eps, &eps_len);
181 if (res != TEE_SUCCESS)
182 return res;
183
184 if (idx < eps_len)
185 return propget_get_ext_prop(eps + idx, type, buf, len);
186 idx -= eps_len;
187
188 res = _utee_get_property((unsigned long)pe->prop_set, idx,
189 NULL, NULL, buf, len, &prop_type);
190 if (res == TEE_ERROR_ITEM_NOT_FOUND)
191 res = TEE_ERROR_BAD_PARAMETERS;
192 }
193
194 *type = prop_type;
195 return res;
196 }
197
TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator,const char * name,char * value,size_t * value_len)198 TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator,
199 const char *name, char *value,
200 size_t *value_len)
201 {
202 TEE_Result res = TEE_ERROR_GENERIC;
203 size_t l = 0;
204 enum user_ta_prop_type type = USER_TA_PROP_TYPE_INVALID;
205 void *tmp_buf = 0;
206 uint32_t tmp_len = 0;
207 uint32_t uint32_val = 0;
208 bool bool_val = false;
209 TEE_Identity *p_identity_val = NULL;
210
211 if (is_propset_pseudo_handle(propsetOrEnumerator))
212 __utee_check_instring_annotation(name);
213 __utee_check_outstring_annotation(value, value_len);
214
215 tmp_len = *value_len;
216 if (tmp_len < sizeof(TEE_Identity))
217 tmp_len = sizeof(TEE_Identity);
218 tmp_buf = TEE_Malloc(tmp_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
219 if (!tmp_buf) {
220 res = TEE_ERROR_OUT_OF_MEMORY;
221 goto out;
222 }
223
224 res = propget_get_property(propsetOrEnumerator, name, &type,
225 tmp_buf, &tmp_len);
226 if (res != TEE_SUCCESS) {
227 if (res == TEE_ERROR_SHORT_BUFFER) {
228 if (type == USER_TA_PROP_TYPE_BINARY_BLOCK) {
229 /*
230 * in this case, we must enlarge the buffer
231 * with the size of the of the base64 encoded
232 * see base64_enc() function
233 */
234 tmp_len = base64_enc_len(tmp_len);
235 }
236 *value_len = tmp_len;
237 }
238 goto out;
239 }
240
241 switch (type) {
242 case USER_TA_PROP_TYPE_BOOL:
243 bool_val = *((bool *)tmp_buf);
244 l = strlcpy(value, (bool_val ? "true" : "false"), *value_len);
245 break;
246
247 case USER_TA_PROP_TYPE_U32:
248 uint32_val = *((uint32_t *)tmp_buf);
249 l = snprintf(value, *value_len, "%u", uint32_val);
250 break;
251
252 case USER_TA_PROP_TYPE_UUID:
253 l = snprintk(value, *value_len, "%pUl", tmp_buf);
254 break;
255
256 case USER_TA_PROP_TYPE_IDENTITY:
257 p_identity_val = ((TEE_Identity *)tmp_buf);
258 l = snprintk(value, *value_len, "%u:%pUl",
259 p_identity_val->login,
260 (void *)(&(p_identity_val->uuid)));
261 break;
262
263 case USER_TA_PROP_TYPE_STRING:
264 l = strlcpy(value, tmp_buf, *value_len);
265 break;
266
267 case USER_TA_PROP_TYPE_BINARY_BLOCK:
268 l = *value_len; /* l includes the zero-termination */
269 if (!base64_enc(tmp_buf, tmp_len, value, &l) &&
270 l <= *value_len) {
271 res = TEE_ERROR_GENERIC;
272 goto out;
273 }
274 l--; /* remove the zero-termination that is added later */
275 break;
276
277 default:
278 res = TEE_ERROR_BAD_FORMAT;
279 goto out;
280 }
281
282 l++; /* include zero termination */
283
284 if (l > *value_len)
285 res = TEE_ERROR_SHORT_BUFFER;
286 *value_len = l;
287
288 out:
289 if (tmp_buf)
290 TEE_Free(tmp_buf);
291 if (res != TEE_SUCCESS &&
292 res != TEE_ERROR_ITEM_NOT_FOUND &&
293 res != TEE_ERROR_SHORT_BUFFER)
294 TEE_Panic(0);
295
296 return res;
297 }
298
__GP11_TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator,const char * name,char * valueBuffer,uint32_t * valueBufferLen)299 TEE_Result __GP11_TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator,
300 const char *name, char *valueBuffer,
301 uint32_t *valueBufferLen)
302 {
303 TEE_Result res = TEE_SUCCESS;
304 size_t l = 0;
305
306 __utee_check_gp11_outstring_annotation(valueBuffer, valueBufferLen);
307 l = *valueBufferLen;
308 res = TEE_GetPropertyAsString(propsetOrEnumerator, name, valueBuffer,
309 &l);
310 *valueBufferLen = l;
311 return res;
312 }
313
TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator,const char * name,bool * value)314 TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator,
315 const char *name, bool *value)
316 {
317 TEE_Result res;
318 enum user_ta_prop_type type;
319 uint32_t bool_len = sizeof(bool);
320
321 if (is_propset_pseudo_handle(propsetOrEnumerator))
322 __utee_check_instring_annotation(name);
323 __utee_check_out_annotation(value, sizeof(*value));
324
325 type = USER_TA_PROP_TYPE_BOOL;
326 res = propget_get_property(propsetOrEnumerator, name, &type,
327 value, &bool_len);
328 if (type != USER_TA_PROP_TYPE_BOOL)
329 res = TEE_ERROR_BAD_FORMAT;
330 if (res != TEE_SUCCESS)
331 goto out;
332
333 out:
334 if (res != TEE_SUCCESS &&
335 res != TEE_ERROR_ITEM_NOT_FOUND &&
336 res != TEE_ERROR_BAD_FORMAT)
337 TEE_Panic(0);
338
339 return res;
340 }
341
TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator,const char * name,uint32_t * value)342 TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator,
343 const char *name, uint32_t *value)
344 {
345 TEE_Result res;
346 enum user_ta_prop_type type;
347 uint32_t uint32_len = sizeof(uint32_t);
348
349 if (is_propset_pseudo_handle(propsetOrEnumerator))
350 __utee_check_instring_annotation(name);
351 __utee_check_out_annotation(value, sizeof(*value));
352
353 type = USER_TA_PROP_TYPE_U32;
354 res = propget_get_property(propsetOrEnumerator, name, &type,
355 value, &uint32_len);
356 if (type != USER_TA_PROP_TYPE_U32)
357 res = TEE_ERROR_BAD_FORMAT;
358
359 if (res != TEE_SUCCESS &&
360 res != TEE_ERROR_ITEM_NOT_FOUND &&
361 res != TEE_ERROR_BAD_FORMAT)
362 TEE_Panic(0);
363
364 return res;
365 }
366
TEE_GetPropertyAsU64(TEE_PropSetHandle propsetOrEnumerator,const char * name,uint64_t * value)367 TEE_Result TEE_GetPropertyAsU64(TEE_PropSetHandle propsetOrEnumerator,
368 const char *name, uint64_t *value)
369 {
370 TEE_Result res;
371 enum user_ta_prop_type type;
372 uint32_t uint64_len = sizeof(*value);
373
374 if (is_propset_pseudo_handle(propsetOrEnumerator))
375 __utee_check_instring_annotation(name);
376 __utee_check_out_annotation(value, sizeof(*value));
377
378 type = USER_TA_PROP_TYPE_U64;
379 res = propget_get_property(propsetOrEnumerator, name, &type,
380 value, &uint64_len);
381 if (type != USER_TA_PROP_TYPE_U64)
382 res = TEE_ERROR_BAD_FORMAT;
383
384 if (res != TEE_SUCCESS &&
385 res != TEE_ERROR_ITEM_NOT_FOUND &&
386 res != TEE_ERROR_BAD_FORMAT)
387 TEE_Panic(0);
388
389 return res;
390 }
391
392 TEE_Result
__GP11_TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator,const char * name,void * value,uint32_t * value_len)393 __GP11_TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator,
394 const char *name, void *value,
395 uint32_t *value_len)
396 {
397 TEE_Result res = TEE_SUCCESS;
398 enum user_ta_prop_type type = USER_TA_PROP_TYPE_BOOL;
399
400 if (is_propset_pseudo_handle(propsetOrEnumerator))
401 __utee_check_instring_annotation(name);
402 __utee_check_gp11_outbuf_annotation(value, value_len);
403
404 type = USER_TA_PROP_TYPE_BINARY_BLOCK;
405 res = propget_get_property(propsetOrEnumerator, name, &type,
406 value, value_len);
407 if (type != USER_TA_PROP_TYPE_BINARY_BLOCK)
408 res = TEE_ERROR_BAD_FORMAT;
409
410 if (res != TEE_SUCCESS &&
411 res != TEE_ERROR_ITEM_NOT_FOUND &&
412 res != TEE_ERROR_BAD_FORMAT &&
413 res != TEE_ERROR_SHORT_BUFFER)
414 TEE_Panic(0);
415
416 return res;
417 }
418
TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator,const char * name,void * value,size_t * value_len)419 TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator,
420 const char *name, void *value,
421 size_t *value_len)
422 {
423 TEE_Result res = TEE_SUCCESS;
424 uint32_t l = 0;
425
426 __utee_check_outbuf_annotation(value, value_len);
427 l = *value_len;
428 res = __GP11_TEE_GetPropertyAsBinaryBlock(propsetOrEnumerator, name,
429 value, &l);
430 *value_len = l;
431 return res;
432 }
433
TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator,const char * name,TEE_UUID * value)434 TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator,
435 const char *name, TEE_UUID *value)
436 {
437 TEE_Result res;
438 enum user_ta_prop_type type;
439 uint32_t uuid_len = sizeof(TEE_UUID);
440
441 if (is_propset_pseudo_handle(propsetOrEnumerator))
442 __utee_check_instring_annotation(name);
443 __utee_check_out_annotation(value, sizeof(*value));
444
445 type = USER_TA_PROP_TYPE_UUID;
446 res = propget_get_property(propsetOrEnumerator, name, &type,
447 value, &uuid_len);
448 if (type != USER_TA_PROP_TYPE_UUID)
449 res = TEE_ERROR_BAD_FORMAT;
450
451 if (res != TEE_SUCCESS &&
452 res != TEE_ERROR_ITEM_NOT_FOUND &&
453 res != TEE_ERROR_BAD_FORMAT)
454 TEE_Panic(0);
455
456 return res;
457 }
458
TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator,const char * name,TEE_Identity * value)459 TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator,
460 const char *name, TEE_Identity *value)
461 {
462 TEE_Result res;
463 enum user_ta_prop_type type;
464 uint32_t identity_len = sizeof(TEE_Identity);
465
466 if (is_propset_pseudo_handle(propsetOrEnumerator))
467 __utee_check_instring_annotation(name);
468 __utee_check_out_annotation(value, sizeof(*value));
469
470 type = USER_TA_PROP_TYPE_IDENTITY;
471 res = propget_get_property(propsetOrEnumerator, name, &type,
472 value, &identity_len);
473 if (type != USER_TA_PROP_TYPE_IDENTITY)
474 res = TEE_ERROR_BAD_FORMAT;
475
476 if (res != TEE_SUCCESS &&
477 res != TEE_ERROR_ITEM_NOT_FOUND &&
478 res != TEE_ERROR_BAD_FORMAT)
479 TEE_Panic(0);
480
481 return res;
482 }
483
TEE_AllocatePropertyEnumerator(TEE_PropSetHandle * enumerator)484 TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator)
485 {
486 TEE_Result res;
487 struct prop_enumerator *pe;
488
489 __utee_check_out_annotation(enumerator, sizeof(*enumerator));
490
491 pe = TEE_Malloc(sizeof(struct prop_enumerator),
492 TEE_USER_MEM_HINT_NO_FILL_ZERO);
493 if (pe == NULL) {
494 res = TEE_ERROR_OUT_OF_MEMORY;
495 goto err;
496 }
497
498 *enumerator = (TEE_PropSetHandle) pe;
499 TEE_ResetPropertyEnumerator(*enumerator);
500
501 goto out;
502
503 err:
504 if (res == TEE_ERROR_OUT_OF_MEMORY)
505 return res;
506 TEE_Panic(0);
507 out:
508 return TEE_SUCCESS;
509 }
510
TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator)511 void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator)
512 {
513 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
514
515 pe->idx = PROP_ENUMERATOR_NOT_STARTED;
516 }
517
TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator)518 void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator)
519 {
520 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
521
522 TEE_Free(pe);
523 }
524
TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator,TEE_PropSetHandle propSet)525 void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator,
526 TEE_PropSetHandle propSet)
527 {
528 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
529
530 if (!pe)
531 return;
532
533 pe->idx = 0;
534 pe->prop_set = propSet;
535 }
536
__GP11_TEE_GetPropertyName(TEE_PropSetHandle enumerator,void * name,uint32_t * name_len)537 TEE_Result __GP11_TEE_GetPropertyName(TEE_PropSetHandle enumerator,
538 void *name, uint32_t *name_len)
539 {
540 TEE_Result res;
541 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
542 const struct user_ta_property *eps;
543 size_t eps_len;
544 const char *str;
545 size_t bufferlen;
546
547 if (!pe) {
548 res = TEE_ERROR_BAD_PARAMETERS;
549 goto err;
550 }
551 __utee_check_gp11_outstring_annotation(name, name_len);
552
553 bufferlen = *name_len;
554 res = propset_get(pe->prop_set, &eps, &eps_len);
555 if (res != TEE_SUCCESS)
556 goto err;
557
558 if (pe->idx < eps_len) {
559 str = eps[pe->idx].name;
560 bufferlen = strlcpy(name, str, *name_len) + 1;
561 if (bufferlen > *name_len)
562 res = TEE_ERROR_SHORT_BUFFER;
563 *name_len = bufferlen;
564 } else {
565 res = _utee_get_property((unsigned long)pe->prop_set,
566 pe->idx - eps_len, name, name_len,
567 NULL, NULL, NULL);
568 if (res != TEE_SUCCESS)
569 goto err;
570 }
571
572 err:
573 if (res != TEE_SUCCESS &&
574 res != TEE_ERROR_ITEM_NOT_FOUND &&
575 res != TEE_ERROR_SHORT_BUFFER)
576 TEE_Panic(0);
577 return res;
578 }
579
TEE_GetPropertyName(TEE_PropSetHandle enumerator,void * nameBuffer,size_t * nameBufferLen)580 TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator,
581 void *nameBuffer, size_t *nameBufferLen)
582 {
583 TEE_Result res = TEE_SUCCESS;
584 uint32_t l = 0;
585
586 __utee_check_outstring_annotation(nameBuffer, nameBufferLen);
587 l = *nameBufferLen;
588 res = __GP11_TEE_GetPropertyName(enumerator, nameBuffer, &l);
589 *nameBufferLen = l;
590 return res;
591 }
592
TEE_GetNextProperty(TEE_PropSetHandle enumerator)593 TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator)
594 {
595 TEE_Result res;
596 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
597 uint32_t next_idx;
598 const struct user_ta_property *eps;
599 size_t eps_len;
600
601 if (!pe) {
602 res = TEE_ERROR_BAD_PARAMETERS;
603 goto out;
604 }
605
606 if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) {
607 res = TEE_ERROR_ITEM_NOT_FOUND;
608 goto out;
609 }
610
611 res = propset_get(pe->prop_set, &eps, &eps_len);
612 if (res != TEE_SUCCESS)
613 goto out;
614
615 next_idx = pe->idx + 1;
616 pe->idx = next_idx;
617 if (next_idx < eps_len)
618 res = TEE_SUCCESS;
619 else
620 res = _utee_get_property((unsigned long)pe->prop_set,
621 next_idx - eps_len, NULL, NULL, NULL,
622 NULL, NULL);
623
624 out:
625 if (res != TEE_SUCCESS &&
626 res != TEE_ERROR_ITEM_NOT_FOUND)
627 TEE_Panic(0);
628 return res;
629 }
630