xref: /optee_os/lib/libutee/tee_api_property.c (revision 6551d565c2f5a7c61c48ffff2148a4b3dac218a5)
11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2b0104773SPascal Brand /*
3b0104773SPascal Brand  * Copyright (c) 2014, STMicroelectronics International N.V.
46915bbbbSJens 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"
216915bbbbSJens Wiklander #include "string_ext.h"
226915bbbbSJens 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;
85*6551d565SJens Wiklander 	case USER_TA_PROP_TYPE_U64:
86*6551d565SJens Wiklander 		l = sizeof(uint64_t);
87*6551d565SJens Wiklander 		break;
88b0104773SPascal Brand 	case USER_TA_PROP_TYPE_UUID:
89b0104773SPascal Brand 		l = sizeof(TEE_UUID);
90b0104773SPascal Brand 		break;
91b0104773SPascal Brand 	case USER_TA_PROP_TYPE_IDENTITY:
92b0104773SPascal Brand 		l = sizeof(TEE_Identity);
93b0104773SPascal Brand 		break;
94b0104773SPascal Brand 	case USER_TA_PROP_TYPE_STRING:
95ff857a3aSPascal Brand 		/* take the leading 0 into account */
96ff857a3aSPascal Brand 		l = strlen(ep->value) + 1;
97ff857a3aSPascal Brand 		break;
98b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
99ff857a3aSPascal Brand 		/*
100ff857a3aSPascal Brand 		 * in case of TA property, a binary block is provided as a
101ff857a3aSPascal Brand 		 * string, which is base64 encoded. We must first decode it,
102ff857a3aSPascal Brand 		 * without taking into account the zero termination of the
103ff857a3aSPascal Brand 		 * string
104ff857a3aSPascal Brand 		 */
105ff857a3aSPascal Brand 		l = *len;
10697b8ba50SJerome Forissier 		if (!_base64_dec(ep->value, strlen(ep->value), buf, &l) &&
107ec930caeSJerome Forissier 		    l <= *len)
108ff857a3aSPascal Brand 			return TEE_ERROR_GENERIC;
109ff857a3aSPascal Brand 		if (*len < l) {
110ff857a3aSPascal Brand 			*len = l;
111ff857a3aSPascal Brand 			return TEE_ERROR_SHORT_BUFFER;
112ff857a3aSPascal Brand 		}
113ff857a3aSPascal Brand 
114ff857a3aSPascal Brand 		*len = l;
115b0104773SPascal Brand 		return TEE_SUCCESS;
116b0104773SPascal Brand 	default:
117b0104773SPascal Brand 		return TEE_ERROR_GENERIC;
118b0104773SPascal Brand 	}
119ff857a3aSPascal Brand 
120ff857a3aSPascal Brand 	if (*len < l) {
121ff857a3aSPascal Brand 		*len = l;
122ff857a3aSPascal Brand 		return TEE_ERROR_SHORT_BUFFER;
123ff857a3aSPascal Brand 	}
124ff857a3aSPascal Brand 
125ff857a3aSPascal Brand 	*len = l;
126ff857a3aSPascal Brand 	memcpy(buf, ep->value, l);
127b0104773SPascal Brand 	return TEE_SUCCESS;
128b0104773SPascal Brand }
129b0104773SPascal Brand 
1306915bbbbSJens Wiklander static bool is_propset_pseudo_handle(TEE_PropSetHandle h)
1316915bbbbSJens Wiklander {
1326915bbbbSJens Wiklander 	return h == TEE_PROPSET_CURRENT_TA ||
1336915bbbbSJens Wiklander 	       h == TEE_PROPSET_CURRENT_CLIENT ||
1346915bbbbSJens Wiklander 	       h == TEE_PROPSET_TEE_IMPLEMENTATION;
1356915bbbbSJens Wiklander }
1366915bbbbSJens Wiklander 
1378f07fe6fSJerome Forissier static TEE_Result propget_get_property(TEE_PropSetHandle h, const char *name,
138ff857a3aSPascal Brand 				       enum user_ta_prop_type *type,
139ff857a3aSPascal Brand 				       void *buf, uint32_t *len)
140b0104773SPascal Brand {
141b0104773SPascal Brand 	TEE_Result res;
142b0104773SPascal Brand 	const struct user_ta_property *eps;
143b0104773SPascal Brand 	size_t eps_len;
14464a5011eSPascal Brand 	uint32_t prop_type;
14564a5011eSPascal Brand 	uint32_t index;
146b0104773SPascal Brand 
1476915bbbbSJens Wiklander 	if (is_propset_pseudo_handle(h)) {
148b0104773SPascal Brand 		size_t n;
149b0104773SPascal Brand 
15064a5011eSPascal Brand 		res = propset_get(h, &eps, &eps_len);
151b0104773SPascal Brand 		if (res != TEE_SUCCESS)
152b0104773SPascal Brand 			return res;
153b0104773SPascal Brand 
154b0104773SPascal Brand 		for (n = 0; n < eps_len; n++) {
15564a5011eSPascal Brand 			if (!strcmp(name, eps[n].name))
156ff857a3aSPascal Brand 				return propget_get_ext_prop(eps + n, type,
157ff857a3aSPascal Brand 							    buf, len);
158b0104773SPascal Brand 		}
15964a5011eSPascal Brand 
16064a5011eSPascal Brand 		/* get the index from the name */
1612c028fdeSJerome Forissier 		res = _utee_get_property_name_to_index((unsigned long)h, name,
1622c028fdeSJerome Forissier 						       strlen(name) + 1,
1632c028fdeSJerome Forissier 						       &index);
16464a5011eSPascal Brand 		if (res != TEE_SUCCESS)
16564a5011eSPascal Brand 			return res;
1662c028fdeSJerome Forissier 		res = _utee_get_property((unsigned long)h, index, NULL, NULL,
167ff857a3aSPascal Brand 					 buf, len, &prop_type);
168b0104773SPascal Brand 	} else {
169b0104773SPascal Brand 		struct prop_enumerator *pe = (struct prop_enumerator *)h;
170b0104773SPascal Brand 		uint32_t idx = pe->idx;
171b0104773SPascal Brand 
172b0104773SPascal Brand 		if (idx == PROP_ENUMERATOR_NOT_STARTED)
173b0104773SPascal Brand 			return TEE_ERROR_ITEM_NOT_FOUND;
174b0104773SPascal Brand 
17564a5011eSPascal Brand 		res = propset_get(pe->prop_set, &eps, &eps_len);
176b0104773SPascal Brand 		if (res != TEE_SUCCESS)
177b0104773SPascal Brand 			return res;
178b0104773SPascal Brand 
179b0104773SPascal Brand 		if (idx < eps_len)
180ff857a3aSPascal Brand 			return propget_get_ext_prop(eps + idx, type, buf, len);
18164a5011eSPascal Brand 		idx -= eps_len;
182b0104773SPascal Brand 
1832c028fdeSJerome Forissier 		res = _utee_get_property((unsigned long)pe->prop_set, idx,
184ff857a3aSPascal Brand 					 NULL, NULL, buf, len, &prop_type);
18564a5011eSPascal Brand 		if (res == TEE_ERROR_ITEM_NOT_FOUND)
18664a5011eSPascal Brand 			res = TEE_ERROR_BAD_PARAMETERS;
187b0104773SPascal Brand 	}
18864a5011eSPascal Brand 
189ff857a3aSPascal Brand 	*type = prop_type;
19064a5011eSPascal Brand 	return res;
191b0104773SPascal Brand }
192b0104773SPascal Brand 
193b0104773SPascal Brand TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator,
1948f07fe6fSJerome Forissier 				   const char *name, char *value,
195*6551d565SJens Wiklander 				   size_t *value_len)
196b0104773SPascal Brand {
197b0104773SPascal Brand 	TEE_Result res;
198b0104773SPascal Brand 	size_t l;
199ff857a3aSPascal Brand 	enum user_ta_prop_type type;
200ff857a3aSPascal Brand 	void *tmp_buf = 0;
201ff857a3aSPascal Brand 	uint32_t tmp_len;
202ff857a3aSPascal Brand 	uint32_t uint32_val;
203d5d50c3cSJens Wiklander 	bool bool_val;
204ff857a3aSPascal Brand 	TEE_Identity *p_identity_val;
205b0104773SPascal Brand 
2066915bbbbSJens Wiklander 	if (is_propset_pseudo_handle(propsetOrEnumerator))
2076915bbbbSJens Wiklander 		__utee_check_instring_annotation(name);
2086915bbbbSJens Wiklander 	__utee_check_outstring_annotation(value, value_len);
209b0104773SPascal Brand 
2100dd3f3a4SPascal Brand 	tmp_len = *value_len;
211ff857a3aSPascal Brand 	if (tmp_len < sizeof(TEE_Identity))
212ff857a3aSPascal Brand 		tmp_len = sizeof(TEE_Identity);
213ff857a3aSPascal Brand 	tmp_buf = TEE_Malloc(tmp_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
214ff857a3aSPascal Brand 	if (!tmp_buf) {
215ff857a3aSPascal Brand 		res = TEE_ERROR_OUT_OF_MEMORY;
216ff857a3aSPascal Brand 		goto out;
217ff857a3aSPascal Brand 	}
218b0104773SPascal Brand 
219ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
220ff857a3aSPascal Brand 				   tmp_buf, &tmp_len);
221ff857a3aSPascal Brand 	if (res != TEE_SUCCESS) {
222254e1d58SPascal Brand 		if (res == TEE_ERROR_SHORT_BUFFER) {
223254e1d58SPascal Brand 			if (type == USER_TA_PROP_TYPE_BINARY_BLOCK) {
224254e1d58SPascal Brand 				/*
225254e1d58SPascal Brand 				 * in this case, we must enlarge the buffer
226254e1d58SPascal Brand 				 * with the size of the of the base64 encoded
227254e1d58SPascal Brand 				 * see base64_enc() function
228254e1d58SPascal Brand 				 */
22997b8ba50SJerome Forissier 				tmp_len = _base64_enc_len(tmp_len);
230254e1d58SPascal Brand 			}
2310dd3f3a4SPascal Brand 			*value_len = tmp_len;
232254e1d58SPascal Brand 		}
233ff857a3aSPascal Brand 		goto out;
234ff857a3aSPascal Brand 	}
235b0104773SPascal Brand 
236ff857a3aSPascal Brand 	switch (type) {
237b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BOOL:
238d5d50c3cSJens Wiklander 		bool_val = *((bool *)tmp_buf);
239d5d50c3cSJens Wiklander 		l = strlcpy(value, (bool_val ? "true" : "false"), *value_len);
240b0104773SPascal Brand 		break;
241b0104773SPascal Brand 
242b0104773SPascal Brand 	case USER_TA_PROP_TYPE_U32:
243ff857a3aSPascal Brand 		uint32_val = *((uint32_t *)tmp_buf);
2440dd3f3a4SPascal Brand 		l = snprintf(value, *value_len, "%u", uint32_val);
245b0104773SPascal Brand 		break;
246b0104773SPascal Brand 
247b0104773SPascal Brand 	case USER_TA_PROP_TYPE_UUID:
2480dd3f3a4SPascal Brand 		l = snprintk(value, *value_len, "%pUl", tmp_buf);
249b0104773SPascal Brand 		break;
250b0104773SPascal Brand 
251b0104773SPascal Brand 	case USER_TA_PROP_TYPE_IDENTITY:
252ff857a3aSPascal Brand 		p_identity_val = ((TEE_Identity *)tmp_buf);
2530dd3f3a4SPascal Brand 		l = snprintk(value, *value_len, "%u:%pUl",
254ff857a3aSPascal Brand 			     p_identity_val->login,
255ff857a3aSPascal Brand 			     (void *)(&(p_identity_val->uuid)));
256b0104773SPascal Brand 		break;
257b0104773SPascal Brand 
258b0104773SPascal Brand 	case USER_TA_PROP_TYPE_STRING:
2590dd3f3a4SPascal Brand 		l = strlcpy(value, tmp_buf, *value_len);
260ff857a3aSPascal Brand 		break;
261ff857a3aSPascal Brand 
262b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
2630dd3f3a4SPascal Brand 		l = *value_len;	/* l includes the zero-termination */
26497b8ba50SJerome Forissier 		if (!_base64_enc(tmp_buf, tmp_len, value, &l) &&
265ec930caeSJerome Forissier 		    l <= *value_len) {
266ff857a3aSPascal Brand 			res = TEE_ERROR_GENERIC;
267ff857a3aSPascal Brand 			goto out;
268ff857a3aSPascal Brand 		}
269ff857a3aSPascal Brand 		l--;	/* remove the zero-termination that is added later */
270b0104773SPascal Brand 		break;
271b0104773SPascal Brand 
272b0104773SPascal Brand 	default:
273ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_FORMAT;
274ba675d69SCedric Chaumont 		goto out;
275ff857a3aSPascal Brand 	}
276ba675d69SCedric Chaumont 
277ff857a3aSPascal Brand 	l++;	/* include zero termination */
278ff857a3aSPascal Brand 
2790dd3f3a4SPascal Brand 	if (l > *value_len)
280ff857a3aSPascal Brand 		res = TEE_ERROR_SHORT_BUFFER;
2810dd3f3a4SPascal Brand 	*value_len = l;
282ff857a3aSPascal Brand 
283ba675d69SCedric Chaumont out:
284ff857a3aSPascal Brand 	if (tmp_buf)
285ff857a3aSPascal Brand 		TEE_Free(tmp_buf);
286ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
287ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
288ff857a3aSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER)
289ff857a3aSPascal Brand 		TEE_Panic(0);
290ff857a3aSPascal Brand 
291ff857a3aSPascal Brand 	return res;
292b0104773SPascal Brand }
293b0104773SPascal Brand 
294*6551d565SJens Wiklander TEE_Result __GP11_TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator,
295*6551d565SJens Wiklander 					  const char *name, char *valueBuffer,
296*6551d565SJens Wiklander 					  uint32_t *valueBufferLen)
297*6551d565SJens Wiklander {
298*6551d565SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
299*6551d565SJens Wiklander 	size_t l = 0;
300*6551d565SJens Wiklander 
301*6551d565SJens Wiklander 	__utee_check_gp11_outstring_annotation(valueBuffer, valueBufferLen);
302*6551d565SJens Wiklander 	l = *valueBufferLen;
303*6551d565SJens Wiklander 	res = TEE_GetPropertyAsString(propsetOrEnumerator, name, valueBuffer,
304*6551d565SJens Wiklander 				      &l);
305*6551d565SJens Wiklander 	*valueBufferLen = l;
306*6551d565SJens Wiklander 	return res;
307*6551d565SJens Wiklander }
308*6551d565SJens Wiklander 
309b0104773SPascal Brand TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator,
3108f07fe6fSJerome Forissier 				 const char *name, bool *value)
311b0104773SPascal Brand {
312b0104773SPascal Brand 	TEE_Result res;
313ff857a3aSPascal Brand 	enum user_ta_prop_type type;
314d5d50c3cSJens Wiklander 	uint32_t bool_len = sizeof(bool);
3156915bbbbSJens Wiklander 
3166915bbbbSJens Wiklander 	if (is_propset_pseudo_handle(propsetOrEnumerator))
3176915bbbbSJens Wiklander 		__utee_check_instring_annotation(name);
3186915bbbbSJens Wiklander 	__utee_check_out_annotation(value, sizeof(*value));
319b0104773SPascal Brand 
320ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_BOOL;
321ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
322d5d50c3cSJens Wiklander 				   value, &bool_len);
323ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_BOOL)
324ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_FORMAT;
325ff857a3aSPascal Brand 	if (res != TEE_SUCCESS)
326ba675d69SCedric Chaumont 		goto out;
327ba675d69SCedric Chaumont 
328ba675d69SCedric Chaumont out:
329ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
330ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
331ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT)
332ff857a3aSPascal Brand 		TEE_Panic(0);
333ff857a3aSPascal Brand 
334ff857a3aSPascal Brand 	return res;
335b0104773SPascal Brand }
336b0104773SPascal Brand 
337b0104773SPascal Brand TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator,
3388f07fe6fSJerome Forissier 				const char *name, uint32_t *value)
339b0104773SPascal Brand {
340b0104773SPascal Brand 	TEE_Result res;
341ff857a3aSPascal Brand 	enum user_ta_prop_type type;
342ff857a3aSPascal Brand 	uint32_t uint32_len = sizeof(uint32_t);
343b0104773SPascal Brand 
3446915bbbbSJens Wiklander 	if (is_propset_pseudo_handle(propsetOrEnumerator))
3456915bbbbSJens Wiklander 		__utee_check_instring_annotation(name);
3466915bbbbSJens Wiklander 	__utee_check_out_annotation(value, sizeof(*value));
347ba675d69SCedric Chaumont 
348ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_U32;
349ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
350ff857a3aSPascal Brand 				   value, &uint32_len);
351ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_U32)
352ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
353ff857a3aSPascal Brand 
354ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
355ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
356ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT)
357ff857a3aSPascal Brand 		TEE_Panic(0);
358ff857a3aSPascal Brand 
359ff857a3aSPascal Brand 	return res;
360b0104773SPascal Brand }
361b0104773SPascal Brand 
362*6551d565SJens Wiklander TEE_Result TEE_GetPropertyAsU64(TEE_PropSetHandle propsetOrEnumerator,
363*6551d565SJens Wiklander 				const char *name, uint64_t *value)
364b0104773SPascal Brand {
365b0104773SPascal Brand 	TEE_Result res;
366ff857a3aSPascal Brand 	enum user_ta_prop_type type;
367*6551d565SJens Wiklander 	uint32_t uint64_len = sizeof(*value);
368b0104773SPascal Brand 
3696915bbbbSJens Wiklander 	if (is_propset_pseudo_handle(propsetOrEnumerator))
3706915bbbbSJens Wiklander 		__utee_check_instring_annotation(name);
371*6551d565SJens Wiklander 	__utee_check_out_annotation(value, sizeof(*value));
372*6551d565SJens Wiklander 
373*6551d565SJens Wiklander 	type = USER_TA_PROP_TYPE_U64;
374*6551d565SJens Wiklander 	res = propget_get_property(propsetOrEnumerator, name, &type,
375*6551d565SJens Wiklander 				   value, &uint64_len);
376*6551d565SJens Wiklander 	if (type != USER_TA_PROP_TYPE_U64)
377*6551d565SJens Wiklander 		res = TEE_ERROR_BAD_FORMAT;
378*6551d565SJens Wiklander 
379*6551d565SJens Wiklander 	if (res != TEE_SUCCESS &&
380*6551d565SJens Wiklander 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
381*6551d565SJens Wiklander 	    res != TEE_ERROR_BAD_FORMAT)
382*6551d565SJens Wiklander 		TEE_Panic(0);
383*6551d565SJens Wiklander 
384*6551d565SJens Wiklander 	return res;
385*6551d565SJens Wiklander }
386*6551d565SJens Wiklander 
387*6551d565SJens Wiklander TEE_Result
388*6551d565SJens Wiklander __GP11_TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator,
389*6551d565SJens Wiklander 				    const char *name, void *value,
390*6551d565SJens Wiklander 				    uint32_t *value_len)
391*6551d565SJens Wiklander {
392*6551d565SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
393*6551d565SJens Wiklander 	enum user_ta_prop_type type = USER_TA_PROP_TYPE_BOOL;
394*6551d565SJens Wiklander 
395*6551d565SJens Wiklander 	if (is_propset_pseudo_handle(propsetOrEnumerator))
396*6551d565SJens Wiklander 		__utee_check_instring_annotation(name);
397*6551d565SJens Wiklander 	__utee_check_gp11_outbuf_annotation(value, value_len);
398ba675d69SCedric Chaumont 
399ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_BINARY_BLOCK;
400ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
4010dd3f3a4SPascal Brand 				   value, value_len);
402ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_BINARY_BLOCK)
403ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
404ff857a3aSPascal Brand 
405ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
406ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
407ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT &&
408ff857a3aSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER)
409ff857a3aSPascal Brand 		TEE_Panic(0);
410ff857a3aSPascal Brand 
411ff857a3aSPascal Brand 	return res;
412b0104773SPascal Brand }
413b0104773SPascal Brand 
414*6551d565SJens Wiklander TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator,
415*6551d565SJens Wiklander 					const char *name, void *value,
416*6551d565SJens Wiklander 					size_t *value_len)
417*6551d565SJens Wiklander {
418*6551d565SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
419*6551d565SJens Wiklander 	uint32_t l = 0;
420*6551d565SJens Wiklander 
421*6551d565SJens Wiklander 	__utee_check_outbuf_annotation(value, value_len);
422*6551d565SJens Wiklander 	l = *value_len;
423*6551d565SJens Wiklander 	res = __GP11_TEE_GetPropertyAsBinaryBlock(propsetOrEnumerator, name,
424*6551d565SJens Wiklander 						  value, &l);
425*6551d565SJens Wiklander 	*value_len = l;
426*6551d565SJens Wiklander 	return res;
427*6551d565SJens Wiklander }
428*6551d565SJens Wiklander 
429b0104773SPascal Brand TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator,
4308f07fe6fSJerome Forissier 				 const char *name, TEE_UUID *value)
431b0104773SPascal Brand {
432b0104773SPascal Brand 	TEE_Result res;
433ff857a3aSPascal Brand 	enum user_ta_prop_type type;
434ff857a3aSPascal Brand 	uint32_t uuid_len = sizeof(TEE_UUID);
435b0104773SPascal Brand 
4366915bbbbSJens Wiklander 	if (is_propset_pseudo_handle(propsetOrEnumerator))
4376915bbbbSJens Wiklander 		__utee_check_instring_annotation(name);
4386915bbbbSJens Wiklander 	__utee_check_out_annotation(value, sizeof(*value));
439ba675d69SCedric Chaumont 
440ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_UUID;
441ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
442ff857a3aSPascal Brand 				   value, &uuid_len);
443ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_UUID)
444ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
445ff857a3aSPascal Brand 
446ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
447ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
448ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT)
449ff857a3aSPascal Brand 		TEE_Panic(0);
450ff857a3aSPascal Brand 
451ff857a3aSPascal Brand 	return res;
452b0104773SPascal Brand }
453b0104773SPascal Brand 
454b0104773SPascal Brand TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator,
4558f07fe6fSJerome Forissier 				     const char *name, TEE_Identity *value)
456b0104773SPascal Brand {
457b0104773SPascal Brand 	TEE_Result res;
458ff857a3aSPascal Brand 	enum user_ta_prop_type type;
459ff857a3aSPascal Brand 	uint32_t identity_len = sizeof(TEE_Identity);
460b0104773SPascal Brand 
4616915bbbbSJens Wiklander 	if (is_propset_pseudo_handle(propsetOrEnumerator))
4626915bbbbSJens Wiklander 		__utee_check_instring_annotation(name);
4636915bbbbSJens Wiklander 	__utee_check_out_annotation(value, sizeof(*value));
464ba675d69SCedric Chaumont 
465ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_IDENTITY;
466ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
467ff857a3aSPascal Brand 				   value, &identity_len);
468ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_IDENTITY)
469ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
470ff857a3aSPascal Brand 
471ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
472ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
473ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT)
474ff857a3aSPascal Brand 		TEE_Panic(0);
475ff857a3aSPascal Brand 
476ff857a3aSPascal Brand 	return res;
477b0104773SPascal Brand }
478b0104773SPascal Brand 
479b0104773SPascal Brand TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator)
480b0104773SPascal Brand {
481ba675d69SCedric Chaumont 	TEE_Result res;
482b0104773SPascal Brand 	struct prop_enumerator *pe;
483b0104773SPascal Brand 
4846915bbbbSJens Wiklander 	__utee_check_out_annotation(enumerator, sizeof(*enumerator));
485b0104773SPascal Brand 
486b0104773SPascal Brand 	pe = TEE_Malloc(sizeof(struct prop_enumerator),
487b0104773SPascal Brand 			TEE_USER_MEM_HINT_NO_FILL_ZERO);
488ba675d69SCedric Chaumont 	if (pe == NULL) {
489ba675d69SCedric Chaumont 		res = TEE_ERROR_OUT_OF_MEMORY;
490ba675d69SCedric Chaumont 		goto err;
491ba675d69SCedric Chaumont 	}
492b0104773SPascal Brand 
493b0104773SPascal Brand 	*enumerator = (TEE_PropSetHandle) pe;
494b0104773SPascal Brand 	TEE_ResetPropertyEnumerator(*enumerator);
495ba675d69SCedric Chaumont 
496ba675d69SCedric Chaumont 	goto out;
497ba675d69SCedric Chaumont 
498ba675d69SCedric Chaumont err:
499ba675d69SCedric Chaumont 	if (res == TEE_ERROR_OUT_OF_MEMORY)
500ba675d69SCedric Chaumont 		return res;
501ba675d69SCedric Chaumont 	TEE_Panic(0);
502ba675d69SCedric Chaumont out:
503b0104773SPascal Brand 	return TEE_SUCCESS;
504b0104773SPascal Brand }
505b0104773SPascal Brand 
506b0104773SPascal Brand void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator)
507b0104773SPascal Brand {
508b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
509b0104773SPascal Brand 
510b0104773SPascal Brand 	pe->idx = PROP_ENUMERATOR_NOT_STARTED;
511b0104773SPascal Brand }
512b0104773SPascal Brand 
513b0104773SPascal Brand void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator)
514b0104773SPascal Brand {
515b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
516b0104773SPascal Brand 
517b0104773SPascal Brand 	TEE_Free(pe);
518b0104773SPascal Brand }
519b0104773SPascal Brand 
520b0104773SPascal Brand void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator,
521b0104773SPascal Brand 				 TEE_PropSetHandle propSet)
522b0104773SPascal Brand {
523b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
524b0104773SPascal Brand 
5250dd3f3a4SPascal Brand 	if (!pe)
526b0104773SPascal Brand 		return;
527b0104773SPascal Brand 
528b0104773SPascal Brand 	pe->idx = 0;
529b0104773SPascal Brand 	pe->prop_set = propSet;
530b0104773SPascal Brand }
531b0104773SPascal Brand 
532*6551d565SJens Wiklander TEE_Result __GP11_TEE_GetPropertyName(TEE_PropSetHandle enumerator,
5330dd3f3a4SPascal Brand 				      void *name, uint32_t *name_len)
534b0104773SPascal Brand {
535b0104773SPascal Brand 	TEE_Result res;
536b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
537b0104773SPascal Brand 	const struct user_ta_property *eps;
538b0104773SPascal Brand 	size_t eps_len;
539b0104773SPascal Brand 	const char *str;
540b0104773SPascal Brand 	size_t bufferlen;
541b0104773SPascal Brand 
5426915bbbbSJens Wiklander 	if (!pe) {
543ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
544ba675d69SCedric Chaumont 		goto err;
545ba675d69SCedric Chaumont 	}
546*6551d565SJens Wiklander 	__utee_check_gp11_outstring_annotation(name, name_len);
547b0104773SPascal Brand 
5480dd3f3a4SPascal Brand 	bufferlen = *name_len;
54964a5011eSPascal Brand 	res = propset_get(pe->prop_set, &eps, &eps_len);
550b0104773SPascal Brand 	if (res != TEE_SUCCESS)
551ba675d69SCedric Chaumont 		goto err;
552b0104773SPascal Brand 
55364a5011eSPascal Brand 	if (pe->idx < eps_len) {
55464a5011eSPascal Brand 		str = eps[pe->idx].name;
5550dd3f3a4SPascal Brand 		bufferlen = strlcpy(name, str, *name_len) + 1;
5560dd3f3a4SPascal Brand 		if (bufferlen > *name_len)
557ba675d69SCedric Chaumont 			res = TEE_ERROR_SHORT_BUFFER;
5580dd3f3a4SPascal Brand 		*name_len = bufferlen;
55964a5011eSPascal Brand 	} else {
5602c028fdeSJerome Forissier 		res = _utee_get_property((unsigned long)pe->prop_set,
5612c028fdeSJerome Forissier 					 pe->idx - eps_len, name, name_len,
5622c028fdeSJerome Forissier 					 NULL, NULL, NULL);
56364a5011eSPascal Brand 		if (res != TEE_SUCCESS)
564ba675d69SCedric Chaumont 			goto err;
565ba675d69SCedric Chaumont 	}
566b0104773SPascal Brand 
567ba675d69SCedric Chaumont err:
56864a5011eSPascal Brand 	if (res != TEE_SUCCESS &&
56964a5011eSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
57064a5011eSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER)
571ba675d69SCedric Chaumont 		TEE_Panic(0);
57264a5011eSPascal Brand 	return res;
573b0104773SPascal Brand }
574b0104773SPascal Brand 
575*6551d565SJens Wiklander TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator,
576*6551d565SJens Wiklander 			       void *nameBuffer, size_t *nameBufferLen)
577*6551d565SJens Wiklander {
578*6551d565SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
579*6551d565SJens Wiklander 	uint32_t l = 0;
580*6551d565SJens Wiklander 
581*6551d565SJens Wiklander 	__utee_check_outstring_annotation(nameBuffer, nameBufferLen);
582*6551d565SJens Wiklander 	l = *nameBufferLen;
583*6551d565SJens Wiklander 	res = __GP11_TEE_GetPropertyName(enumerator, nameBuffer, &l);
584*6551d565SJens Wiklander 	*nameBufferLen = l;
585*6551d565SJens Wiklander 	return res;
586*6551d565SJens Wiklander }
587*6551d565SJens Wiklander 
588b0104773SPascal Brand TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator)
589b0104773SPascal Brand {
590b0104773SPascal Brand 	TEE_Result res;
591b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
592b0104773SPascal Brand 	uint32_t next_idx;
593b0104773SPascal Brand 	const struct user_ta_property *eps;
594b0104773SPascal Brand 	size_t eps_len;
595b0104773SPascal Brand 
5960dd3f3a4SPascal Brand 	if (!pe) {
597ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
59864a5011eSPascal Brand 		goto out;
599ba675d69SCedric Chaumont 	}
600b0104773SPascal Brand 
601ba675d69SCedric Chaumont 	if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) {
602ba675d69SCedric Chaumont 		res = TEE_ERROR_ITEM_NOT_FOUND;
60364a5011eSPascal Brand 		goto out;
604ba675d69SCedric Chaumont 	}
605b0104773SPascal Brand 
60664a5011eSPascal Brand 	res = propset_get(pe->prop_set, &eps, &eps_len);
607b0104773SPascal Brand 	if (res != TEE_SUCCESS)
60864a5011eSPascal Brand 		goto out;
609b0104773SPascal Brand 
610b0104773SPascal Brand 	next_idx = pe->idx + 1;
611b0104773SPascal Brand 	pe->idx = next_idx;
61264a5011eSPascal Brand 	if (next_idx < eps_len)
61364a5011eSPascal Brand 		res = TEE_SUCCESS;
61464a5011eSPascal Brand 	else
6152c028fdeSJerome Forissier 		res = _utee_get_property((unsigned long)pe->prop_set,
6162c028fdeSJerome Forissier 					 next_idx - eps_len, NULL, NULL, NULL,
6172c028fdeSJerome Forissier 					 NULL, NULL);
618b0104773SPascal Brand 
619ba675d69SCedric Chaumont out:
62064a5011eSPascal Brand 	if (res != TEE_SUCCESS &&
62164a5011eSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND)
62264a5011eSPascal Brand 		TEE_Panic(0);
62364a5011eSPascal Brand 	return res;
624b0104773SPascal Brand }
625