xref: /optee_os/lib/libutee/tee_api_property.c (revision 64a5011e3774c8664fefc6dff966d0096cdd56d7)
1 /*
2  * Copyright (c) 2014, STMicroelectronics International N.V.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 #include <tee_api.h>
28 
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <tee_api_defines.h>
33 #include <tee_api_types.h>
34 #include <user_ta_header.h>
35 #include <tee_internal_api_extensions.h>
36 #include <tee_arith_internal.h>
37 #include <util.h>
38 #include <utee_syscalls.h>
39 
40 #include "string_ext.h"
41 #include "base64.h"
42 
43 #define PROP_STR_MAX    80
44 
45 #define PROP_ENUMERATOR_NOT_STARTED 0xffffffff
46 
47 struct prop_enumerator {
48 	uint32_t idx;			/* current index */
49 	TEE_PropSetHandle prop_set;	/* part of TEE_PROPSET_xxx */
50 };
51 
52 struct prop_value {
53 	enum user_ta_prop_type type;
54 	union {
55 		uint32_t bool_val;
56 		uint32_t int_val;
57 		TEE_UUID uuid_val;
58 		TEE_Identity identity_val;
59 		char str_val[PROP_STR_MAX];
60 	} u;
61 };
62 
63 const struct user_ta_property tee_props[] = {
64 	{
65 		"gpd.tee.arith.maxBigIntSize",
66 		USER_TA_PROP_TYPE_U32,
67 		&(const uint32_t){TEE_MAX_NUMBER_OF_SUPPORTED_BITS}
68 	},
69 };
70 
71 static TEE_Result propset_get(TEE_PropSetHandle h,
72 			      const struct user_ta_property **eps,
73 			      size_t *eps_len)
74 {
75 	if (h == TEE_PROPSET_CURRENT_TA) {
76 		*eps = ta_props;
77 		*eps_len = ta_num_props;
78 	} else if (h == TEE_PROPSET_CURRENT_CLIENT) {
79 		*eps = NULL;
80 		*eps_len = 0;
81 	} else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) {
82 		*eps = tee_props;
83 		*eps_len = ARRAY_SIZE(tee_props);
84 	} else {
85 		return TEE_ERROR_ITEM_NOT_FOUND;
86 	}
87 
88 	return TEE_SUCCESS;
89 }
90 
91 static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep,
92 				       struct prop_value *pv)
93 {
94 	size_t l;
95 
96 	pv->type = ep->type;
97 	switch (ep->type) {
98 	case USER_TA_PROP_TYPE_BOOL:
99 		l = sizeof(uint32_t);
100 		break;
101 	case USER_TA_PROP_TYPE_U32:
102 		l = sizeof(uint32_t);
103 		break;
104 	case USER_TA_PROP_TYPE_UUID:
105 		l = sizeof(TEE_UUID);
106 		break;
107 	case USER_TA_PROP_TYPE_IDENTITY:
108 		l = sizeof(TEE_Identity);
109 		break;
110 	case USER_TA_PROP_TYPE_STRING:
111 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
112 		/* Handle too large strings by truncating them */
113 		strlcpy(pv->u.str_val, ep->value, sizeof(pv->u.str_val));
114 		return TEE_SUCCESS;
115 	default:
116 		return TEE_ERROR_GENERIC;
117 	}
118 	memcpy(&pv->u, ep->value, l);
119 	return TEE_SUCCESS;
120 }
121 
122 static TEE_Result propget_get_property(TEE_PropSetHandle h, char *name,
123 				       struct prop_value *pv)
124 {
125 	TEE_Result res;
126 	const struct user_ta_property *eps;
127 	size_t eps_len;
128 	uint32_t prop_type;
129 	uint32_t index;
130 	uint32_t size;
131 
132 	if (h == TEE_PROPSET_CURRENT_TA || h == TEE_PROPSET_CURRENT_CLIENT ||
133 	    h == TEE_PROPSET_TEE_IMPLEMENTATION) {
134 		size_t n;
135 
136 		res = propset_get(h, &eps, &eps_len);
137 		if (res != TEE_SUCCESS)
138 			return res;
139 
140 		for (n = 0; n < eps_len; n++) {
141 			if (!strcmp(name, eps[n].name))
142 				return propget_get_ext_prop(eps + n, pv);
143 		}
144 
145 		/* get the index from the name */
146 		res = utee_get_property_name_to_index((unsigned long)h, name,
147 						strlen(name) + 1, &index);
148 		if (res != TEE_SUCCESS)
149 			return res;
150 		size = sizeof(pv->u);
151 		res = utee_get_property((unsigned long)h, index, 0, 0,
152 					&pv->u, &size, &prop_type);
153 	} else {
154 		struct prop_enumerator *pe = (struct prop_enumerator *)h;
155 		uint32_t idx = pe->idx;
156 
157 		if (idx == PROP_ENUMERATOR_NOT_STARTED)
158 			return TEE_ERROR_ITEM_NOT_FOUND;
159 
160 		res = propset_get(pe->prop_set, &eps, &eps_len);
161 		if (res != TEE_SUCCESS)
162 			return res;
163 
164 		if (idx < eps_len)
165 			return propget_get_ext_prop(eps + idx, pv);
166 		idx -= eps_len;
167 
168 		size = sizeof(pv->u);
169 		res = utee_get_property((unsigned long)pe->prop_set, idx,
170 					0, 0, &pv->u, &size, &prop_type);
171 		if (res == TEE_ERROR_ITEM_NOT_FOUND)
172 			res = TEE_ERROR_BAD_PARAMETERS;
173 	}
174 
175 	if (res == TEE_SUCCESS)
176 		pv->type = prop_type;
177 	return res;
178 }
179 
180 TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator,
181 				   char *name, char *valueBuffer,
182 				   uint32_t *valueBufferLen)
183 {
184 	TEE_Result res;
185 	struct prop_value pv;
186 	size_t l;
187 	size_t bufferlen;
188 
189 	if (valueBuffer == NULL || valueBufferLen == NULL) {
190 		res = TEE_ERROR_BAD_PARAMETERS;
191 		goto err;
192 	}
193 
194 	bufferlen = *valueBufferLen;
195 
196 	res = propget_get_property(propsetOrEnumerator, name, &pv);
197 	if (res != TEE_SUCCESS)
198 		goto err;
199 
200 	switch (pv.type) {
201 	case USER_TA_PROP_TYPE_BOOL:
202 		l = strlcpy(valueBuffer, pv.u.bool_val ? "true" : "false",
203 			    bufferlen);
204 		break;
205 
206 	case USER_TA_PROP_TYPE_U32:
207 		l = snprintf(valueBuffer, bufferlen, "%u",
208 			     (unsigned int)pv.u.int_val);
209 		break;
210 
211 	case USER_TA_PROP_TYPE_UUID:
212 		l = snprintf(valueBuffer, bufferlen,
213 			     "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x",
214 			     (unsigned int)pv.u.uuid_val.timeLow,
215 			     pv.u.uuid_val.timeMid,
216 			     pv.u.uuid_val.timeHiAndVersion,
217 			     pv.u.uuid_val.clockSeqAndNode[0],
218 			     pv.u.uuid_val.clockSeqAndNode[1],
219 			     pv.u.uuid_val.clockSeqAndNode[2],
220 			     pv.u.uuid_val.clockSeqAndNode[3],
221 			     pv.u.uuid_val.clockSeqAndNode[4],
222 			     pv.u.uuid_val.clockSeqAndNode[5],
223 			     pv.u.uuid_val.clockSeqAndNode[6],
224 			     pv.u.uuid_val.clockSeqAndNode[7]);
225 		break;
226 
227 	case USER_TA_PROP_TYPE_IDENTITY:
228 		l = snprintf(valueBuffer, bufferlen,
229 			     "%u:%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x",
230 			     (unsigned int)pv.u.identity_val.login,
231 			     (unsigned int)pv.u.identity_val.uuid.timeLow,
232 			     pv.u.identity_val.uuid.timeMid,
233 			     pv.u.identity_val.uuid.timeHiAndVersion,
234 			     pv.u.identity_val.uuid.clockSeqAndNode[0],
235 			     pv.u.identity_val.uuid.clockSeqAndNode[1],
236 			     pv.u.identity_val.uuid.clockSeqAndNode[2],
237 			     pv.u.identity_val.uuid.clockSeqAndNode[3],
238 			     pv.u.identity_val.uuid.clockSeqAndNode[4],
239 			     pv.u.identity_val.uuid.clockSeqAndNode[5],
240 			     pv.u.identity_val.uuid.clockSeqAndNode[6],
241 			     pv.u.identity_val.uuid.clockSeqAndNode[7]);
242 		break;
243 
244 	case USER_TA_PROP_TYPE_STRING:
245 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
246 		l = strlcpy(valueBuffer, pv.u.str_val, bufferlen);
247 		break;
248 
249 	default:
250 		res = TEE_ERROR_BAD_FORMAT;
251 		goto err;
252 	}
253 
254 	/* The size "must account for the zero terminator" */
255 	*valueBufferLen = l + 1;
256 
257 	if (l >= bufferlen) {
258 		res = TEE_ERROR_SHORT_BUFFER;
259 		goto err;
260 	}
261 
262 	goto out;
263 
264 err:
265 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
266 	    res == TEE_ERROR_SHORT_BUFFER)
267 		return res;
268 	TEE_Panic(0);
269 out:
270 	return TEE_SUCCESS;
271 }
272 
273 TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator,
274 				 char *name, bool *value)
275 {
276 	TEE_Result res;
277 	struct prop_value pv;
278 
279 	if (value == NULL) {
280 		res = TEE_ERROR_BAD_PARAMETERS;
281 		goto err;
282 	}
283 
284 	res = propget_get_property(propsetOrEnumerator, name, &pv);
285 	if (res != TEE_SUCCESS)
286 		goto err;
287 
288 	if (pv.type != USER_TA_PROP_TYPE_BOOL) {
289 		res = TEE_ERROR_BAD_FORMAT;
290 		goto err;
291 	}
292 
293 	*value = !!pv.u.bool_val;
294 
295 	goto out;
296 
297 err:
298 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
299 	    res == TEE_ERROR_BAD_FORMAT)
300 		return res;
301 	TEE_Panic(0);
302 out:
303 	return TEE_SUCCESS;
304 }
305 
306 TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator,
307 				char *name, uint32_t *value)
308 {
309 	TEE_Result res;
310 	struct prop_value pv;
311 
312 	if (value == NULL) {
313 		res = TEE_ERROR_BAD_PARAMETERS;
314 		goto err;
315 	}
316 
317 	res = propget_get_property(propsetOrEnumerator, name, &pv);
318 	if (res != TEE_SUCCESS)
319 		goto err;
320 
321 	if (pv.type != USER_TA_PROP_TYPE_U32) {
322 		res = TEE_ERROR_BAD_FORMAT;
323 		goto err;
324 	}
325 
326 	*value = pv.u.int_val;
327 
328 	goto out;
329 
330 err:
331 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
332 	    res == TEE_ERROR_BAD_FORMAT)
333 		return res;
334 	TEE_Panic(0);
335 out:
336 	return TEE_SUCCESS;
337 }
338 
339 TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator,
340 					char *name, void *valueBuffer,
341 					uint32_t *valueBufferLen)
342 {
343 	TEE_Result res;
344 	struct prop_value pv;
345 	void *val;
346 	int val_len;
347 	size_t size;
348 
349 	if (valueBuffer == NULL || valueBufferLen == NULL) {
350 		res = TEE_ERROR_BAD_PARAMETERS;
351 		goto err;
352 	}
353 
354 	res = propget_get_property(propsetOrEnumerator, name, &pv);
355 	if (res != TEE_SUCCESS)
356 		goto err;
357 
358 	if (pv.type != USER_TA_PROP_TYPE_BINARY_BLOCK) {
359 		res = TEE_ERROR_BAD_FORMAT;
360 		goto err;
361 	}
362 
363 	val = pv.u.str_val;
364 	val_len = strlen(val);
365 	size = *valueBufferLen;
366 	if (!base64_dec(val, val_len, valueBuffer, &size)) {
367 		res = TEE_ERROR_SHORT_BUFFER;
368 		goto err;
369 	}
370 
371 	*valueBufferLen = size;
372 
373 	goto out;
374 
375 err:
376 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
377 	    res == TEE_ERROR_BAD_FORMAT ||
378 	    res == TEE_ERROR_SHORT_BUFFER)
379 		return res;
380 	TEE_Panic(0);
381 out:
382 	return TEE_SUCCESS;
383 }
384 
385 TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator,
386 				 char *name, TEE_UUID *value)
387 {
388 	TEE_Result res;
389 	struct prop_value pv;
390 
391 	if (value == NULL) {
392 		res = TEE_ERROR_BAD_PARAMETERS;
393 		goto err;
394 	}
395 
396 	res = propget_get_property(propsetOrEnumerator, name, &pv);
397 	if (res != TEE_SUCCESS)
398 		goto err;
399 
400 	if (pv.type != USER_TA_PROP_TYPE_UUID) {
401 		res = TEE_ERROR_BAD_FORMAT;
402 		goto err;
403 	}
404 
405 	*value = pv.u.uuid_val;	/* struct copy */
406 
407 	goto out;
408 
409 err:
410 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
411 	    res == TEE_ERROR_BAD_FORMAT)
412 		return res;
413 	TEE_Panic(0);
414 out:
415 	return TEE_SUCCESS;
416 }
417 
418 TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator,
419 				     char *name, TEE_Identity *value)
420 {
421 	TEE_Result res;
422 	struct prop_value pv;
423 
424 	if (value == NULL) {
425 		res = TEE_ERROR_BAD_PARAMETERS;
426 		goto err;
427 	}
428 
429 	res = propget_get_property(propsetOrEnumerator, name, &pv);
430 	if (res != TEE_SUCCESS)
431 		goto err;
432 
433 	if (pv.type != USER_TA_PROP_TYPE_IDENTITY) {
434 		res = TEE_ERROR_BAD_FORMAT;
435 		goto err;
436 	}
437 
438 	*value = pv.u.identity_val;	/* struct copy */
439 
440 	goto out;
441 
442 err:
443 	if (res == TEE_ERROR_ITEM_NOT_FOUND ||
444 	    res == TEE_ERROR_BAD_FORMAT)
445 		return res;
446 	TEE_Panic(0);
447 out:
448 	return TEE_SUCCESS;
449 }
450 
451 TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator)
452 {
453 	TEE_Result res;
454 	struct prop_enumerator *pe;
455 
456 	if (enumerator == NULL) {
457 		res = TEE_ERROR_BAD_PARAMETERS;
458 		goto err;
459 	}
460 
461 	pe = TEE_Malloc(sizeof(struct prop_enumerator),
462 			TEE_USER_MEM_HINT_NO_FILL_ZERO);
463 	if (pe == NULL) {
464 		res = TEE_ERROR_OUT_OF_MEMORY;
465 		goto err;
466 	}
467 
468 	*enumerator = (TEE_PropSetHandle) pe;
469 	TEE_ResetPropertyEnumerator(*enumerator);
470 
471 	goto out;
472 
473 err:
474 	if (res == TEE_ERROR_OUT_OF_MEMORY)
475 		return res;
476 	TEE_Panic(0);
477 out:
478 	return TEE_SUCCESS;
479 }
480 
481 void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator)
482 {
483 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
484 
485 	pe->idx = PROP_ENUMERATOR_NOT_STARTED;
486 }
487 
488 void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator)
489 {
490 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
491 
492 	TEE_Free(pe);
493 }
494 
495 void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator,
496 				 TEE_PropSetHandle propSet)
497 {
498 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
499 
500 	if (pe == NULL)
501 		return;
502 
503 	pe->idx = 0;
504 	pe->prop_set = propSet;
505 }
506 
507 TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator,
508 			       void *nameBuffer, uint32_t *nameBufferLen)
509 {
510 	TEE_Result res;
511 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
512 	const struct user_ta_property *eps;
513 	size_t eps_len;
514 	const char *str;
515 	size_t bufferlen;
516 
517 	if (pe == NULL || nameBuffer == NULL || nameBufferLen == NULL) {
518 		res = TEE_ERROR_BAD_PARAMETERS;
519 		goto err;
520 	}
521 
522 	bufferlen = *nameBufferLen;
523 	res = propset_get(pe->prop_set, &eps, &eps_len);
524 	if (res != TEE_SUCCESS)
525 		goto err;
526 
527 	if (pe->idx < eps_len) {
528 		str = eps[pe->idx].name;
529 		bufferlen = strlcpy(nameBuffer, str, *nameBufferLen);
530 		if (bufferlen >= *nameBufferLen)
531 			res = TEE_ERROR_SHORT_BUFFER;
532 		*nameBufferLen = bufferlen;
533 	} else {
534 		res = utee_get_property((unsigned long)pe->prop_set,
535 					pe->idx - eps_len,
536 					nameBuffer, nameBufferLen,
537 					0, 0, 0);
538 		if (res != TEE_SUCCESS)
539 			goto err;
540 	}
541 
542 err:
543 	if (res != TEE_SUCCESS &&
544 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
545 	    res != TEE_ERROR_SHORT_BUFFER)
546 		TEE_Panic(0);
547 	return res;
548 }
549 
550 TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator)
551 {
552 	TEE_Result res;
553 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
554 	uint32_t next_idx;
555 	const struct user_ta_property *eps;
556 	size_t eps_len;
557 
558 	if (pe == NULL) {
559 		res = TEE_ERROR_BAD_PARAMETERS;
560 		goto out;
561 	}
562 
563 	if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) {
564 		res = TEE_ERROR_ITEM_NOT_FOUND;
565 		goto out;
566 	}
567 
568 	res = propset_get(pe->prop_set, &eps, &eps_len);
569 	if (res != TEE_SUCCESS)
570 		goto out;
571 
572 	next_idx = pe->idx + 1;
573 	pe->idx = next_idx;
574 	if (next_idx < eps_len)
575 		res = TEE_SUCCESS;
576 	else
577 		res = utee_get_property((unsigned long)pe->prop_set,
578 					next_idx - eps_len, 0, 0, 0, 0, 0);
579 
580 out:
581 	if (res != TEE_SUCCESS &&
582 	    res != TEE_ERROR_ITEM_NOT_FOUND)
583 		TEE_Panic(0);
584 	return res;
585 }
586