xref: /optee_os/lib/libutee/tee_api_property.c (revision 6915bbbb5b56e147ee652b98f6172f4dfbb325b9)
11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2b0104773SPascal Brand /*
3b0104773SPascal Brand  * Copyright (c) 2014, STMicroelectronics International N.V.
4*6915bbbbSJens Wiklander  * Copyright (c) 2017-2020, Linaro Limited
5b0104773SPascal Brand  */
6a32a96edSJens Wiklander #include <printk.h>
7a32a96edSJens Wiklander #include <stdio.h>
8b0104773SPascal Brand #include <stdlib.h>
9b0104773SPascal Brand #include <string.h>
10b0104773SPascal Brand #include <tee_api_defines.h>
11a32a96edSJens Wiklander #include <tee_api.h>
12b0104773SPascal Brand #include <tee_api_types.h>
13647f9c76SJerome Forissier #include <tee_arith_internal.h>
14a32a96edSJens Wiklander #include <tee_internal_api_extensions.h>
15a32a96edSJens Wiklander #include <tee_isocket.h>
16a32a96edSJens Wiklander #include <user_ta_header.h>
17b0104773SPascal Brand #include <utee_syscalls.h>
18a32a96edSJens Wiklander #include <util.h>
19b0104773SPascal Brand 
20b0104773SPascal Brand #include "base64.h"
21*6915bbbbSJens Wiklander #include "string_ext.h"
22*6915bbbbSJens Wiklander #include "tee_api_private.h"
23b0104773SPascal Brand 
24b0104773SPascal Brand #define PROP_STR_MAX    80
25b0104773SPascal Brand 
26b0104773SPascal Brand #define PROP_ENUMERATOR_NOT_STARTED 0xffffffff
27b0104773SPascal Brand 
28b0104773SPascal Brand struct prop_enumerator {
2964a5011eSPascal Brand 	uint32_t idx;			/* current index */
3064a5011eSPascal Brand 	TEE_PropSetHandle prop_set;	/* part of TEE_PROPSET_xxx */
31b0104773SPascal Brand };
32b0104773SPascal Brand 
3364a5011eSPascal Brand const struct user_ta_property tee_props[] = {
3464a5011eSPascal Brand 	{
3564a5011eSPascal Brand 		"gpd.tee.arith.maxBigIntSize",
3664a5011eSPascal Brand 		USER_TA_PROP_TYPE_U32,
37e3458e03SJerome Forissier 		&(const uint32_t){CFG_TA_BIGNUM_MAX_BITS}
3864a5011eSPascal Brand 	},
39a32a96edSJens Wiklander 	{
40a32a96edSJens Wiklander 		"gpd.tee.sockets.version",
41a32a96edSJens Wiklander 		USER_TA_PROP_TYPE_U32,
42a32a96edSJens Wiklander 		&(const uint32_t){TEE_ISOCKET_VERSION}
43a32a96edSJens Wiklander 	},
44a32a96edSJens Wiklander 	{
45a32a96edSJens Wiklander 		"gpd.tee.sockets.tcp.version",
46a32a96edSJens Wiklander 		USER_TA_PROP_TYPE_U32,
47a32a96edSJens Wiklander 		&(const uint32_t){TEE_ISOCKET_VERSION}
48a32a96edSJens Wiklander 	},
49b0104773SPascal Brand };
50b0104773SPascal Brand 
5164a5011eSPascal Brand static TEE_Result propset_get(TEE_PropSetHandle h,
52b0104773SPascal Brand 			      const struct user_ta_property **eps,
53b0104773SPascal Brand 			      size_t *eps_len)
54b0104773SPascal Brand {
55b0104773SPascal Brand 	if (h == TEE_PROPSET_CURRENT_TA) {
56b0104773SPascal Brand 		*eps = ta_props;
57b0104773SPascal Brand 		*eps_len = ta_num_props;
58b0104773SPascal Brand 	} else if (h == TEE_PROPSET_CURRENT_CLIENT) {
59b0104773SPascal Brand 		*eps = NULL;
60b0104773SPascal Brand 		*eps_len = 0;
61b0104773SPascal Brand 	} else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) {
6264a5011eSPascal Brand 		*eps = tee_props;
6364a5011eSPascal Brand 		*eps_len = ARRAY_SIZE(tee_props);
64b0104773SPascal Brand 	} else {
65b0104773SPascal Brand 		return TEE_ERROR_ITEM_NOT_FOUND;
66b0104773SPascal Brand 	}
67b0104773SPascal Brand 
68b0104773SPascal Brand 	return TEE_SUCCESS;
69b0104773SPascal Brand }
70b0104773SPascal Brand 
71b0104773SPascal Brand static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep,
72ff857a3aSPascal Brand 				       enum user_ta_prop_type *type,
73ff857a3aSPascal Brand 				       void *buf, uint32_t *len)
74b0104773SPascal Brand {
75b0104773SPascal Brand 	size_t l;
76b0104773SPascal Brand 
77ff857a3aSPascal Brand 	*type = ep->type;
78ff857a3aSPascal Brand 	switch (*type) {
79b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BOOL:
80d5d50c3cSJens Wiklander 		l = sizeof(bool);
81b0104773SPascal Brand 		break;
82b0104773SPascal Brand 	case USER_TA_PROP_TYPE_U32:
83b0104773SPascal Brand 		l = sizeof(uint32_t);
84b0104773SPascal Brand 		break;
85b0104773SPascal Brand 	case USER_TA_PROP_TYPE_UUID:
86b0104773SPascal Brand 		l = sizeof(TEE_UUID);
87b0104773SPascal Brand 		break;
88b0104773SPascal Brand 	case USER_TA_PROP_TYPE_IDENTITY:
89b0104773SPascal Brand 		l = sizeof(TEE_Identity);
90b0104773SPascal Brand 		break;
91b0104773SPascal Brand 	case USER_TA_PROP_TYPE_STRING:
92ff857a3aSPascal Brand 		/* take the leading 0 into account */
93ff857a3aSPascal Brand 		l = strlen(ep->value) + 1;
94ff857a3aSPascal Brand 		break;
95b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
96ff857a3aSPascal Brand 		/*
97ff857a3aSPascal Brand 		 * in case of TA property, a binary block is provided as a
98ff857a3aSPascal Brand 		 * string, which is base64 encoded. We must first decode it,
99ff857a3aSPascal Brand 		 * without taking into account the zero termination of the
100ff857a3aSPascal Brand 		 * string
101ff857a3aSPascal Brand 		 */
102ff857a3aSPascal Brand 		l = *len;
10397b8ba50SJerome Forissier 		if (!_base64_dec(ep->value, strlen(ep->value), buf, &l) &&
104ec930caeSJerome Forissier 		    l <= *len)
105ff857a3aSPascal Brand 			return TEE_ERROR_GENERIC;
106ff857a3aSPascal Brand 		if (*len < l) {
107ff857a3aSPascal Brand 			*len = l;
108ff857a3aSPascal Brand 			return TEE_ERROR_SHORT_BUFFER;
109ff857a3aSPascal Brand 		}
110ff857a3aSPascal Brand 
111ff857a3aSPascal Brand 		*len = l;
112b0104773SPascal Brand 		return TEE_SUCCESS;
113b0104773SPascal Brand 	default:
114b0104773SPascal Brand 		return TEE_ERROR_GENERIC;
115b0104773SPascal Brand 	}
116ff857a3aSPascal Brand 
117ff857a3aSPascal Brand 	if (*len < l) {
118ff857a3aSPascal Brand 		*len = l;
119ff857a3aSPascal Brand 		return TEE_ERROR_SHORT_BUFFER;
120ff857a3aSPascal Brand 	}
121ff857a3aSPascal Brand 
122ff857a3aSPascal Brand 	*len = l;
123ff857a3aSPascal Brand 	memcpy(buf, ep->value, l);
124b0104773SPascal Brand 	return TEE_SUCCESS;
125b0104773SPascal Brand }
126b0104773SPascal Brand 
127*6915bbbbSJens Wiklander static bool is_propset_pseudo_handle(TEE_PropSetHandle h)
128*6915bbbbSJens Wiklander {
129*6915bbbbSJens Wiklander 	return h == TEE_PROPSET_CURRENT_TA ||
130*6915bbbbSJens Wiklander 	       h == TEE_PROPSET_CURRENT_CLIENT ||
131*6915bbbbSJens Wiklander 	       h == TEE_PROPSET_TEE_IMPLEMENTATION;
132*6915bbbbSJens Wiklander }
133*6915bbbbSJens Wiklander 
1348f07fe6fSJerome Forissier static TEE_Result propget_get_property(TEE_PropSetHandle h, const char *name,
135ff857a3aSPascal Brand 				       enum user_ta_prop_type *type,
136ff857a3aSPascal Brand 				       void *buf, uint32_t *len)
137b0104773SPascal Brand {
138b0104773SPascal Brand 	TEE_Result res;
139b0104773SPascal Brand 	const struct user_ta_property *eps;
140b0104773SPascal Brand 	size_t eps_len;
14164a5011eSPascal Brand 	uint32_t prop_type;
14264a5011eSPascal Brand 	uint32_t index;
143b0104773SPascal Brand 
144*6915bbbbSJens Wiklander 	if (is_propset_pseudo_handle(h)) {
145b0104773SPascal Brand 		size_t n;
146b0104773SPascal Brand 
14764a5011eSPascal Brand 		res = propset_get(h, &eps, &eps_len);
148b0104773SPascal Brand 		if (res != TEE_SUCCESS)
149b0104773SPascal Brand 			return res;
150b0104773SPascal Brand 
151b0104773SPascal Brand 		for (n = 0; n < eps_len; n++) {
15264a5011eSPascal Brand 			if (!strcmp(name, eps[n].name))
153ff857a3aSPascal Brand 				return propget_get_ext_prop(eps + n, type,
154ff857a3aSPascal Brand 							    buf, len);
155b0104773SPascal Brand 		}
15664a5011eSPascal Brand 
15764a5011eSPascal Brand 		/* get the index from the name */
1582c028fdeSJerome Forissier 		res = _utee_get_property_name_to_index((unsigned long)h, name,
1592c028fdeSJerome Forissier 						       strlen(name) + 1,
1602c028fdeSJerome Forissier 						       &index);
16164a5011eSPascal Brand 		if (res != TEE_SUCCESS)
16264a5011eSPascal Brand 			return res;
1632c028fdeSJerome Forissier 		res = _utee_get_property((unsigned long)h, index, NULL, NULL,
164ff857a3aSPascal Brand 					 buf, len, &prop_type);
165b0104773SPascal Brand 	} else {
166b0104773SPascal Brand 		struct prop_enumerator *pe = (struct prop_enumerator *)h;
167b0104773SPascal Brand 		uint32_t idx = pe->idx;
168b0104773SPascal Brand 
169b0104773SPascal Brand 		if (idx == PROP_ENUMERATOR_NOT_STARTED)
170b0104773SPascal Brand 			return TEE_ERROR_ITEM_NOT_FOUND;
171b0104773SPascal Brand 
17264a5011eSPascal Brand 		res = propset_get(pe->prop_set, &eps, &eps_len);
173b0104773SPascal Brand 		if (res != TEE_SUCCESS)
174b0104773SPascal Brand 			return res;
175b0104773SPascal Brand 
176b0104773SPascal Brand 		if (idx < eps_len)
177ff857a3aSPascal Brand 			return propget_get_ext_prop(eps + idx, type, buf, len);
17864a5011eSPascal Brand 		idx -= eps_len;
179b0104773SPascal Brand 
1802c028fdeSJerome Forissier 		res = _utee_get_property((unsigned long)pe->prop_set, idx,
181ff857a3aSPascal Brand 					 NULL, NULL, buf, len, &prop_type);
18264a5011eSPascal Brand 		if (res == TEE_ERROR_ITEM_NOT_FOUND)
18364a5011eSPascal Brand 			res = TEE_ERROR_BAD_PARAMETERS;
184b0104773SPascal Brand 	}
18564a5011eSPascal Brand 
186ff857a3aSPascal Brand 	*type = prop_type;
18764a5011eSPascal Brand 	return res;
188b0104773SPascal Brand }
189b0104773SPascal Brand 
190b0104773SPascal Brand TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator,
1918f07fe6fSJerome Forissier 				   const char *name, char *value,
1920dd3f3a4SPascal Brand 				   uint32_t *value_len)
193b0104773SPascal Brand {
194b0104773SPascal Brand 	TEE_Result res;
195b0104773SPascal Brand 	size_t l;
196ff857a3aSPascal Brand 	enum user_ta_prop_type type;
197ff857a3aSPascal Brand 	void *tmp_buf = 0;
198ff857a3aSPascal Brand 	uint32_t tmp_len;
199ff857a3aSPascal Brand 	uint32_t uint32_val;
200d5d50c3cSJens Wiklander 	bool bool_val;
201ff857a3aSPascal Brand 	TEE_Identity *p_identity_val;
202b0104773SPascal Brand 
203*6915bbbbSJens Wiklander 	if (is_propset_pseudo_handle(propsetOrEnumerator))
204*6915bbbbSJens Wiklander 		__utee_check_instring_annotation(name);
205*6915bbbbSJens Wiklander 	__utee_check_outstring_annotation(value, value_len);
206b0104773SPascal Brand 
2070dd3f3a4SPascal Brand 	tmp_len = *value_len;
208ff857a3aSPascal Brand 	if (tmp_len < sizeof(TEE_Identity))
209ff857a3aSPascal Brand 		tmp_len = sizeof(TEE_Identity);
210ff857a3aSPascal Brand 	tmp_buf = TEE_Malloc(tmp_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
211ff857a3aSPascal Brand 	if (!tmp_buf) {
212ff857a3aSPascal Brand 		res = TEE_ERROR_OUT_OF_MEMORY;
213ff857a3aSPascal Brand 		goto out;
214ff857a3aSPascal Brand 	}
215b0104773SPascal Brand 
216ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
217ff857a3aSPascal Brand 				   tmp_buf, &tmp_len);
218ff857a3aSPascal Brand 	if (res != TEE_SUCCESS) {
219254e1d58SPascal Brand 		if (res == TEE_ERROR_SHORT_BUFFER) {
220254e1d58SPascal Brand 			if (type == USER_TA_PROP_TYPE_BINARY_BLOCK) {
221254e1d58SPascal Brand 				/*
222254e1d58SPascal Brand 				 * in this case, we must enlarge the buffer
223254e1d58SPascal Brand 				 * with the size of the of the base64 encoded
224254e1d58SPascal Brand 				 * see base64_enc() function
225254e1d58SPascal Brand 				 */
22697b8ba50SJerome Forissier 				tmp_len = _base64_enc_len(tmp_len);
227254e1d58SPascal Brand 			}
2280dd3f3a4SPascal Brand 			*value_len = tmp_len;
229254e1d58SPascal Brand 		}
230ff857a3aSPascal Brand 		goto out;
231ff857a3aSPascal Brand 	}
232b0104773SPascal Brand 
233ff857a3aSPascal Brand 	switch (type) {
234b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BOOL:
235d5d50c3cSJens Wiklander 		bool_val = *((bool *)tmp_buf);
236d5d50c3cSJens Wiklander 		l = strlcpy(value, (bool_val ? "true" : "false"), *value_len);
237b0104773SPascal Brand 		break;
238b0104773SPascal Brand 
239b0104773SPascal Brand 	case USER_TA_PROP_TYPE_U32:
240ff857a3aSPascal Brand 		uint32_val = *((uint32_t *)tmp_buf);
2410dd3f3a4SPascal Brand 		l = snprintf(value, *value_len, "%u", uint32_val);
242b0104773SPascal Brand 		break;
243b0104773SPascal Brand 
244b0104773SPascal Brand 	case USER_TA_PROP_TYPE_UUID:
2450dd3f3a4SPascal Brand 		l = snprintk(value, *value_len, "%pUl", tmp_buf);
246b0104773SPascal Brand 		break;
247b0104773SPascal Brand 
248b0104773SPascal Brand 	case USER_TA_PROP_TYPE_IDENTITY:
249ff857a3aSPascal Brand 		p_identity_val = ((TEE_Identity *)tmp_buf);
2500dd3f3a4SPascal Brand 		l = snprintk(value, *value_len, "%u:%pUl",
251ff857a3aSPascal Brand 			     p_identity_val->login,
252ff857a3aSPascal Brand 			     (void *)(&(p_identity_val->uuid)));
253b0104773SPascal Brand 		break;
254b0104773SPascal Brand 
255b0104773SPascal Brand 	case USER_TA_PROP_TYPE_STRING:
2560dd3f3a4SPascal Brand 		l = strlcpy(value, tmp_buf, *value_len);
257ff857a3aSPascal Brand 		break;
258ff857a3aSPascal Brand 
259b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
2600dd3f3a4SPascal Brand 		l = *value_len;	/* l includes the zero-termination */
26197b8ba50SJerome Forissier 		if (!_base64_enc(tmp_buf, tmp_len, value, &l) &&
262ec930caeSJerome Forissier 		    l <= *value_len) {
263ff857a3aSPascal Brand 			res = TEE_ERROR_GENERIC;
264ff857a3aSPascal Brand 			goto out;
265ff857a3aSPascal Brand 		}
266ff857a3aSPascal Brand 		l--;	/* remove the zero-termination that is added later */
267b0104773SPascal Brand 		break;
268b0104773SPascal Brand 
269b0104773SPascal Brand 	default:
270ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_FORMAT;
271ba675d69SCedric Chaumont 		goto out;
272ff857a3aSPascal Brand 	}
273ba675d69SCedric Chaumont 
274ff857a3aSPascal Brand 	l++;	/* include zero termination */
275ff857a3aSPascal Brand 
2760dd3f3a4SPascal Brand 	if (l > *value_len)
277ff857a3aSPascal Brand 		res = TEE_ERROR_SHORT_BUFFER;
2780dd3f3a4SPascal Brand 	*value_len = l;
279ff857a3aSPascal Brand 
280ba675d69SCedric Chaumont out:
281ff857a3aSPascal Brand 	if (tmp_buf)
282ff857a3aSPascal Brand 		TEE_Free(tmp_buf);
283ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
284ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
285ff857a3aSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER)
286ff857a3aSPascal Brand 		TEE_Panic(0);
287ff857a3aSPascal Brand 
288ff857a3aSPascal Brand 	return res;
289b0104773SPascal Brand }
290b0104773SPascal Brand 
291b0104773SPascal Brand TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator,
2928f07fe6fSJerome Forissier 				 const char *name, bool *value)
293b0104773SPascal Brand {
294b0104773SPascal Brand 	TEE_Result res;
295ff857a3aSPascal Brand 	enum user_ta_prop_type type;
296d5d50c3cSJens Wiklander 	uint32_t bool_len = sizeof(bool);
297*6915bbbbSJens Wiklander 
298*6915bbbbSJens Wiklander 	if (is_propset_pseudo_handle(propsetOrEnumerator))
299*6915bbbbSJens Wiklander 		__utee_check_instring_annotation(name);
300*6915bbbbSJens Wiklander 	__utee_check_out_annotation(value, sizeof(*value));
301b0104773SPascal Brand 
302ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_BOOL;
303ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
304d5d50c3cSJens Wiklander 				   value, &bool_len);
305ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_BOOL)
306ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_FORMAT;
307ff857a3aSPascal Brand 	if (res != TEE_SUCCESS)
308ba675d69SCedric Chaumont 		goto out;
309ba675d69SCedric Chaumont 
310ba675d69SCedric Chaumont out:
311ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
312ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
313ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT)
314ff857a3aSPascal Brand 		TEE_Panic(0);
315ff857a3aSPascal Brand 
316ff857a3aSPascal Brand 	return res;
317b0104773SPascal Brand }
318b0104773SPascal Brand 
319b0104773SPascal Brand TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator,
3208f07fe6fSJerome Forissier 				const char *name, uint32_t *value)
321b0104773SPascal Brand {
322b0104773SPascal Brand 	TEE_Result res;
323ff857a3aSPascal Brand 	enum user_ta_prop_type type;
324ff857a3aSPascal Brand 	uint32_t uint32_len = sizeof(uint32_t);
325b0104773SPascal Brand 
326*6915bbbbSJens Wiklander 	if (is_propset_pseudo_handle(propsetOrEnumerator))
327*6915bbbbSJens Wiklander 		__utee_check_instring_annotation(name);
328*6915bbbbSJens Wiklander 	__utee_check_out_annotation(value, sizeof(*value));
329ba675d69SCedric Chaumont 
330ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_U32;
331ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
332ff857a3aSPascal Brand 				   value, &uint32_len);
333ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_U32)
334ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
335ff857a3aSPascal Brand 
336ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
337ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
338ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT)
339ff857a3aSPascal Brand 		TEE_Panic(0);
340ff857a3aSPascal Brand 
341ff857a3aSPascal Brand 	return res;
342b0104773SPascal Brand }
343b0104773SPascal Brand 
344b0104773SPascal Brand TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator,
3458f07fe6fSJerome Forissier 					const char *name, void *value,
3460dd3f3a4SPascal Brand 					uint32_t *value_len)
347b0104773SPascal Brand {
348b0104773SPascal Brand 	TEE_Result res;
349ff857a3aSPascal Brand 	enum user_ta_prop_type type;
350b0104773SPascal Brand 
351*6915bbbbSJens Wiklander 	if (is_propset_pseudo_handle(propsetOrEnumerator))
352*6915bbbbSJens Wiklander 		__utee_check_instring_annotation(name);
353*6915bbbbSJens Wiklander 	__utee_check_outbuf_annotation(value, value_len);
354ba675d69SCedric Chaumont 
355ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_BINARY_BLOCK;
356ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
3570dd3f3a4SPascal Brand 				   value, value_len);
358ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_BINARY_BLOCK)
359ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
360ff857a3aSPascal Brand 
361ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
362ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
363ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT &&
364ff857a3aSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER)
365ff857a3aSPascal Brand 		TEE_Panic(0);
366ff857a3aSPascal Brand 
367ff857a3aSPascal Brand 	return res;
368b0104773SPascal Brand }
369b0104773SPascal Brand 
370b0104773SPascal Brand TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator,
3718f07fe6fSJerome Forissier 				 const char *name, TEE_UUID *value)
372b0104773SPascal Brand {
373b0104773SPascal Brand 	TEE_Result res;
374ff857a3aSPascal Brand 	enum user_ta_prop_type type;
375ff857a3aSPascal Brand 	uint32_t uuid_len = sizeof(TEE_UUID);
376b0104773SPascal Brand 
377*6915bbbbSJens Wiklander 	if (is_propset_pseudo_handle(propsetOrEnumerator))
378*6915bbbbSJens Wiklander 		__utee_check_instring_annotation(name);
379*6915bbbbSJens Wiklander 	__utee_check_out_annotation(value, sizeof(*value));
380ba675d69SCedric Chaumont 
381ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_UUID;
382ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
383ff857a3aSPascal Brand 				   value, &uuid_len);
384ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_UUID)
385ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
386ff857a3aSPascal Brand 
387ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
388ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
389ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT)
390ff857a3aSPascal Brand 		TEE_Panic(0);
391ff857a3aSPascal Brand 
392ff857a3aSPascal Brand 	return res;
393b0104773SPascal Brand }
394b0104773SPascal Brand 
395b0104773SPascal Brand TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator,
3968f07fe6fSJerome Forissier 				     const char *name, TEE_Identity *value)
397b0104773SPascal Brand {
398b0104773SPascal Brand 	TEE_Result res;
399ff857a3aSPascal Brand 	enum user_ta_prop_type type;
400ff857a3aSPascal Brand 	uint32_t identity_len = sizeof(TEE_Identity);
401b0104773SPascal Brand 
402*6915bbbbSJens Wiklander 	if (is_propset_pseudo_handle(propsetOrEnumerator))
403*6915bbbbSJens Wiklander 		__utee_check_instring_annotation(name);
404*6915bbbbSJens Wiklander 	__utee_check_out_annotation(value, sizeof(*value));
405ba675d69SCedric Chaumont 
406ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_IDENTITY;
407ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
408ff857a3aSPascal Brand 				   value, &identity_len);
409ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_IDENTITY)
410ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
411ff857a3aSPascal Brand 
412ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
413ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
414ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT)
415ff857a3aSPascal Brand 		TEE_Panic(0);
416ff857a3aSPascal Brand 
417ff857a3aSPascal Brand 	return res;
418b0104773SPascal Brand }
419b0104773SPascal Brand 
420b0104773SPascal Brand TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator)
421b0104773SPascal Brand {
422ba675d69SCedric Chaumont 	TEE_Result res;
423b0104773SPascal Brand 	struct prop_enumerator *pe;
424b0104773SPascal Brand 
425*6915bbbbSJens Wiklander 	__utee_check_out_annotation(enumerator, sizeof(*enumerator));
426b0104773SPascal Brand 
427b0104773SPascal Brand 	pe = TEE_Malloc(sizeof(struct prop_enumerator),
428b0104773SPascal Brand 			TEE_USER_MEM_HINT_NO_FILL_ZERO);
429ba675d69SCedric Chaumont 	if (pe == NULL) {
430ba675d69SCedric Chaumont 		res = TEE_ERROR_OUT_OF_MEMORY;
431ba675d69SCedric Chaumont 		goto err;
432ba675d69SCedric Chaumont 	}
433b0104773SPascal Brand 
434b0104773SPascal Brand 	*enumerator = (TEE_PropSetHandle) pe;
435b0104773SPascal Brand 	TEE_ResetPropertyEnumerator(*enumerator);
436ba675d69SCedric Chaumont 
437ba675d69SCedric Chaumont 	goto out;
438ba675d69SCedric Chaumont 
439ba675d69SCedric Chaumont err:
440ba675d69SCedric Chaumont 	if (res == TEE_ERROR_OUT_OF_MEMORY)
441ba675d69SCedric Chaumont 		return res;
442ba675d69SCedric Chaumont 	TEE_Panic(0);
443ba675d69SCedric Chaumont out:
444b0104773SPascal Brand 	return TEE_SUCCESS;
445b0104773SPascal Brand }
446b0104773SPascal Brand 
447b0104773SPascal Brand void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator)
448b0104773SPascal Brand {
449b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
450b0104773SPascal Brand 
451b0104773SPascal Brand 	pe->idx = PROP_ENUMERATOR_NOT_STARTED;
452b0104773SPascal Brand }
453b0104773SPascal Brand 
454b0104773SPascal Brand void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator)
455b0104773SPascal Brand {
456b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
457b0104773SPascal Brand 
458b0104773SPascal Brand 	TEE_Free(pe);
459b0104773SPascal Brand }
460b0104773SPascal Brand 
461b0104773SPascal Brand void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator,
462b0104773SPascal Brand 				 TEE_PropSetHandle propSet)
463b0104773SPascal Brand {
464b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
465b0104773SPascal Brand 
4660dd3f3a4SPascal Brand 	if (!pe)
467b0104773SPascal Brand 		return;
468b0104773SPascal Brand 
469b0104773SPascal Brand 	pe->idx = 0;
470b0104773SPascal Brand 	pe->prop_set = propSet;
471b0104773SPascal Brand }
472b0104773SPascal Brand 
473b0104773SPascal Brand TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator,
4740dd3f3a4SPascal Brand 			       void *name, uint32_t *name_len)
475b0104773SPascal Brand {
476b0104773SPascal Brand 	TEE_Result res;
477b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
478b0104773SPascal Brand 	const struct user_ta_property *eps;
479b0104773SPascal Brand 	size_t eps_len;
480b0104773SPascal Brand 	const char *str;
481b0104773SPascal Brand 	size_t bufferlen;
482b0104773SPascal Brand 
483*6915bbbbSJens Wiklander 	if (!pe) {
484ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
485ba675d69SCedric Chaumont 		goto err;
486ba675d69SCedric Chaumont 	}
487*6915bbbbSJens Wiklander 	__utee_check_outstring_annotation(name, name_len);
488b0104773SPascal Brand 
4890dd3f3a4SPascal Brand 	bufferlen = *name_len;
49064a5011eSPascal Brand 	res = propset_get(pe->prop_set, &eps, &eps_len);
491b0104773SPascal Brand 	if (res != TEE_SUCCESS)
492ba675d69SCedric Chaumont 		goto err;
493b0104773SPascal Brand 
49464a5011eSPascal Brand 	if (pe->idx < eps_len) {
49564a5011eSPascal Brand 		str = eps[pe->idx].name;
4960dd3f3a4SPascal Brand 		bufferlen = strlcpy(name, str, *name_len) + 1;
4970dd3f3a4SPascal Brand 		if (bufferlen > *name_len)
498ba675d69SCedric Chaumont 			res = TEE_ERROR_SHORT_BUFFER;
4990dd3f3a4SPascal Brand 		*name_len = bufferlen;
50064a5011eSPascal Brand 	} else {
5012c028fdeSJerome Forissier 		res = _utee_get_property((unsigned long)pe->prop_set,
5022c028fdeSJerome Forissier 					 pe->idx - eps_len, name, name_len,
5032c028fdeSJerome Forissier 					 NULL, NULL, NULL);
50464a5011eSPascal Brand 		if (res != TEE_SUCCESS)
505ba675d69SCedric Chaumont 			goto err;
506ba675d69SCedric Chaumont 	}
507b0104773SPascal Brand 
508ba675d69SCedric Chaumont err:
50964a5011eSPascal Brand 	if (res != TEE_SUCCESS &&
51064a5011eSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
51164a5011eSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER)
512ba675d69SCedric Chaumont 		TEE_Panic(0);
51364a5011eSPascal Brand 	return res;
514b0104773SPascal Brand }
515b0104773SPascal Brand 
516b0104773SPascal Brand TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator)
517b0104773SPascal Brand {
518b0104773SPascal Brand 	TEE_Result res;
519b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
520b0104773SPascal Brand 	uint32_t next_idx;
521b0104773SPascal Brand 	const struct user_ta_property *eps;
522b0104773SPascal Brand 	size_t eps_len;
523b0104773SPascal Brand 
5240dd3f3a4SPascal Brand 	if (!pe) {
525ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
52664a5011eSPascal Brand 		goto out;
527ba675d69SCedric Chaumont 	}
528b0104773SPascal Brand 
529ba675d69SCedric Chaumont 	if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) {
530ba675d69SCedric Chaumont 		res = TEE_ERROR_ITEM_NOT_FOUND;
53164a5011eSPascal Brand 		goto out;
532ba675d69SCedric Chaumont 	}
533b0104773SPascal Brand 
53464a5011eSPascal Brand 	res = propset_get(pe->prop_set, &eps, &eps_len);
535b0104773SPascal Brand 	if (res != TEE_SUCCESS)
53664a5011eSPascal Brand 		goto out;
537b0104773SPascal Brand 
538b0104773SPascal Brand 	next_idx = pe->idx + 1;
539b0104773SPascal Brand 	pe->idx = next_idx;
54064a5011eSPascal Brand 	if (next_idx < eps_len)
54164a5011eSPascal Brand 		res = TEE_SUCCESS;
54264a5011eSPascal Brand 	else
5432c028fdeSJerome Forissier 		res = _utee_get_property((unsigned long)pe->prop_set,
5442c028fdeSJerome Forissier 					 next_idx - eps_len, NULL, NULL, NULL,
5452c028fdeSJerome Forissier 					 NULL, NULL);
546b0104773SPascal Brand 
547ba675d69SCedric Chaumont out:
54864a5011eSPascal Brand 	if (res != TEE_SUCCESS &&
54964a5011eSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND)
55064a5011eSPascal Brand 		TEE_Panic(0);
55164a5011eSPascal Brand 	return res;
552b0104773SPascal Brand }
553