xref: /optee_os/lib/libutee/tee_api_property.c (revision a32a96ed0f53597ad86f74e3ff2dcb122a932a55)
1b0104773SPascal Brand /*
2b0104773SPascal Brand  * Copyright (c) 2014, STMicroelectronics International N.V.
3*a32a96edSJens Wiklander  * Copyright (c) 2017, Linaro Limited
4b0104773SPascal Brand  * All rights reserved.
5b0104773SPascal Brand  *
6b0104773SPascal Brand  * Redistribution and use in source and binary forms, with or without
7b0104773SPascal Brand  * modification, are permitted provided that the following conditions are met:
8b0104773SPascal Brand  *
9b0104773SPascal Brand  * 1. Redistributions of source code must retain the above copyright notice,
10b0104773SPascal Brand  * this list of conditions and the following disclaimer.
11b0104773SPascal Brand  *
12b0104773SPascal Brand  * 2. Redistributions in binary form must reproduce the above copyright notice,
13b0104773SPascal Brand  * this list of conditions and the following disclaimer in the documentation
14b0104773SPascal Brand  * and/or other materials provided with the distribution.
15b0104773SPascal Brand  *
16b0104773SPascal Brand  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17b0104773SPascal Brand  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18b0104773SPascal Brand  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19b0104773SPascal Brand  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20b0104773SPascal Brand  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21b0104773SPascal Brand  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22b0104773SPascal Brand  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23b0104773SPascal Brand  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24b0104773SPascal Brand  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25b0104773SPascal Brand  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26b0104773SPascal Brand  * POSSIBILITY OF SUCH DAMAGE.
27b0104773SPascal Brand  */
28*a32a96edSJens Wiklander #include <printk.h>
29*a32a96edSJens Wiklander #include <stdio.h>
30b0104773SPascal Brand #include <stdlib.h>
31b0104773SPascal Brand #include <string.h>
32b0104773SPascal Brand #include <tee_api_defines.h>
33*a32a96edSJens Wiklander #include <tee_api.h>
34b0104773SPascal Brand #include <tee_api_types.h>
35647f9c76SJerome Forissier #include <tee_arith_internal.h>
36*a32a96edSJens Wiklander #include <tee_internal_api_extensions.h>
37*a32a96edSJens Wiklander #include <tee_isocket.h>
38*a32a96edSJens Wiklander #include <user_ta_header.h>
39b0104773SPascal Brand #include <utee_syscalls.h>
40*a32a96edSJens Wiklander #include <util.h>
41b0104773SPascal Brand 
42b0104773SPascal Brand #include "string_ext.h"
43b0104773SPascal Brand #include "base64.h"
44b0104773SPascal Brand 
45b0104773SPascal Brand #define PROP_STR_MAX    80
46b0104773SPascal Brand 
47b0104773SPascal Brand #define PROP_ENUMERATOR_NOT_STARTED 0xffffffff
48b0104773SPascal Brand 
49b0104773SPascal Brand struct prop_enumerator {
5064a5011eSPascal Brand 	uint32_t idx;			/* current index */
5164a5011eSPascal Brand 	TEE_PropSetHandle prop_set;	/* part of TEE_PROPSET_xxx */
52b0104773SPascal Brand };
53b0104773SPascal Brand 
5464a5011eSPascal Brand const struct user_ta_property tee_props[] = {
5564a5011eSPascal Brand 	{
5664a5011eSPascal Brand 		"gpd.tee.arith.maxBigIntSize",
5764a5011eSPascal Brand 		USER_TA_PROP_TYPE_U32,
5864a5011eSPascal Brand 		&(const uint32_t){TEE_MAX_NUMBER_OF_SUPPORTED_BITS}
5964a5011eSPascal Brand 	},
60*a32a96edSJens Wiklander 	{
61*a32a96edSJens Wiklander 		"gpd.tee.sockets.version",
62*a32a96edSJens Wiklander 		USER_TA_PROP_TYPE_U32,
63*a32a96edSJens Wiklander 		&(const uint32_t){TEE_ISOCKET_VERSION}
64*a32a96edSJens Wiklander 	},
65*a32a96edSJens Wiklander 	{
66*a32a96edSJens Wiklander 		"gpd.tee.sockets.tcp.version",
67*a32a96edSJens Wiklander 		USER_TA_PROP_TYPE_U32,
68*a32a96edSJens Wiklander 		&(const uint32_t){TEE_ISOCKET_VERSION}
69*a32a96edSJens Wiklander 	},
70b0104773SPascal Brand };
71b0104773SPascal Brand 
7264a5011eSPascal Brand static TEE_Result propset_get(TEE_PropSetHandle h,
73b0104773SPascal Brand 			      const struct user_ta_property **eps,
74b0104773SPascal Brand 			      size_t *eps_len)
75b0104773SPascal Brand {
76b0104773SPascal Brand 	if (h == TEE_PROPSET_CURRENT_TA) {
77b0104773SPascal Brand 		*eps = ta_props;
78b0104773SPascal Brand 		*eps_len = ta_num_props;
79b0104773SPascal Brand 	} else if (h == TEE_PROPSET_CURRENT_CLIENT) {
80b0104773SPascal Brand 		*eps = NULL;
81b0104773SPascal Brand 		*eps_len = 0;
82b0104773SPascal Brand 	} else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) {
8364a5011eSPascal Brand 		*eps = tee_props;
8464a5011eSPascal Brand 		*eps_len = ARRAY_SIZE(tee_props);
85b0104773SPascal Brand 	} else {
86b0104773SPascal Brand 		return TEE_ERROR_ITEM_NOT_FOUND;
87b0104773SPascal Brand 	}
88b0104773SPascal Brand 
89b0104773SPascal Brand 	return TEE_SUCCESS;
90b0104773SPascal Brand }
91b0104773SPascal Brand 
92b0104773SPascal Brand static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep,
93ff857a3aSPascal Brand 				       enum user_ta_prop_type *type,
94ff857a3aSPascal Brand 				       void *buf, uint32_t *len)
95b0104773SPascal Brand {
96b0104773SPascal Brand 	size_t l;
97b0104773SPascal Brand 
98ff857a3aSPascal Brand 	*type = ep->type;
99ff857a3aSPascal Brand 	switch (*type) {
100b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BOOL:
10164a5011eSPascal Brand 		l = sizeof(uint32_t);
102b0104773SPascal Brand 		break;
103b0104773SPascal Brand 	case USER_TA_PROP_TYPE_U32:
104b0104773SPascal Brand 		l = sizeof(uint32_t);
105b0104773SPascal Brand 		break;
106b0104773SPascal Brand 	case USER_TA_PROP_TYPE_UUID:
107b0104773SPascal Brand 		l = sizeof(TEE_UUID);
108b0104773SPascal Brand 		break;
109b0104773SPascal Brand 	case USER_TA_PROP_TYPE_IDENTITY:
110b0104773SPascal Brand 		l = sizeof(TEE_Identity);
111b0104773SPascal Brand 		break;
112b0104773SPascal Brand 	case USER_TA_PROP_TYPE_STRING:
113ff857a3aSPascal Brand 		/* take the leading 0 into account */
114ff857a3aSPascal Brand 		l = strlen(ep->value) + 1;
115ff857a3aSPascal Brand 		break;
116b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
117ff857a3aSPascal Brand 		/*
118ff857a3aSPascal Brand 		 * in case of TA property, a binary block is provided as a
119ff857a3aSPascal Brand 		 * string, which is base64 encoded. We must first decode it,
120ff857a3aSPascal Brand 		 * without taking into account the zero termination of the
121ff857a3aSPascal Brand 		 * string
122ff857a3aSPascal Brand 		 */
123ff857a3aSPascal Brand 		l = *len;
124ff857a3aSPascal Brand 		if (!base64_dec(ep->value, strlen(ep->value), buf, &l) &&
125ff857a3aSPascal Brand 		    (l <= *len))
126ff857a3aSPascal Brand 			return TEE_ERROR_GENERIC;
127ff857a3aSPascal Brand 		if (*len < l) {
128ff857a3aSPascal Brand 			*len = l;
129ff857a3aSPascal Brand 			return TEE_ERROR_SHORT_BUFFER;
130ff857a3aSPascal Brand 		}
131ff857a3aSPascal Brand 
132ff857a3aSPascal Brand 		*len = l;
133b0104773SPascal Brand 		return TEE_SUCCESS;
134b0104773SPascal Brand 	default:
135b0104773SPascal Brand 		return TEE_ERROR_GENERIC;
136b0104773SPascal Brand 	}
137ff857a3aSPascal Brand 
138ff857a3aSPascal Brand 	if (*len < l) {
139ff857a3aSPascal Brand 		*len = l;
140ff857a3aSPascal Brand 		return TEE_ERROR_SHORT_BUFFER;
141ff857a3aSPascal Brand 	}
142ff857a3aSPascal Brand 
143ff857a3aSPascal Brand 	*len = l;
144ff857a3aSPascal Brand 	memcpy(buf, ep->value, l);
145b0104773SPascal Brand 	return TEE_SUCCESS;
146b0104773SPascal Brand }
147b0104773SPascal Brand 
1488f07fe6fSJerome Forissier static TEE_Result propget_get_property(TEE_PropSetHandle h, const char *name,
149ff857a3aSPascal Brand 				       enum user_ta_prop_type *type,
150ff857a3aSPascal Brand 				       void *buf, uint32_t *len)
151b0104773SPascal Brand {
152b0104773SPascal Brand 	TEE_Result res;
153b0104773SPascal Brand 	const struct user_ta_property *eps;
154b0104773SPascal Brand 	size_t eps_len;
15564a5011eSPascal Brand 	uint32_t prop_type;
15664a5011eSPascal Brand 	uint32_t index;
157b0104773SPascal Brand 
158b0104773SPascal Brand 	if (h == TEE_PROPSET_CURRENT_TA || h == TEE_PROPSET_CURRENT_CLIENT ||
159b0104773SPascal Brand 	    h == TEE_PROPSET_TEE_IMPLEMENTATION) {
160b0104773SPascal Brand 		size_t n;
161b0104773SPascal Brand 
16264a5011eSPascal Brand 		res = propset_get(h, &eps, &eps_len);
163b0104773SPascal Brand 		if (res != TEE_SUCCESS)
164b0104773SPascal Brand 			return res;
165b0104773SPascal Brand 
166b0104773SPascal Brand 		for (n = 0; n < eps_len; n++) {
16764a5011eSPascal Brand 			if (!strcmp(name, eps[n].name))
168ff857a3aSPascal Brand 				return propget_get_ext_prop(eps + n, type,
169ff857a3aSPascal Brand 							    buf, len);
170b0104773SPascal Brand 		}
17164a5011eSPascal Brand 
17264a5011eSPascal Brand 		/* get the index from the name */
17364a5011eSPascal Brand 		res = utee_get_property_name_to_index((unsigned long)h, name,
17464a5011eSPascal Brand 						strlen(name) + 1, &index);
17564a5011eSPascal Brand 		if (res != TEE_SUCCESS)
17664a5011eSPascal Brand 			return res;
177ff857a3aSPascal Brand 		res = utee_get_property((unsigned long)h, index, NULL, NULL,
178ff857a3aSPascal Brand 					buf, len, &prop_type);
179b0104773SPascal Brand 	} else {
180b0104773SPascal Brand 		struct prop_enumerator *pe = (struct prop_enumerator *)h;
181b0104773SPascal Brand 		uint32_t idx = pe->idx;
182b0104773SPascal Brand 
183b0104773SPascal Brand 		if (idx == PROP_ENUMERATOR_NOT_STARTED)
184b0104773SPascal Brand 			return TEE_ERROR_ITEM_NOT_FOUND;
185b0104773SPascal Brand 
18664a5011eSPascal Brand 		res = propset_get(pe->prop_set, &eps, &eps_len);
187b0104773SPascal Brand 		if (res != TEE_SUCCESS)
188b0104773SPascal Brand 			return res;
189b0104773SPascal Brand 
190b0104773SPascal Brand 		if (idx < eps_len)
191ff857a3aSPascal Brand 			return propget_get_ext_prop(eps + idx, type, buf, len);
19264a5011eSPascal Brand 		idx -= eps_len;
193b0104773SPascal Brand 
19464a5011eSPascal Brand 		res = utee_get_property((unsigned long)pe->prop_set, idx,
195ff857a3aSPascal Brand 					NULL, NULL, buf, len, &prop_type);
19664a5011eSPascal Brand 		if (res == TEE_ERROR_ITEM_NOT_FOUND)
19764a5011eSPascal Brand 			res = TEE_ERROR_BAD_PARAMETERS;
198b0104773SPascal Brand 	}
19964a5011eSPascal Brand 
200ff857a3aSPascal Brand 	*type = prop_type;
20164a5011eSPascal Brand 	return res;
202b0104773SPascal Brand }
203b0104773SPascal Brand 
204b0104773SPascal Brand TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator,
2058f07fe6fSJerome Forissier 				   const char *name, char *value,
2060dd3f3a4SPascal Brand 				   uint32_t *value_len)
207b0104773SPascal Brand {
208b0104773SPascal Brand 	TEE_Result res;
209b0104773SPascal Brand 	size_t l;
210ff857a3aSPascal Brand 	enum user_ta_prop_type type;
211ff857a3aSPascal Brand 	void *tmp_buf = 0;
212ff857a3aSPascal Brand 	uint32_t tmp_len;
213ff857a3aSPascal Brand 	uint32_t uint32_val;
214ff857a3aSPascal Brand 	TEE_Identity *p_identity_val;
215b0104773SPascal Brand 
2160dd3f3a4SPascal Brand 	if (!value || !value_len) {
217ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
218ff857a3aSPascal Brand 		goto out;
219ba675d69SCedric Chaumont 	}
220b0104773SPascal Brand 
2210dd3f3a4SPascal Brand 	tmp_len = *value_len;
222ff857a3aSPascal Brand 	if (tmp_len < sizeof(TEE_Identity))
223ff857a3aSPascal Brand 		tmp_len = sizeof(TEE_Identity);
224ff857a3aSPascal Brand 	tmp_buf = TEE_Malloc(tmp_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
225ff857a3aSPascal Brand 	if (!tmp_buf) {
226ff857a3aSPascal Brand 		res = TEE_ERROR_OUT_OF_MEMORY;
227ff857a3aSPascal Brand 		goto out;
228ff857a3aSPascal Brand 	}
229b0104773SPascal Brand 
230ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
231ff857a3aSPascal Brand 				   tmp_buf, &tmp_len);
232ff857a3aSPascal Brand 	if (res != TEE_SUCCESS) {
233254e1d58SPascal Brand 		if (res == TEE_ERROR_SHORT_BUFFER) {
234254e1d58SPascal Brand 			if (type == USER_TA_PROP_TYPE_BINARY_BLOCK) {
235254e1d58SPascal Brand 				/*
236254e1d58SPascal Brand 				 * in this case, we must enlarge the buffer
237254e1d58SPascal Brand 				 * with the size of the of the base64 encoded
238254e1d58SPascal Brand 				 * see base64_enc() function
239254e1d58SPascal Brand 				 */
240254e1d58SPascal Brand 				tmp_len = base64_enc_len(tmp_len);
241254e1d58SPascal Brand 			}
2420dd3f3a4SPascal Brand 			*value_len = tmp_len;
243254e1d58SPascal Brand 		}
244ff857a3aSPascal Brand 		goto out;
245ff857a3aSPascal Brand 	}
246b0104773SPascal Brand 
247ff857a3aSPascal Brand 	switch (type) {
248b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BOOL:
249ff857a3aSPascal Brand 		uint32_val = *((uint32_t *)tmp_buf);
2500dd3f3a4SPascal Brand 		l = strlcpy(value, (uint32_val ? "true" : "false"),
2510dd3f3a4SPascal Brand 			    *value_len);
252b0104773SPascal Brand 		break;
253b0104773SPascal Brand 
254b0104773SPascal Brand 	case USER_TA_PROP_TYPE_U32:
255ff857a3aSPascal Brand 		uint32_val = *((uint32_t *)tmp_buf);
2560dd3f3a4SPascal Brand 		l = snprintf(value, *value_len, "%u", uint32_val);
257b0104773SPascal Brand 		break;
258b0104773SPascal Brand 
259b0104773SPascal Brand 	case USER_TA_PROP_TYPE_UUID:
2600dd3f3a4SPascal Brand 		l = snprintk(value, *value_len, "%pUl", tmp_buf);
261b0104773SPascal Brand 		break;
262b0104773SPascal Brand 
263b0104773SPascal Brand 	case USER_TA_PROP_TYPE_IDENTITY:
264ff857a3aSPascal Brand 		p_identity_val = ((TEE_Identity *)tmp_buf);
2650dd3f3a4SPascal Brand 		l = snprintk(value, *value_len, "%u:%pUl",
266ff857a3aSPascal Brand 			     p_identity_val->login,
267ff857a3aSPascal Brand 			     (void *)(&(p_identity_val->uuid)));
268b0104773SPascal Brand 		break;
269b0104773SPascal Brand 
270b0104773SPascal Brand 	case USER_TA_PROP_TYPE_STRING:
2710dd3f3a4SPascal Brand 		l = strlcpy(value, tmp_buf, *value_len);
272ff857a3aSPascal Brand 		break;
273ff857a3aSPascal Brand 
274b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
2750dd3f3a4SPascal Brand 		l = *value_len;	/* l includes the zero-termination */
2760dd3f3a4SPascal Brand 		if (!base64_enc(tmp_buf, tmp_len, value, &l) &&
2770dd3f3a4SPascal Brand 		    (l <= *value_len)) {
278ff857a3aSPascal Brand 			res = TEE_ERROR_GENERIC;
279ff857a3aSPascal Brand 			goto out;
280ff857a3aSPascal Brand 		}
281ff857a3aSPascal Brand 		l--;	/* remove the zero-termination that is added later */
282b0104773SPascal Brand 		break;
283b0104773SPascal Brand 
284b0104773SPascal Brand 	default:
285ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_FORMAT;
286ba675d69SCedric Chaumont 		goto out;
287ff857a3aSPascal Brand 	}
288ba675d69SCedric Chaumont 
289ff857a3aSPascal Brand 	l++;	/* include zero termination */
290ff857a3aSPascal Brand 
2910dd3f3a4SPascal Brand 	if (l > *value_len)
292ff857a3aSPascal Brand 		res = TEE_ERROR_SHORT_BUFFER;
2930dd3f3a4SPascal Brand 	*value_len = l;
294ff857a3aSPascal Brand 
295ba675d69SCedric Chaumont out:
296ff857a3aSPascal Brand 	if (tmp_buf)
297ff857a3aSPascal Brand 		TEE_Free(tmp_buf);
298ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
299ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
300ff857a3aSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER)
301ff857a3aSPascal Brand 		TEE_Panic(0);
302ff857a3aSPascal Brand 
303ff857a3aSPascal Brand 	return res;
304b0104773SPascal Brand }
305b0104773SPascal Brand 
306b0104773SPascal Brand TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator,
3078f07fe6fSJerome Forissier 				 const char *name, bool *value)
308b0104773SPascal Brand {
309b0104773SPascal Brand 	TEE_Result res;
310ff857a3aSPascal Brand 	enum user_ta_prop_type type;
311ff857a3aSPascal Brand 	uint32_t uint32_val;
312ff857a3aSPascal Brand 	uint32_t uint32_len = sizeof(uint32_val);
313ba675d69SCedric Chaumont 	if (value == NULL) {
314ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
315ff857a3aSPascal Brand 		goto out;
316ba675d69SCedric Chaumont 	}
317b0104773SPascal Brand 
318ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_BOOL;
319ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
320ff857a3aSPascal Brand 				   &uint32_val, &uint32_len);
321ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_BOOL)
322ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_FORMAT;
323ff857a3aSPascal Brand 	if (res != TEE_SUCCESS)
324ba675d69SCedric Chaumont 		goto out;
325ba675d69SCedric Chaumont 
326ff857a3aSPascal Brand 	*value = !!uint32_val;
327ff857a3aSPascal Brand 
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 
3440dd3f3a4SPascal Brand 	if (!value) {
345ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
346ba675d69SCedric Chaumont 		goto out;
347ff857a3aSPascal Brand 	}
348ba675d69SCedric Chaumont 
349ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_U32;
350ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
351ff857a3aSPascal Brand 				   value, &uint32_len);
352ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_U32)
353ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
354ff857a3aSPascal Brand 
355ba675d69SCedric Chaumont out:
356ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
357ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
358ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT)
359ff857a3aSPascal Brand 		TEE_Panic(0);
360ff857a3aSPascal Brand 
361ff857a3aSPascal Brand 	return res;
362b0104773SPascal Brand }
363b0104773SPascal Brand 
364b0104773SPascal Brand TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator,
3658f07fe6fSJerome Forissier 					const char *name, void *value,
3660dd3f3a4SPascal Brand 					uint32_t *value_len)
367b0104773SPascal Brand {
368b0104773SPascal Brand 	TEE_Result res;
369ff857a3aSPascal Brand 	enum user_ta_prop_type type;
370b0104773SPascal Brand 
3710dd3f3a4SPascal Brand 	if (!value || !value_len) {
372ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
373ba675d69SCedric Chaumont 		goto out;
374ff857a3aSPascal Brand 	}
375ba675d69SCedric Chaumont 
376ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_BINARY_BLOCK;
377ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
3780dd3f3a4SPascal Brand 				   value, value_len);
379ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_BINARY_BLOCK)
380ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
381ff857a3aSPascal Brand 
382ba675d69SCedric Chaumont out:
383ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
384ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
385ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT &&
386ff857a3aSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER)
387ff857a3aSPascal Brand 		TEE_Panic(0);
388ff857a3aSPascal Brand 
389ff857a3aSPascal Brand 	return res;
390b0104773SPascal Brand }
391b0104773SPascal Brand 
392b0104773SPascal Brand TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator,
3938f07fe6fSJerome Forissier 				 const char *name, TEE_UUID *value)
394b0104773SPascal Brand {
395b0104773SPascal Brand 	TEE_Result res;
396ff857a3aSPascal Brand 	enum user_ta_prop_type type;
397ff857a3aSPascal Brand 	uint32_t uuid_len = sizeof(TEE_UUID);
398b0104773SPascal Brand 
3990dd3f3a4SPascal Brand 	if (!value) {
400ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
401ba675d69SCedric Chaumont 		goto out;
402ff857a3aSPascal Brand 	}
403ba675d69SCedric Chaumont 
404ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_UUID;
405ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
406ff857a3aSPascal Brand 				   value, &uuid_len);
407ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_UUID)
408ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
409ff857a3aSPascal Brand 
410ba675d69SCedric Chaumont out:
411ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
412ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
413ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT)
414ff857a3aSPascal Brand 		TEE_Panic(0);
415ff857a3aSPascal Brand 
416ff857a3aSPascal Brand 	return res;
417b0104773SPascal Brand }
418b0104773SPascal Brand 
419b0104773SPascal Brand TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator,
4208f07fe6fSJerome Forissier 				     const char *name, TEE_Identity *value)
421b0104773SPascal Brand {
422b0104773SPascal Brand 	TEE_Result res;
423ff857a3aSPascal Brand 	enum user_ta_prop_type type;
424ff857a3aSPascal Brand 	uint32_t identity_len = sizeof(TEE_Identity);
425b0104773SPascal Brand 
4260dd3f3a4SPascal Brand 	if (!value) {
427ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
428ba675d69SCedric Chaumont 		goto out;
429ff857a3aSPascal Brand 	}
430ba675d69SCedric Chaumont 
431ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_IDENTITY;
432ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
433ff857a3aSPascal Brand 				   value, &identity_len);
434ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_IDENTITY)
435ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
436ff857a3aSPascal Brand 
437ba675d69SCedric Chaumont out:
438ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
439ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
440ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT)
441ff857a3aSPascal Brand 		TEE_Panic(0);
442ff857a3aSPascal Brand 
443ff857a3aSPascal Brand 	return res;
444b0104773SPascal Brand }
445b0104773SPascal Brand 
446b0104773SPascal Brand TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator)
447b0104773SPascal Brand {
448ba675d69SCedric Chaumont 	TEE_Result res;
449b0104773SPascal Brand 	struct prop_enumerator *pe;
450b0104773SPascal Brand 
4510dd3f3a4SPascal Brand 	if (!enumerator) {
452ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
453ba675d69SCedric Chaumont 		goto err;
454ba675d69SCedric Chaumont 	}
455b0104773SPascal Brand 
456b0104773SPascal Brand 	pe = TEE_Malloc(sizeof(struct prop_enumerator),
457b0104773SPascal Brand 			TEE_USER_MEM_HINT_NO_FILL_ZERO);
458ba675d69SCedric Chaumont 	if (pe == NULL) {
459ba675d69SCedric Chaumont 		res = TEE_ERROR_OUT_OF_MEMORY;
460ba675d69SCedric Chaumont 		goto err;
461ba675d69SCedric Chaumont 	}
462b0104773SPascal Brand 
463b0104773SPascal Brand 	*enumerator = (TEE_PropSetHandle) pe;
464b0104773SPascal Brand 	TEE_ResetPropertyEnumerator(*enumerator);
465ba675d69SCedric Chaumont 
466ba675d69SCedric Chaumont 	goto out;
467ba675d69SCedric Chaumont 
468ba675d69SCedric Chaumont err:
469ba675d69SCedric Chaumont 	if (res == TEE_ERROR_OUT_OF_MEMORY)
470ba675d69SCedric Chaumont 		return res;
471ba675d69SCedric Chaumont 	TEE_Panic(0);
472ba675d69SCedric Chaumont out:
473b0104773SPascal Brand 	return TEE_SUCCESS;
474b0104773SPascal Brand }
475b0104773SPascal Brand 
476b0104773SPascal Brand void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator)
477b0104773SPascal Brand {
478b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
479b0104773SPascal Brand 
480b0104773SPascal Brand 	pe->idx = PROP_ENUMERATOR_NOT_STARTED;
481b0104773SPascal Brand }
482b0104773SPascal Brand 
483b0104773SPascal Brand void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator)
484b0104773SPascal Brand {
485b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
486b0104773SPascal Brand 
487b0104773SPascal Brand 	TEE_Free(pe);
488b0104773SPascal Brand }
489b0104773SPascal Brand 
490b0104773SPascal Brand void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator,
491b0104773SPascal Brand 				 TEE_PropSetHandle propSet)
492b0104773SPascal Brand {
493b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
494b0104773SPascal Brand 
4950dd3f3a4SPascal Brand 	if (!pe)
496b0104773SPascal Brand 		return;
497b0104773SPascal Brand 
498b0104773SPascal Brand 	pe->idx = 0;
499b0104773SPascal Brand 	pe->prop_set = propSet;
500b0104773SPascal Brand }
501b0104773SPascal Brand 
502b0104773SPascal Brand TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator,
5030dd3f3a4SPascal Brand 			       void *name, uint32_t *name_len)
504b0104773SPascal Brand {
505b0104773SPascal Brand 	TEE_Result res;
506b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
507b0104773SPascal Brand 	const struct user_ta_property *eps;
508b0104773SPascal Brand 	size_t eps_len;
509b0104773SPascal Brand 	const char *str;
510b0104773SPascal Brand 	size_t bufferlen;
511b0104773SPascal Brand 
5120dd3f3a4SPascal Brand 	if (!pe || !name || !name_len) {
513ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
514ba675d69SCedric Chaumont 		goto err;
515ba675d69SCedric Chaumont 	}
516b0104773SPascal Brand 
5170dd3f3a4SPascal Brand 	bufferlen = *name_len;
51864a5011eSPascal Brand 	res = propset_get(pe->prop_set, &eps, &eps_len);
519b0104773SPascal Brand 	if (res != TEE_SUCCESS)
520ba675d69SCedric Chaumont 		goto err;
521b0104773SPascal Brand 
52264a5011eSPascal Brand 	if (pe->idx < eps_len) {
52364a5011eSPascal Brand 		str = eps[pe->idx].name;
5240dd3f3a4SPascal Brand 		bufferlen = strlcpy(name, str, *name_len) + 1;
5250dd3f3a4SPascal Brand 		if (bufferlen > *name_len)
526ba675d69SCedric Chaumont 			res = TEE_ERROR_SHORT_BUFFER;
5270dd3f3a4SPascal Brand 		*name_len = bufferlen;
52864a5011eSPascal Brand 	} else {
52964a5011eSPascal Brand 		res = utee_get_property((unsigned long)pe->prop_set,
53064a5011eSPascal Brand 					pe->idx - eps_len,
5310dd3f3a4SPascal Brand 					name, name_len, NULL, NULL, NULL);
53264a5011eSPascal Brand 		if (res != TEE_SUCCESS)
533ba675d69SCedric Chaumont 			goto err;
534ba675d69SCedric Chaumont 	}
535b0104773SPascal Brand 
536ba675d69SCedric Chaumont err:
53764a5011eSPascal Brand 	if (res != TEE_SUCCESS &&
53864a5011eSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
53964a5011eSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER)
540ba675d69SCedric Chaumont 		TEE_Panic(0);
54164a5011eSPascal Brand 	return res;
542b0104773SPascal Brand }
543b0104773SPascal Brand 
544b0104773SPascal Brand TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator)
545b0104773SPascal Brand {
546b0104773SPascal Brand 	TEE_Result res;
547b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
548b0104773SPascal Brand 	uint32_t next_idx;
549b0104773SPascal Brand 	const struct user_ta_property *eps;
550b0104773SPascal Brand 	size_t eps_len;
551b0104773SPascal Brand 
5520dd3f3a4SPascal Brand 	if (!pe) {
553ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
55464a5011eSPascal Brand 		goto out;
555ba675d69SCedric Chaumont 	}
556b0104773SPascal Brand 
557ba675d69SCedric Chaumont 	if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) {
558ba675d69SCedric Chaumont 		res = TEE_ERROR_ITEM_NOT_FOUND;
55964a5011eSPascal Brand 		goto out;
560ba675d69SCedric Chaumont 	}
561b0104773SPascal Brand 
56264a5011eSPascal Brand 	res = propset_get(pe->prop_set, &eps, &eps_len);
563b0104773SPascal Brand 	if (res != TEE_SUCCESS)
56464a5011eSPascal Brand 		goto out;
565b0104773SPascal Brand 
566b0104773SPascal Brand 	next_idx = pe->idx + 1;
567b0104773SPascal Brand 	pe->idx = next_idx;
56864a5011eSPascal Brand 	if (next_idx < eps_len)
56964a5011eSPascal Brand 		res = TEE_SUCCESS;
57064a5011eSPascal Brand 	else
57164a5011eSPascal Brand 		res = utee_get_property((unsigned long)pe->prop_set,
572ff857a3aSPascal Brand 					next_idx - eps_len,
573ff857a3aSPascal Brand 					NULL, NULL, NULL, NULL, NULL);
574b0104773SPascal Brand 
575ba675d69SCedric Chaumont out:
57664a5011eSPascal Brand 	if (res != TEE_SUCCESS &&
57764a5011eSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND)
57864a5011eSPascal Brand 		TEE_Panic(0);
57964a5011eSPascal Brand 	return res;
580b0104773SPascal Brand }
581