xref: /optee_os/lib/libutee/tee_api_property.c (revision 8f07fe6f754c642bcc33224df2772359b36f7d2b)
1b0104773SPascal Brand /*
2b0104773SPascal Brand  * Copyright (c) 2014, STMicroelectronics International N.V.
3b0104773SPascal Brand  * All rights reserved.
4b0104773SPascal Brand  *
5b0104773SPascal Brand  * Redistribution and use in source and binary forms, with or without
6b0104773SPascal Brand  * modification, are permitted provided that the following conditions are met:
7b0104773SPascal Brand  *
8b0104773SPascal Brand  * 1. Redistributions of source code must retain the above copyright notice,
9b0104773SPascal Brand  * this list of conditions and the following disclaimer.
10b0104773SPascal Brand  *
11b0104773SPascal Brand  * 2. Redistributions in binary form must reproduce the above copyright notice,
12b0104773SPascal Brand  * this list of conditions and the following disclaimer in the documentation
13b0104773SPascal Brand  * and/or other materials provided with the distribution.
14b0104773SPascal Brand  *
15b0104773SPascal Brand  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16b0104773SPascal Brand  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17b0104773SPascal Brand  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18b0104773SPascal Brand  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19b0104773SPascal Brand  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20b0104773SPascal Brand  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21b0104773SPascal Brand  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22b0104773SPascal Brand  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23b0104773SPascal Brand  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24b0104773SPascal Brand  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25b0104773SPascal Brand  * POSSIBILITY OF SUCH DAMAGE.
26b0104773SPascal Brand  */
27b0104773SPascal Brand #include <tee_api.h>
28b0104773SPascal Brand 
29b0104773SPascal Brand #include <stdlib.h>
30b0104773SPascal Brand #include <string.h>
31b0104773SPascal Brand #include <stdio.h>
32ff857a3aSPascal Brand #include <printk.h>
33b0104773SPascal Brand #include <tee_api_defines.h>
34b0104773SPascal Brand #include <tee_api_types.h>
35b0104773SPascal Brand #include <user_ta_header.h>
36b0104773SPascal Brand #include <tee_internal_api_extensions.h>
37647f9c76SJerome Forissier #include <tee_arith_internal.h>
3864a5011eSPascal Brand #include <util.h>
39b0104773SPascal Brand #include <utee_syscalls.h>
40b0104773SPascal Brand 
41b0104773SPascal Brand #include "string_ext.h"
42b0104773SPascal Brand #include "base64.h"
43b0104773SPascal Brand 
44b0104773SPascal Brand #define PROP_STR_MAX    80
45b0104773SPascal Brand 
46b0104773SPascal Brand #define PROP_ENUMERATOR_NOT_STARTED 0xffffffff
47b0104773SPascal Brand 
48b0104773SPascal Brand struct prop_enumerator {
4964a5011eSPascal Brand 	uint32_t idx;			/* current index */
5064a5011eSPascal Brand 	TEE_PropSetHandle prop_set;	/* part of TEE_PROPSET_xxx */
51b0104773SPascal Brand };
52b0104773SPascal Brand 
5364a5011eSPascal Brand const struct user_ta_property tee_props[] = {
5464a5011eSPascal Brand 	{
5564a5011eSPascal Brand 		"gpd.tee.arith.maxBigIntSize",
5664a5011eSPascal Brand 		USER_TA_PROP_TYPE_U32,
5764a5011eSPascal Brand 		&(const uint32_t){TEE_MAX_NUMBER_OF_SUPPORTED_BITS}
5864a5011eSPascal Brand 	},
59b0104773SPascal Brand };
60b0104773SPascal Brand 
6164a5011eSPascal Brand static TEE_Result propset_get(TEE_PropSetHandle h,
62b0104773SPascal Brand 			      const struct user_ta_property **eps,
63b0104773SPascal Brand 			      size_t *eps_len)
64b0104773SPascal Brand {
65b0104773SPascal Brand 	if (h == TEE_PROPSET_CURRENT_TA) {
66b0104773SPascal Brand 		*eps = ta_props;
67b0104773SPascal Brand 		*eps_len = ta_num_props;
68b0104773SPascal Brand 	} else if (h == TEE_PROPSET_CURRENT_CLIENT) {
69b0104773SPascal Brand 		*eps = NULL;
70b0104773SPascal Brand 		*eps_len = 0;
71b0104773SPascal Brand 	} else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) {
7264a5011eSPascal Brand 		*eps = tee_props;
7364a5011eSPascal Brand 		*eps_len = ARRAY_SIZE(tee_props);
74b0104773SPascal Brand 	} else {
75b0104773SPascal Brand 		return TEE_ERROR_ITEM_NOT_FOUND;
76b0104773SPascal Brand 	}
77b0104773SPascal Brand 
78b0104773SPascal Brand 	return TEE_SUCCESS;
79b0104773SPascal Brand }
80b0104773SPascal Brand 
81b0104773SPascal Brand static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep,
82ff857a3aSPascal Brand 				       enum user_ta_prop_type *type,
83ff857a3aSPascal Brand 				       void *buf, uint32_t *len)
84b0104773SPascal Brand {
85b0104773SPascal Brand 	size_t l;
86b0104773SPascal Brand 
87ff857a3aSPascal Brand 	*type = ep->type;
88ff857a3aSPascal Brand 	switch (*type) {
89b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BOOL:
9064a5011eSPascal Brand 		l = sizeof(uint32_t);
91b0104773SPascal Brand 		break;
92b0104773SPascal Brand 	case USER_TA_PROP_TYPE_U32:
93b0104773SPascal Brand 		l = sizeof(uint32_t);
94b0104773SPascal Brand 		break;
95b0104773SPascal Brand 	case USER_TA_PROP_TYPE_UUID:
96b0104773SPascal Brand 		l = sizeof(TEE_UUID);
97b0104773SPascal Brand 		break;
98b0104773SPascal Brand 	case USER_TA_PROP_TYPE_IDENTITY:
99b0104773SPascal Brand 		l = sizeof(TEE_Identity);
100b0104773SPascal Brand 		break;
101b0104773SPascal Brand 	case USER_TA_PROP_TYPE_STRING:
102ff857a3aSPascal Brand 		/* take the leading 0 into account */
103ff857a3aSPascal Brand 		l = strlen(ep->value) + 1;
104ff857a3aSPascal Brand 		break;
105b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
106ff857a3aSPascal Brand 		/*
107ff857a3aSPascal Brand 		 * in case of TA property, a binary block is provided as a
108ff857a3aSPascal Brand 		 * string, which is base64 encoded. We must first decode it,
109ff857a3aSPascal Brand 		 * without taking into account the zero termination of the
110ff857a3aSPascal Brand 		 * string
111ff857a3aSPascal Brand 		 */
112ff857a3aSPascal Brand 		l = *len;
113ff857a3aSPascal Brand 		if (!base64_dec(ep->value, strlen(ep->value), buf, &l) &&
114ff857a3aSPascal Brand 		    (l <= *len))
115ff857a3aSPascal Brand 			return TEE_ERROR_GENERIC;
116ff857a3aSPascal Brand 		if (*len < l) {
117ff857a3aSPascal Brand 			*len = l;
118ff857a3aSPascal Brand 			return TEE_ERROR_SHORT_BUFFER;
119ff857a3aSPascal Brand 		}
120ff857a3aSPascal Brand 
121ff857a3aSPascal Brand 		*len = l;
122b0104773SPascal Brand 		return TEE_SUCCESS;
123b0104773SPascal Brand 	default:
124b0104773SPascal Brand 		return TEE_ERROR_GENERIC;
125b0104773SPascal Brand 	}
126ff857a3aSPascal Brand 
127ff857a3aSPascal Brand 	if (*len < l) {
128ff857a3aSPascal Brand 		*len = l;
129ff857a3aSPascal Brand 		return TEE_ERROR_SHORT_BUFFER;
130ff857a3aSPascal Brand 	}
131ff857a3aSPascal Brand 
132ff857a3aSPascal Brand 	*len = l;
133ff857a3aSPascal Brand 	memcpy(buf, ep->value, l);
134b0104773SPascal Brand 	return TEE_SUCCESS;
135b0104773SPascal Brand }
136b0104773SPascal Brand 
137*8f07fe6fSJerome 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 
147b0104773SPascal Brand 	if (h == TEE_PROPSET_CURRENT_TA || h == TEE_PROPSET_CURRENT_CLIENT ||
148b0104773SPascal Brand 	    h == TEE_PROPSET_TEE_IMPLEMENTATION) {
149b0104773SPascal Brand 		size_t n;
150b0104773SPascal Brand 
15164a5011eSPascal Brand 		res = propset_get(h, &eps, &eps_len);
152b0104773SPascal Brand 		if (res != TEE_SUCCESS)
153b0104773SPascal Brand 			return res;
154b0104773SPascal Brand 
155b0104773SPascal Brand 		for (n = 0; n < eps_len; n++) {
15664a5011eSPascal Brand 			if (!strcmp(name, eps[n].name))
157ff857a3aSPascal Brand 				return propget_get_ext_prop(eps + n, type,
158ff857a3aSPascal Brand 							    buf, len);
159b0104773SPascal Brand 		}
16064a5011eSPascal Brand 
16164a5011eSPascal Brand 		/* get the index from the name */
16264a5011eSPascal Brand 		res = utee_get_property_name_to_index((unsigned long)h, name,
16364a5011eSPascal Brand 						strlen(name) + 1, &index);
16464a5011eSPascal Brand 		if (res != TEE_SUCCESS)
16564a5011eSPascal Brand 			return res;
166ff857a3aSPascal Brand 		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 
18364a5011eSPascal Brand 		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,
194*8f07fe6fSJerome Forissier 				   const char *name, char *value,
1950dd3f3a4SPascal Brand 				   uint32_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;
203ff857a3aSPascal Brand 	TEE_Identity *p_identity_val;
204b0104773SPascal Brand 
2050dd3f3a4SPascal Brand 	if (!value || !value_len) {
206ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
207ff857a3aSPascal Brand 		goto out;
208ba675d69SCedric Chaumont 	}
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 				 */
229254e1d58SPascal Brand 				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:
238ff857a3aSPascal Brand 		uint32_val = *((uint32_t *)tmp_buf);
2390dd3f3a4SPascal Brand 		l = strlcpy(value, (uint32_val ? "true" : "false"),
2400dd3f3a4SPascal Brand 			    *value_len);
241b0104773SPascal Brand 		break;
242b0104773SPascal Brand 
243b0104773SPascal Brand 	case USER_TA_PROP_TYPE_U32:
244ff857a3aSPascal Brand 		uint32_val = *((uint32_t *)tmp_buf);
2450dd3f3a4SPascal Brand 		l = snprintf(value, *value_len, "%u", uint32_val);
246b0104773SPascal Brand 		break;
247b0104773SPascal Brand 
248b0104773SPascal Brand 	case USER_TA_PROP_TYPE_UUID:
2490dd3f3a4SPascal Brand 		l = snprintk(value, *value_len, "%pUl", tmp_buf);
250b0104773SPascal Brand 		break;
251b0104773SPascal Brand 
252b0104773SPascal Brand 	case USER_TA_PROP_TYPE_IDENTITY:
253ff857a3aSPascal Brand 		p_identity_val = ((TEE_Identity *)tmp_buf);
2540dd3f3a4SPascal Brand 		l = snprintk(value, *value_len, "%u:%pUl",
255ff857a3aSPascal Brand 			     p_identity_val->login,
256ff857a3aSPascal Brand 			     (void *)(&(p_identity_val->uuid)));
257b0104773SPascal Brand 		break;
258b0104773SPascal Brand 
259b0104773SPascal Brand 	case USER_TA_PROP_TYPE_STRING:
2600dd3f3a4SPascal Brand 		l = strlcpy(value, tmp_buf, *value_len);
261ff857a3aSPascal Brand 		break;
262ff857a3aSPascal Brand 
263b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
2640dd3f3a4SPascal Brand 		l = *value_len;	/* l includes the zero-termination */
2650dd3f3a4SPascal Brand 		if (!base64_enc(tmp_buf, tmp_len, value, &l) &&
2660dd3f3a4SPascal Brand 		    (l <= *value_len)) {
267ff857a3aSPascal Brand 			res = TEE_ERROR_GENERIC;
268ff857a3aSPascal Brand 			goto out;
269ff857a3aSPascal Brand 		}
270ff857a3aSPascal Brand 		l--;	/* remove the zero-termination that is added later */
271b0104773SPascal Brand 		break;
272b0104773SPascal Brand 
273b0104773SPascal Brand 	default:
274ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_FORMAT;
275ba675d69SCedric Chaumont 		goto out;
276ff857a3aSPascal Brand 	}
277ba675d69SCedric Chaumont 
278ff857a3aSPascal Brand 	l++;	/* include zero termination */
279ff857a3aSPascal Brand 
2800dd3f3a4SPascal Brand 	if (l > *value_len)
281ff857a3aSPascal Brand 		res = TEE_ERROR_SHORT_BUFFER;
2820dd3f3a4SPascal Brand 	*value_len = l;
283ff857a3aSPascal Brand 
284ba675d69SCedric Chaumont out:
285ff857a3aSPascal Brand 	if (tmp_buf)
286ff857a3aSPascal Brand 		TEE_Free(tmp_buf);
287ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
288ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
289ff857a3aSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER)
290ff857a3aSPascal Brand 		TEE_Panic(0);
291ff857a3aSPascal Brand 
292ff857a3aSPascal Brand 	return res;
293b0104773SPascal Brand }
294b0104773SPascal Brand 
295b0104773SPascal Brand TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator,
296*8f07fe6fSJerome Forissier 				 const char *name, bool *value)
297b0104773SPascal Brand {
298b0104773SPascal Brand 	TEE_Result res;
299ff857a3aSPascal Brand 	enum user_ta_prop_type type;
300ff857a3aSPascal Brand 	uint32_t uint32_val;
301ff857a3aSPascal Brand 	uint32_t uint32_len = sizeof(uint32_val);
302ba675d69SCedric Chaumont 	if (value == NULL) {
303ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
304ff857a3aSPascal Brand 		goto out;
305ba675d69SCedric Chaumont 	}
306b0104773SPascal Brand 
307ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_BOOL;
308ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
309ff857a3aSPascal Brand 				   &uint32_val, &uint32_len);
310ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_BOOL)
311ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_FORMAT;
312ff857a3aSPascal Brand 	if (res != TEE_SUCCESS)
313ba675d69SCedric Chaumont 		goto out;
314ba675d69SCedric Chaumont 
315ff857a3aSPascal Brand 	*value = !!uint32_val;
316ff857a3aSPascal Brand 
317ba675d69SCedric Chaumont out:
318ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
319ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
320ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT)
321ff857a3aSPascal Brand 		TEE_Panic(0);
322ff857a3aSPascal Brand 
323ff857a3aSPascal Brand 	return res;
324b0104773SPascal Brand }
325b0104773SPascal Brand 
326b0104773SPascal Brand TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator,
327*8f07fe6fSJerome Forissier 				const char *name, uint32_t *value)
328b0104773SPascal Brand {
329b0104773SPascal Brand 	TEE_Result res;
330ff857a3aSPascal Brand 	enum user_ta_prop_type type;
331ff857a3aSPascal Brand 	uint32_t uint32_len = sizeof(uint32_t);
332b0104773SPascal Brand 
3330dd3f3a4SPascal Brand 	if (!value) {
334ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
335ba675d69SCedric Chaumont 		goto out;
336ff857a3aSPascal Brand 	}
337ba675d69SCedric Chaumont 
338ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_U32;
339ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
340ff857a3aSPascal Brand 				   value, &uint32_len);
341ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_U32)
342ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
343ff857a3aSPascal Brand 
344ba675d69SCedric Chaumont out:
345ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
346ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
347ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT)
348ff857a3aSPascal Brand 		TEE_Panic(0);
349ff857a3aSPascal Brand 
350ff857a3aSPascal Brand 	return res;
351b0104773SPascal Brand }
352b0104773SPascal Brand 
353b0104773SPascal Brand TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator,
354*8f07fe6fSJerome Forissier 					const char *name, void *value,
3550dd3f3a4SPascal Brand 					uint32_t *value_len)
356b0104773SPascal Brand {
357b0104773SPascal Brand 	TEE_Result res;
358ff857a3aSPascal Brand 	enum user_ta_prop_type type;
359b0104773SPascal Brand 
3600dd3f3a4SPascal Brand 	if (!value || !value_len) {
361ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
362ba675d69SCedric Chaumont 		goto out;
363ff857a3aSPascal Brand 	}
364ba675d69SCedric Chaumont 
365ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_BINARY_BLOCK;
366ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
3670dd3f3a4SPascal Brand 				   value, value_len);
368ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_BINARY_BLOCK)
369ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
370ff857a3aSPascal Brand 
371ba675d69SCedric Chaumont out:
372ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
373ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
374ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT &&
375ff857a3aSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER)
376ff857a3aSPascal Brand 		TEE_Panic(0);
377ff857a3aSPascal Brand 
378ff857a3aSPascal Brand 	return res;
379b0104773SPascal Brand }
380b0104773SPascal Brand 
381b0104773SPascal Brand TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator,
382*8f07fe6fSJerome Forissier 				 const char *name, TEE_UUID *value)
383b0104773SPascal Brand {
384b0104773SPascal Brand 	TEE_Result res;
385ff857a3aSPascal Brand 	enum user_ta_prop_type type;
386ff857a3aSPascal Brand 	uint32_t uuid_len = sizeof(TEE_UUID);
387b0104773SPascal Brand 
3880dd3f3a4SPascal Brand 	if (!value) {
389ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
390ba675d69SCedric Chaumont 		goto out;
391ff857a3aSPascal Brand 	}
392ba675d69SCedric Chaumont 
393ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_UUID;
394ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
395ff857a3aSPascal Brand 				   value, &uuid_len);
396ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_UUID)
397ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
398ff857a3aSPascal Brand 
399ba675d69SCedric Chaumont out:
400ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
401ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
402ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT)
403ff857a3aSPascal Brand 		TEE_Panic(0);
404ff857a3aSPascal Brand 
405ff857a3aSPascal Brand 	return res;
406b0104773SPascal Brand }
407b0104773SPascal Brand 
408b0104773SPascal Brand TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator,
409*8f07fe6fSJerome Forissier 				     const char *name, TEE_Identity *value)
410b0104773SPascal Brand {
411b0104773SPascal Brand 	TEE_Result res;
412ff857a3aSPascal Brand 	enum user_ta_prop_type type;
413ff857a3aSPascal Brand 	uint32_t identity_len = sizeof(TEE_Identity);
414b0104773SPascal Brand 
4150dd3f3a4SPascal Brand 	if (!value) {
416ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
417ba675d69SCedric Chaumont 		goto out;
418ff857a3aSPascal Brand 	}
419ba675d69SCedric Chaumont 
420ff857a3aSPascal Brand 	type = USER_TA_PROP_TYPE_IDENTITY;
421ff857a3aSPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &type,
422ff857a3aSPascal Brand 				   value, &identity_len);
423ff857a3aSPascal Brand 	if (type != USER_TA_PROP_TYPE_IDENTITY)
424ff857a3aSPascal Brand 		res = TEE_ERROR_BAD_FORMAT;
425ff857a3aSPascal Brand 
426ba675d69SCedric Chaumont out:
427ff857a3aSPascal Brand 	if (res != TEE_SUCCESS &&
428ff857a3aSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
429ff857a3aSPascal Brand 	    res != TEE_ERROR_BAD_FORMAT)
430ff857a3aSPascal Brand 		TEE_Panic(0);
431ff857a3aSPascal Brand 
432ff857a3aSPascal Brand 	return res;
433b0104773SPascal Brand }
434b0104773SPascal Brand 
435b0104773SPascal Brand TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator)
436b0104773SPascal Brand {
437ba675d69SCedric Chaumont 	TEE_Result res;
438b0104773SPascal Brand 	struct prop_enumerator *pe;
439b0104773SPascal Brand 
4400dd3f3a4SPascal Brand 	if (!enumerator) {
441ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
442ba675d69SCedric Chaumont 		goto err;
443ba675d69SCedric Chaumont 	}
444b0104773SPascal Brand 
445b0104773SPascal Brand 	pe = TEE_Malloc(sizeof(struct prop_enumerator),
446b0104773SPascal Brand 			TEE_USER_MEM_HINT_NO_FILL_ZERO);
447ba675d69SCedric Chaumont 	if (pe == NULL) {
448ba675d69SCedric Chaumont 		res = TEE_ERROR_OUT_OF_MEMORY;
449ba675d69SCedric Chaumont 		goto err;
450ba675d69SCedric Chaumont 	}
451b0104773SPascal Brand 
452b0104773SPascal Brand 	*enumerator = (TEE_PropSetHandle) pe;
453b0104773SPascal Brand 	TEE_ResetPropertyEnumerator(*enumerator);
454ba675d69SCedric Chaumont 
455ba675d69SCedric Chaumont 	goto out;
456ba675d69SCedric Chaumont 
457ba675d69SCedric Chaumont err:
458ba675d69SCedric Chaumont 	if (res == TEE_ERROR_OUT_OF_MEMORY)
459ba675d69SCedric Chaumont 		return res;
460ba675d69SCedric Chaumont 	TEE_Panic(0);
461ba675d69SCedric Chaumont out:
462b0104773SPascal Brand 	return TEE_SUCCESS;
463b0104773SPascal Brand }
464b0104773SPascal Brand 
465b0104773SPascal Brand void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator)
466b0104773SPascal Brand {
467b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
468b0104773SPascal Brand 
469b0104773SPascal Brand 	pe->idx = PROP_ENUMERATOR_NOT_STARTED;
470b0104773SPascal Brand }
471b0104773SPascal Brand 
472b0104773SPascal Brand void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator)
473b0104773SPascal Brand {
474b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
475b0104773SPascal Brand 
476b0104773SPascal Brand 	TEE_Free(pe);
477b0104773SPascal Brand }
478b0104773SPascal Brand 
479b0104773SPascal Brand void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator,
480b0104773SPascal Brand 				 TEE_PropSetHandle propSet)
481b0104773SPascal Brand {
482b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
483b0104773SPascal Brand 
4840dd3f3a4SPascal Brand 	if (!pe)
485b0104773SPascal Brand 		return;
486b0104773SPascal Brand 
487b0104773SPascal Brand 	pe->idx = 0;
488b0104773SPascal Brand 	pe->prop_set = propSet;
489b0104773SPascal Brand }
490b0104773SPascal Brand 
491b0104773SPascal Brand TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator,
4920dd3f3a4SPascal Brand 			       void *name, uint32_t *name_len)
493b0104773SPascal Brand {
494b0104773SPascal Brand 	TEE_Result res;
495b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
496b0104773SPascal Brand 	const struct user_ta_property *eps;
497b0104773SPascal Brand 	size_t eps_len;
498b0104773SPascal Brand 	const char *str;
499b0104773SPascal Brand 	size_t bufferlen;
500b0104773SPascal Brand 
5010dd3f3a4SPascal Brand 	if (!pe || !name || !name_len) {
502ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
503ba675d69SCedric Chaumont 		goto err;
504ba675d69SCedric Chaumont 	}
505b0104773SPascal Brand 
5060dd3f3a4SPascal Brand 	bufferlen = *name_len;
50764a5011eSPascal Brand 	res = propset_get(pe->prop_set, &eps, &eps_len);
508b0104773SPascal Brand 	if (res != TEE_SUCCESS)
509ba675d69SCedric Chaumont 		goto err;
510b0104773SPascal Brand 
51164a5011eSPascal Brand 	if (pe->idx < eps_len) {
51264a5011eSPascal Brand 		str = eps[pe->idx].name;
5130dd3f3a4SPascal Brand 		bufferlen = strlcpy(name, str, *name_len) + 1;
5140dd3f3a4SPascal Brand 		if (bufferlen > *name_len)
515ba675d69SCedric Chaumont 			res = TEE_ERROR_SHORT_BUFFER;
5160dd3f3a4SPascal Brand 		*name_len = bufferlen;
51764a5011eSPascal Brand 	} else {
51864a5011eSPascal Brand 		res = utee_get_property((unsigned long)pe->prop_set,
51964a5011eSPascal Brand 					pe->idx - eps_len,
5200dd3f3a4SPascal Brand 					name, name_len, NULL, NULL, NULL);
52164a5011eSPascal Brand 		if (res != TEE_SUCCESS)
522ba675d69SCedric Chaumont 			goto err;
523ba675d69SCedric Chaumont 	}
524b0104773SPascal Brand 
525ba675d69SCedric Chaumont err:
52664a5011eSPascal Brand 	if (res != TEE_SUCCESS &&
52764a5011eSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
52864a5011eSPascal Brand 	    res != TEE_ERROR_SHORT_BUFFER)
529ba675d69SCedric Chaumont 		TEE_Panic(0);
53064a5011eSPascal Brand 	return res;
531b0104773SPascal Brand }
532b0104773SPascal Brand 
533b0104773SPascal Brand TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator)
534b0104773SPascal Brand {
535b0104773SPascal Brand 	TEE_Result res;
536b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
537b0104773SPascal Brand 	uint32_t next_idx;
538b0104773SPascal Brand 	const struct user_ta_property *eps;
539b0104773SPascal Brand 	size_t eps_len;
540b0104773SPascal Brand 
5410dd3f3a4SPascal Brand 	if (!pe) {
542ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
54364a5011eSPascal Brand 		goto out;
544ba675d69SCedric Chaumont 	}
545b0104773SPascal Brand 
546ba675d69SCedric Chaumont 	if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) {
547ba675d69SCedric Chaumont 		res = TEE_ERROR_ITEM_NOT_FOUND;
54864a5011eSPascal Brand 		goto out;
549ba675d69SCedric Chaumont 	}
550b0104773SPascal Brand 
55164a5011eSPascal Brand 	res = propset_get(pe->prop_set, &eps, &eps_len);
552b0104773SPascal Brand 	if (res != TEE_SUCCESS)
55364a5011eSPascal Brand 		goto out;
554b0104773SPascal Brand 
555b0104773SPascal Brand 	next_idx = pe->idx + 1;
556b0104773SPascal Brand 	pe->idx = next_idx;
55764a5011eSPascal Brand 	if (next_idx < eps_len)
55864a5011eSPascal Brand 		res = TEE_SUCCESS;
55964a5011eSPascal Brand 	else
56064a5011eSPascal Brand 		res = utee_get_property((unsigned long)pe->prop_set,
561ff857a3aSPascal Brand 					next_idx - eps_len,
562ff857a3aSPascal Brand 					NULL, NULL, NULL, NULL, NULL);
563b0104773SPascal Brand 
564ba675d69SCedric Chaumont out:
56564a5011eSPascal Brand 	if (res != TEE_SUCCESS &&
56664a5011eSPascal Brand 	    res != TEE_ERROR_ITEM_NOT_FOUND)
56764a5011eSPascal Brand 		TEE_Panic(0);
56864a5011eSPascal Brand 	return res;
569b0104773SPascal Brand }
570