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