xref: /optee_os/lib/libutee/tee_api_property.c (revision c2f5808039471d8cb9ac43385b63fb8dc6aa8ac4)
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 <printk.h>
33 #include <tee_api_defines.h>
34 #include <tee_api_types.h>
35 #include <user_ta_header.h>
36 #include <tee_internal_api_extensions.h>
37 #include <tee_arith_internal.h>
38 #include <util.h>
39 #include <utee_syscalls.h>
40 
41 #include "string_ext.h"
42 #include "base64.h"
43 
44 #define PROP_STR_MAX    80
45 
46 #define PROP_ENUMERATOR_NOT_STARTED 0xffffffff
47 
48 struct prop_enumerator {
49 	uint32_t idx;			/* current index */
50 	TEE_PropSetHandle prop_set;	/* part of TEE_PROPSET_xxx */
51 };
52 
53 const struct user_ta_property tee_props[] = {
54 	{
55 		"gpd.tee.arith.maxBigIntSize",
56 		USER_TA_PROP_TYPE_U32,
57 		&(const uint32_t){TEE_MAX_NUMBER_OF_SUPPORTED_BITS}
58 	},
59 };
60 
61 static TEE_Result propset_get(TEE_PropSetHandle h,
62 			      const struct user_ta_property **eps,
63 			      size_t *eps_len)
64 {
65 	if (h == TEE_PROPSET_CURRENT_TA) {
66 		*eps = ta_props;
67 		*eps_len = ta_num_props;
68 	} else if (h == TEE_PROPSET_CURRENT_CLIENT) {
69 		*eps = NULL;
70 		*eps_len = 0;
71 	} else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) {
72 		*eps = tee_props;
73 		*eps_len = ARRAY_SIZE(tee_props);
74 	} else {
75 		return TEE_ERROR_ITEM_NOT_FOUND;
76 	}
77 
78 	return TEE_SUCCESS;
79 }
80 
81 static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep,
82 				       enum user_ta_prop_type *type,
83 				       void *buf, uint32_t *len)
84 {
85 	size_t l;
86 
87 	*type = ep->type;
88 	switch (*type) {
89 	case USER_TA_PROP_TYPE_BOOL:
90 		l = sizeof(uint32_t);
91 		break;
92 	case USER_TA_PROP_TYPE_U32:
93 		l = sizeof(uint32_t);
94 		break;
95 	case USER_TA_PROP_TYPE_UUID:
96 		l = sizeof(TEE_UUID);
97 		break;
98 	case USER_TA_PROP_TYPE_IDENTITY:
99 		l = sizeof(TEE_Identity);
100 		break;
101 	case USER_TA_PROP_TYPE_STRING:
102 		/* take the leading 0 into account */
103 		l = strlen(ep->value) + 1;
104 		break;
105 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
106 		/*
107 		 * in case of TA property, a binary block is provided as a
108 		 * string, which is base64 encoded. We must first decode it,
109 		 * without taking into account the zero termination of the
110 		 * string
111 		 */
112 		l = *len;
113 		if (!base64_dec(ep->value, strlen(ep->value), buf, &l) &&
114 		    (l <= *len))
115 			return TEE_ERROR_GENERIC;
116 		if (*len < l) {
117 			*len = l;
118 			return TEE_ERROR_SHORT_BUFFER;
119 		}
120 
121 		*len = l;
122 		return TEE_SUCCESS;
123 	default:
124 		return TEE_ERROR_GENERIC;
125 	}
126 
127 	if (*len < l) {
128 		*len = l;
129 		return TEE_ERROR_SHORT_BUFFER;
130 	}
131 
132 	*len = l;
133 	memcpy(buf, ep->value, l);
134 	return TEE_SUCCESS;
135 }
136 
137 static TEE_Result propget_get_property(TEE_PropSetHandle h, char *name,
138 				       enum user_ta_prop_type *type,
139 				       void *buf, uint32_t *len)
140 {
141 	TEE_Result res;
142 	const struct user_ta_property *eps;
143 	size_t eps_len;
144 	uint32_t prop_type;
145 	uint32_t index;
146 
147 	if (h == TEE_PROPSET_CURRENT_TA || h == TEE_PROPSET_CURRENT_CLIENT ||
148 	    h == TEE_PROPSET_TEE_IMPLEMENTATION) {
149 		size_t n;
150 
151 		res = propset_get(h, &eps, &eps_len);
152 		if (res != TEE_SUCCESS)
153 			return res;
154 
155 		for (n = 0; n < eps_len; n++) {
156 			if (!strcmp(name, eps[n].name))
157 				return propget_get_ext_prop(eps + n, type,
158 							    buf, len);
159 		}
160 
161 		/* get the index from the name */
162 		res = utee_get_property_name_to_index((unsigned long)h, name,
163 						strlen(name) + 1, &index);
164 		if (res != TEE_SUCCESS)
165 			return res;
166 		res = utee_get_property((unsigned long)h, index, NULL, NULL,
167 					buf, len, &prop_type);
168 	} else {
169 		struct prop_enumerator *pe = (struct prop_enumerator *)h;
170 		uint32_t idx = pe->idx;
171 
172 		if (idx == PROP_ENUMERATOR_NOT_STARTED)
173 			return TEE_ERROR_ITEM_NOT_FOUND;
174 
175 		res = propset_get(pe->prop_set, &eps, &eps_len);
176 		if (res != TEE_SUCCESS)
177 			return res;
178 
179 		if (idx < eps_len)
180 			return propget_get_ext_prop(eps + idx, type, buf, len);
181 		idx -= eps_len;
182 
183 		res = utee_get_property((unsigned long)pe->prop_set, idx,
184 					NULL, NULL, buf, len, &prop_type);
185 		if (res == TEE_ERROR_ITEM_NOT_FOUND)
186 			res = TEE_ERROR_BAD_PARAMETERS;
187 	}
188 
189 	*type = prop_type;
190 	return res;
191 }
192 
193 TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator,
194 				   char *name, char *value,
195 				   uint32_t *value_len)
196 {
197 	TEE_Result res;
198 	size_t l;
199 	enum user_ta_prop_type type;
200 	void *tmp_buf = 0;
201 	uint32_t tmp_len;
202 	uint32_t uint32_val;
203 	TEE_Identity *p_identity_val;
204 
205 	if (!value || !value_len) {
206 		res = TEE_ERROR_BAD_PARAMETERS;
207 		goto out;
208 	}
209 
210 	tmp_len = *value_len;
211 	if (tmp_len < sizeof(TEE_Identity))
212 		tmp_len = sizeof(TEE_Identity);
213 	tmp_buf = TEE_Malloc(tmp_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
214 	if (!tmp_buf) {
215 		res = TEE_ERROR_OUT_OF_MEMORY;
216 		goto out;
217 	}
218 
219 	res = propget_get_property(propsetOrEnumerator, name, &type,
220 				   tmp_buf, &tmp_len);
221 	if (res != TEE_SUCCESS) {
222 		if (res == TEE_ERROR_SHORT_BUFFER) {
223 			if (type == USER_TA_PROP_TYPE_BINARY_BLOCK) {
224 				/*
225 				 * in this case, we must enlarge the buffer
226 				 * with the size of the of the base64 encoded
227 				 * see base64_enc() function
228 				 */
229 				tmp_len = base64_enc_len(tmp_len);
230 			}
231 			*value_len = tmp_len;
232 		}
233 		goto out;
234 	}
235 
236 	switch (type) {
237 	case USER_TA_PROP_TYPE_BOOL:
238 		uint32_val = *((uint32_t *)tmp_buf);
239 		l = strlcpy(value, (uint32_val ? "true" : "false"),
240 			    *value_len);
241 		break;
242 
243 	case USER_TA_PROP_TYPE_U32:
244 		uint32_val = *((uint32_t *)tmp_buf);
245 		l = snprintf(value, *value_len, "%u", uint32_val);
246 		break;
247 
248 	case USER_TA_PROP_TYPE_UUID:
249 		l = snprintk(value, *value_len, "%pUl", tmp_buf);
250 		break;
251 
252 	case USER_TA_PROP_TYPE_IDENTITY:
253 		p_identity_val = ((TEE_Identity *)tmp_buf);
254 		l = snprintk(value, *value_len, "%u:%pUl",
255 			     p_identity_val->login,
256 			     (void *)(&(p_identity_val->uuid)));
257 		break;
258 
259 	case USER_TA_PROP_TYPE_STRING:
260 		l = strlcpy(value, tmp_buf, *value_len);
261 		break;
262 
263 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
264 		l = *value_len;	/* l includes the zero-termination */
265 		if (!base64_enc(tmp_buf, tmp_len, value, &l) &&
266 		    (l <= *value_len)) {
267 			res = TEE_ERROR_GENERIC;
268 			goto out;
269 		}
270 		l--;	/* remove the zero-termination that is added later */
271 		break;
272 
273 	default:
274 		res = TEE_ERROR_BAD_FORMAT;
275 		goto out;
276 	}
277 
278 	l++;	/* include zero termination */
279 
280 	if (l > *value_len)
281 		res = TEE_ERROR_SHORT_BUFFER;
282 	*value_len = l;
283 
284 out:
285 	if (tmp_buf)
286 		TEE_Free(tmp_buf);
287 	if (res != TEE_SUCCESS &&
288 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
289 	    res != TEE_ERROR_SHORT_BUFFER)
290 		TEE_Panic(0);
291 
292 	return res;
293 }
294 
295 TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator,
296 				 char *name, bool *value)
297 {
298 	TEE_Result res;
299 	enum user_ta_prop_type type;
300 	uint32_t uint32_val;
301 	uint32_t uint32_len = sizeof(uint32_val);
302 	if (value == NULL) {
303 		res = TEE_ERROR_BAD_PARAMETERS;
304 		goto out;
305 	}
306 
307 	type = USER_TA_PROP_TYPE_BOOL;
308 	res = propget_get_property(propsetOrEnumerator, name, &type,
309 				   &uint32_val, &uint32_len);
310 	if (type != USER_TA_PROP_TYPE_BOOL)
311 		res = TEE_ERROR_BAD_FORMAT;
312 	if (res != TEE_SUCCESS)
313 		goto out;
314 
315 	*value = !!uint32_val;
316 
317 out:
318 	if (res != TEE_SUCCESS &&
319 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
320 	    res != TEE_ERROR_BAD_FORMAT)
321 		TEE_Panic(0);
322 
323 	return res;
324 }
325 
326 TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator,
327 				char *name, uint32_t *value)
328 {
329 	TEE_Result res;
330 	enum user_ta_prop_type type;
331 	uint32_t uint32_len = sizeof(uint32_t);
332 
333 	if (!value) {
334 		res = TEE_ERROR_BAD_PARAMETERS;
335 		goto out;
336 	}
337 
338 	type = USER_TA_PROP_TYPE_U32;
339 	res = propget_get_property(propsetOrEnumerator, name, &type,
340 				   value, &uint32_len);
341 	if (type != USER_TA_PROP_TYPE_U32)
342 		res = TEE_ERROR_BAD_FORMAT;
343 
344 out:
345 	if (res != TEE_SUCCESS &&
346 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
347 	    res != TEE_ERROR_BAD_FORMAT)
348 		TEE_Panic(0);
349 
350 	return res;
351 }
352 
353 TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator,
354 					char *name, void *value,
355 					uint32_t *value_len)
356 {
357 	TEE_Result res;
358 	enum user_ta_prop_type type;
359 
360 	if (!value || !value_len) {
361 		res = TEE_ERROR_BAD_PARAMETERS;
362 		goto out;
363 	}
364 
365 	type = USER_TA_PROP_TYPE_BINARY_BLOCK;
366 	res = propget_get_property(propsetOrEnumerator, name, &type,
367 				   value, value_len);
368 	if (type != USER_TA_PROP_TYPE_BINARY_BLOCK)
369 		res = TEE_ERROR_BAD_FORMAT;
370 
371 out:
372 	if (res != TEE_SUCCESS &&
373 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
374 	    res != TEE_ERROR_BAD_FORMAT &&
375 	    res != TEE_ERROR_SHORT_BUFFER)
376 		TEE_Panic(0);
377 
378 	return res;
379 }
380 
381 TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator,
382 				 char *name, TEE_UUID *value)
383 {
384 	TEE_Result res;
385 	enum user_ta_prop_type type;
386 	uint32_t uuid_len = sizeof(TEE_UUID);
387 
388 	if (!value) {
389 		res = TEE_ERROR_BAD_PARAMETERS;
390 		goto out;
391 	}
392 
393 	type = USER_TA_PROP_TYPE_UUID;
394 	res = propget_get_property(propsetOrEnumerator, name, &type,
395 				   value, &uuid_len);
396 	if (type != USER_TA_PROP_TYPE_UUID)
397 		res = TEE_ERROR_BAD_FORMAT;
398 
399 out:
400 	if (res != TEE_SUCCESS &&
401 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
402 	    res != TEE_ERROR_BAD_FORMAT)
403 		TEE_Panic(0);
404 
405 	return res;
406 }
407 
408 TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator,
409 				     char *name, TEE_Identity *value)
410 {
411 	TEE_Result res;
412 	enum user_ta_prop_type type;
413 	uint32_t identity_len = sizeof(TEE_Identity);
414 
415 	if (!value) {
416 		res = TEE_ERROR_BAD_PARAMETERS;
417 		goto out;
418 	}
419 
420 	type = USER_TA_PROP_TYPE_IDENTITY;
421 	res = propget_get_property(propsetOrEnumerator, name, &type,
422 				   value, &identity_len);
423 	if (type != USER_TA_PROP_TYPE_IDENTITY)
424 		res = TEE_ERROR_BAD_FORMAT;
425 
426 out:
427 	if (res != TEE_SUCCESS &&
428 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
429 	    res != TEE_ERROR_BAD_FORMAT)
430 		TEE_Panic(0);
431 
432 	return res;
433 }
434 
435 TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator)
436 {
437 	TEE_Result res;
438 	struct prop_enumerator *pe;
439 
440 	if (!enumerator) {
441 		res = TEE_ERROR_BAD_PARAMETERS;
442 		goto err;
443 	}
444 
445 	pe = TEE_Malloc(sizeof(struct prop_enumerator),
446 			TEE_USER_MEM_HINT_NO_FILL_ZERO);
447 	if (pe == NULL) {
448 		res = TEE_ERROR_OUT_OF_MEMORY;
449 		goto err;
450 	}
451 
452 	*enumerator = (TEE_PropSetHandle) pe;
453 	TEE_ResetPropertyEnumerator(*enumerator);
454 
455 	goto out;
456 
457 err:
458 	if (res == TEE_ERROR_OUT_OF_MEMORY)
459 		return res;
460 	TEE_Panic(0);
461 out:
462 	return TEE_SUCCESS;
463 }
464 
465 void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator)
466 {
467 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
468 
469 	pe->idx = PROP_ENUMERATOR_NOT_STARTED;
470 }
471 
472 void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator)
473 {
474 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
475 
476 	TEE_Free(pe);
477 }
478 
479 void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator,
480 				 TEE_PropSetHandle propSet)
481 {
482 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
483 
484 	if (!pe)
485 		return;
486 
487 	pe->idx = 0;
488 	pe->prop_set = propSet;
489 }
490 
491 TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator,
492 			       void *name, uint32_t *name_len)
493 {
494 	TEE_Result res;
495 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
496 	const struct user_ta_property *eps;
497 	size_t eps_len;
498 	const char *str;
499 	size_t bufferlen;
500 
501 	if (!pe || !name || !name_len) {
502 		res = TEE_ERROR_BAD_PARAMETERS;
503 		goto err;
504 	}
505 
506 	bufferlen = *name_len;
507 	res = propset_get(pe->prop_set, &eps, &eps_len);
508 	if (res != TEE_SUCCESS)
509 		goto err;
510 
511 	if (pe->idx < eps_len) {
512 		str = eps[pe->idx].name;
513 		bufferlen = strlcpy(name, str, *name_len) + 1;
514 		if (bufferlen > *name_len)
515 			res = TEE_ERROR_SHORT_BUFFER;
516 		*name_len = bufferlen;
517 	} else {
518 		res = utee_get_property((unsigned long)pe->prop_set,
519 					pe->idx - eps_len,
520 					name, name_len, NULL, NULL, NULL);
521 		if (res != TEE_SUCCESS)
522 			goto err;
523 	}
524 
525 err:
526 	if (res != TEE_SUCCESS &&
527 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
528 	    res != TEE_ERROR_SHORT_BUFFER)
529 		TEE_Panic(0);
530 	return res;
531 }
532 
533 TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator)
534 {
535 	TEE_Result res;
536 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
537 	uint32_t next_idx;
538 	const struct user_ta_property *eps;
539 	size_t eps_len;
540 
541 	if (!pe) {
542 		res = TEE_ERROR_BAD_PARAMETERS;
543 		goto out;
544 	}
545 
546 	if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) {
547 		res = TEE_ERROR_ITEM_NOT_FOUND;
548 		goto out;
549 	}
550 
551 	res = propset_get(pe->prop_set, &eps, &eps_len);
552 	if (res != TEE_SUCCESS)
553 		goto out;
554 
555 	next_idx = pe->idx + 1;
556 	pe->idx = next_idx;
557 	if (next_idx < eps_len)
558 		res = TEE_SUCCESS;
559 	else
560 		res = utee_get_property((unsigned long)pe->prop_set,
561 					next_idx - eps_len,
562 					NULL, NULL, NULL, NULL, NULL);
563 
564 out:
565 	if (res != TEE_SUCCESS &&
566 	    res != TEE_ERROR_ITEM_NOT_FOUND)
567 		TEE_Panic(0);
568 	return res;
569 }
570