xref: /optee_os/lib/libutee/tee_api_property.c (revision ec930cae3503c7a2672b5408a6551a924cebe86d)
11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2b0104773SPascal Brand /*
3b0104773SPascal Brand  * Copyright (c) 2014, STMicroelectronics International N.V.
4a32a96edSJens Wiklander  * Copyright (c) 2017, 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 "string_ext.h"
21b0104773SPascal Brand #include "base64.h"
22b0104773SPascal Brand 
23b0104773SPascal Brand #define PROP_STR_MAX    80
24b0104773SPascal Brand 
25b0104773SPascal Brand #define PROP_ENUMERATOR_NOT_STARTED 0xffffffff
26b0104773SPascal Brand 
27b0104773SPascal Brand struct prop_enumerator {
2864a5011eSPascal Brand 	uint32_t idx;			/* current index */
2964a5011eSPascal Brand 	TEE_PropSetHandle prop_set;	/* part of TEE_PROPSET_xxx */
30b0104773SPascal Brand };
31b0104773SPascal Brand 
3264a5011eSPascal Brand const struct user_ta_property tee_props[] = {
3364a5011eSPascal Brand 	{
3464a5011eSPascal Brand 		"gpd.tee.arith.maxBigIntSize",
3564a5011eSPascal Brand 		USER_TA_PROP_TYPE_U32,
36e3458e03SJerome Forissier 		&(const uint32_t){CFG_TA_BIGNUM_MAX_BITS}
3764a5011eSPascal Brand 	},
38a32a96edSJens Wiklander 	{
39a32a96edSJens Wiklander 		"gpd.tee.sockets.version",
40a32a96edSJens Wiklander 		USER_TA_PROP_TYPE_U32,
41a32a96edSJens Wiklander 		&(const uint32_t){TEE_ISOCKET_VERSION}
42a32a96edSJens Wiklander 	},
43a32a96edSJens Wiklander 	{
44a32a96edSJens Wiklander 		"gpd.tee.sockets.tcp.version",
45a32a96edSJens Wiklander 		USER_TA_PROP_TYPE_U32,
46a32a96edSJens Wiklander 		&(const uint32_t){TEE_ISOCKET_VERSION}
47a32a96edSJens Wiklander 	},
48b0104773SPascal Brand };
49b0104773SPascal Brand 
5064a5011eSPascal Brand static TEE_Result propset_get(TEE_PropSetHandle h,
51b0104773SPascal Brand 			      const struct user_ta_property **eps,
52b0104773SPascal Brand 			      size_t *eps_len)
53b0104773SPascal Brand {
54b0104773SPascal Brand 	if (h == TEE_PROPSET_CURRENT_TA) {
55b0104773SPascal Brand 		*eps = ta_props;
56b0104773SPascal Brand 		*eps_len = ta_num_props;
57b0104773SPascal Brand 	} else if (h == TEE_PROPSET_CURRENT_CLIENT) {
58b0104773SPascal Brand 		*eps = NULL;
59b0104773SPascal Brand 		*eps_len = 0;
60b0104773SPascal Brand 	} else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) {
6164a5011eSPascal Brand 		*eps = tee_props;
6264a5011eSPascal Brand 		*eps_len = ARRAY_SIZE(tee_props);
63b0104773SPascal Brand 	} else {
64b0104773SPascal Brand 		return TEE_ERROR_ITEM_NOT_FOUND;
65b0104773SPascal Brand 	}
66b0104773SPascal Brand 
67b0104773SPascal Brand 	return TEE_SUCCESS;
68b0104773SPascal Brand }
69b0104773SPascal Brand 
70b0104773SPascal Brand static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep,
71ff857a3aSPascal Brand 				       enum user_ta_prop_type *type,
72ff857a3aSPascal Brand 				       void *buf, uint32_t *len)
73b0104773SPascal Brand {
74b0104773SPascal Brand 	size_t l;
75b0104773SPascal Brand 
76ff857a3aSPascal Brand 	*type = ep->type;
77ff857a3aSPascal Brand 	switch (*type) {
78b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BOOL:
79d5d50c3cSJens Wiklander 		l = sizeof(bool);
80b0104773SPascal Brand 		break;
81b0104773SPascal Brand 	case USER_TA_PROP_TYPE_U32:
82b0104773SPascal Brand 		l = sizeof(uint32_t);
83b0104773SPascal Brand 		break;
84b0104773SPascal Brand 	case USER_TA_PROP_TYPE_UUID:
85b0104773SPascal Brand 		l = sizeof(TEE_UUID);
86b0104773SPascal Brand 		break;
87b0104773SPascal Brand 	case USER_TA_PROP_TYPE_IDENTITY:
88b0104773SPascal Brand 		l = sizeof(TEE_Identity);
89b0104773SPascal Brand 		break;
90b0104773SPascal Brand 	case USER_TA_PROP_TYPE_STRING:
91ff857a3aSPascal Brand 		/* take the leading 0 into account */
92ff857a3aSPascal Brand 		l = strlen(ep->value) + 1;
93ff857a3aSPascal Brand 		break;
94b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
95ff857a3aSPascal Brand 		/*
96ff857a3aSPascal Brand 		 * in case of TA property, a binary block is provided as a
97ff857a3aSPascal Brand 		 * string, which is base64 encoded. We must first decode it,
98ff857a3aSPascal Brand 		 * without taking into account the zero termination of the
99ff857a3aSPascal Brand 		 * string
100ff857a3aSPascal Brand 		 */
101ff857a3aSPascal Brand 		l = *len;
102ff857a3aSPascal Brand 		if (!base64_dec(ep->value, strlen(ep->value), buf, &l) &&
103*ec930caeSJerome Forissier 		    l <= *len)
104ff857a3aSPascal Brand 			return TEE_ERROR_GENERIC;
105ff857a3aSPascal Brand 		if (*len < l) {
106ff857a3aSPascal Brand 			*len = l;
107ff857a3aSPascal Brand 			return TEE_ERROR_SHORT_BUFFER;
108ff857a3aSPascal Brand 		}
109ff857a3aSPascal Brand 
110ff857a3aSPascal Brand 		*len = l;
111b0104773SPascal Brand 		return TEE_SUCCESS;
112b0104773SPascal Brand 	default:
113b0104773SPascal Brand 		return TEE_ERROR_GENERIC;
114b0104773SPascal Brand 	}
115ff857a3aSPascal Brand 
116ff857a3aSPascal Brand 	if (*len < l) {
117ff857a3aSPascal Brand 		*len = l;
118ff857a3aSPascal Brand 		return TEE_ERROR_SHORT_BUFFER;
119ff857a3aSPascal Brand 	}
120ff857a3aSPascal Brand 
121ff857a3aSPascal Brand 	*len = l;
122ff857a3aSPascal Brand 	memcpy(buf, ep->value, l);
123b0104773SPascal Brand 	return TEE_SUCCESS;
124b0104773SPascal Brand }
125b0104773SPascal Brand 
1268f07fe6fSJerome Forissier static TEE_Result propget_get_property(TEE_PropSetHandle h, const char *name,
127ff857a3aSPascal Brand 				       enum user_ta_prop_type *type,
128ff857a3aSPascal Brand 				       void *buf, uint32_t *len)
129b0104773SPascal Brand {
130b0104773SPascal Brand 	TEE_Result res;
131b0104773SPascal Brand 	const struct user_ta_property *eps;
132b0104773SPascal Brand 	size_t eps_len;
13364a5011eSPascal Brand 	uint32_t prop_type;
13464a5011eSPascal Brand 	uint32_t index;
135b0104773SPascal Brand 
136b0104773SPascal Brand 	if (h == TEE_PROPSET_CURRENT_TA || h == TEE_PROPSET_CURRENT_CLIENT ||
137b0104773SPascal Brand 	    h == TEE_PROPSET_TEE_IMPLEMENTATION) {
138b0104773SPascal Brand 		size_t n;
139b0104773SPascal Brand 
14064a5011eSPascal Brand 		res = propset_get(h, &eps, &eps_len);
141b0104773SPascal Brand 		if (res != TEE_SUCCESS)
142b0104773SPascal Brand 			return res;
143b0104773SPascal Brand 
144b0104773SPascal Brand 		for (n = 0; n < eps_len; n++) {
14564a5011eSPascal Brand 			if (!strcmp(name, eps[n].name))
146ff857a3aSPascal Brand 				return propget_get_ext_prop(eps + n, type,
147ff857a3aSPascal Brand 							    buf, len);
148b0104773SPascal Brand 		}
14964a5011eSPascal Brand 
15064a5011eSPascal Brand 		/* get the index from the name */
1512c028fdeSJerome Forissier 		res = _utee_get_property_name_to_index((unsigned long)h, name,
1522c028fdeSJerome Forissier 						       strlen(name) + 1,
1532c028fdeSJerome Forissier 						       &index);
15464a5011eSPascal Brand 		if (res != TEE_SUCCESS)
15564a5011eSPascal Brand 			return res;
1562c028fdeSJerome Forissier 		res = _utee_get_property((unsigned long)h, index, NULL, NULL,
157ff857a3aSPascal Brand 					 buf, len, &prop_type);
158b0104773SPascal Brand 	} else {
159b0104773SPascal Brand 		struct prop_enumerator *pe = (struct prop_enumerator *)h;
160b0104773SPascal Brand 		uint32_t idx = pe->idx;
161b0104773SPascal Brand 
162b0104773SPascal Brand 		if (idx == PROP_ENUMERATOR_NOT_STARTED)
163b0104773SPascal Brand 			return TEE_ERROR_ITEM_NOT_FOUND;
164b0104773SPascal Brand 
16564a5011eSPascal Brand 		res = propset_get(pe->prop_set, &eps, &eps_len);
166b0104773SPascal Brand 		if (res != TEE_SUCCESS)
167b0104773SPascal Brand 			return res;
168b0104773SPascal Brand 
169b0104773SPascal Brand 		if (idx < eps_len)
170ff857a3aSPascal Brand 			return propget_get_ext_prop(eps + idx, type, buf, len);
17164a5011eSPascal Brand 		idx -= eps_len;
172b0104773SPascal Brand 
1732c028fdeSJerome Forissier 		res = _utee_get_property((unsigned long)pe->prop_set, idx,
174ff857a3aSPascal Brand 					 NULL, NULL, buf, len, &prop_type);
17564a5011eSPascal Brand 		if (res == TEE_ERROR_ITEM_NOT_FOUND)
17664a5011eSPascal Brand 			res = TEE_ERROR_BAD_PARAMETERS;
177b0104773SPascal Brand 	}
17864a5011eSPascal Brand 
179ff857a3aSPascal Brand 	*type = prop_type;
18064a5011eSPascal Brand 	return res;
181b0104773SPascal Brand }
182b0104773SPascal Brand 
183b0104773SPascal Brand TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator,
1848f07fe6fSJerome Forissier 				   const char *name, char *value,
1850dd3f3a4SPascal Brand 				   uint32_t *value_len)
186b0104773SPascal Brand {
187b0104773SPascal Brand 	TEE_Result res;
188b0104773SPascal Brand 	size_t l;
189ff857a3aSPascal Brand 	enum user_ta_prop_type type;
190ff857a3aSPascal Brand 	void *tmp_buf = 0;
191ff857a3aSPascal Brand 	uint32_t tmp_len;
192ff857a3aSPascal Brand 	uint32_t uint32_val;
193d5d50c3cSJens Wiklander 	bool bool_val;
194ff857a3aSPascal Brand 	TEE_Identity *p_identity_val;
195b0104773SPascal Brand 
1960dd3f3a4SPascal Brand 	if (!value || !value_len) {
197ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
198ff857a3aSPascal Brand 		goto out;
199ba675d69SCedric Chaumont 	}
200b0104773SPascal Brand 
2010dd3f3a4SPascal Brand 	tmp_len = *value_len;
202ff857a3aSPascal Brand 	if (tmp_len < sizeof(TEE_Identity))
203ff857a3aSPascal Brand 		tmp_len = sizeof(TEE_Identity);
204ff857a3aSPascal Brand 	tmp_buf = TEE_Malloc(tmp_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
205ff857a3aSPascal Brand 	if (!tmp_buf) {
206ff857a3aSPascal Brand 		res = TEE_ERROR_OUT_OF_MEMORY;
207ff857a3aSPascal Brand 		goto out;
208ff857a3aSPascal Brand 	}
209b0104773SPascal Brand 
210ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
211ff857a3aSPascal Brand 				   tmp_buf, &tmp_len);
212ff857a3aSPascal Brand 	if (res != TEE_SUCCESS) {
213254e1d58SPascal Brand 		if (res == TEE_ERROR_SHORT_BUFFER) {
214254e1d58SPascal Brand 			if (type == USER_TA_PROP_TYPE_BINARY_BLOCK) {
215254e1d58SPascal Brand 				/*
216254e1d58SPascal Brand 				 * in this case, we must enlarge the buffer
217254e1d58SPascal Brand 				 * with the size of the of the base64 encoded
218254e1d58SPascal Brand 				 * see base64_enc() function
219254e1d58SPascal Brand 				 */
220254e1d58SPascal Brand 				tmp_len = base64_enc_len(tmp_len);
221254e1d58SPascal Brand 			}
2220dd3f3a4SPascal Brand 			*value_len = tmp_len;
223254e1d58SPascal Brand 		}
224ff857a3aSPascal Brand 		goto out;
225ff857a3aSPascal Brand 	}
226b0104773SPascal Brand 
227ff857a3aSPascal Brand 	switch (type) {
228b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BOOL:
229d5d50c3cSJens Wiklander 		bool_val = *((bool *)tmp_buf);
230d5d50c3cSJens Wiklander 		l = strlcpy(value, (bool_val ? "true" : "false"), *value_len);
231b0104773SPascal Brand 		break;
232b0104773SPascal Brand 
233b0104773SPascal Brand 	case USER_TA_PROP_TYPE_U32:
234ff857a3aSPascal Brand 		uint32_val = *((uint32_t *)tmp_buf);
2350dd3f3a4SPascal Brand 		l = snprintf(value, *value_len, "%u", uint32_val);
236b0104773SPascal Brand 		break;
237b0104773SPascal Brand 
238b0104773SPascal Brand 	case USER_TA_PROP_TYPE_UUID:
2390dd3f3a4SPascal Brand 		l = snprintk(value, *value_len, "%pUl", tmp_buf);
240b0104773SPascal Brand 		break;
241b0104773SPascal Brand 
242b0104773SPascal Brand 	case USER_TA_PROP_TYPE_IDENTITY:
243ff857a3aSPascal Brand 		p_identity_val = ((TEE_Identity *)tmp_buf);
2440dd3f3a4SPascal Brand 		l = snprintk(value, *value_len, "%u:%pUl",
245ff857a3aSPascal Brand 			     p_identity_val->login,
246ff857a3aSPascal Brand 			     (void *)(&(p_identity_val->uuid)));
247b0104773SPascal Brand 		break;
248b0104773SPascal Brand 
249b0104773SPascal Brand 	case USER_TA_PROP_TYPE_STRING:
2500dd3f3a4SPascal Brand 		l = strlcpy(value, tmp_buf, *value_len);
251ff857a3aSPascal Brand 		break;
252ff857a3aSPascal Brand 
253b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
2540dd3f3a4SPascal Brand 		l = *value_len;	/* l includes the zero-termination */
2550dd3f3a4SPascal Brand 		if (!base64_enc(tmp_buf, tmp_len, value, &l) &&
256*ec930caeSJerome Forissier 		    l <= *value_len) {
257ff857a3aSPascal Brand 			res = TEE_ERROR_GENERIC;
258ff857a3aSPascal Brand 			goto out;
259ff857a3aSPascal Brand 		}
260ff857a3aSPascal Brand 		l--;	/* remove the zero-termination that is added later */
261b0104773SPascal Brand 		break;
262b0104773SPascal Brand 
263b0104773SPascal Brand 	default:
264ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_FORMAT;
265ba675d69SCedric Chaumont 		goto out;
266ff857a3aSPascal Brand 	}
267ba675d69SCedric Chaumont 
268ff857a3aSPascal Brand 	l++;	/* include zero termination */
269ff857a3aSPascal Brand 
2700dd3f3a4SPascal Brand 	if (l > *value_len)
271ff857a3aSPascal Brand 		res = TEE_ERROR_SHORT_BUFFER;
2720dd3f3a4SPascal Brand 	*value_len = l;
273ff857a3aSPascal Brand 
274ba675d69SCedric Chaumont out:
275ff857a3aSPascal Brand 	if (tmp_buf)
276ff857a3aSPascal Brand 		TEE_Free(tmp_buf);
277ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
278ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
279ff857a3aSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER)
280ff857a3aSPascal Brand 		TEE_Panic(0);
281ff857a3aSPascal Brand 
282ff857a3aSPascal Brand 	return res;
283b0104773SPascal Brand }
284b0104773SPascal Brand 
285b0104773SPascal Brand TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator,
2868f07fe6fSJerome Forissier 				 const char *name, bool *value)
287b0104773SPascal Brand {
288b0104773SPascal Brand 	TEE_Result res;
289ff857a3aSPascal Brand 	enum user_ta_prop_type type;
290d5d50c3cSJens Wiklander 	uint32_t bool_len = sizeof(bool);
291ba675d69SCedric Chaumont 	if (value == NULL) {
292ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
293ff857a3aSPascal Brand 		goto out;
294ba675d69SCedric Chaumont 	}
295b0104773SPascal Brand 
296ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_BOOL;
297ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
298d5d50c3cSJens Wiklander 				   value, &bool_len);
299ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_BOOL)
300ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_FORMAT;
301ff857a3aSPascal Brand 	if (res != TEE_SUCCESS)
302ba675d69SCedric Chaumont 		goto out;
303ba675d69SCedric Chaumont 
304ba675d69SCedric Chaumont out:
305ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
306ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
307ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT)
308ff857a3aSPascal Brand 		TEE_Panic(0);
309ff857a3aSPascal Brand 
310ff857a3aSPascal Brand 	return res;
311b0104773SPascal Brand }
312b0104773SPascal Brand 
313b0104773SPascal Brand TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator,
3148f07fe6fSJerome Forissier 				const char *name, uint32_t *value)
315b0104773SPascal Brand {
316b0104773SPascal Brand 	TEE_Result res;
317ff857a3aSPascal Brand 	enum user_ta_prop_type type;
318ff857a3aSPascal Brand 	uint32_t uint32_len = sizeof(uint32_t);
319b0104773SPascal Brand 
3200dd3f3a4SPascal Brand 	if (!value) {
321ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
322ba675d69SCedric Chaumont 		goto out;
323ff857a3aSPascal Brand 	}
324ba675d69SCedric Chaumont 
325ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_U32;
326ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
327ff857a3aSPascal Brand 				   value, &uint32_len);
328ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_U32)
329ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
330ff857a3aSPascal Brand 
331ba675d69SCedric Chaumont out:
332ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
333ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
334ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT)
335ff857a3aSPascal Brand 		TEE_Panic(0);
336ff857a3aSPascal Brand 
337ff857a3aSPascal Brand 	return res;
338b0104773SPascal Brand }
339b0104773SPascal Brand 
340b0104773SPascal Brand TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator,
3418f07fe6fSJerome Forissier 					const char *name, void *value,
3420dd3f3a4SPascal Brand 					uint32_t *value_len)
343b0104773SPascal Brand {
344b0104773SPascal Brand 	TEE_Result res;
345ff857a3aSPascal Brand 	enum user_ta_prop_type type;
346b0104773SPascal Brand 
347614e8b8aSEtienne Carriere 	if (!value_len) {
348ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
349ba675d69SCedric Chaumont 		goto out;
350ff857a3aSPascal Brand 	}
351ba675d69SCedric Chaumont 
352ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_BINARY_BLOCK;
353ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
3540dd3f3a4SPascal Brand 				   value, value_len);
355ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_BINARY_BLOCK)
356ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
357ff857a3aSPascal Brand 
358ba675d69SCedric Chaumont out:
359ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
360ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
361ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT &&
362ff857a3aSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER)
363ff857a3aSPascal Brand 		TEE_Panic(0);
364ff857a3aSPascal Brand 
365ff857a3aSPascal Brand 	return res;
366b0104773SPascal Brand }
367b0104773SPascal Brand 
368b0104773SPascal Brand TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator,
3698f07fe6fSJerome Forissier 				 const char *name, TEE_UUID *value)
370b0104773SPascal Brand {
371b0104773SPascal Brand 	TEE_Result res;
372ff857a3aSPascal Brand 	enum user_ta_prop_type type;
373ff857a3aSPascal Brand 	uint32_t uuid_len = sizeof(TEE_UUID);
374b0104773SPascal Brand 
3750dd3f3a4SPascal Brand 	if (!value) {
376ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
377ba675d69SCedric Chaumont 		goto out;
378ff857a3aSPascal Brand 	}
379ba675d69SCedric Chaumont 
380ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_UUID;
381ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
382ff857a3aSPascal Brand 				   value, &uuid_len);
383ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_UUID)
384ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
385ff857a3aSPascal Brand 
386ba675d69SCedric Chaumont out:
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 
4020dd3f3a4SPascal Brand 	if (!value) {
403ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
404ba675d69SCedric Chaumont 		goto out;
405ff857a3aSPascal Brand 	}
406ba675d69SCedric Chaumont 
407ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_IDENTITY;
408ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
409ff857a3aSPascal Brand 				   value, &identity_len);
410ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_IDENTITY)
411ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
412ff857a3aSPascal Brand 
413ba675d69SCedric Chaumont out:
414ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
415ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
416ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT)
417ff857a3aSPascal Brand 		TEE_Panic(0);
418ff857a3aSPascal Brand 
419ff857a3aSPascal Brand 	return res;
420b0104773SPascal Brand }
421b0104773SPascal Brand 
422b0104773SPascal Brand TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator)
423b0104773SPascal Brand {
424ba675d69SCedric Chaumont 	TEE_Result res;
425b0104773SPascal Brand 	struct prop_enumerator *pe;
426b0104773SPascal Brand 
4270dd3f3a4SPascal Brand 	if (!enumerator) {
428ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
429ba675d69SCedric Chaumont 		goto err;
430ba675d69SCedric Chaumont 	}
431b0104773SPascal Brand 
432b0104773SPascal Brand 	pe = TEE_Malloc(sizeof(struct prop_enumerator),
433b0104773SPascal Brand 			TEE_USER_MEM_HINT_NO_FILL_ZERO);
434ba675d69SCedric Chaumont 	if (pe == NULL) {
435ba675d69SCedric Chaumont 		res = TEE_ERROR_OUT_OF_MEMORY;
436ba675d69SCedric Chaumont 		goto err;
437ba675d69SCedric Chaumont 	}
438b0104773SPascal Brand 
439b0104773SPascal Brand 	*enumerator = (TEE_PropSetHandle) pe;
440b0104773SPascal Brand 	TEE_ResetPropertyEnumerator(*enumerator);
441ba675d69SCedric Chaumont 
442ba675d69SCedric Chaumont 	goto out;
443ba675d69SCedric Chaumont 
444ba675d69SCedric Chaumont err:
445ba675d69SCedric Chaumont 	if (res == TEE_ERROR_OUT_OF_MEMORY)
446ba675d69SCedric Chaumont 		return res;
447ba675d69SCedric Chaumont 	TEE_Panic(0);
448ba675d69SCedric Chaumont out:
449b0104773SPascal Brand 	return TEE_SUCCESS;
450b0104773SPascal Brand }
451b0104773SPascal Brand 
452b0104773SPascal Brand void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator)
453b0104773SPascal Brand {
454b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
455b0104773SPascal Brand 
456b0104773SPascal Brand 	pe->idx = PROP_ENUMERATOR_NOT_STARTED;
457b0104773SPascal Brand }
458b0104773SPascal Brand 
459b0104773SPascal Brand void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator)
460b0104773SPascal Brand {
461b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
462b0104773SPascal Brand 
463b0104773SPascal Brand 	TEE_Free(pe);
464b0104773SPascal Brand }
465b0104773SPascal Brand 
466b0104773SPascal Brand void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator,
467b0104773SPascal Brand 				 TEE_PropSetHandle propSet)
468b0104773SPascal Brand {
469b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
470b0104773SPascal Brand 
4710dd3f3a4SPascal Brand 	if (!pe)
472b0104773SPascal Brand 		return;
473b0104773SPascal Brand 
474b0104773SPascal Brand 	pe->idx = 0;
475b0104773SPascal Brand 	pe->prop_set = propSet;
476b0104773SPascal Brand }
477b0104773SPascal Brand 
478b0104773SPascal Brand TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator,
4790dd3f3a4SPascal Brand 			       void *name, uint32_t *name_len)
480b0104773SPascal Brand {
481b0104773SPascal Brand 	TEE_Result res;
482b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
483b0104773SPascal Brand 	const struct user_ta_property *eps;
484b0104773SPascal Brand 	size_t eps_len;
485b0104773SPascal Brand 	const char *str;
486b0104773SPascal Brand 	size_t bufferlen;
487b0104773SPascal Brand 
4880dd3f3a4SPascal Brand 	if (!pe || !name || !name_len) {
489ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
490ba675d69SCedric Chaumont 		goto err;
491ba675d69SCedric Chaumont 	}
492b0104773SPascal Brand 
4930dd3f3a4SPascal Brand 	bufferlen = *name_len;
49464a5011eSPascal Brand 	res = propset_get(pe->prop_set, &eps, &eps_len);
495b0104773SPascal Brand 	if (res != TEE_SUCCESS)
496ba675d69SCedric Chaumont 		goto err;
497b0104773SPascal Brand 
49864a5011eSPascal Brand 	if (pe->idx < eps_len) {
49964a5011eSPascal Brand 		str = eps[pe->idx].name;
5000dd3f3a4SPascal Brand 		bufferlen = strlcpy(name, str, *name_len) + 1;
5010dd3f3a4SPascal Brand 		if (bufferlen > *name_len)
502ba675d69SCedric Chaumont 			res = TEE_ERROR_SHORT_BUFFER;
5030dd3f3a4SPascal Brand 		*name_len = bufferlen;
50464a5011eSPascal Brand 	} else {
5052c028fdeSJerome Forissier 		res = _utee_get_property((unsigned long)pe->prop_set,
5062c028fdeSJerome Forissier 					 pe->idx - eps_len, name, name_len,
5072c028fdeSJerome Forissier 					 NULL, NULL, NULL);
50864a5011eSPascal Brand 		if (res != TEE_SUCCESS)
509ba675d69SCedric Chaumont 			goto err;
510ba675d69SCedric Chaumont 	}
511b0104773SPascal Brand 
512ba675d69SCedric Chaumont err:
51364a5011eSPascal Brand 	if (res != TEE_SUCCESS &&
51464a5011eSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
51564a5011eSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER)
516ba675d69SCedric Chaumont 		TEE_Panic(0);
51764a5011eSPascal Brand 	return res;
518b0104773SPascal Brand }
519b0104773SPascal Brand 
520b0104773SPascal Brand TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator)
521b0104773SPascal Brand {
522b0104773SPascal Brand 	TEE_Result res;
523b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
524b0104773SPascal Brand 	uint32_t next_idx;
525b0104773SPascal Brand 	const struct user_ta_property *eps;
526b0104773SPascal Brand 	size_t eps_len;
527b0104773SPascal Brand 
5280dd3f3a4SPascal Brand 	if (!pe) {
529ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
53064a5011eSPascal Brand 		goto out;
531ba675d69SCedric Chaumont 	}
532b0104773SPascal Brand 
533ba675d69SCedric Chaumont 	if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) {
534ba675d69SCedric Chaumont 		res = TEE_ERROR_ITEM_NOT_FOUND;
53564a5011eSPascal Brand 		goto out;
536ba675d69SCedric Chaumont 	}
537b0104773SPascal Brand 
53864a5011eSPascal Brand 	res = propset_get(pe->prop_set, &eps, &eps_len);
539b0104773SPascal Brand 	if (res != TEE_SUCCESS)
54064a5011eSPascal Brand 		goto out;
541b0104773SPascal Brand 
542b0104773SPascal Brand 	next_idx = pe->idx + 1;
543b0104773SPascal Brand 	pe->idx = next_idx;
54464a5011eSPascal Brand 	if (next_idx < eps_len)
54564a5011eSPascal Brand 		res = TEE_SUCCESS;
54664a5011eSPascal Brand 	else
5472c028fdeSJerome Forissier 		res = _utee_get_property((unsigned long)pe->prop_set,
5482c028fdeSJerome Forissier 					 next_idx - eps_len, NULL, NULL, NULL,
5492c028fdeSJerome Forissier 					 NULL, NULL);
550b0104773SPascal Brand 
551ba675d69SCedric Chaumont out:
55264a5011eSPascal Brand 	if (res != TEE_SUCCESS &&
55364a5011eSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND)
55464a5011eSPascal Brand 		TEE_Panic(0);
55564a5011eSPascal Brand 	return res;
556b0104773SPascal Brand }
557