xref: /optee_os/lib/libutee/tee_api_property.c (revision 9403c583381528e7fb391e3769644cc9653cfbb6)
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 <tee_api.h>
28 
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <tee_api_defines.h>
33 #include <tee_api_types.h>
34 #include <user_ta_header.h>
35 #include <tee_internal_api_extensions.h>
36 #include <tee_arith_internal.h>
37 
38 #include <utee_syscalls.h>
39 
40 #include "string_ext.h"
41 #include "base64.h"
42 
43 #define PROP_STR_MAX    80
44 
45 #define PROP_ENUMERATOR_NOT_STARTED 0xffffffff
46 
47 struct prop_enumerator {
48 	uint32_t idx;
49 	TEE_PropSetHandle prop_set;
50 };
51 
52 struct prop_value {
53 	enum user_ta_prop_type type;
54 	union {
55 		bool bool_val;
56 		uint32_t int_val;
57 		TEE_UUID uuid_val;
58 		TEE_Identity identity_val;
59 		char str_val[PROP_STR_MAX];
60 	} u;
61 };
62 
63 typedef TEE_Result(*ta_propget_func_t) (struct prop_value *pv);
64 
65 struct prop_set {
66 	const char *str;
67 	ta_propget_func_t get;
68 };
69 
70 static TEE_Result propget_gpd_ta_app_id(struct prop_value *pv)
71 {
72 	pv->type = USER_TA_PROP_TYPE_UUID;
73 	return utee_get_property(UTEE_PROP_TA_APP_ID, &pv->u.uuid_val,
74 				 sizeof(pv->u.uuid_val));
75 }
76 
77 static TEE_Result propget_gpd_client_identity(struct prop_value *pv)
78 {
79 	pv->type = USER_TA_PROP_TYPE_IDENTITY;
80 	return utee_get_property(UTEE_PROP_CLIENT_ID, &pv->u.identity_val,
81 				 sizeof(pv->u.identity_val));
82 }
83 
84 static TEE_Result propget_gpd_tee_api_version(struct prop_value *pv)
85 {
86 	pv->type = USER_TA_PROP_TYPE_STRING;
87 	return utee_get_property(UTEE_PROP_TEE_API_VERSION, &pv->u.str_val,
88 				 sizeof(pv->u.str_val));
89 }
90 
91 static TEE_Result propget_gpd_tee_description(struct prop_value *pv)
92 {
93 	pv->type = USER_TA_PROP_TYPE_STRING;
94 	return utee_get_property(UTEE_PROP_TEE_DESCR, &pv->u.str_val,
95 				 sizeof(pv->u.str_val));
96 }
97 
98 static TEE_Result propget_gpd_tee_device_id(struct prop_value *pv)
99 {
100 	pv->type = USER_TA_PROP_TYPE_UUID;
101 	return utee_get_property(UTEE_PROP_TEE_DEV_ID, &pv->u.uuid_val,
102 				 sizeof(pv->u.uuid_val));
103 }
104 
105 static TEE_Result propget_gpd_tee_sys_time_protection_level(struct prop_value
106 							    *pv)
107 {
108 	pv->type = USER_TA_PROP_TYPE_U32;
109 	return utee_get_property(UTEE_PROP_TEE_SYS_TIME_PROT_LEVEL,
110 				 &pv->u.int_val, sizeof(pv->u.int_val));
111 }
112 
113 static TEE_Result propget_gpd_tee_ta_time_protection_level(struct prop_value
114 							   *pv)
115 {
116 	pv->type = USER_TA_PROP_TYPE_U32;
117 	return utee_get_property(UTEE_PROP_TEE_TA_TIME_PROT_LEVEL,
118 				 &pv->u.int_val, sizeof(pv->u.int_val));
119 }
120 
121 static TEE_Result propget_gpd_tee_arith_max_big_int_size(struct prop_value *pv)
122 {
123 	pv->type = USER_TA_PROP_TYPE_U32;
124 	pv->u.int_val = TEE_MAX_NUMBER_OF_SUPPORTED_BITS;
125 	return TEE_SUCCESS;
126 }
127 
128 static TEE_Result propget_gpd_tee_cryptography_ecc(struct prop_value
129 							   *pv)
130 {
131 	pv->type = USER_TA_PROP_TYPE_BOOL;
132 	return utee_get_property(UTEE_PROP_TEE_CRYPTOGRAPHY_ECC,
133 				 &pv->u.bool_val, sizeof(pv->u.bool_val));
134 }
135 
136 static TEE_Result propget_gpd_tee_ts_antiroll_protection_level(
137 						struct prop_value *pv)
138 {
139 	pv->type = USER_TA_PROP_TYPE_U32;
140 	return utee_get_property(UTEE_PROP_TEE_TS_ANTIROLL_PROT_LEVEL,
141 				 &pv->u.int_val, sizeof(pv->u.int_val));
142 }
143 
144 static TEE_Result propget_gpd_tee_trustedos_impl_version(struct prop_value *pv)
145 {
146 	pv->type = USER_TA_PROP_TYPE_STRING;
147 	return utee_get_property(UTEE_PROP_TEE_TRUSTEDOS_IMPL_VERSION,
148 				 &pv->u.str_val, sizeof(pv->u.str_val));
149 }
150 
151 static TEE_Result propget_gpd_tee_trustedos_impl_bin_version(
152 						struct prop_value *pv)
153 {
154 	pv->type = USER_TA_PROP_TYPE_U32;
155 	return utee_get_property(UTEE_PROP_TEE_TRUSTEDOS_IMPL_BIN_VERSION,
156 				 &pv->u.int_val, sizeof(pv->u.int_val));
157 }
158 
159 static TEE_Result propget_gpd_tee_trustedos_manufacturer(struct prop_value *pv)
160 {
161 	pv->type = USER_TA_PROP_TYPE_STRING;
162 	return utee_get_property(UTEE_PROP_TEE_TRUSTEDOS_MANUFACTURER,
163 				 &pv->u.str_val, sizeof(pv->u.str_val));
164 }
165 
166 static TEE_Result propget_gpd_tee_fw_impl_version(struct prop_value *pv)
167 {
168 	pv->type = USER_TA_PROP_TYPE_STRING;
169 	return utee_get_property(UTEE_PROP_TEE_FW_IMPL_VERSION, &pv->u.str_val,
170 				 sizeof(pv->u.str_val));
171 }
172 
173 static TEE_Result propget_gpd_tee_fw_impl_bin_version(struct prop_value *pv)
174 {
175 	pv->type = USER_TA_PROP_TYPE_U32;
176 	return utee_get_property(UTEE_PROP_TEE_FW_IMPL_BIN_VERSION,
177 				 &pv->u.int_val, sizeof(pv->u.int_val));
178 }
179 
180 static TEE_Result propget_gpd_tee_fw_manufacturer(struct prop_value *pv)
181 {
182 	pv->type = USER_TA_PROP_TYPE_STRING;
183 	return utee_get_property(UTEE_PROP_TEE_FW_MANUFACTURER, &pv->u.str_val,
184 				 sizeof(pv->u.str_val));
185 }
186 
187 static const struct prop_set propset_current_ta[] = {
188 	{"gpd.ta.appID", propget_gpd_ta_app_id},
189 };
190 
191 static const size_t propset_current_ta_len =
192 	sizeof(propset_current_ta) / sizeof(propset_current_ta[0]);
193 
194 static const struct prop_set propset_current_client[] = {
195 	{"gpd.client.identity", propget_gpd_client_identity},
196 };
197 
198 static const size_t propset_current_client_len =
199 	sizeof(propset_current_client) / sizeof(propset_current_client[0]);
200 
201 static const struct prop_set propset_implementation[] = {
202 	{"gpd.tee.apiversion", propget_gpd_tee_api_version},
203 	{"gpd.tee.description", propget_gpd_tee_description},
204 	{"gpd.tee.deviceID", propget_gpd_tee_device_id},
205 	{"gpd.tee.systemTime.protectionLevel",
206 	 propget_gpd_tee_sys_time_protection_level},
207 	{"gpd.tee.TAPersistentTime.protectionLevel",
208 	 propget_gpd_tee_ta_time_protection_level},
209 	{"gpd.tee.arith.maxBigIntSize", propget_gpd_tee_arith_max_big_int_size},
210 	{"gpd.tee.cryptography.ecc", propget_gpd_tee_cryptography_ecc},
211 	{"gpd.tee.trustedStorage.antiRollback.protectionLevel",
212 	 propget_gpd_tee_ts_antiroll_protection_level},
213 	{"gpd.tee.trustedos.implementation.version",
214 	 propget_gpd_tee_trustedos_impl_version},
215 	{"gpd.tee.trustedos.implementation.binaryversion",
216 	 propget_gpd_tee_trustedos_impl_bin_version},
217 	{"gpd.tee.trustedos.manufacturer",
218 	 propget_gpd_tee_trustedos_manufacturer},
219 	{"gpd.tee.firmware.implementation.version",
220 	 propget_gpd_tee_fw_impl_version},
221 	{"gpd.tee.firmware.implementation.binaryversion",
222 	 propget_gpd_tee_fw_impl_bin_version},
223 	{"gpd.tee.firmware.manufacturer",
224 	 propget_gpd_tee_fw_manufacturer},
225 };
226 
227 static const size_t propset_implementation_len =
228 	sizeof(propset_implementation) / sizeof(propset_implementation[0]);
229 
230 static TEE_Result propset_get(TEE_PropSetHandle h, const struct prop_set **ps,
231 			      size_t *ps_len,
232 			      const struct user_ta_property **eps,
233 			      size_t *eps_len)
234 {
235 	if (h == TEE_PROPSET_CURRENT_TA) {
236 		*ps = propset_current_ta;
237 		*ps_len = propset_current_ta_len;
238 		*eps = ta_props;
239 		*eps_len = ta_num_props;
240 	} else if (h == TEE_PROPSET_CURRENT_CLIENT) {
241 		*ps = propset_current_client;
242 		*ps_len = propset_current_client_len;
243 		*eps = NULL;
244 		*eps_len = 0;
245 	} else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) {
246 		*ps = propset_implementation;
247 		*ps_len = propset_implementation_len;
248 		*eps = NULL;
249 		*eps_len = 0;
250 	} else {
251 		return TEE_ERROR_ITEM_NOT_FOUND;
252 	}
253 
254 	return TEE_SUCCESS;
255 }
256 
257 static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep,
258 				       struct prop_value *pv)
259 {
260 	size_t l;
261 
262 	pv->type = ep->type;
263 	switch (ep->type) {
264 	case USER_TA_PROP_TYPE_BOOL:
265 		l = sizeof(bool);
266 		break;
267 	case USER_TA_PROP_TYPE_U32:
268 		l = sizeof(uint32_t);
269 		break;
270 	case USER_TA_PROP_TYPE_UUID:
271 		l = sizeof(TEE_UUID);
272 		break;
273 	case USER_TA_PROP_TYPE_IDENTITY:
274 		l = sizeof(TEE_Identity);
275 		break;
276 	case USER_TA_PROP_TYPE_STRING:
277 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
278 		/* Handle too large strings by truncating them */
279 		strlcpy(pv->u.str_val, ep->value, sizeof(pv->u.str_val));
280 		return TEE_SUCCESS;
281 	default:
282 		return TEE_ERROR_GENERIC;
283 	}
284 	memcpy(&pv->u, ep->value, l);
285 	return TEE_SUCCESS;
286 }
287 
288 static TEE_Result propget_get_property(TEE_PropSetHandle h, char *name,
289 				       struct prop_value *pv)
290 {
291 	TEE_Result res;
292 	const struct prop_set *ps;
293 	size_t ps_len;
294 	const struct user_ta_property *eps;
295 	size_t eps_len;
296 
297 	if (h == TEE_PROPSET_CURRENT_TA || h == TEE_PROPSET_CURRENT_CLIENT ||
298 	    h == TEE_PROPSET_TEE_IMPLEMENTATION) {
299 		size_t n;
300 
301 		res = propset_get(h, &ps, &ps_len, &eps, &eps_len);
302 		if (res != TEE_SUCCESS)
303 			return res;
304 
305 		for (n = 0; n < ps_len; n++) {
306 			if (strcmp(name, ps[n].str) == 0)
307 				return ps[n].get(pv);
308 		}
309 		for (n = 0; n < eps_len; n++) {
310 			if (strcmp(name, eps[n].name) == 0)
311 				return propget_get_ext_prop(eps + n, pv);
312 		}
313 		return TEE_ERROR_ITEM_NOT_FOUND;
314 	} else {
315 		struct prop_enumerator *pe = (struct prop_enumerator *)h;
316 		uint32_t idx = pe->idx;
317 
318 		if (idx == PROP_ENUMERATOR_NOT_STARTED)
319 			return TEE_ERROR_ITEM_NOT_FOUND;
320 
321 		res = propset_get(pe->prop_set, &ps, &ps_len, &eps, &eps_len);
322 		if (res != TEE_SUCCESS)
323 			return res;
324 
325 		if (idx < ps_len)
326 			return ps[idx].get(pv);
327 
328 		idx -= ps_len;
329 		if (idx < eps_len)
330 			return propget_get_ext_prop(eps + idx, pv);
331 
332 		return TEE_ERROR_BAD_PARAMETERS;
333 	}
334 }
335 
336 TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator,
337 				   char *name, char *valueBuffer,
338 				   uint32_t *valueBufferLen)
339 {
340 	TEE_Result res;
341 	struct prop_value pv;
342 	size_t l;
343 	size_t bufferlen;
344 
345 	if (valueBuffer == NULL || valueBufferLen == NULL) {
346 		res = TEE_ERROR_BAD_PARAMETERS;
347 		goto err;
348 	}
349 
350 	bufferlen = *valueBufferLen;
351 
352 	res = propget_get_property(propsetOrEnumerator, name, &pv);
353 	if (res != TEE_SUCCESS)
354 		goto err;
355 
356 	switch (pv.type) {
357 	case USER_TA_PROP_TYPE_BOOL:
358 		l = strlcpy(valueBuffer, pv.u.bool_val ? "true" : "false",
359 			    bufferlen);
360 		break;
361 
362 	case USER_TA_PROP_TYPE_U32:
363 		l = snprintf(valueBuffer, bufferlen, "%u",
364 			     (unsigned int)pv.u.int_val);
365 		break;
366 
367 	case USER_TA_PROP_TYPE_UUID:
368 		l = snprintf(valueBuffer, bufferlen,
369 			     "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x",
370 			     (unsigned int)pv.u.uuid_val.timeLow,
371 			     pv.u.uuid_val.timeMid,
372 			     pv.u.uuid_val.timeHiAndVersion,
373 			     pv.u.uuid_val.clockSeqAndNode[0],
374 			     pv.u.uuid_val.clockSeqAndNode[1],
375 			     pv.u.uuid_val.clockSeqAndNode[2],
376 			     pv.u.uuid_val.clockSeqAndNode[3],
377 			     pv.u.uuid_val.clockSeqAndNode[4],
378 			     pv.u.uuid_val.clockSeqAndNode[5],
379 			     pv.u.uuid_val.clockSeqAndNode[6],
380 			     pv.u.uuid_val.clockSeqAndNode[7]);
381 		break;
382 
383 	case USER_TA_PROP_TYPE_IDENTITY:
384 		l = snprintf(valueBuffer, bufferlen,
385 			     "%u:%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x",
386 			     (unsigned int)pv.u.identity_val.login,
387 			     (unsigned int)pv.u.identity_val.uuid.timeLow,
388 			     pv.u.identity_val.uuid.timeMid,
389 			     pv.u.identity_val.uuid.timeHiAndVersion,
390 			     pv.u.identity_val.uuid.clockSeqAndNode[0],
391 			     pv.u.identity_val.uuid.clockSeqAndNode[1],
392 			     pv.u.identity_val.uuid.clockSeqAndNode[2],
393 			     pv.u.identity_val.uuid.clockSeqAndNode[3],
394 			     pv.u.identity_val.uuid.clockSeqAndNode[4],
395 			     pv.u.identity_val.uuid.clockSeqAndNode[5],
396 			     pv.u.identity_val.uuid.clockSeqAndNode[6],
397 			     pv.u.identity_val.uuid.clockSeqAndNode[7]);
398 		break;
399 
400 	case USER_TA_PROP_TYPE_STRING:
401 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
402 		l = strlcpy(valueBuffer, pv.u.str_val, bufferlen);
403 		break;
404 
405 	default:
406 		res = TEE_ERROR_BAD_FORMAT;
407 		goto err;
408 	}
409 
410 	/* The size "must account for the zero terminator" */
411 	*valueBufferLen = l + 1;
412 
413 	if (l >= bufferlen) {
414 		res = TEE_ERROR_SHORT_BUFFER;
415 		goto err;
416 	}
417 
418 	goto out;
419 
420 err:
421 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
422 	    res == TEE_ERROR_SHORT_BUFFER)
423 		return res;
424 	TEE_Panic(0);
425 out:
426 	return TEE_SUCCESS;
427 }
428 
429 TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator,
430 				 char *name, bool *value)
431 {
432 	TEE_Result res;
433 	struct prop_value pv;
434 
435 	if (value == NULL) {
436 		res = TEE_ERROR_BAD_PARAMETERS;
437 		goto err;
438 	}
439 
440 	res = propget_get_property(propsetOrEnumerator, name, &pv);
441 	if (res != TEE_SUCCESS)
442 		goto err;
443 
444 	if (pv.type != USER_TA_PROP_TYPE_BOOL) {
445 		res = TEE_ERROR_BAD_FORMAT;
446 		goto err;
447 	}
448 
449 	*value = pv.u.bool_val;
450 
451 	goto out;
452 
453 err:
454 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
455 	    res == TEE_ERROR_BAD_FORMAT)
456 		return res;
457 	TEE_Panic(0);
458 out:
459 	return TEE_SUCCESS;
460 }
461 
462 TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator,
463 				char *name, uint32_t *value)
464 {
465 	TEE_Result res;
466 	struct prop_value pv;
467 
468 	if (value == NULL) {
469 		res = TEE_ERROR_BAD_PARAMETERS;
470 		goto err;
471 	}
472 
473 	res = propget_get_property(propsetOrEnumerator, name, &pv);
474 	if (res != TEE_SUCCESS)
475 		goto err;
476 
477 	if (pv.type != USER_TA_PROP_TYPE_U32) {
478 		res = TEE_ERROR_BAD_FORMAT;
479 		goto err;
480 	}
481 
482 	*value = pv.u.int_val;
483 
484 	goto out;
485 
486 err:
487 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
488 	    res == TEE_ERROR_BAD_FORMAT)
489 		return res;
490 	TEE_Panic(0);
491 out:
492 	return TEE_SUCCESS;
493 }
494 
495 TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator,
496 					char *name, void *valueBuffer,
497 					uint32_t *valueBufferLen)
498 {
499 	TEE_Result res;
500 	struct prop_value pv;
501 	void *val;
502 	int val_len;
503 	size_t size;
504 
505 	if (valueBuffer == NULL || valueBufferLen == NULL) {
506 		res = TEE_ERROR_BAD_PARAMETERS;
507 		goto err;
508 	}
509 
510 	res = propget_get_property(propsetOrEnumerator, name, &pv);
511 	if (res != TEE_SUCCESS)
512 		goto err;
513 
514 	if (pv.type != USER_TA_PROP_TYPE_BINARY_BLOCK) {
515 		res = TEE_ERROR_BAD_FORMAT;
516 		goto err;
517 	}
518 
519 	val = pv.u.str_val;
520 	val_len = strlen(val);
521 	size = *valueBufferLen;
522 	if (!base64_dec(val, val_len, valueBuffer, &size)) {
523 		res = TEE_ERROR_SHORT_BUFFER;
524 		goto err;
525 	}
526 
527 	*valueBufferLen = size;
528 
529 	goto out;
530 
531 err:
532 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
533 	    res == TEE_ERROR_BAD_FORMAT ||
534 	    res == TEE_ERROR_SHORT_BUFFER)
535 		return res;
536 	TEE_Panic(0);
537 out:
538 	return TEE_SUCCESS;
539 }
540 
541 TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator,
542 				 char *name, TEE_UUID *value)
543 {
544 	TEE_Result res;
545 	struct prop_value pv;
546 
547 	if (value == NULL) {
548 		res = TEE_ERROR_BAD_PARAMETERS;
549 		goto err;
550 	}
551 
552 	res = propget_get_property(propsetOrEnumerator, name, &pv);
553 	if (res != TEE_SUCCESS)
554 		goto err;
555 
556 	if (pv.type != USER_TA_PROP_TYPE_UUID) {
557 		res = TEE_ERROR_BAD_FORMAT;
558 		goto err;
559 	}
560 
561 	*value = pv.u.uuid_val;	/* struct copy */
562 
563 	goto out;
564 
565 err:
566 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
567 	    res == TEE_ERROR_BAD_FORMAT)
568 		return res;
569 	TEE_Panic(0);
570 out:
571 	return TEE_SUCCESS;
572 }
573 
574 TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator,
575 				     char *name, TEE_Identity *value)
576 {
577 	TEE_Result res;
578 	struct prop_value pv;
579 
580 	if (value == NULL) {
581 		res = TEE_ERROR_BAD_PARAMETERS;
582 		goto err;
583 	}
584 
585 	res = propget_get_property(propsetOrEnumerator, name, &pv);
586 	if (res != TEE_SUCCESS)
587 		goto err;
588 
589 	if (pv.type != USER_TA_PROP_TYPE_IDENTITY) {
590 		res = TEE_ERROR_BAD_FORMAT;
591 		goto err;
592 	}
593 
594 	*value = pv.u.identity_val;	/* struct copy */
595 
596 	goto out;
597 
598 err:
599 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
600 	    res == TEE_ERROR_BAD_FORMAT)
601 		return res;
602 	TEE_Panic(0);
603 out:
604 	return TEE_SUCCESS;
605 }
606 
607 TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator)
608 {
609 	TEE_Result res;
610 	struct prop_enumerator *pe;
611 
612 	if (enumerator == NULL) {
613 		res = TEE_ERROR_BAD_PARAMETERS;
614 		goto err;
615 	}
616 
617 	pe = TEE_Malloc(sizeof(struct prop_enumerator),
618 			TEE_USER_MEM_HINT_NO_FILL_ZERO);
619 	if (pe == NULL) {
620 		res = TEE_ERROR_OUT_OF_MEMORY;
621 		goto err;
622 	}
623 
624 	*enumerator = (TEE_PropSetHandle) pe;
625 	TEE_ResetPropertyEnumerator(*enumerator);
626 
627 	goto out;
628 
629 err:
630 	if (res == TEE_ERROR_OUT_OF_MEMORY)
631 		return res;
632 	TEE_Panic(0);
633 out:
634 	return TEE_SUCCESS;
635 }
636 
637 void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator)
638 {
639 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
640 
641 	pe->idx = PROP_ENUMERATOR_NOT_STARTED;
642 }
643 
644 void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator)
645 {
646 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
647 
648 	TEE_Free(pe);
649 }
650 
651 void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator,
652 				 TEE_PropSetHandle propSet)
653 {
654 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
655 
656 	if (pe == NULL)
657 		return;
658 
659 	pe->idx = 0;
660 	pe->prop_set = propSet;
661 }
662 
663 TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator,
664 			       void *nameBuffer, uint32_t *nameBufferLen)
665 {
666 	TEE_Result res;
667 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
668 	const struct prop_set *ps;
669 	size_t ps_len;
670 	const struct user_ta_property *eps;
671 	size_t eps_len;
672 	size_t l;
673 	const char *str;
674 	size_t bufferlen;
675 
676 	if (pe == NULL || nameBuffer == NULL || nameBufferLen == NULL) {
677 		res = TEE_ERROR_BAD_PARAMETERS;
678 		goto err;
679 	}
680 
681 	bufferlen = *nameBufferLen;
682 	res = propset_get(pe->prop_set, &ps, &ps_len, &eps, &eps_len);
683 	if (res != TEE_SUCCESS)
684 		goto err;
685 
686 	if (pe->idx < ps_len)
687 		str = ps[pe->idx].str;
688 	else if ((pe->idx - ps_len) < eps_len)
689 		str = ta_props[pe->idx - ps_len].name;
690 	else {
691 		res = TEE_ERROR_ITEM_NOT_FOUND;
692 		goto err;
693 	}
694 
695 	l = strlcpy(nameBuffer, str, bufferlen);
696 
697 	/* The size "must account for the zero terminator" */
698 	*nameBufferLen = l + 1;
699 
700 	if (l >= bufferlen) {
701 		res = TEE_ERROR_SHORT_BUFFER;
702 		goto err;
703 	}
704 
705 	goto out;
706 
707 err:
708 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
709 	    res == TEE_ERROR_SHORT_BUFFER)
710 		return res;
711 	TEE_Panic(0);
712 out:
713 	return TEE_SUCCESS;
714 }
715 
716 TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator)
717 {
718 	TEE_Result res;
719 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
720 	uint32_t next_idx;
721 	const struct prop_set *ps;
722 	size_t ps_len;
723 	const struct user_ta_property *eps;
724 	size_t eps_len;
725 
726 	if (pe == NULL) {
727 		res = TEE_ERROR_BAD_PARAMETERS;
728 		goto err;
729 	}
730 
731 	if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) {
732 		res = TEE_ERROR_ITEM_NOT_FOUND;
733 		goto err;
734 	}
735 
736 	res = propset_get(pe->prop_set, &ps, &ps_len, &eps, &eps_len);
737 	if (res != TEE_SUCCESS)
738 		goto err;
739 
740 	next_idx = pe->idx + 1;
741 	pe->idx = next_idx;
742 	if (next_idx >= (ps_len + eps_len)) {
743 		res = TEE_ERROR_ITEM_NOT_FOUND;
744 		goto err;
745 	}
746 
747 	goto out;
748 
749 err:
750 	if (res == TEE_ERROR_ITEM_NOT_FOUND)
751 		return res;
752 	TEE_Panic(0);
753 out:
754 	return TEE_SUCCESS;
755 }
756