xref: /optee_os/lib/libutee/tee_api_property.c (revision ff857a3ae7de6d1c5929af477a32407bdf10e69d)
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 *valueBuffer,
195 				   uint32_t *valueBufferLen)
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 (valueBuffer == NULL || valueBufferLen == NULL) {
206 		res = TEE_ERROR_BAD_PARAMETERS;
207 		goto out;
208 	}
209 
210 	tmp_len = *valueBufferLen;
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 			*valueBufferLen = tmp_len;
224 		goto out;
225 	}
226 
227 	switch (type) {
228 	case USER_TA_PROP_TYPE_BOOL:
229 		uint32_val = *((uint32_t *)tmp_buf);
230 		l = strlcpy(valueBuffer, (uint32_val ? "true" : "false"),
231 			    *valueBufferLen);
232 		break;
233 
234 	case USER_TA_PROP_TYPE_U32:
235 		uint32_val = *((uint32_t *)tmp_buf);
236 		l = snprintf(valueBuffer, *valueBufferLen, "%u", uint32_val);
237 		break;
238 
239 	case USER_TA_PROP_TYPE_UUID:
240 		l = snprintk(valueBuffer, *valueBufferLen, "%pUl", tmp_buf);
241 		break;
242 
243 	case USER_TA_PROP_TYPE_IDENTITY:
244 		p_identity_val = ((TEE_Identity *)tmp_buf);
245 		l = snprintk(valueBuffer, *valueBufferLen, "%u:%pUl",
246 			     p_identity_val->login,
247 			     (void *)(&(p_identity_val->uuid)));
248 		break;
249 
250 	case USER_TA_PROP_TYPE_STRING:
251 		l = strlcpy(valueBuffer, tmp_buf, *valueBufferLen);
252 		break;
253 
254 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
255 		l = *valueBufferLen;	/* l includes the zero-termination */
256 		if (!base64_enc(tmp_buf, tmp_len, valueBuffer, &l) &&
257 		    (l <= *valueBufferLen)) {
258 			res = TEE_ERROR_GENERIC;
259 			goto out;
260 		}
261 		l--;	/* remove the zero-termination that is added later */
262 		break;
263 
264 	default:
265 		res = TEE_ERROR_BAD_FORMAT;
266 		goto out;
267 	}
268 
269 	l++;	/* include zero termination */
270 
271 	if (l > *valueBufferLen)
272 		res = TEE_ERROR_SHORT_BUFFER;
273 	*valueBufferLen = l;
274 
275 out:
276 	if (tmp_buf)
277 		TEE_Free(tmp_buf);
278 	if (res != TEE_SUCCESS &&
279 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
280 	    res != TEE_ERROR_SHORT_BUFFER)
281 		TEE_Panic(0);
282 
283 	return res;
284 }
285 
286 TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator,
287 				 char *name, bool *value)
288 {
289 	TEE_Result res;
290 	enum user_ta_prop_type type;
291 	uint32_t uint32_val;
292 	uint32_t uint32_len = sizeof(uint32_val);
293 	if (value == NULL) {
294 		res = TEE_ERROR_BAD_PARAMETERS;
295 		goto out;
296 	}
297 
298 	type = USER_TA_PROP_TYPE_BOOL;
299 	res = propget_get_property(propsetOrEnumerator, name, &type,
300 				   &uint32_val, &uint32_len);
301 	if (type != USER_TA_PROP_TYPE_BOOL)
302 		res = TEE_ERROR_BAD_FORMAT;
303 	if (res != TEE_SUCCESS)
304 		goto out;
305 
306 	*value = !!uint32_val;
307 
308 out:
309 	if (res != TEE_SUCCESS &&
310 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
311 	    res != TEE_ERROR_BAD_FORMAT)
312 		TEE_Panic(0);
313 
314 	return res;
315 }
316 
317 TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator,
318 				char *name, uint32_t *value)
319 {
320 	TEE_Result res;
321 	enum user_ta_prop_type type;
322 	uint32_t uint32_len = sizeof(uint32_t);
323 
324 	if (value == NULL) {
325 		res = TEE_ERROR_BAD_PARAMETERS;
326 		goto out;
327 	}
328 
329 	type = USER_TA_PROP_TYPE_U32;
330 	res = propget_get_property(propsetOrEnumerator, name, &type,
331 				   value, &uint32_len);
332 	if (type != USER_TA_PROP_TYPE_U32)
333 		res = TEE_ERROR_BAD_FORMAT;
334 
335 out:
336 	if (res != TEE_SUCCESS &&
337 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
338 	    res != TEE_ERROR_BAD_FORMAT)
339 		TEE_Panic(0);
340 
341 	return res;
342 }
343 
344 TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator,
345 					char *name, void *valueBuffer,
346 					uint32_t *valueBufferLen)
347 {
348 	TEE_Result res;
349 	enum user_ta_prop_type type;
350 
351 	if (valueBuffer == NULL || valueBufferLen == NULL) {
352 		res = TEE_ERROR_BAD_PARAMETERS;
353 		goto out;
354 	}
355 
356 	type = USER_TA_PROP_TYPE_BINARY_BLOCK;
357 	res = propget_get_property(propsetOrEnumerator, name, &type,
358 				   valueBuffer, valueBufferLen);
359 	if (type != USER_TA_PROP_TYPE_BINARY_BLOCK)
360 		res = TEE_ERROR_BAD_FORMAT;
361 
362 out:
363 	if (res != TEE_SUCCESS &&
364 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
365 	    res != TEE_ERROR_BAD_FORMAT &&
366 	    res != TEE_ERROR_SHORT_BUFFER)
367 		TEE_Panic(0);
368 
369 	return res;
370 }
371 
372 TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator,
373 				 char *name, TEE_UUID *value)
374 {
375 	TEE_Result res;
376 	enum user_ta_prop_type type;
377 	uint32_t uuid_len = sizeof(TEE_UUID);
378 
379 	if (value == NULL) {
380 		res = TEE_ERROR_BAD_PARAMETERS;
381 		goto out;
382 	}
383 
384 	type = USER_TA_PROP_TYPE_UUID;
385 	res = propget_get_property(propsetOrEnumerator, name, &type,
386 				   value, &uuid_len);
387 	if (type != USER_TA_PROP_TYPE_UUID)
388 		res = TEE_ERROR_BAD_FORMAT;
389 
390 out:
391 	if (res != TEE_SUCCESS &&
392 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
393 	    res != TEE_ERROR_BAD_FORMAT)
394 		TEE_Panic(0);
395 
396 	return res;
397 }
398 
399 TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator,
400 				     char *name, TEE_Identity *value)
401 {
402 	TEE_Result res;
403 	enum user_ta_prop_type type;
404 	uint32_t identity_len = sizeof(TEE_Identity);
405 
406 	if (value == NULL) {
407 		res = TEE_ERROR_BAD_PARAMETERS;
408 		goto out;
409 	}
410 
411 	type = USER_TA_PROP_TYPE_IDENTITY;
412 	res = propget_get_property(propsetOrEnumerator, name, &type,
413 				   value, &identity_len);
414 	if (type != USER_TA_PROP_TYPE_IDENTITY)
415 		res = TEE_ERROR_BAD_FORMAT;
416 
417 out:
418 	if (res != TEE_SUCCESS &&
419 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
420 	    res != TEE_ERROR_BAD_FORMAT)
421 		TEE_Panic(0);
422 
423 	return res;
424 }
425 
426 TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator)
427 {
428 	TEE_Result res;
429 	struct prop_enumerator *pe;
430 
431 	if (enumerator == NULL) {
432 		res = TEE_ERROR_BAD_PARAMETERS;
433 		goto err;
434 	}
435 
436 	pe = TEE_Malloc(sizeof(struct prop_enumerator),
437 			TEE_USER_MEM_HINT_NO_FILL_ZERO);
438 	if (pe == NULL) {
439 		res = TEE_ERROR_OUT_OF_MEMORY;
440 		goto err;
441 	}
442 
443 	*enumerator = (TEE_PropSetHandle) pe;
444 	TEE_ResetPropertyEnumerator(*enumerator);
445 
446 	goto out;
447 
448 err:
449 	if (res == TEE_ERROR_OUT_OF_MEMORY)
450 		return res;
451 	TEE_Panic(0);
452 out:
453 	return TEE_SUCCESS;
454 }
455 
456 void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator)
457 {
458 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
459 
460 	pe->idx = PROP_ENUMERATOR_NOT_STARTED;
461 }
462 
463 void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator)
464 {
465 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
466 
467 	TEE_Free(pe);
468 }
469 
470 void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator,
471 				 TEE_PropSetHandle propSet)
472 {
473 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
474 
475 	if (pe == NULL)
476 		return;
477 
478 	pe->idx = 0;
479 	pe->prop_set = propSet;
480 }
481 
482 TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator,
483 			       void *nameBuffer, uint32_t *nameBufferLen)
484 {
485 	TEE_Result res;
486 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
487 	const struct user_ta_property *eps;
488 	size_t eps_len;
489 	const char *str;
490 	size_t bufferlen;
491 
492 	if (pe == NULL || nameBuffer == NULL || nameBufferLen == NULL) {
493 		res = TEE_ERROR_BAD_PARAMETERS;
494 		goto err;
495 	}
496 
497 	bufferlen = *nameBufferLen;
498 	res = propset_get(pe->prop_set, &eps, &eps_len);
499 	if (res != TEE_SUCCESS)
500 		goto err;
501 
502 	if (pe->idx < eps_len) {
503 		str = eps[pe->idx].name;
504 		bufferlen = strlcpy(nameBuffer, str, *nameBufferLen) + 1;
505 		if (bufferlen > *nameBufferLen)
506 			res = TEE_ERROR_SHORT_BUFFER;
507 		*nameBufferLen = bufferlen;
508 	} else {
509 		res = utee_get_property((unsigned long)pe->prop_set,
510 					pe->idx - eps_len,
511 					nameBuffer, nameBufferLen,
512 					NULL, NULL, NULL);
513 		if (res != TEE_SUCCESS)
514 			goto err;
515 	}
516 
517 err:
518 	if (res != TEE_SUCCESS &&
519 	    res != TEE_ERROR_ITEM_NOT_FOUND &&
520 	    res != TEE_ERROR_SHORT_BUFFER)
521 		TEE_Panic(0);
522 	return res;
523 }
524 
525 TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator)
526 {
527 	TEE_Result res;
528 	struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
529 	uint32_t next_idx;
530 	const struct user_ta_property *eps;
531 	size_t eps_len;
532 
533 	if (pe == NULL) {
534 		res = TEE_ERROR_BAD_PARAMETERS;
535 		goto out;
536 	}
537 
538 	if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) {
539 		res = TEE_ERROR_ITEM_NOT_FOUND;
540 		goto out;
541 	}
542 
543 	res = propset_get(pe->prop_set, &eps, &eps_len);
544 	if (res != TEE_SUCCESS)
545 		goto out;
546 
547 	next_idx = pe->idx + 1;
548 	pe->idx = next_idx;
549 	if (next_idx < eps_len)
550 		res = TEE_SUCCESS;
551 	else
552 		res = utee_get_property((unsigned long)pe->prop_set,
553 					next_idx - eps_len,
554 					NULL, NULL, NULL, NULL, NULL);
555 
556 out:
557 	if (res != TEE_SUCCESS &&
558 	    res != TEE_ERROR_ITEM_NOT_FOUND)
559 		TEE_Panic(0);
560 	return res;
561 }
562