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 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 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_U64: 86 l = sizeof(uint64_t); 87 break; 88 case USER_TA_PROP_TYPE_UUID: 89 l = sizeof(TEE_UUID); 90 break; 91 case USER_TA_PROP_TYPE_IDENTITY: 92 l = sizeof(TEE_Identity); 93 break; 94 case USER_TA_PROP_TYPE_STRING: 95 /* take the leading 0 into account */ 96 l = strlen(ep->value) + 1; 97 break; 98 case USER_TA_PROP_TYPE_BINARY_BLOCK: 99 /* 100 * in case of TA property, a binary block is provided as a 101 * string, which is base64 encoded. We must first decode it, 102 * without taking into account the zero termination of the 103 * string 104 */ 105 l = *len; 106 if (!_base64_dec(ep->value, strlen(ep->value), buf, &l) && 107 l <= *len) 108 return TEE_ERROR_GENERIC; 109 if (*len < l) { 110 *len = l; 111 return TEE_ERROR_SHORT_BUFFER; 112 } 113 114 *len = l; 115 return TEE_SUCCESS; 116 default: 117 return TEE_ERROR_GENERIC; 118 } 119 120 if (*len < l) { 121 *len = l; 122 return TEE_ERROR_SHORT_BUFFER; 123 } 124 125 *len = l; 126 memcpy(buf, ep->value, l); 127 return TEE_SUCCESS; 128 } 129 130 static bool is_propset_pseudo_handle(TEE_PropSetHandle h) 131 { 132 return h == TEE_PROPSET_CURRENT_TA || 133 h == TEE_PROPSET_CURRENT_CLIENT || 134 h == TEE_PROPSET_TEE_IMPLEMENTATION; 135 } 136 137 static TEE_Result propget_get_property(TEE_PropSetHandle h, const 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 (is_propset_pseudo_handle(h)) { 148 size_t n; 149 150 res = propset_get(h, &eps, &eps_len); 151 if (res != TEE_SUCCESS) 152 return res; 153 154 for (n = 0; n < eps_len; n++) { 155 if (!strcmp(name, eps[n].name)) 156 return propget_get_ext_prop(eps + n, type, 157 buf, len); 158 } 159 160 /* get the index from the name */ 161 res = _utee_get_property_name_to_index((unsigned long)h, name, 162 strlen(name) + 1, 163 &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 const char *name, char *value, 195 size_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 bool bool_val; 204 TEE_Identity *p_identity_val; 205 206 if (is_propset_pseudo_handle(propsetOrEnumerator)) 207 __utee_check_instring_annotation(name); 208 __utee_check_outstring_annotation(value, value_len); 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 bool_val = *((bool *)tmp_buf); 239 l = strlcpy(value, (bool_val ? "true" : "false"), *value_len); 240 break; 241 242 case USER_TA_PROP_TYPE_U32: 243 uint32_val = *((uint32_t *)tmp_buf); 244 l = snprintf(value, *value_len, "%u", uint32_val); 245 break; 246 247 case USER_TA_PROP_TYPE_UUID: 248 l = snprintk(value, *value_len, "%pUl", tmp_buf); 249 break; 250 251 case USER_TA_PROP_TYPE_IDENTITY: 252 p_identity_val = ((TEE_Identity *)tmp_buf); 253 l = snprintk(value, *value_len, "%u:%pUl", 254 p_identity_val->login, 255 (void *)(&(p_identity_val->uuid))); 256 break; 257 258 case USER_TA_PROP_TYPE_STRING: 259 l = strlcpy(value, tmp_buf, *value_len); 260 break; 261 262 case USER_TA_PROP_TYPE_BINARY_BLOCK: 263 l = *value_len; /* l includes the zero-termination */ 264 if (!_base64_enc(tmp_buf, tmp_len, value, &l) && 265 l <= *value_len) { 266 res = TEE_ERROR_GENERIC; 267 goto out; 268 } 269 l--; /* remove the zero-termination that is added later */ 270 break; 271 272 default: 273 res = TEE_ERROR_BAD_FORMAT; 274 goto out; 275 } 276 277 l++; /* include zero termination */ 278 279 if (l > *value_len) 280 res = TEE_ERROR_SHORT_BUFFER; 281 *value_len = l; 282 283 out: 284 if (tmp_buf) 285 TEE_Free(tmp_buf); 286 if (res != TEE_SUCCESS && 287 res != TEE_ERROR_ITEM_NOT_FOUND && 288 res != TEE_ERROR_SHORT_BUFFER) 289 TEE_Panic(0); 290 291 return res; 292 } 293 294 TEE_Result __GP11_TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, 295 const char *name, char *valueBuffer, 296 uint32_t *valueBufferLen) 297 { 298 TEE_Result res = TEE_SUCCESS; 299 size_t l = 0; 300 301 __utee_check_gp11_outstring_annotation(valueBuffer, valueBufferLen); 302 l = *valueBufferLen; 303 res = TEE_GetPropertyAsString(propsetOrEnumerator, name, valueBuffer, 304 &l); 305 *valueBufferLen = l; 306 return res; 307 } 308 309 TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator, 310 const char *name, bool *value) 311 { 312 TEE_Result res; 313 enum user_ta_prop_type type; 314 uint32_t bool_len = sizeof(bool); 315 316 if (is_propset_pseudo_handle(propsetOrEnumerator)) 317 __utee_check_instring_annotation(name); 318 __utee_check_out_annotation(value, sizeof(*value)); 319 320 type = USER_TA_PROP_TYPE_BOOL; 321 res = propget_get_property(propsetOrEnumerator, name, &type, 322 value, &bool_len); 323 if (type != USER_TA_PROP_TYPE_BOOL) 324 res = TEE_ERROR_BAD_FORMAT; 325 if (res != TEE_SUCCESS) 326 goto out; 327 328 out: 329 if (res != TEE_SUCCESS && 330 res != TEE_ERROR_ITEM_NOT_FOUND && 331 res != TEE_ERROR_BAD_FORMAT) 332 TEE_Panic(0); 333 334 return res; 335 } 336 337 TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator, 338 const char *name, uint32_t *value) 339 { 340 TEE_Result res; 341 enum user_ta_prop_type type; 342 uint32_t uint32_len = sizeof(uint32_t); 343 344 if (is_propset_pseudo_handle(propsetOrEnumerator)) 345 __utee_check_instring_annotation(name); 346 __utee_check_out_annotation(value, sizeof(*value)); 347 348 type = USER_TA_PROP_TYPE_U32; 349 res = propget_get_property(propsetOrEnumerator, name, &type, 350 value, &uint32_len); 351 if (type != USER_TA_PROP_TYPE_U32) 352 res = TEE_ERROR_BAD_FORMAT; 353 354 if (res != TEE_SUCCESS && 355 res != TEE_ERROR_ITEM_NOT_FOUND && 356 res != TEE_ERROR_BAD_FORMAT) 357 TEE_Panic(0); 358 359 return res; 360 } 361 362 TEE_Result TEE_GetPropertyAsU64(TEE_PropSetHandle propsetOrEnumerator, 363 const char *name, uint64_t *value) 364 { 365 TEE_Result res; 366 enum user_ta_prop_type type; 367 uint32_t uint64_len = sizeof(*value); 368 369 if (is_propset_pseudo_handle(propsetOrEnumerator)) 370 __utee_check_instring_annotation(name); 371 __utee_check_out_annotation(value, sizeof(*value)); 372 373 type = USER_TA_PROP_TYPE_U64; 374 res = propget_get_property(propsetOrEnumerator, name, &type, 375 value, &uint64_len); 376 if (type != USER_TA_PROP_TYPE_U64) 377 res = TEE_ERROR_BAD_FORMAT; 378 379 if (res != TEE_SUCCESS && 380 res != TEE_ERROR_ITEM_NOT_FOUND && 381 res != TEE_ERROR_BAD_FORMAT) 382 TEE_Panic(0); 383 384 return res; 385 } 386 387 TEE_Result 388 __GP11_TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, 389 const char *name, void *value, 390 uint32_t *value_len) 391 { 392 TEE_Result res = TEE_SUCCESS; 393 enum user_ta_prop_type type = USER_TA_PROP_TYPE_BOOL; 394 395 if (is_propset_pseudo_handle(propsetOrEnumerator)) 396 __utee_check_instring_annotation(name); 397 __utee_check_gp11_outbuf_annotation(value, value_len); 398 399 type = USER_TA_PROP_TYPE_BINARY_BLOCK; 400 res = propget_get_property(propsetOrEnumerator, name, &type, 401 value, value_len); 402 if (type != USER_TA_PROP_TYPE_BINARY_BLOCK) 403 res = TEE_ERROR_BAD_FORMAT; 404 405 if (res != TEE_SUCCESS && 406 res != TEE_ERROR_ITEM_NOT_FOUND && 407 res != TEE_ERROR_BAD_FORMAT && 408 res != TEE_ERROR_SHORT_BUFFER) 409 TEE_Panic(0); 410 411 return res; 412 } 413 414 TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, 415 const char *name, void *value, 416 size_t *value_len) 417 { 418 TEE_Result res = TEE_SUCCESS; 419 uint32_t l = 0; 420 421 __utee_check_outbuf_annotation(value, value_len); 422 l = *value_len; 423 res = __GP11_TEE_GetPropertyAsBinaryBlock(propsetOrEnumerator, name, 424 value, &l); 425 *value_len = l; 426 return res; 427 } 428 429 TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator, 430 const char *name, TEE_UUID *value) 431 { 432 TEE_Result res; 433 enum user_ta_prop_type type; 434 uint32_t uuid_len = sizeof(TEE_UUID); 435 436 if (is_propset_pseudo_handle(propsetOrEnumerator)) 437 __utee_check_instring_annotation(name); 438 __utee_check_out_annotation(value, sizeof(*value)); 439 440 type = USER_TA_PROP_TYPE_UUID; 441 res = propget_get_property(propsetOrEnumerator, name, &type, 442 value, &uuid_len); 443 if (type != USER_TA_PROP_TYPE_UUID) 444 res = TEE_ERROR_BAD_FORMAT; 445 446 if (res != TEE_SUCCESS && 447 res != TEE_ERROR_ITEM_NOT_FOUND && 448 res != TEE_ERROR_BAD_FORMAT) 449 TEE_Panic(0); 450 451 return res; 452 } 453 454 TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator, 455 const char *name, TEE_Identity *value) 456 { 457 TEE_Result res; 458 enum user_ta_prop_type type; 459 uint32_t identity_len = sizeof(TEE_Identity); 460 461 if (is_propset_pseudo_handle(propsetOrEnumerator)) 462 __utee_check_instring_annotation(name); 463 __utee_check_out_annotation(value, sizeof(*value)); 464 465 type = USER_TA_PROP_TYPE_IDENTITY; 466 res = propget_get_property(propsetOrEnumerator, name, &type, 467 value, &identity_len); 468 if (type != USER_TA_PROP_TYPE_IDENTITY) 469 res = TEE_ERROR_BAD_FORMAT; 470 471 if (res != TEE_SUCCESS && 472 res != TEE_ERROR_ITEM_NOT_FOUND && 473 res != TEE_ERROR_BAD_FORMAT) 474 TEE_Panic(0); 475 476 return res; 477 } 478 479 TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator) 480 { 481 TEE_Result res; 482 struct prop_enumerator *pe; 483 484 __utee_check_out_annotation(enumerator, sizeof(*enumerator)); 485 486 pe = TEE_Malloc(sizeof(struct prop_enumerator), 487 TEE_USER_MEM_HINT_NO_FILL_ZERO); 488 if (pe == NULL) { 489 res = TEE_ERROR_OUT_OF_MEMORY; 490 goto err; 491 } 492 493 *enumerator = (TEE_PropSetHandle) pe; 494 TEE_ResetPropertyEnumerator(*enumerator); 495 496 goto out; 497 498 err: 499 if (res == TEE_ERROR_OUT_OF_MEMORY) 500 return res; 501 TEE_Panic(0); 502 out: 503 return TEE_SUCCESS; 504 } 505 506 void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator) 507 { 508 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 509 510 pe->idx = PROP_ENUMERATOR_NOT_STARTED; 511 } 512 513 void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator) 514 { 515 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 516 517 TEE_Free(pe); 518 } 519 520 void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator, 521 TEE_PropSetHandle propSet) 522 { 523 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 524 525 if (!pe) 526 return; 527 528 pe->idx = 0; 529 pe->prop_set = propSet; 530 } 531 532 TEE_Result __GP11_TEE_GetPropertyName(TEE_PropSetHandle enumerator, 533 void *name, uint32_t *name_len) 534 { 535 TEE_Result res; 536 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 537 const struct user_ta_property *eps; 538 size_t eps_len; 539 const char *str; 540 size_t bufferlen; 541 542 if (!pe) { 543 res = TEE_ERROR_BAD_PARAMETERS; 544 goto err; 545 } 546 __utee_check_gp11_outstring_annotation(name, name_len); 547 548 bufferlen = *name_len; 549 res = propset_get(pe->prop_set, &eps, &eps_len); 550 if (res != TEE_SUCCESS) 551 goto err; 552 553 if (pe->idx < eps_len) { 554 str = eps[pe->idx].name; 555 bufferlen = strlcpy(name, str, *name_len) + 1; 556 if (bufferlen > *name_len) 557 res = TEE_ERROR_SHORT_BUFFER; 558 *name_len = bufferlen; 559 } else { 560 res = _utee_get_property((unsigned long)pe->prop_set, 561 pe->idx - eps_len, name, name_len, 562 NULL, NULL, NULL); 563 if (res != TEE_SUCCESS) 564 goto err; 565 } 566 567 err: 568 if (res != TEE_SUCCESS && 569 res != TEE_ERROR_ITEM_NOT_FOUND && 570 res != TEE_ERROR_SHORT_BUFFER) 571 TEE_Panic(0); 572 return res; 573 } 574 575 TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator, 576 void *nameBuffer, size_t *nameBufferLen) 577 { 578 TEE_Result res = TEE_SUCCESS; 579 uint32_t l = 0; 580 581 __utee_check_outstring_annotation(nameBuffer, nameBufferLen); 582 l = *nameBufferLen; 583 res = __GP11_TEE_GetPropertyName(enumerator, nameBuffer, &l); 584 *nameBufferLen = l; 585 return res; 586 } 587 588 TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator) 589 { 590 TEE_Result res; 591 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 592 uint32_t next_idx; 593 const struct user_ta_property *eps; 594 size_t eps_len; 595 596 if (!pe) { 597 res = TEE_ERROR_BAD_PARAMETERS; 598 goto out; 599 } 600 601 if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) { 602 res = TEE_ERROR_ITEM_NOT_FOUND; 603 goto out; 604 } 605 606 res = propset_get(pe->prop_set, &eps, &eps_len); 607 if (res != TEE_SUCCESS) 608 goto out; 609 610 next_idx = pe->idx + 1; 611 pe->idx = next_idx; 612 if (next_idx < eps_len) 613 res = TEE_SUCCESS; 614 else 615 res = _utee_get_property((unsigned long)pe->prop_set, 616 next_idx - eps_len, NULL, NULL, NULL, 617 NULL, NULL); 618 619 out: 620 if (res != TEE_SUCCESS && 621 res != TEE_ERROR_ITEM_NOT_FOUND) 622 TEE_Panic(0); 623 return res; 624 } 625