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 <tee_api_defines.h> 33 #include <tee_api_types.h> 34 #include <user_ta_header.h> 35 #include <tee_internal_api_extensions.h> 36 #include <tee_arith_internal.h> 37 38 #include <utee_syscalls.h> 39 40 #include "string_ext.h" 41 #include "base64.h" 42 43 #define PROP_STR_MAX 80 44 45 #define PROP_ENUMERATOR_NOT_STARTED 0xffffffff 46 47 struct prop_enumerator { 48 uint32_t idx; 49 TEE_PropSetHandle prop_set; 50 }; 51 52 struct prop_value { 53 enum user_ta_prop_type type; 54 union { 55 bool bool_val; 56 uint32_t int_val; 57 TEE_UUID uuid_val; 58 TEE_Identity identity_val; 59 char str_val[PROP_STR_MAX]; 60 } u; 61 }; 62 63 typedef TEE_Result(*ta_propget_func_t) (struct prop_value *pv); 64 65 struct prop_set { 66 const char *str; 67 ta_propget_func_t get; 68 }; 69 70 static TEE_Result propget_gpd_ta_app_id(struct prop_value *pv) 71 { 72 pv->type = USER_TA_PROP_TYPE_UUID; 73 return utee_get_property(UTEE_PROP_TA_APP_ID, &pv->u.uuid_val, 74 sizeof(pv->u.uuid_val)); 75 } 76 77 static TEE_Result propget_gpd_client_identity(struct prop_value *pv) 78 { 79 pv->type = USER_TA_PROP_TYPE_IDENTITY; 80 return utee_get_property(UTEE_PROP_CLIENT_ID, &pv->u.identity_val, 81 sizeof(pv->u.identity_val)); 82 } 83 84 static TEE_Result propget_gpd_tee_api_version(struct prop_value *pv) 85 { 86 pv->type = USER_TA_PROP_TYPE_STRING; 87 return utee_get_property(UTEE_PROP_TEE_API_VERSION, &pv->u.str_val, 88 sizeof(pv->u.str_val)); 89 } 90 91 static TEE_Result propget_gpd_tee_description(struct prop_value *pv) 92 { 93 pv->type = USER_TA_PROP_TYPE_STRING; 94 return utee_get_property(UTEE_PROP_TEE_DESCR, &pv->u.str_val, 95 sizeof(pv->u.str_val)); 96 } 97 98 static TEE_Result propget_gpd_tee_device_id(struct prop_value *pv) 99 { 100 pv->type = USER_TA_PROP_TYPE_UUID; 101 return utee_get_property(UTEE_PROP_TEE_DEV_ID, &pv->u.uuid_val, 102 sizeof(pv->u.uuid_val)); 103 } 104 105 static TEE_Result propget_gpd_tee_sys_time_protection_level(struct prop_value 106 *pv) 107 { 108 pv->type = USER_TA_PROP_TYPE_U32; 109 return utee_get_property(UTEE_PROP_TEE_SYS_TIME_PROT_LEVEL, 110 &pv->u.int_val, sizeof(pv->u.int_val)); 111 } 112 113 static TEE_Result propget_gpd_tee_ta_time_protection_level(struct prop_value 114 *pv) 115 { 116 pv->type = USER_TA_PROP_TYPE_U32; 117 return utee_get_property(UTEE_PROP_TEE_TA_TIME_PROT_LEVEL, 118 &pv->u.int_val, sizeof(pv->u.int_val)); 119 } 120 121 static TEE_Result propget_gpd_tee_arith_max_big_int_size(struct prop_value *pv) 122 { 123 pv->type = USER_TA_PROP_TYPE_U32; 124 pv->u.int_val = TEE_MAX_NUMBER_OF_SUPPORTED_BITS; 125 return TEE_SUCCESS; 126 } 127 128 static TEE_Result propget_gpd_tee_cryptography_ecc(struct prop_value 129 *pv) 130 { 131 pv->type = USER_TA_PROP_TYPE_BOOL; 132 return utee_get_property(UTEE_PROP_TEE_CRYPTOGRAPHY_ECC, 133 &pv->u.bool_val, sizeof(pv->u.bool_val)); 134 } 135 136 static TEE_Result propget_gpd_tee_ts_antiroll_protection_level( 137 struct prop_value *pv) 138 { 139 pv->type = USER_TA_PROP_TYPE_U32; 140 return utee_get_property(UTEE_PROP_TEE_TS_ANTIROLL_PROT_LEVEL, 141 &pv->u.int_val, sizeof(pv->u.int_val)); 142 } 143 144 static TEE_Result propget_gpd_tee_trustedos_impl_version(struct prop_value *pv) 145 { 146 pv->type = USER_TA_PROP_TYPE_STRING; 147 return utee_get_property(UTEE_PROP_TEE_TRUSTEDOS_IMPL_VERSION, 148 &pv->u.str_val, sizeof(pv->u.str_val)); 149 } 150 151 static TEE_Result propget_gpd_tee_trustedos_impl_bin_version( 152 struct prop_value *pv) 153 { 154 pv->type = USER_TA_PROP_TYPE_U32; 155 return utee_get_property(UTEE_PROP_TEE_TRUSTEDOS_IMPL_BIN_VERSION, 156 &pv->u.int_val, sizeof(pv->u.int_val)); 157 } 158 159 static TEE_Result propget_gpd_tee_trustedos_manufacturer(struct prop_value *pv) 160 { 161 pv->type = USER_TA_PROP_TYPE_STRING; 162 return utee_get_property(UTEE_PROP_TEE_TRUSTEDOS_MANUFACTURER, 163 &pv->u.str_val, sizeof(pv->u.str_val)); 164 } 165 166 static TEE_Result propget_gpd_tee_fw_impl_version(struct prop_value *pv) 167 { 168 pv->type = USER_TA_PROP_TYPE_STRING; 169 return utee_get_property(UTEE_PROP_TEE_FW_IMPL_VERSION, &pv->u.str_val, 170 sizeof(pv->u.str_val)); 171 } 172 173 static TEE_Result propget_gpd_tee_fw_impl_bin_version(struct prop_value *pv) 174 { 175 pv->type = USER_TA_PROP_TYPE_U32; 176 return utee_get_property(UTEE_PROP_TEE_FW_IMPL_BIN_VERSION, 177 &pv->u.int_val, sizeof(pv->u.int_val)); 178 } 179 180 static TEE_Result propget_gpd_tee_fw_manufacturer(struct prop_value *pv) 181 { 182 pv->type = USER_TA_PROP_TYPE_STRING; 183 return utee_get_property(UTEE_PROP_TEE_FW_MANUFACTURER, &pv->u.str_val, 184 sizeof(pv->u.str_val)); 185 } 186 187 static const struct prop_set propset_current_ta[] = { 188 {"gpd.ta.appID", propget_gpd_ta_app_id}, 189 }; 190 191 static const size_t propset_current_ta_len = 192 sizeof(propset_current_ta) / sizeof(propset_current_ta[0]); 193 194 static const struct prop_set propset_current_client[] = { 195 {"gpd.client.identity", propget_gpd_client_identity}, 196 }; 197 198 static const size_t propset_current_client_len = 199 sizeof(propset_current_client) / sizeof(propset_current_client[0]); 200 201 static const struct prop_set propset_implementation[] = { 202 {"gpd.tee.apiversion", propget_gpd_tee_api_version}, 203 {"gpd.tee.description", propget_gpd_tee_description}, 204 {"gpd.tee.deviceID", propget_gpd_tee_device_id}, 205 {"gpd.tee.systemTime.protectionLevel", 206 propget_gpd_tee_sys_time_protection_level}, 207 {"gpd.tee.TAPersistentTime.protectionLevel", 208 propget_gpd_tee_ta_time_protection_level}, 209 {"gpd.tee.arith.maxBigIntSize", propget_gpd_tee_arith_max_big_int_size}, 210 {"gpd.tee.cryptography.ecc", propget_gpd_tee_cryptography_ecc}, 211 {"gpd.tee.trustedStorage.antiRollback.protectionLevel", 212 propget_gpd_tee_ts_antiroll_protection_level}, 213 {"gpd.tee.trustedos.implementation.version", 214 propget_gpd_tee_trustedos_impl_version}, 215 {"gpd.tee.trustedos.implementation.binaryversion", 216 propget_gpd_tee_trustedos_impl_bin_version}, 217 {"gpd.tee.trustedos.manufacturer", 218 propget_gpd_tee_trustedos_manufacturer}, 219 {"gpd.tee.firmware.implementation.version", 220 propget_gpd_tee_fw_impl_version}, 221 {"gpd.tee.firmware.implementation.binaryversion", 222 propget_gpd_tee_fw_impl_bin_version}, 223 {"gpd.tee.firmware.manufacturer", 224 propget_gpd_tee_fw_manufacturer}, 225 }; 226 227 static const size_t propset_implementation_len = 228 sizeof(propset_implementation) / sizeof(propset_implementation[0]); 229 230 static TEE_Result propset_get(TEE_PropSetHandle h, const struct prop_set **ps, 231 size_t *ps_len, 232 const struct user_ta_property **eps, 233 size_t *eps_len) 234 { 235 if (h == TEE_PROPSET_CURRENT_TA) { 236 *ps = propset_current_ta; 237 *ps_len = propset_current_ta_len; 238 *eps = ta_props; 239 *eps_len = ta_num_props; 240 } else if (h == TEE_PROPSET_CURRENT_CLIENT) { 241 *ps = propset_current_client; 242 *ps_len = propset_current_client_len; 243 *eps = NULL; 244 *eps_len = 0; 245 } else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) { 246 *ps = propset_implementation; 247 *ps_len = propset_implementation_len; 248 *eps = NULL; 249 *eps_len = 0; 250 } else { 251 return TEE_ERROR_ITEM_NOT_FOUND; 252 } 253 254 return TEE_SUCCESS; 255 } 256 257 static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep, 258 struct prop_value *pv) 259 { 260 size_t l; 261 262 pv->type = ep->type; 263 switch (ep->type) { 264 case USER_TA_PROP_TYPE_BOOL: 265 l = sizeof(bool); 266 break; 267 case USER_TA_PROP_TYPE_U32: 268 l = sizeof(uint32_t); 269 break; 270 case USER_TA_PROP_TYPE_UUID: 271 l = sizeof(TEE_UUID); 272 break; 273 case USER_TA_PROP_TYPE_IDENTITY: 274 l = sizeof(TEE_Identity); 275 break; 276 case USER_TA_PROP_TYPE_STRING: 277 case USER_TA_PROP_TYPE_BINARY_BLOCK: 278 /* Handle too large strings by truncating them */ 279 strlcpy(pv->u.str_val, ep->value, sizeof(pv->u.str_val)); 280 return TEE_SUCCESS; 281 default: 282 return TEE_ERROR_GENERIC; 283 } 284 memcpy(&pv->u, ep->value, l); 285 return TEE_SUCCESS; 286 } 287 288 static TEE_Result propget_get_property(TEE_PropSetHandle h, char *name, 289 struct prop_value *pv) 290 { 291 TEE_Result res; 292 const struct prop_set *ps; 293 size_t ps_len; 294 const struct user_ta_property *eps; 295 size_t eps_len; 296 297 if (h == TEE_PROPSET_CURRENT_TA || h == TEE_PROPSET_CURRENT_CLIENT || 298 h == TEE_PROPSET_TEE_IMPLEMENTATION) { 299 size_t n; 300 301 res = propset_get(h, &ps, &ps_len, &eps, &eps_len); 302 if (res != TEE_SUCCESS) 303 return res; 304 305 for (n = 0; n < ps_len; n++) { 306 if (strcmp(name, ps[n].str) == 0) 307 return ps[n].get(pv); 308 } 309 for (n = 0; n < eps_len; n++) { 310 if (strcmp(name, eps[n].name) == 0) 311 return propget_get_ext_prop(eps + n, pv); 312 } 313 return TEE_ERROR_ITEM_NOT_FOUND; 314 } else { 315 struct prop_enumerator *pe = (struct prop_enumerator *)h; 316 uint32_t idx = pe->idx; 317 318 if (idx == PROP_ENUMERATOR_NOT_STARTED) 319 return TEE_ERROR_ITEM_NOT_FOUND; 320 321 res = propset_get(pe->prop_set, &ps, &ps_len, &eps, &eps_len); 322 if (res != TEE_SUCCESS) 323 return res; 324 325 if (idx < ps_len) 326 return ps[idx].get(pv); 327 328 idx -= ps_len; 329 if (idx < eps_len) 330 return propget_get_ext_prop(eps + idx, pv); 331 332 return TEE_ERROR_BAD_PARAMETERS; 333 } 334 } 335 336 TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, 337 char *name, char *valueBuffer, 338 uint32_t *valueBufferLen) 339 { 340 TEE_Result res; 341 struct prop_value pv; 342 size_t l; 343 size_t bufferlen; 344 345 if (valueBuffer == NULL || valueBufferLen == NULL) { 346 res = TEE_ERROR_BAD_PARAMETERS; 347 goto err; 348 } 349 350 bufferlen = *valueBufferLen; 351 352 res = propget_get_property(propsetOrEnumerator, name, &pv); 353 if (res != TEE_SUCCESS) 354 goto err; 355 356 switch (pv.type) { 357 case USER_TA_PROP_TYPE_BOOL: 358 l = strlcpy(valueBuffer, pv.u.bool_val ? "true" : "false", 359 bufferlen); 360 break; 361 362 case USER_TA_PROP_TYPE_U32: 363 l = snprintf(valueBuffer, bufferlen, "%u", 364 (unsigned int)pv.u.int_val); 365 break; 366 367 case USER_TA_PROP_TYPE_UUID: 368 l = snprintf(valueBuffer, bufferlen, 369 "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", 370 (unsigned int)pv.u.uuid_val.timeLow, 371 pv.u.uuid_val.timeMid, 372 pv.u.uuid_val.timeHiAndVersion, 373 pv.u.uuid_val.clockSeqAndNode[0], 374 pv.u.uuid_val.clockSeqAndNode[1], 375 pv.u.uuid_val.clockSeqAndNode[2], 376 pv.u.uuid_val.clockSeqAndNode[3], 377 pv.u.uuid_val.clockSeqAndNode[4], 378 pv.u.uuid_val.clockSeqAndNode[5], 379 pv.u.uuid_val.clockSeqAndNode[6], 380 pv.u.uuid_val.clockSeqAndNode[7]); 381 break; 382 383 case USER_TA_PROP_TYPE_IDENTITY: 384 l = snprintf(valueBuffer, bufferlen, 385 "%u:%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", 386 (unsigned int)pv.u.identity_val.login, 387 (unsigned int)pv.u.identity_val.uuid.timeLow, 388 pv.u.identity_val.uuid.timeMid, 389 pv.u.identity_val.uuid.timeHiAndVersion, 390 pv.u.identity_val.uuid.clockSeqAndNode[0], 391 pv.u.identity_val.uuid.clockSeqAndNode[1], 392 pv.u.identity_val.uuid.clockSeqAndNode[2], 393 pv.u.identity_val.uuid.clockSeqAndNode[3], 394 pv.u.identity_val.uuid.clockSeqAndNode[4], 395 pv.u.identity_val.uuid.clockSeqAndNode[5], 396 pv.u.identity_val.uuid.clockSeqAndNode[6], 397 pv.u.identity_val.uuid.clockSeqAndNode[7]); 398 break; 399 400 case USER_TA_PROP_TYPE_STRING: 401 case USER_TA_PROP_TYPE_BINARY_BLOCK: 402 l = strlcpy(valueBuffer, pv.u.str_val, bufferlen); 403 break; 404 405 default: 406 res = TEE_ERROR_BAD_FORMAT; 407 goto err; 408 } 409 410 /* The size "must account for the zero terminator" */ 411 *valueBufferLen = l + 1; 412 413 if (l >= bufferlen) { 414 res = TEE_ERROR_SHORT_BUFFER; 415 goto err; 416 } 417 418 goto out; 419 420 err: 421 if (res == TEE_ERROR_ITEM_NOT_FOUND || 422 res == TEE_ERROR_SHORT_BUFFER) 423 return res; 424 TEE_Panic(0); 425 out: 426 return TEE_SUCCESS; 427 } 428 429 TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator, 430 char *name, bool *value) 431 { 432 TEE_Result res; 433 struct prop_value pv; 434 435 if (value == NULL) { 436 res = TEE_ERROR_BAD_PARAMETERS; 437 goto err; 438 } 439 440 res = propget_get_property(propsetOrEnumerator, name, &pv); 441 if (res != TEE_SUCCESS) 442 goto err; 443 444 if (pv.type != USER_TA_PROP_TYPE_BOOL) { 445 res = TEE_ERROR_BAD_FORMAT; 446 goto err; 447 } 448 449 *value = pv.u.bool_val; 450 451 goto out; 452 453 err: 454 if (res == TEE_ERROR_ITEM_NOT_FOUND || 455 res == TEE_ERROR_BAD_FORMAT) 456 return res; 457 TEE_Panic(0); 458 out: 459 return TEE_SUCCESS; 460 } 461 462 TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator, 463 char *name, uint32_t *value) 464 { 465 TEE_Result res; 466 struct prop_value pv; 467 468 if (value == NULL) { 469 res = TEE_ERROR_BAD_PARAMETERS; 470 goto err; 471 } 472 473 res = propget_get_property(propsetOrEnumerator, name, &pv); 474 if (res != TEE_SUCCESS) 475 goto err; 476 477 if (pv.type != USER_TA_PROP_TYPE_U32) { 478 res = TEE_ERROR_BAD_FORMAT; 479 goto err; 480 } 481 482 *value = pv.u.int_val; 483 484 goto out; 485 486 err: 487 if (res == TEE_ERROR_ITEM_NOT_FOUND || 488 res == TEE_ERROR_BAD_FORMAT) 489 return res; 490 TEE_Panic(0); 491 out: 492 return TEE_SUCCESS; 493 } 494 495 TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, 496 char *name, void *valueBuffer, 497 uint32_t *valueBufferLen) 498 { 499 TEE_Result res; 500 struct prop_value pv; 501 void *val; 502 int val_len; 503 size_t size; 504 505 if (valueBuffer == NULL || valueBufferLen == NULL) { 506 res = TEE_ERROR_BAD_PARAMETERS; 507 goto err; 508 } 509 510 res = propget_get_property(propsetOrEnumerator, name, &pv); 511 if (res != TEE_SUCCESS) 512 goto err; 513 514 if (pv.type != USER_TA_PROP_TYPE_BINARY_BLOCK) { 515 res = TEE_ERROR_BAD_FORMAT; 516 goto err; 517 } 518 519 val = pv.u.str_val; 520 val_len = strlen(val); 521 size = *valueBufferLen; 522 if (!base64_dec(val, val_len, valueBuffer, &size)) { 523 res = TEE_ERROR_SHORT_BUFFER; 524 goto err; 525 } 526 527 *valueBufferLen = size; 528 529 goto out; 530 531 err: 532 if (res == TEE_ERROR_ITEM_NOT_FOUND || 533 res == TEE_ERROR_BAD_FORMAT || 534 res == TEE_ERROR_SHORT_BUFFER) 535 return res; 536 TEE_Panic(0); 537 out: 538 return TEE_SUCCESS; 539 } 540 541 TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator, 542 char *name, TEE_UUID *value) 543 { 544 TEE_Result res; 545 struct prop_value pv; 546 547 if (value == NULL) { 548 res = TEE_ERROR_BAD_PARAMETERS; 549 goto err; 550 } 551 552 res = propget_get_property(propsetOrEnumerator, name, &pv); 553 if (res != TEE_SUCCESS) 554 goto err; 555 556 if (pv.type != USER_TA_PROP_TYPE_UUID) { 557 res = TEE_ERROR_BAD_FORMAT; 558 goto err; 559 } 560 561 *value = pv.u.uuid_val; /* struct copy */ 562 563 goto out; 564 565 err: 566 if (res == TEE_ERROR_ITEM_NOT_FOUND || 567 res == TEE_ERROR_BAD_FORMAT) 568 return res; 569 TEE_Panic(0); 570 out: 571 return TEE_SUCCESS; 572 } 573 574 TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator, 575 char *name, TEE_Identity *value) 576 { 577 TEE_Result res; 578 struct prop_value pv; 579 580 if (value == NULL) { 581 res = TEE_ERROR_BAD_PARAMETERS; 582 goto err; 583 } 584 585 res = propget_get_property(propsetOrEnumerator, name, &pv); 586 if (res != TEE_SUCCESS) 587 goto err; 588 589 if (pv.type != USER_TA_PROP_TYPE_IDENTITY) { 590 res = TEE_ERROR_BAD_FORMAT; 591 goto err; 592 } 593 594 *value = pv.u.identity_val; /* struct copy */ 595 596 goto out; 597 598 err: 599 if (res == TEE_ERROR_ITEM_NOT_FOUND || 600 res == TEE_ERROR_BAD_FORMAT) 601 return res; 602 TEE_Panic(0); 603 out: 604 return TEE_SUCCESS; 605 } 606 607 TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator) 608 { 609 TEE_Result res; 610 struct prop_enumerator *pe; 611 612 if (enumerator == NULL) { 613 res = TEE_ERROR_BAD_PARAMETERS; 614 goto err; 615 } 616 617 pe = TEE_Malloc(sizeof(struct prop_enumerator), 618 TEE_USER_MEM_HINT_NO_FILL_ZERO); 619 if (pe == NULL) { 620 res = TEE_ERROR_OUT_OF_MEMORY; 621 goto err; 622 } 623 624 *enumerator = (TEE_PropSetHandle) pe; 625 TEE_ResetPropertyEnumerator(*enumerator); 626 627 goto out; 628 629 err: 630 if (res == TEE_ERROR_OUT_OF_MEMORY) 631 return res; 632 TEE_Panic(0); 633 out: 634 return TEE_SUCCESS; 635 } 636 637 void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator) 638 { 639 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 640 641 pe->idx = PROP_ENUMERATOR_NOT_STARTED; 642 } 643 644 void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator) 645 { 646 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 647 648 TEE_Free(pe); 649 } 650 651 void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator, 652 TEE_PropSetHandle propSet) 653 { 654 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 655 656 if (pe == NULL) 657 return; 658 659 pe->idx = 0; 660 pe->prop_set = propSet; 661 } 662 663 TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator, 664 void *nameBuffer, uint32_t *nameBufferLen) 665 { 666 TEE_Result res; 667 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 668 const struct prop_set *ps; 669 size_t ps_len; 670 const struct user_ta_property *eps; 671 size_t eps_len; 672 size_t l; 673 const char *str; 674 size_t bufferlen; 675 676 if (pe == NULL || nameBuffer == NULL || nameBufferLen == NULL) { 677 res = TEE_ERROR_BAD_PARAMETERS; 678 goto err; 679 } 680 681 bufferlen = *nameBufferLen; 682 res = propset_get(pe->prop_set, &ps, &ps_len, &eps, &eps_len); 683 if (res != TEE_SUCCESS) 684 goto err; 685 686 if (pe->idx < ps_len) 687 str = ps[pe->idx].str; 688 else if ((pe->idx - ps_len) < eps_len) 689 str = ta_props[pe->idx - ps_len].name; 690 else { 691 res = TEE_ERROR_ITEM_NOT_FOUND; 692 goto err; 693 } 694 695 l = strlcpy(nameBuffer, str, bufferlen); 696 697 /* The size "must account for the zero terminator" */ 698 *nameBufferLen = l + 1; 699 700 if (l >= bufferlen) { 701 res = TEE_ERROR_SHORT_BUFFER; 702 goto err; 703 } 704 705 goto out; 706 707 err: 708 if (res == TEE_ERROR_ITEM_NOT_FOUND || 709 res == TEE_ERROR_SHORT_BUFFER) 710 return res; 711 TEE_Panic(0); 712 out: 713 return TEE_SUCCESS; 714 } 715 716 TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator) 717 { 718 TEE_Result res; 719 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 720 uint32_t next_idx; 721 const struct prop_set *ps; 722 size_t ps_len; 723 const struct user_ta_property *eps; 724 size_t eps_len; 725 726 if (pe == NULL) { 727 res = TEE_ERROR_BAD_PARAMETERS; 728 goto err; 729 } 730 731 if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) { 732 res = TEE_ERROR_ITEM_NOT_FOUND; 733 goto err; 734 } 735 736 res = propset_get(pe->prop_set, &ps, &ps_len, &eps, &eps_len); 737 if (res != TEE_SUCCESS) 738 goto err; 739 740 next_idx = pe->idx + 1; 741 pe->idx = next_idx; 742 if (next_idx >= (ps_len + eps_len)) { 743 res = TEE_ERROR_ITEM_NOT_FOUND; 744 goto err; 745 } 746 747 goto out; 748 749 err: 750 if (res == TEE_ERROR_ITEM_NOT_FOUND) 751 return res; 752 TEE_Panic(0); 753 out: 754 return TEE_SUCCESS; 755 } 756