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