xref: /optee_os/lib/libutee/tee_api_property.c (revision ba675d69487f1725d21cafc4f0d646ce1deb44bb)
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>
32b0104773SPascal Brand #include <tee_api_defines.h>
33b0104773SPascal Brand #include <tee_api_types.h>
34b0104773SPascal Brand #include <user_ta_header.h>
35b0104773SPascal Brand #include <tee_internal_api_extensions.h>
36647f9c76SJerome Forissier #include <tee_arith_internal.h>
37b0104773SPascal Brand 
38b0104773SPascal Brand #include <utee_syscalls.h>
39b0104773SPascal Brand 
40b0104773SPascal Brand #include "string_ext.h"
41b0104773SPascal Brand #include "base64.h"
42b0104773SPascal Brand 
43b0104773SPascal Brand #define PROP_STR_MAX    80
44b0104773SPascal Brand 
45b0104773SPascal Brand #define PROP_ENUMERATOR_NOT_STARTED 0xffffffff
46b0104773SPascal Brand 
47b0104773SPascal Brand struct prop_enumerator {
48b0104773SPascal Brand 	uint32_t idx;
49b0104773SPascal Brand 	TEE_PropSetHandle prop_set;
50b0104773SPascal Brand };
51b0104773SPascal Brand 
52b0104773SPascal Brand struct prop_value {
53b0104773SPascal Brand 	enum user_ta_prop_type type;
54b0104773SPascal Brand 	union {
55b0104773SPascal Brand 		bool bool_val;
56b0104773SPascal Brand 		uint32_t int_val;
57b0104773SPascal Brand 		TEE_UUID uuid_val;
58b0104773SPascal Brand 		TEE_Identity identity_val;
59b0104773SPascal Brand 		char str_val[PROP_STR_MAX];
60b0104773SPascal Brand 	} u;
61b0104773SPascal Brand };
62b0104773SPascal Brand 
63b0104773SPascal Brand typedef TEE_Result(*ta_propget_func_t) (struct prop_value *pv);
64b0104773SPascal Brand 
65b0104773SPascal Brand struct prop_set {
66b0104773SPascal Brand 	const char *str;
67b0104773SPascal Brand 	ta_propget_func_t get;
68b0104773SPascal Brand };
69b0104773SPascal Brand 
70b0104773SPascal Brand static TEE_Result propget_gpd_ta_app_id(struct prop_value *pv)
71b0104773SPascal Brand {
72b0104773SPascal Brand 	pv->type = USER_TA_PROP_TYPE_UUID;
73b0104773SPascal Brand 	return utee_get_property(UTEE_PROP_TA_APP_ID, &pv->u.uuid_val,
74b0104773SPascal Brand 				 sizeof(pv->u.uuid_val));
75b0104773SPascal Brand }
76b0104773SPascal Brand 
77b0104773SPascal Brand static TEE_Result propget_gpd_client_identity(struct prop_value *pv)
78b0104773SPascal Brand {
79b0104773SPascal Brand 	pv->type = USER_TA_PROP_TYPE_IDENTITY;
80b0104773SPascal Brand 	return utee_get_property(UTEE_PROP_CLIENT_ID, &pv->u.identity_val,
81b0104773SPascal Brand 				 sizeof(pv->u.identity_val));
82b0104773SPascal Brand }
83b0104773SPascal Brand 
84b0104773SPascal Brand static TEE_Result propget_gpd_tee_api_version(struct prop_value *pv)
85b0104773SPascal Brand {
86b0104773SPascal Brand 	pv->type = USER_TA_PROP_TYPE_STRING;
87b0104773SPascal Brand 	return utee_get_property(UTEE_PROP_TEE_API_VERSION, &pv->u.str_val,
88b0104773SPascal Brand 				 sizeof(pv->u.str_val));
89b0104773SPascal Brand }
90b0104773SPascal Brand 
91b0104773SPascal Brand static TEE_Result propget_gpd_tee_description(struct prop_value *pv)
92b0104773SPascal Brand {
93b0104773SPascal Brand 	pv->type = USER_TA_PROP_TYPE_STRING;
94b0104773SPascal Brand 	return utee_get_property(UTEE_PROP_TEE_DESCR, &pv->u.str_val,
95b0104773SPascal Brand 				 sizeof(pv->u.str_val));
96b0104773SPascal Brand }
97b0104773SPascal Brand 
98b0104773SPascal Brand static TEE_Result propget_gpd_tee_device_id(struct prop_value *pv)
99b0104773SPascal Brand {
100b0104773SPascal Brand 	pv->type = USER_TA_PROP_TYPE_UUID;
101b0104773SPascal Brand 	return utee_get_property(UTEE_PROP_TEE_DEV_ID, &pv->u.uuid_val,
102b0104773SPascal Brand 				 sizeof(pv->u.uuid_val));
103b0104773SPascal Brand }
104b0104773SPascal Brand 
105b0104773SPascal Brand static TEE_Result propget_gpd_tee_sys_time_protection_level(struct prop_value
106b0104773SPascal Brand 							    *pv)
107b0104773SPascal Brand {
108b0104773SPascal Brand 	pv->type = USER_TA_PROP_TYPE_U32;
109b0104773SPascal Brand 	return utee_get_property(UTEE_PROP_TEE_SYS_TIME_PROT_LEVEL,
110b0104773SPascal Brand 				 &pv->u.int_val, sizeof(pv->u.int_val));
111b0104773SPascal Brand }
112b0104773SPascal Brand 
113b0104773SPascal Brand static TEE_Result propget_gpd_tee_ta_time_protection_level(struct prop_value
114b0104773SPascal Brand 							   *pv)
115b0104773SPascal Brand {
116b0104773SPascal Brand 	pv->type = USER_TA_PROP_TYPE_U32;
117b0104773SPascal Brand 	return utee_get_property(UTEE_PROP_TEE_TA_TIME_PROT_LEVEL,
118b0104773SPascal Brand 				 &pv->u.int_val, sizeof(pv->u.int_val));
119b0104773SPascal Brand }
120b0104773SPascal Brand 
121b0104773SPascal Brand static TEE_Result propget_gpd_tee_arith_max_big_int_size(struct prop_value *pv)
122b0104773SPascal Brand {
123b0104773SPascal Brand 	pv->type = USER_TA_PROP_TYPE_U32;
124647f9c76SJerome Forissier 	pv->u.int_val = TEE_MAX_NUMBER_OF_SUPPORTED_BITS;
125647f9c76SJerome Forissier 	return TEE_SUCCESS;
126b0104773SPascal Brand }
127b0104773SPascal Brand 
128b0104773SPascal Brand static const struct prop_set propset_current_ta[] = {
129b0104773SPascal Brand 	{"gpd.ta.appID", propget_gpd_ta_app_id},
130b0104773SPascal Brand };
131b0104773SPascal Brand 
132b0104773SPascal Brand static const size_t propset_current_ta_len =
133b0104773SPascal Brand 	sizeof(propset_current_ta) / sizeof(propset_current_ta[0]);
134b0104773SPascal Brand 
135b0104773SPascal Brand static const struct prop_set propset_current_client[] = {
136b0104773SPascal Brand 	{"gpd.client.identity", propget_gpd_client_identity},
137b0104773SPascal Brand };
138b0104773SPascal Brand 
139b0104773SPascal Brand static const size_t propset_current_client_len =
140b0104773SPascal Brand 	sizeof(propset_current_client) / sizeof(propset_current_client[0]);
141b0104773SPascal Brand 
142b0104773SPascal Brand static const struct prop_set propset_implementation[] = {
143b0104773SPascal Brand 	{"gpd.tee.apiversion", propget_gpd_tee_api_version},
144b0104773SPascal Brand 	{"gpd.tee.description", propget_gpd_tee_description},
145b0104773SPascal Brand 	{"gpd.tee.deviceID", propget_gpd_tee_device_id},
146b0104773SPascal Brand 	{"gpd.tee.systemTime.protectionLevel",
147b0104773SPascal Brand 	 propget_gpd_tee_sys_time_protection_level},
148b0104773SPascal Brand 	{"gpd.tee.TAPersistentTime.protectionLevel",
149b0104773SPascal Brand 	 propget_gpd_tee_ta_time_protection_level},
150b0104773SPascal Brand 	{"gpd.tee.arith.maxBigIntSize", propget_gpd_tee_arith_max_big_int_size},
151b0104773SPascal Brand };
152b0104773SPascal Brand 
153b0104773SPascal Brand static const size_t propset_implementation_len =
154b0104773SPascal Brand 	sizeof(propset_implementation) / sizeof(propset_implementation[0]);
155b0104773SPascal Brand 
156b0104773SPascal Brand static TEE_Result propset_get(TEE_PropSetHandle h, const struct prop_set **ps,
157b0104773SPascal Brand 			      size_t *ps_len,
158b0104773SPascal Brand 			      const struct user_ta_property **eps,
159b0104773SPascal Brand 			      size_t *eps_len)
160b0104773SPascal Brand {
161b0104773SPascal Brand 	if (h == TEE_PROPSET_CURRENT_TA) {
162b0104773SPascal Brand 		*ps = propset_current_ta;
163b0104773SPascal Brand 		*ps_len = propset_current_ta_len;
164b0104773SPascal Brand 		*eps = ta_props;
165b0104773SPascal Brand 		*eps_len = ta_num_props;
166b0104773SPascal Brand 	} else if (h == TEE_PROPSET_CURRENT_CLIENT) {
167b0104773SPascal Brand 		*ps = propset_current_client;
168b0104773SPascal Brand 		*ps_len = propset_current_client_len;
169b0104773SPascal Brand 		*eps = NULL;
170b0104773SPascal Brand 		*eps_len = 0;
171b0104773SPascal Brand 	} else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) {
172b0104773SPascal Brand 		*ps = propset_implementation;
173b0104773SPascal Brand 		*ps_len = propset_implementation_len;
174b0104773SPascal Brand 		*eps = NULL;
175b0104773SPascal Brand 		*eps_len = 0;
176b0104773SPascal Brand 	} else {
177b0104773SPascal Brand 		return TEE_ERROR_ITEM_NOT_FOUND;
178b0104773SPascal Brand 	}
179b0104773SPascal Brand 
180b0104773SPascal Brand 	return TEE_SUCCESS;
181b0104773SPascal Brand }
182b0104773SPascal Brand 
183b0104773SPascal Brand static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep,
184b0104773SPascal Brand 				       struct prop_value *pv)
185b0104773SPascal Brand {
186b0104773SPascal Brand 	size_t l;
187b0104773SPascal Brand 
188b0104773SPascal Brand 	pv->type = ep->type;
189b0104773SPascal Brand 	switch (ep->type) {
190b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BOOL:
191b0104773SPascal Brand 		l = sizeof(bool);
192b0104773SPascal Brand 		break;
193b0104773SPascal Brand 	case USER_TA_PROP_TYPE_U32:
194b0104773SPascal Brand 		l = sizeof(uint32_t);
195b0104773SPascal Brand 		break;
196b0104773SPascal Brand 	case USER_TA_PROP_TYPE_UUID:
197b0104773SPascal Brand 		l = sizeof(TEE_UUID);
198b0104773SPascal Brand 		break;
199b0104773SPascal Brand 	case USER_TA_PROP_TYPE_IDENTITY:
200b0104773SPascal Brand 		l = sizeof(TEE_Identity);
201b0104773SPascal Brand 		break;
202b0104773SPascal Brand 	case USER_TA_PROP_TYPE_STRING:
203b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
204b0104773SPascal Brand 		/* Handle too large strings by truncating them */
205b0104773SPascal Brand 		strlcpy(pv->u.str_val, ep->value, sizeof(pv->u.str_val));
206b0104773SPascal Brand 		return TEE_SUCCESS;
207b0104773SPascal Brand 	default:
208b0104773SPascal Brand 		return TEE_ERROR_GENERIC;
209b0104773SPascal Brand 	}
210b0104773SPascal Brand 	memcpy(&pv->u, ep->value, l);
211b0104773SPascal Brand 	return TEE_SUCCESS;
212b0104773SPascal Brand }
213b0104773SPascal Brand 
214b0104773SPascal Brand static TEE_Result propget_get_property(TEE_PropSetHandle h, char *name,
215b0104773SPascal Brand 				       struct prop_value *pv)
216b0104773SPascal Brand {
217b0104773SPascal Brand 	TEE_Result res;
218b0104773SPascal Brand 	const struct prop_set *ps;
219b0104773SPascal Brand 	size_t ps_len;
220b0104773SPascal Brand 	const struct user_ta_property *eps;
221b0104773SPascal Brand 	size_t eps_len;
222b0104773SPascal Brand 
223b0104773SPascal Brand 	if (h == TEE_PROPSET_CURRENT_TA || h == TEE_PROPSET_CURRENT_CLIENT ||
224b0104773SPascal Brand 	    h == TEE_PROPSET_TEE_IMPLEMENTATION) {
225b0104773SPascal Brand 		size_t n;
226b0104773SPascal Brand 
227b0104773SPascal Brand 		res = propset_get(h, &ps, &ps_len, &eps, &eps_len);
228b0104773SPascal Brand 		if (res != TEE_SUCCESS)
229b0104773SPascal Brand 			return res;
230b0104773SPascal Brand 
231b0104773SPascal Brand 		for (n = 0; n < ps_len; n++) {
232b0104773SPascal Brand 			if (strcmp(name, ps[n].str) == 0)
233b0104773SPascal Brand 				return ps[n].get(pv);
234b0104773SPascal Brand 		}
235b0104773SPascal Brand 		for (n = 0; n < eps_len; n++) {
236b0104773SPascal Brand 			if (strcmp(name, eps[n].name) == 0)
237b0104773SPascal Brand 				return propget_get_ext_prop(eps + n, pv);
238b0104773SPascal Brand 		}
239b0104773SPascal Brand 		return TEE_ERROR_ITEM_NOT_FOUND;
240b0104773SPascal Brand 	} else {
241b0104773SPascal Brand 		struct prop_enumerator *pe = (struct prop_enumerator *)h;
242b0104773SPascal Brand 		uint32_t idx = pe->idx;
243b0104773SPascal Brand 
244b0104773SPascal Brand 		if (idx == PROP_ENUMERATOR_NOT_STARTED)
245b0104773SPascal Brand 			return TEE_ERROR_ITEM_NOT_FOUND;
246b0104773SPascal Brand 
247b0104773SPascal Brand 		res = propset_get(pe->prop_set, &ps, &ps_len, &eps, &eps_len);
248b0104773SPascal Brand 		if (res != TEE_SUCCESS)
249b0104773SPascal Brand 			return res;
250b0104773SPascal Brand 
251b0104773SPascal Brand 		if (idx < ps_len)
252b0104773SPascal Brand 			return ps[idx].get(pv);
253b0104773SPascal Brand 
254b0104773SPascal Brand 		idx -= ps_len;
255b0104773SPascal Brand 		if (idx < eps_len)
256b0104773SPascal Brand 			return propget_get_ext_prop(eps + idx, pv);
257b0104773SPascal Brand 
258b0104773SPascal Brand 		return TEE_ERROR_BAD_PARAMETERS;
259b0104773SPascal Brand 	}
260b0104773SPascal Brand }
261b0104773SPascal Brand 
262b0104773SPascal Brand TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator,
263b0104773SPascal Brand 				   char *name, char *valueBuffer,
26479a3c601SCedric Chaumont 				   uint32_t *valueBufferLen)
265b0104773SPascal Brand {
266b0104773SPascal Brand 	TEE_Result res;
267b0104773SPascal Brand 	struct prop_value pv;
268b0104773SPascal Brand 	size_t l;
269b0104773SPascal Brand 	size_t bufferlen;
270b0104773SPascal Brand 
271*ba675d69SCedric Chaumont 	if (valueBuffer == NULL || valueBufferLen == NULL) {
272*ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
273*ba675d69SCedric Chaumont 		goto err;
274*ba675d69SCedric Chaumont 	}
275b0104773SPascal Brand 
276b0104773SPascal Brand 	bufferlen = *valueBufferLen;
277b0104773SPascal Brand 
278b0104773SPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &pv);
279b0104773SPascal Brand 	if (res != TEE_SUCCESS)
280*ba675d69SCedric Chaumont 		goto err;
281b0104773SPascal Brand 
282b0104773SPascal Brand 	switch (pv.type) {
283b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BOOL:
284b0104773SPascal Brand 		l = strlcpy(valueBuffer, pv.u.bool_val ? "true" : "false",
285b0104773SPascal Brand 			    bufferlen);
286b0104773SPascal Brand 		break;
287b0104773SPascal Brand 
288b0104773SPascal Brand 	case USER_TA_PROP_TYPE_U32:
289b0104773SPascal Brand 		l = snprintf(valueBuffer, bufferlen, "%u",
290b0104773SPascal Brand 			     (unsigned int)pv.u.int_val);
291b0104773SPascal Brand 		break;
292b0104773SPascal Brand 
293b0104773SPascal Brand 	case USER_TA_PROP_TYPE_UUID:
294b0104773SPascal Brand 		l = snprintf(valueBuffer, bufferlen,
295b0104773SPascal Brand 			     "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x",
296b0104773SPascal Brand 			     (unsigned int)pv.u.uuid_val.timeLow,
297b0104773SPascal Brand 			     pv.u.uuid_val.timeMid,
298b0104773SPascal Brand 			     pv.u.uuid_val.timeHiAndVersion,
299b0104773SPascal Brand 			     pv.u.uuid_val.clockSeqAndNode[0],
300b0104773SPascal Brand 			     pv.u.uuid_val.clockSeqAndNode[1],
301b0104773SPascal Brand 			     pv.u.uuid_val.clockSeqAndNode[2],
302b0104773SPascal Brand 			     pv.u.uuid_val.clockSeqAndNode[3],
303b0104773SPascal Brand 			     pv.u.uuid_val.clockSeqAndNode[4],
304b0104773SPascal Brand 			     pv.u.uuid_val.clockSeqAndNode[5],
305b0104773SPascal Brand 			     pv.u.uuid_val.clockSeqAndNode[6],
306b0104773SPascal Brand 			     pv.u.uuid_val.clockSeqAndNode[7]);
307b0104773SPascal Brand 		break;
308b0104773SPascal Brand 
309b0104773SPascal Brand 	case USER_TA_PROP_TYPE_IDENTITY:
310b0104773SPascal Brand 		l = snprintf(valueBuffer, bufferlen,
311b0104773SPascal Brand 			     "%u:%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x",
312b0104773SPascal Brand 			     (unsigned int)pv.u.identity_val.login,
313b0104773SPascal Brand 			     (unsigned int)pv.u.identity_val.uuid.timeLow,
314b0104773SPascal Brand 			     pv.u.identity_val.uuid.timeMid,
315b0104773SPascal Brand 			     pv.u.identity_val.uuid.timeHiAndVersion,
316b0104773SPascal Brand 			     pv.u.identity_val.uuid.clockSeqAndNode[0],
317b0104773SPascal Brand 			     pv.u.identity_val.uuid.clockSeqAndNode[1],
318b0104773SPascal Brand 			     pv.u.identity_val.uuid.clockSeqAndNode[2],
319b0104773SPascal Brand 			     pv.u.identity_val.uuid.clockSeqAndNode[3],
320b0104773SPascal Brand 			     pv.u.identity_val.uuid.clockSeqAndNode[4],
321b0104773SPascal Brand 			     pv.u.identity_val.uuid.clockSeqAndNode[5],
322b0104773SPascal Brand 			     pv.u.identity_val.uuid.clockSeqAndNode[6],
323b0104773SPascal Brand 			     pv.u.identity_val.uuid.clockSeqAndNode[7]);
324b0104773SPascal Brand 		break;
325b0104773SPascal Brand 
326b0104773SPascal Brand 	case USER_TA_PROP_TYPE_STRING:
327b0104773SPascal Brand 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
328b0104773SPascal Brand 		l = strlcpy(valueBuffer, pv.u.str_val, bufferlen);
329b0104773SPascal Brand 		break;
330b0104773SPascal Brand 
331b0104773SPascal Brand 	default:
332*ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_FORMAT;
333*ba675d69SCedric Chaumont 		goto err;
334b0104773SPascal Brand 	}
335b0104773SPascal Brand 
336b0104773SPascal Brand 	/* The size "must account for the zero terminator" */
337b0104773SPascal Brand 	*valueBufferLen = l + 1;
338b0104773SPascal Brand 
339*ba675d69SCedric Chaumont 	if (l >= bufferlen) {
340*ba675d69SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
341*ba675d69SCedric Chaumont 		goto err;
342*ba675d69SCedric Chaumont 	}
343b0104773SPascal Brand 
344*ba675d69SCedric Chaumont 	goto out;
345*ba675d69SCedric Chaumont 
346*ba675d69SCedric Chaumont err:
347*ba675d69SCedric Chaumont 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
348*ba675d69SCedric Chaumont 	    res == TEE_ERROR_SHORT_BUFFER)
349*ba675d69SCedric Chaumont 		return res;
350*ba675d69SCedric Chaumont 	TEE_Panic(0);
351*ba675d69SCedric Chaumont out:
352b0104773SPascal Brand 	return TEE_SUCCESS;
353b0104773SPascal Brand }
354b0104773SPascal Brand 
355b0104773SPascal Brand TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator,
356b0104773SPascal Brand 				 char *name, bool *value)
357b0104773SPascal Brand {
358b0104773SPascal Brand 	TEE_Result res;
359b0104773SPascal Brand 	struct prop_value pv;
360b0104773SPascal Brand 
361*ba675d69SCedric Chaumont 	if (value == NULL) {
362*ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
363*ba675d69SCedric Chaumont 		goto err;
364*ba675d69SCedric Chaumont 	}
365b0104773SPascal Brand 
366b0104773SPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &pv);
367b0104773SPascal Brand 	if (res != TEE_SUCCESS)
368*ba675d69SCedric Chaumont 		goto err;
369b0104773SPascal Brand 
370*ba675d69SCedric Chaumont 	if (pv.type != USER_TA_PROP_TYPE_BOOL) {
371*ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_FORMAT;
372*ba675d69SCedric Chaumont 		goto err;
373*ba675d69SCedric Chaumont 	}
374b0104773SPascal Brand 
375b0104773SPascal Brand 	*value = pv.u.bool_val;
376*ba675d69SCedric Chaumont 
377*ba675d69SCedric Chaumont 	goto out;
378*ba675d69SCedric Chaumont 
379*ba675d69SCedric Chaumont err:
380*ba675d69SCedric Chaumont 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
381*ba675d69SCedric Chaumont 	    res == TEE_ERROR_BAD_FORMAT)
382*ba675d69SCedric Chaumont 		return res;
383*ba675d69SCedric Chaumont 	TEE_Panic(0);
384*ba675d69SCedric Chaumont out:
385b0104773SPascal Brand 	return TEE_SUCCESS;
386b0104773SPascal Brand }
387b0104773SPascal Brand 
388b0104773SPascal Brand TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator,
389b0104773SPascal Brand 				char *name, uint32_t *value)
390b0104773SPascal Brand {
391b0104773SPascal Brand 	TEE_Result res;
392b0104773SPascal Brand 	struct prop_value pv;
393b0104773SPascal Brand 
394*ba675d69SCedric Chaumont 	if (value == NULL) {
395*ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
396*ba675d69SCedric Chaumont 		goto err;
397*ba675d69SCedric Chaumont 	}
398b0104773SPascal Brand 
399b0104773SPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &pv);
400b0104773SPascal Brand 	if (res != TEE_SUCCESS)
401*ba675d69SCedric Chaumont 		goto err;
402b0104773SPascal Brand 
403*ba675d69SCedric Chaumont 	if (pv.type != USER_TA_PROP_TYPE_U32) {
404*ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_FORMAT;
405*ba675d69SCedric Chaumont 		goto err;
406*ba675d69SCedric Chaumont 	}
407b0104773SPascal Brand 
408b0104773SPascal Brand 	*value = pv.u.int_val;
409*ba675d69SCedric Chaumont 
410*ba675d69SCedric Chaumont 	goto out;
411*ba675d69SCedric Chaumont 
412*ba675d69SCedric Chaumont err:
413*ba675d69SCedric Chaumont 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
414*ba675d69SCedric Chaumont 	    res == TEE_ERROR_BAD_FORMAT)
415*ba675d69SCedric Chaumont 		return res;
416*ba675d69SCedric Chaumont 	TEE_Panic(0);
417*ba675d69SCedric Chaumont out:
418b0104773SPascal Brand 	return TEE_SUCCESS;
419b0104773SPascal Brand }
420b0104773SPascal Brand 
421b0104773SPascal Brand TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator,
422b0104773SPascal Brand 					char *name, void *valueBuffer,
42379a3c601SCedric Chaumont 					uint32_t *valueBufferLen)
424b0104773SPascal Brand {
425b0104773SPascal Brand 	TEE_Result res;
426b0104773SPascal Brand 	struct prop_value pv;
427b0104773SPascal Brand 	void *val;
428b0104773SPascal Brand 	int val_len;
4297f74c64aSPascal Brand 	size_t size;
430b0104773SPascal Brand 
431*ba675d69SCedric Chaumont 	if (valueBuffer == NULL || valueBufferLen == NULL) {
432*ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
433*ba675d69SCedric Chaumont 		goto err;
434*ba675d69SCedric Chaumont 	}
435b0104773SPascal Brand 
436b0104773SPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &pv);
437b0104773SPascal Brand 	if (res != TEE_SUCCESS)
438*ba675d69SCedric Chaumont 		goto err;
439b0104773SPascal Brand 
440*ba675d69SCedric Chaumont 	if (pv.type != USER_TA_PROP_TYPE_BINARY_BLOCK) {
441*ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_FORMAT;
442*ba675d69SCedric Chaumont 		goto err;
443*ba675d69SCedric Chaumont 	}
444b0104773SPascal Brand 
445b0104773SPascal Brand 	val = pv.u.str_val;
446b0104773SPascal Brand 	val_len = strlen(val);
4477f74c64aSPascal Brand 	size = *valueBufferLen;
448*ba675d69SCedric Chaumont 	if (!base64_dec(val, val_len, valueBuffer, &size)) {
4497f74c64aSPascal Brand 		res = TEE_ERROR_SHORT_BUFFER;
450*ba675d69SCedric Chaumont 		goto err;
451*ba675d69SCedric Chaumont 	}
452*ba675d69SCedric Chaumont 
4537f74c64aSPascal Brand 	*valueBufferLen = size;
454*ba675d69SCedric Chaumont 
455*ba675d69SCedric Chaumont 	goto out;
456*ba675d69SCedric Chaumont 
457*ba675d69SCedric Chaumont err:
458*ba675d69SCedric Chaumont 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
459*ba675d69SCedric Chaumont 	    res == TEE_ERROR_BAD_FORMAT ||
460*ba675d69SCedric Chaumont 	    res == TEE_ERROR_SHORT_BUFFER)
4617f74c64aSPascal Brand 		return res;
462*ba675d69SCedric Chaumont 	TEE_Panic(0);
463*ba675d69SCedric Chaumont out:
464*ba675d69SCedric Chaumont 	return TEE_SUCCESS;
465b0104773SPascal Brand }
466b0104773SPascal Brand 
467b0104773SPascal Brand TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator,
468b0104773SPascal Brand 				 char *name, TEE_UUID *value)
469b0104773SPascal Brand {
470b0104773SPascal Brand 	TEE_Result res;
471b0104773SPascal Brand 	struct prop_value pv;
472b0104773SPascal Brand 
473*ba675d69SCedric Chaumont 	if (value == NULL) {
474*ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
475*ba675d69SCedric Chaumont 		goto err;
476*ba675d69SCedric Chaumont 	}
477b0104773SPascal Brand 
478b0104773SPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &pv);
479b0104773SPascal Brand 	if (res != TEE_SUCCESS)
480*ba675d69SCedric Chaumont 		goto err;
481b0104773SPascal Brand 
482*ba675d69SCedric Chaumont 	if (pv.type != USER_TA_PROP_TYPE_UUID) {
483*ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_FORMAT;
484*ba675d69SCedric Chaumont 		goto err;
485*ba675d69SCedric Chaumont 	}
486b0104773SPascal Brand 
487b0104773SPascal Brand 	*value = pv.u.uuid_val;	/* struct copy */
488*ba675d69SCedric Chaumont 
489*ba675d69SCedric Chaumont 	goto out;
490*ba675d69SCedric Chaumont 
491*ba675d69SCedric Chaumont err:
492*ba675d69SCedric Chaumont 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
493*ba675d69SCedric Chaumont 	    res == TEE_ERROR_BAD_FORMAT)
494*ba675d69SCedric Chaumont 		return res;
495*ba675d69SCedric Chaumont 	TEE_Panic(0);
496*ba675d69SCedric Chaumont out:
497b0104773SPascal Brand 	return TEE_SUCCESS;
498b0104773SPascal Brand }
499b0104773SPascal Brand 
500b0104773SPascal Brand TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator,
501b0104773SPascal Brand 				     char *name, TEE_Identity *value)
502b0104773SPascal Brand {
503b0104773SPascal Brand 	TEE_Result res;
504b0104773SPascal Brand 	struct prop_value pv;
505b0104773SPascal Brand 
506*ba675d69SCedric Chaumont 	if (value == NULL) {
507*ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
508*ba675d69SCedric Chaumont 		goto err;
509*ba675d69SCedric Chaumont 	}
510b0104773SPascal Brand 
511b0104773SPascal Brand 	res = propget_get_property(propsetOrEnumerator, name, &pv);
512b0104773SPascal Brand 	if (res != TEE_SUCCESS)
513*ba675d69SCedric Chaumont 		goto err;
514b0104773SPascal Brand 
515*ba675d69SCedric Chaumont 	if (pv.type != USER_TA_PROP_TYPE_IDENTITY) {
516*ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_FORMAT;
517*ba675d69SCedric Chaumont 		goto err;
518*ba675d69SCedric Chaumont 	}
519b0104773SPascal Brand 
520b0104773SPascal Brand 	*value = pv.u.identity_val;	/* struct copy */
521*ba675d69SCedric Chaumont 
522*ba675d69SCedric Chaumont 	goto out;
523*ba675d69SCedric Chaumont 
524*ba675d69SCedric Chaumont err:
525*ba675d69SCedric Chaumont 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
526*ba675d69SCedric Chaumont 	    res == TEE_ERROR_BAD_FORMAT)
527*ba675d69SCedric Chaumont 		return res;
528*ba675d69SCedric Chaumont 	TEE_Panic(0);
529*ba675d69SCedric Chaumont out:
530b0104773SPascal Brand 	return TEE_SUCCESS;
531b0104773SPascal Brand }
532b0104773SPascal Brand 
533b0104773SPascal Brand TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator)
534b0104773SPascal Brand {
535*ba675d69SCedric Chaumont 	TEE_Result res;
536b0104773SPascal Brand 	struct prop_enumerator *pe;
537b0104773SPascal Brand 
538*ba675d69SCedric Chaumont 	if (enumerator == NULL) {
539*ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
540*ba675d69SCedric Chaumont 		goto err;
541*ba675d69SCedric Chaumont 	}
542b0104773SPascal Brand 
543b0104773SPascal Brand 	pe = TEE_Malloc(sizeof(struct prop_enumerator),
544b0104773SPascal Brand 			TEE_USER_MEM_HINT_NO_FILL_ZERO);
545*ba675d69SCedric Chaumont 	if (pe == NULL) {
546*ba675d69SCedric Chaumont 		res = TEE_ERROR_OUT_OF_MEMORY;
547*ba675d69SCedric Chaumont 		goto err;
548*ba675d69SCedric Chaumont 	}
549b0104773SPascal Brand 
550b0104773SPascal Brand 	*enumerator = (TEE_PropSetHandle) pe;
551b0104773SPascal Brand 	TEE_ResetPropertyEnumerator(*enumerator);
552*ba675d69SCedric Chaumont 
553*ba675d69SCedric Chaumont 	goto out;
554*ba675d69SCedric Chaumont 
555*ba675d69SCedric Chaumont err:
556*ba675d69SCedric Chaumont 	if (res == TEE_ERROR_OUT_OF_MEMORY)
557*ba675d69SCedric Chaumont 		return res;
558*ba675d69SCedric Chaumont 	TEE_Panic(0);
559*ba675d69SCedric Chaumont out:
560b0104773SPascal Brand 	return TEE_SUCCESS;
561b0104773SPascal Brand }
562b0104773SPascal Brand 
563b0104773SPascal Brand void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator)
564b0104773SPascal Brand {
565b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
566b0104773SPascal Brand 
567b0104773SPascal Brand 	pe->idx = PROP_ENUMERATOR_NOT_STARTED;
568b0104773SPascal Brand }
569b0104773SPascal Brand 
570b0104773SPascal Brand void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator)
571b0104773SPascal Brand {
572b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
573b0104773SPascal Brand 
574b0104773SPascal Brand 	TEE_Free(pe);
575b0104773SPascal Brand }
576b0104773SPascal Brand 
577b0104773SPascal Brand void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator,
578b0104773SPascal Brand 				 TEE_PropSetHandle propSet)
579b0104773SPascal Brand {
580b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
581b0104773SPascal Brand 
582b0104773SPascal Brand 	if (pe == NULL)
583b0104773SPascal Brand 		return;
584b0104773SPascal Brand 
585b0104773SPascal Brand 	pe->idx = 0;
586b0104773SPascal Brand 	pe->prop_set = propSet;
587b0104773SPascal Brand }
588b0104773SPascal Brand 
589b0104773SPascal Brand TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator,
59079a3c601SCedric Chaumont 			       void *nameBuffer, uint32_t *nameBufferLen)
591b0104773SPascal Brand {
592b0104773SPascal Brand 	TEE_Result res;
593b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
594b0104773SPascal Brand 	const struct prop_set *ps;
595b0104773SPascal Brand 	size_t ps_len;
596b0104773SPascal Brand 	const struct user_ta_property *eps;
597b0104773SPascal Brand 	size_t eps_len;
598b0104773SPascal Brand 	size_t l;
599b0104773SPascal Brand 	const char *str;
600b0104773SPascal Brand 	size_t bufferlen;
601b0104773SPascal Brand 
602*ba675d69SCedric Chaumont 	if (pe == NULL || nameBuffer == NULL || nameBufferLen == NULL) {
603*ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
604*ba675d69SCedric Chaumont 		goto err;
605*ba675d69SCedric Chaumont 	}
606b0104773SPascal Brand 
607b0104773SPascal Brand 	bufferlen = *nameBufferLen;
608b0104773SPascal Brand 	res = propset_get(pe->prop_set, &ps, &ps_len, &eps, &eps_len);
609b0104773SPascal Brand 	if (res != TEE_SUCCESS)
610*ba675d69SCedric Chaumont 		goto err;
611b0104773SPascal Brand 
612b0104773SPascal Brand 	if (pe->idx < ps_len)
613b0104773SPascal Brand 		str = ps[pe->idx].str;
614b0104773SPascal Brand 	else if ((pe->idx - ps_len) < eps_len)
615b0104773SPascal Brand 		str = ta_props[pe->idx - ps_len].name;
616*ba675d69SCedric Chaumont 	else {
617*ba675d69SCedric Chaumont 		res = TEE_ERROR_ITEM_NOT_FOUND;
618*ba675d69SCedric Chaumont 		goto err;
619*ba675d69SCedric Chaumont 	}
620b0104773SPascal Brand 
621b0104773SPascal Brand 	l = strlcpy(nameBuffer, str, bufferlen);
622b0104773SPascal Brand 
623b0104773SPascal Brand 	/* The size "must account for the zero terminator" */
624b0104773SPascal Brand 	*nameBufferLen = l + 1;
625b0104773SPascal Brand 
626*ba675d69SCedric Chaumont 	if (l >= bufferlen) {
627*ba675d69SCedric Chaumont 		res = TEE_ERROR_SHORT_BUFFER;
628*ba675d69SCedric Chaumont 		goto err;
629*ba675d69SCedric Chaumont 	}
630b0104773SPascal Brand 
631*ba675d69SCedric Chaumont 	goto out;
632*ba675d69SCedric Chaumont 
633*ba675d69SCedric Chaumont err:
634*ba675d69SCedric Chaumont 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
635*ba675d69SCedric Chaumont 	    res == TEE_ERROR_SHORT_BUFFER)
636*ba675d69SCedric Chaumont 		return res;
637*ba675d69SCedric Chaumont 	TEE_Panic(0);
638*ba675d69SCedric Chaumont out:
639b0104773SPascal Brand 	return TEE_SUCCESS;
640b0104773SPascal Brand }
641b0104773SPascal Brand 
642b0104773SPascal Brand TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator)
643b0104773SPascal Brand {
644b0104773SPascal Brand 	TEE_Result res;
645b0104773SPascal Brand 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
646b0104773SPascal Brand 	uint32_t next_idx;
647b0104773SPascal Brand 	const struct prop_set *ps;
648b0104773SPascal Brand 	size_t ps_len;
649b0104773SPascal Brand 	const struct user_ta_property *eps;
650b0104773SPascal Brand 	size_t eps_len;
651b0104773SPascal Brand 
652*ba675d69SCedric Chaumont 	if (pe == NULL) {
653*ba675d69SCedric Chaumont 		res = TEE_ERROR_BAD_PARAMETERS;
654*ba675d69SCedric Chaumont 		goto err;
655*ba675d69SCedric Chaumont 	}
656b0104773SPascal Brand 
657*ba675d69SCedric Chaumont 	if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) {
658*ba675d69SCedric Chaumont 		res = TEE_ERROR_ITEM_NOT_FOUND;
659*ba675d69SCedric Chaumont 		goto err;
660*ba675d69SCedric Chaumont 	}
661b0104773SPascal Brand 
662b0104773SPascal Brand 	res = propset_get(pe->prop_set, &ps, &ps_len, &eps, &eps_len);
663b0104773SPascal Brand 	if (res != TEE_SUCCESS)
664*ba675d69SCedric Chaumont 		goto err;
665b0104773SPascal Brand 
666b0104773SPascal Brand 	next_idx = pe->idx + 1;
667b0104773SPascal Brand 	pe->idx = next_idx;
668*ba675d69SCedric Chaumont 	if (next_idx >= (ps_len + eps_len)) {
669*ba675d69SCedric Chaumont 		res = TEE_ERROR_ITEM_NOT_FOUND;
670*ba675d69SCedric Chaumont 		goto err;
671*ba675d69SCedric Chaumont 	}
672b0104773SPascal Brand 
673*ba675d69SCedric Chaumont 	goto out;
674*ba675d69SCedric Chaumont 
675*ba675d69SCedric Chaumont err:
676*ba675d69SCedric Chaumont 	if (res == TEE_ERROR_ITEM_NOT_FOUND)
677*ba675d69SCedric Chaumont 		return res;
678*ba675d69SCedric Chaumont 	TEE_Panic(0);
679*ba675d69SCedric Chaumont out:
680b0104773SPascal Brand 	return TEE_SUCCESS;
681b0104773SPascal Brand }
682