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 const struct prop_set propset_current_ta[] = { 129 {"gpd.ta.appID", propget_gpd_ta_app_id}, 130 }; 131 132 static const size_t propset_current_ta_len = 133 sizeof(propset_current_ta) / sizeof(propset_current_ta[0]); 134 135 static const struct prop_set propset_current_client[] = { 136 {"gpd.client.identity", propget_gpd_client_identity}, 137 }; 138 139 static const size_t propset_current_client_len = 140 sizeof(propset_current_client) / sizeof(propset_current_client[0]); 141 142 static const struct prop_set propset_implementation[] = { 143 {"gpd.tee.apiversion", propget_gpd_tee_api_version}, 144 {"gpd.tee.description", propget_gpd_tee_description}, 145 {"gpd.tee.deviceID", propget_gpd_tee_device_id}, 146 {"gpd.tee.systemTime.protectionLevel", 147 propget_gpd_tee_sys_time_protection_level}, 148 {"gpd.tee.TAPersistentTime.protectionLevel", 149 propget_gpd_tee_ta_time_protection_level}, 150 {"gpd.tee.arith.maxBigIntSize", propget_gpd_tee_arith_max_big_int_size}, 151 }; 152 153 static const size_t propset_implementation_len = 154 sizeof(propset_implementation) / sizeof(propset_implementation[0]); 155 156 static TEE_Result propset_get(TEE_PropSetHandle h, const struct prop_set **ps, 157 size_t *ps_len, 158 const struct user_ta_property **eps, 159 size_t *eps_len) 160 { 161 if (h == TEE_PROPSET_CURRENT_TA) { 162 *ps = propset_current_ta; 163 *ps_len = propset_current_ta_len; 164 *eps = ta_props; 165 *eps_len = ta_num_props; 166 } else if (h == TEE_PROPSET_CURRENT_CLIENT) { 167 *ps = propset_current_client; 168 *ps_len = propset_current_client_len; 169 *eps = NULL; 170 *eps_len = 0; 171 } else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) { 172 *ps = propset_implementation; 173 *ps_len = propset_implementation_len; 174 *eps = NULL; 175 *eps_len = 0; 176 } else { 177 return TEE_ERROR_ITEM_NOT_FOUND; 178 } 179 180 return TEE_SUCCESS; 181 } 182 183 static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep, 184 struct prop_value *pv) 185 { 186 size_t l; 187 188 pv->type = ep->type; 189 switch (ep->type) { 190 case USER_TA_PROP_TYPE_BOOL: 191 l = sizeof(bool); 192 break; 193 case USER_TA_PROP_TYPE_U32: 194 l = sizeof(uint32_t); 195 break; 196 case USER_TA_PROP_TYPE_UUID: 197 l = sizeof(TEE_UUID); 198 break; 199 case USER_TA_PROP_TYPE_IDENTITY: 200 l = sizeof(TEE_Identity); 201 break; 202 case USER_TA_PROP_TYPE_STRING: 203 case USER_TA_PROP_TYPE_BINARY_BLOCK: 204 /* Handle too large strings by truncating them */ 205 strlcpy(pv->u.str_val, ep->value, sizeof(pv->u.str_val)); 206 return TEE_SUCCESS; 207 default: 208 return TEE_ERROR_GENERIC; 209 } 210 memcpy(&pv->u, ep->value, l); 211 return TEE_SUCCESS; 212 } 213 214 static TEE_Result propget_get_property(TEE_PropSetHandle h, char *name, 215 struct prop_value *pv) 216 { 217 TEE_Result res; 218 const struct prop_set *ps; 219 size_t ps_len; 220 const struct user_ta_property *eps; 221 size_t eps_len; 222 223 if (h == TEE_PROPSET_CURRENT_TA || h == TEE_PROPSET_CURRENT_CLIENT || 224 h == TEE_PROPSET_TEE_IMPLEMENTATION) { 225 size_t n; 226 227 res = propset_get(h, &ps, &ps_len, &eps, &eps_len); 228 if (res != TEE_SUCCESS) 229 return res; 230 231 for (n = 0; n < ps_len; n++) { 232 if (strcmp(name, ps[n].str) == 0) 233 return ps[n].get(pv); 234 } 235 for (n = 0; n < eps_len; n++) { 236 if (strcmp(name, eps[n].name) == 0) 237 return propget_get_ext_prop(eps + n, pv); 238 } 239 return TEE_ERROR_ITEM_NOT_FOUND; 240 } else { 241 struct prop_enumerator *pe = (struct prop_enumerator *)h; 242 uint32_t idx = pe->idx; 243 244 if (idx == PROP_ENUMERATOR_NOT_STARTED) 245 return TEE_ERROR_ITEM_NOT_FOUND; 246 247 res = propset_get(pe->prop_set, &ps, &ps_len, &eps, &eps_len); 248 if (res != TEE_SUCCESS) 249 return res; 250 251 if (idx < ps_len) 252 return ps[idx].get(pv); 253 254 idx -= ps_len; 255 if (idx < eps_len) 256 return propget_get_ext_prop(eps + idx, pv); 257 258 return TEE_ERROR_BAD_PARAMETERS; 259 } 260 } 261 262 TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, 263 char *name, char *valueBuffer, 264 uint32_t *valueBufferLen) 265 { 266 TEE_Result res; 267 struct prop_value pv; 268 size_t l; 269 size_t bufferlen; 270 271 if (valueBuffer == NULL || valueBufferLen == NULL) { 272 res = TEE_ERROR_BAD_PARAMETERS; 273 goto err; 274 } 275 276 bufferlen = *valueBufferLen; 277 278 res = propget_get_property(propsetOrEnumerator, name, &pv); 279 if (res != TEE_SUCCESS) 280 goto err; 281 282 switch (pv.type) { 283 case USER_TA_PROP_TYPE_BOOL: 284 l = strlcpy(valueBuffer, pv.u.bool_val ? "true" : "false", 285 bufferlen); 286 break; 287 288 case USER_TA_PROP_TYPE_U32: 289 l = snprintf(valueBuffer, bufferlen, "%u", 290 (unsigned int)pv.u.int_val); 291 break; 292 293 case USER_TA_PROP_TYPE_UUID: 294 l = snprintf(valueBuffer, bufferlen, 295 "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", 296 (unsigned int)pv.u.uuid_val.timeLow, 297 pv.u.uuid_val.timeMid, 298 pv.u.uuid_val.timeHiAndVersion, 299 pv.u.uuid_val.clockSeqAndNode[0], 300 pv.u.uuid_val.clockSeqAndNode[1], 301 pv.u.uuid_val.clockSeqAndNode[2], 302 pv.u.uuid_val.clockSeqAndNode[3], 303 pv.u.uuid_val.clockSeqAndNode[4], 304 pv.u.uuid_val.clockSeqAndNode[5], 305 pv.u.uuid_val.clockSeqAndNode[6], 306 pv.u.uuid_val.clockSeqAndNode[7]); 307 break; 308 309 case USER_TA_PROP_TYPE_IDENTITY: 310 l = snprintf(valueBuffer, bufferlen, 311 "%u:%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", 312 (unsigned int)pv.u.identity_val.login, 313 (unsigned int)pv.u.identity_val.uuid.timeLow, 314 pv.u.identity_val.uuid.timeMid, 315 pv.u.identity_val.uuid.timeHiAndVersion, 316 pv.u.identity_val.uuid.clockSeqAndNode[0], 317 pv.u.identity_val.uuid.clockSeqAndNode[1], 318 pv.u.identity_val.uuid.clockSeqAndNode[2], 319 pv.u.identity_val.uuid.clockSeqAndNode[3], 320 pv.u.identity_val.uuid.clockSeqAndNode[4], 321 pv.u.identity_val.uuid.clockSeqAndNode[5], 322 pv.u.identity_val.uuid.clockSeqAndNode[6], 323 pv.u.identity_val.uuid.clockSeqAndNode[7]); 324 break; 325 326 case USER_TA_PROP_TYPE_STRING: 327 case USER_TA_PROP_TYPE_BINARY_BLOCK: 328 l = strlcpy(valueBuffer, pv.u.str_val, bufferlen); 329 break; 330 331 default: 332 res = TEE_ERROR_BAD_FORMAT; 333 goto err; 334 } 335 336 /* The size "must account for the zero terminator" */ 337 *valueBufferLen = l + 1; 338 339 if (l >= bufferlen) { 340 res = TEE_ERROR_SHORT_BUFFER; 341 goto err; 342 } 343 344 goto out; 345 346 err: 347 if (res == TEE_ERROR_ITEM_NOT_FOUND || 348 res == TEE_ERROR_SHORT_BUFFER) 349 return res; 350 TEE_Panic(0); 351 out: 352 return TEE_SUCCESS; 353 } 354 355 TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator, 356 char *name, bool *value) 357 { 358 TEE_Result res; 359 struct prop_value pv; 360 361 if (value == NULL) { 362 res = TEE_ERROR_BAD_PARAMETERS; 363 goto err; 364 } 365 366 res = propget_get_property(propsetOrEnumerator, name, &pv); 367 if (res != TEE_SUCCESS) 368 goto err; 369 370 if (pv.type != USER_TA_PROP_TYPE_BOOL) { 371 res = TEE_ERROR_BAD_FORMAT; 372 goto err; 373 } 374 375 *value = pv.u.bool_val; 376 377 goto out; 378 379 err: 380 if (res == TEE_ERROR_ITEM_NOT_FOUND || 381 res == TEE_ERROR_BAD_FORMAT) 382 return res; 383 TEE_Panic(0); 384 out: 385 return TEE_SUCCESS; 386 } 387 388 TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator, 389 char *name, uint32_t *value) 390 { 391 TEE_Result res; 392 struct prop_value pv; 393 394 if (value == NULL) { 395 res = TEE_ERROR_BAD_PARAMETERS; 396 goto err; 397 } 398 399 res = propget_get_property(propsetOrEnumerator, name, &pv); 400 if (res != TEE_SUCCESS) 401 goto err; 402 403 if (pv.type != USER_TA_PROP_TYPE_U32) { 404 res = TEE_ERROR_BAD_FORMAT; 405 goto err; 406 } 407 408 *value = pv.u.int_val; 409 410 goto out; 411 412 err: 413 if (res == TEE_ERROR_ITEM_NOT_FOUND || 414 res == TEE_ERROR_BAD_FORMAT) 415 return res; 416 TEE_Panic(0); 417 out: 418 return TEE_SUCCESS; 419 } 420 421 TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, 422 char *name, void *valueBuffer, 423 uint32_t *valueBufferLen) 424 { 425 TEE_Result res; 426 struct prop_value pv; 427 void *val; 428 int val_len; 429 size_t size; 430 431 if (valueBuffer == NULL || valueBufferLen == NULL) { 432 res = TEE_ERROR_BAD_PARAMETERS; 433 goto err; 434 } 435 436 res = propget_get_property(propsetOrEnumerator, name, &pv); 437 if (res != TEE_SUCCESS) 438 goto err; 439 440 if (pv.type != USER_TA_PROP_TYPE_BINARY_BLOCK) { 441 res = TEE_ERROR_BAD_FORMAT; 442 goto err; 443 } 444 445 val = pv.u.str_val; 446 val_len = strlen(val); 447 size = *valueBufferLen; 448 if (!base64_dec(val, val_len, valueBuffer, &size)) { 449 res = TEE_ERROR_SHORT_BUFFER; 450 goto err; 451 } 452 453 *valueBufferLen = size; 454 455 goto out; 456 457 err: 458 if (res == TEE_ERROR_ITEM_NOT_FOUND || 459 res == TEE_ERROR_BAD_FORMAT || 460 res == TEE_ERROR_SHORT_BUFFER) 461 return res; 462 TEE_Panic(0); 463 out: 464 return TEE_SUCCESS; 465 } 466 467 TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator, 468 char *name, TEE_UUID *value) 469 { 470 TEE_Result res; 471 struct prop_value pv; 472 473 if (value == NULL) { 474 res = TEE_ERROR_BAD_PARAMETERS; 475 goto err; 476 } 477 478 res = propget_get_property(propsetOrEnumerator, name, &pv); 479 if (res != TEE_SUCCESS) 480 goto err; 481 482 if (pv.type != USER_TA_PROP_TYPE_UUID) { 483 res = TEE_ERROR_BAD_FORMAT; 484 goto err; 485 } 486 487 *value = pv.u.uuid_val; /* struct copy */ 488 489 goto out; 490 491 err: 492 if (res == TEE_ERROR_ITEM_NOT_FOUND || 493 res == TEE_ERROR_BAD_FORMAT) 494 return res; 495 TEE_Panic(0); 496 out: 497 return TEE_SUCCESS; 498 } 499 500 TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator, 501 char *name, TEE_Identity *value) 502 { 503 TEE_Result res; 504 struct prop_value pv; 505 506 if (value == NULL) { 507 res = TEE_ERROR_BAD_PARAMETERS; 508 goto err; 509 } 510 511 res = propget_get_property(propsetOrEnumerator, name, &pv); 512 if (res != TEE_SUCCESS) 513 goto err; 514 515 if (pv.type != USER_TA_PROP_TYPE_IDENTITY) { 516 res = TEE_ERROR_BAD_FORMAT; 517 goto err; 518 } 519 520 *value = pv.u.identity_val; /* struct copy */ 521 522 goto out; 523 524 err: 525 if (res == TEE_ERROR_ITEM_NOT_FOUND || 526 res == TEE_ERROR_BAD_FORMAT) 527 return res; 528 TEE_Panic(0); 529 out: 530 return TEE_SUCCESS; 531 } 532 533 TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator) 534 { 535 TEE_Result res; 536 struct prop_enumerator *pe; 537 538 if (enumerator == NULL) { 539 res = TEE_ERROR_BAD_PARAMETERS; 540 goto err; 541 } 542 543 pe = TEE_Malloc(sizeof(struct prop_enumerator), 544 TEE_USER_MEM_HINT_NO_FILL_ZERO); 545 if (pe == NULL) { 546 res = TEE_ERROR_OUT_OF_MEMORY; 547 goto err; 548 } 549 550 *enumerator = (TEE_PropSetHandle) pe; 551 TEE_ResetPropertyEnumerator(*enumerator); 552 553 goto out; 554 555 err: 556 if (res == TEE_ERROR_OUT_OF_MEMORY) 557 return res; 558 TEE_Panic(0); 559 out: 560 return TEE_SUCCESS; 561 } 562 563 void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator) 564 { 565 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 566 567 pe->idx = PROP_ENUMERATOR_NOT_STARTED; 568 } 569 570 void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator) 571 { 572 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 573 574 TEE_Free(pe); 575 } 576 577 void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator, 578 TEE_PropSetHandle propSet) 579 { 580 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 581 582 if (pe == NULL) 583 return; 584 585 pe->idx = 0; 586 pe->prop_set = propSet; 587 } 588 589 TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator, 590 void *nameBuffer, uint32_t *nameBufferLen) 591 { 592 TEE_Result res; 593 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 594 const struct prop_set *ps; 595 size_t ps_len; 596 const struct user_ta_property *eps; 597 size_t eps_len; 598 size_t l; 599 const char *str; 600 size_t bufferlen; 601 602 if (pe == NULL || nameBuffer == NULL || nameBufferLen == NULL) { 603 res = TEE_ERROR_BAD_PARAMETERS; 604 goto err; 605 } 606 607 bufferlen = *nameBufferLen; 608 res = propset_get(pe->prop_set, &ps, &ps_len, &eps, &eps_len); 609 if (res != TEE_SUCCESS) 610 goto err; 611 612 if (pe->idx < ps_len) 613 str = ps[pe->idx].str; 614 else if ((pe->idx - ps_len) < eps_len) 615 str = ta_props[pe->idx - ps_len].name; 616 else { 617 res = TEE_ERROR_ITEM_NOT_FOUND; 618 goto err; 619 } 620 621 l = strlcpy(nameBuffer, str, bufferlen); 622 623 /* The size "must account for the zero terminator" */ 624 *nameBufferLen = l + 1; 625 626 if (l >= bufferlen) { 627 res = TEE_ERROR_SHORT_BUFFER; 628 goto err; 629 } 630 631 goto out; 632 633 err: 634 if (res == TEE_ERROR_ITEM_NOT_FOUND || 635 res == TEE_ERROR_SHORT_BUFFER) 636 return res; 637 TEE_Panic(0); 638 out: 639 return TEE_SUCCESS; 640 } 641 642 TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator) 643 { 644 TEE_Result res; 645 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 646 uint32_t next_idx; 647 const struct prop_set *ps; 648 size_t ps_len; 649 const struct user_ta_property *eps; 650 size_t eps_len; 651 652 if (pe == NULL) { 653 res = TEE_ERROR_BAD_PARAMETERS; 654 goto err; 655 } 656 657 if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) { 658 res = TEE_ERROR_ITEM_NOT_FOUND; 659 goto err; 660 } 661 662 res = propset_get(pe->prop_set, &ps, &ps_len, &eps, &eps_len); 663 if (res != TEE_SUCCESS) 664 goto err; 665 666 next_idx = pe->idx + 1; 667 pe->idx = next_idx; 668 if (next_idx >= (ps_len + eps_len)) { 669 res = TEE_ERROR_ITEM_NOT_FOUND; 670 goto err; 671 } 672 673 goto out; 674 675 err: 676 if (res == TEE_ERROR_ITEM_NOT_FOUND) 677 return res; 678 TEE_Panic(0); 679 out: 680 return TEE_SUCCESS; 681 } 682