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