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 #include <util.h> 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; /* current index */ 49 TEE_PropSetHandle prop_set; /* part of TEE_PROPSET_xxx */ 50 }; 51 52 struct prop_value { 53 enum user_ta_prop_type type; 54 union { 55 uint32_t 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 const struct user_ta_property tee_props[] = { 64 { 65 "gpd.tee.arith.maxBigIntSize", 66 USER_TA_PROP_TYPE_U32, 67 &(const uint32_t){TEE_MAX_NUMBER_OF_SUPPORTED_BITS} 68 }, 69 }; 70 71 static TEE_Result propset_get(TEE_PropSetHandle h, 72 const struct user_ta_property **eps, 73 size_t *eps_len) 74 { 75 if (h == TEE_PROPSET_CURRENT_TA) { 76 *eps = ta_props; 77 *eps_len = ta_num_props; 78 } else if (h == TEE_PROPSET_CURRENT_CLIENT) { 79 *eps = NULL; 80 *eps_len = 0; 81 } else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) { 82 *eps = tee_props; 83 *eps_len = ARRAY_SIZE(tee_props); 84 } else { 85 return TEE_ERROR_ITEM_NOT_FOUND; 86 } 87 88 return TEE_SUCCESS; 89 } 90 91 static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep, 92 struct prop_value *pv) 93 { 94 size_t l; 95 96 pv->type = ep->type; 97 switch (ep->type) { 98 case USER_TA_PROP_TYPE_BOOL: 99 l = sizeof(uint32_t); 100 break; 101 case USER_TA_PROP_TYPE_U32: 102 l = sizeof(uint32_t); 103 break; 104 case USER_TA_PROP_TYPE_UUID: 105 l = sizeof(TEE_UUID); 106 break; 107 case USER_TA_PROP_TYPE_IDENTITY: 108 l = sizeof(TEE_Identity); 109 break; 110 case USER_TA_PROP_TYPE_STRING: 111 case USER_TA_PROP_TYPE_BINARY_BLOCK: 112 /* Handle too large strings by truncating them */ 113 strlcpy(pv->u.str_val, ep->value, sizeof(pv->u.str_val)); 114 return TEE_SUCCESS; 115 default: 116 return TEE_ERROR_GENERIC; 117 } 118 memcpy(&pv->u, ep->value, l); 119 return TEE_SUCCESS; 120 } 121 122 static TEE_Result propget_get_property(TEE_PropSetHandle h, char *name, 123 struct prop_value *pv) 124 { 125 TEE_Result res; 126 const struct user_ta_property *eps; 127 size_t eps_len; 128 uint32_t prop_type; 129 uint32_t index; 130 uint32_t size; 131 132 if (h == TEE_PROPSET_CURRENT_TA || h == TEE_PROPSET_CURRENT_CLIENT || 133 h == TEE_PROPSET_TEE_IMPLEMENTATION) { 134 size_t n; 135 136 res = propset_get(h, &eps, &eps_len); 137 if (res != TEE_SUCCESS) 138 return res; 139 140 for (n = 0; n < eps_len; n++) { 141 if (!strcmp(name, eps[n].name)) 142 return propget_get_ext_prop(eps + n, pv); 143 } 144 145 /* get the index from the name */ 146 res = utee_get_property_name_to_index((unsigned long)h, name, 147 strlen(name) + 1, &index); 148 if (res != TEE_SUCCESS) 149 return res; 150 size = sizeof(pv->u); 151 res = utee_get_property((unsigned long)h, index, 0, 0, 152 &pv->u, &size, &prop_type); 153 } else { 154 struct prop_enumerator *pe = (struct prop_enumerator *)h; 155 uint32_t idx = pe->idx; 156 157 if (idx == PROP_ENUMERATOR_NOT_STARTED) 158 return TEE_ERROR_ITEM_NOT_FOUND; 159 160 res = propset_get(pe->prop_set, &eps, &eps_len); 161 if (res != TEE_SUCCESS) 162 return res; 163 164 if (idx < eps_len) 165 return propget_get_ext_prop(eps + idx, pv); 166 idx -= eps_len; 167 168 size = sizeof(pv->u); 169 res = utee_get_property((unsigned long)pe->prop_set, idx, 170 0, 0, &pv->u, &size, &prop_type); 171 if (res == TEE_ERROR_ITEM_NOT_FOUND) 172 res = TEE_ERROR_BAD_PARAMETERS; 173 } 174 175 if (res == TEE_SUCCESS) 176 pv->type = prop_type; 177 return res; 178 } 179 180 TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, 181 char *name, char *valueBuffer, 182 uint32_t *valueBufferLen) 183 { 184 TEE_Result res; 185 struct prop_value pv; 186 size_t l; 187 size_t bufferlen; 188 189 if (valueBuffer == NULL || valueBufferLen == NULL) { 190 res = TEE_ERROR_BAD_PARAMETERS; 191 goto err; 192 } 193 194 bufferlen = *valueBufferLen; 195 196 res = propget_get_property(propsetOrEnumerator, name, &pv); 197 if (res != TEE_SUCCESS) 198 goto err; 199 200 switch (pv.type) { 201 case USER_TA_PROP_TYPE_BOOL: 202 l = strlcpy(valueBuffer, pv.u.bool_val ? "true" : "false", 203 bufferlen); 204 break; 205 206 case USER_TA_PROP_TYPE_U32: 207 l = snprintf(valueBuffer, bufferlen, "%u", 208 (unsigned int)pv.u.int_val); 209 break; 210 211 case USER_TA_PROP_TYPE_UUID: 212 l = snprintf(valueBuffer, bufferlen, 213 "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", 214 (unsigned int)pv.u.uuid_val.timeLow, 215 pv.u.uuid_val.timeMid, 216 pv.u.uuid_val.timeHiAndVersion, 217 pv.u.uuid_val.clockSeqAndNode[0], 218 pv.u.uuid_val.clockSeqAndNode[1], 219 pv.u.uuid_val.clockSeqAndNode[2], 220 pv.u.uuid_val.clockSeqAndNode[3], 221 pv.u.uuid_val.clockSeqAndNode[4], 222 pv.u.uuid_val.clockSeqAndNode[5], 223 pv.u.uuid_val.clockSeqAndNode[6], 224 pv.u.uuid_val.clockSeqAndNode[7]); 225 break; 226 227 case USER_TA_PROP_TYPE_IDENTITY: 228 l = snprintf(valueBuffer, bufferlen, 229 "%u:%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", 230 (unsigned int)pv.u.identity_val.login, 231 (unsigned int)pv.u.identity_val.uuid.timeLow, 232 pv.u.identity_val.uuid.timeMid, 233 pv.u.identity_val.uuid.timeHiAndVersion, 234 pv.u.identity_val.uuid.clockSeqAndNode[0], 235 pv.u.identity_val.uuid.clockSeqAndNode[1], 236 pv.u.identity_val.uuid.clockSeqAndNode[2], 237 pv.u.identity_val.uuid.clockSeqAndNode[3], 238 pv.u.identity_val.uuid.clockSeqAndNode[4], 239 pv.u.identity_val.uuid.clockSeqAndNode[5], 240 pv.u.identity_val.uuid.clockSeqAndNode[6], 241 pv.u.identity_val.uuid.clockSeqAndNode[7]); 242 break; 243 244 case USER_TA_PROP_TYPE_STRING: 245 case USER_TA_PROP_TYPE_BINARY_BLOCK: 246 l = strlcpy(valueBuffer, pv.u.str_val, bufferlen); 247 break; 248 249 default: 250 res = TEE_ERROR_BAD_FORMAT; 251 goto err; 252 } 253 254 /* The size "must account for the zero terminator" */ 255 *valueBufferLen = l + 1; 256 257 if (l >= bufferlen) { 258 res = TEE_ERROR_SHORT_BUFFER; 259 goto err; 260 } 261 262 goto out; 263 264 err: 265 if (res == TEE_ERROR_ITEM_NOT_FOUND || 266 res == TEE_ERROR_SHORT_BUFFER) 267 return res; 268 TEE_Panic(0); 269 out: 270 return TEE_SUCCESS; 271 } 272 273 TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator, 274 char *name, bool *value) 275 { 276 TEE_Result res; 277 struct prop_value pv; 278 279 if (value == NULL) { 280 res = TEE_ERROR_BAD_PARAMETERS; 281 goto err; 282 } 283 284 res = propget_get_property(propsetOrEnumerator, name, &pv); 285 if (res != TEE_SUCCESS) 286 goto err; 287 288 if (pv.type != USER_TA_PROP_TYPE_BOOL) { 289 res = TEE_ERROR_BAD_FORMAT; 290 goto err; 291 } 292 293 *value = !!pv.u.bool_val; 294 295 goto out; 296 297 err: 298 if (res == TEE_ERROR_ITEM_NOT_FOUND || 299 res == TEE_ERROR_BAD_FORMAT) 300 return res; 301 TEE_Panic(0); 302 out: 303 return TEE_SUCCESS; 304 } 305 306 TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator, 307 char *name, uint32_t *value) 308 { 309 TEE_Result res; 310 struct prop_value pv; 311 312 if (value == NULL) { 313 res = TEE_ERROR_BAD_PARAMETERS; 314 goto err; 315 } 316 317 res = propget_get_property(propsetOrEnumerator, name, &pv); 318 if (res != TEE_SUCCESS) 319 goto err; 320 321 if (pv.type != USER_TA_PROP_TYPE_U32) { 322 res = TEE_ERROR_BAD_FORMAT; 323 goto err; 324 } 325 326 *value = pv.u.int_val; 327 328 goto out; 329 330 err: 331 if (res == TEE_ERROR_ITEM_NOT_FOUND || 332 res == TEE_ERROR_BAD_FORMAT) 333 return res; 334 TEE_Panic(0); 335 out: 336 return TEE_SUCCESS; 337 } 338 339 TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, 340 char *name, void *valueBuffer, 341 uint32_t *valueBufferLen) 342 { 343 TEE_Result res; 344 struct prop_value pv; 345 void *val; 346 int val_len; 347 size_t size; 348 349 if (valueBuffer == NULL || valueBufferLen == NULL) { 350 res = TEE_ERROR_BAD_PARAMETERS; 351 goto err; 352 } 353 354 res = propget_get_property(propsetOrEnumerator, name, &pv); 355 if (res != TEE_SUCCESS) 356 goto err; 357 358 if (pv.type != USER_TA_PROP_TYPE_BINARY_BLOCK) { 359 res = TEE_ERROR_BAD_FORMAT; 360 goto err; 361 } 362 363 val = pv.u.str_val; 364 val_len = strlen(val); 365 size = *valueBufferLen; 366 if (!base64_dec(val, val_len, valueBuffer, &size)) { 367 res = TEE_ERROR_SHORT_BUFFER; 368 goto err; 369 } 370 371 *valueBufferLen = size; 372 373 goto out; 374 375 err: 376 if (res == TEE_ERROR_ITEM_NOT_FOUND || 377 res == TEE_ERROR_BAD_FORMAT || 378 res == TEE_ERROR_SHORT_BUFFER) 379 return res; 380 TEE_Panic(0); 381 out: 382 return TEE_SUCCESS; 383 } 384 385 TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator, 386 char *name, TEE_UUID *value) 387 { 388 TEE_Result res; 389 struct prop_value pv; 390 391 if (value == NULL) { 392 res = TEE_ERROR_BAD_PARAMETERS; 393 goto err; 394 } 395 396 res = propget_get_property(propsetOrEnumerator, name, &pv); 397 if (res != TEE_SUCCESS) 398 goto err; 399 400 if (pv.type != USER_TA_PROP_TYPE_UUID) { 401 res = TEE_ERROR_BAD_FORMAT; 402 goto err; 403 } 404 405 *value = pv.u.uuid_val; /* struct copy */ 406 407 goto out; 408 409 err: 410 if (res == TEE_ERROR_ITEM_NOT_FOUND || 411 res == TEE_ERROR_BAD_FORMAT) 412 return res; 413 TEE_Panic(0); 414 out: 415 return TEE_SUCCESS; 416 } 417 418 TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator, 419 char *name, TEE_Identity *value) 420 { 421 TEE_Result res; 422 struct prop_value pv; 423 424 if (value == NULL) { 425 res = TEE_ERROR_BAD_PARAMETERS; 426 goto err; 427 } 428 429 res = propget_get_property(propsetOrEnumerator, name, &pv); 430 if (res != TEE_SUCCESS) 431 goto err; 432 433 if (pv.type != USER_TA_PROP_TYPE_IDENTITY) { 434 res = TEE_ERROR_BAD_FORMAT; 435 goto err; 436 } 437 438 *value = pv.u.identity_val; /* struct copy */ 439 440 goto out; 441 442 err: 443 if (res == TEE_ERROR_ITEM_NOT_FOUND || 444 res == TEE_ERROR_BAD_FORMAT) 445 return res; 446 TEE_Panic(0); 447 out: 448 return TEE_SUCCESS; 449 } 450 451 TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator) 452 { 453 TEE_Result res; 454 struct prop_enumerator *pe; 455 456 if (enumerator == NULL) { 457 res = TEE_ERROR_BAD_PARAMETERS; 458 goto err; 459 } 460 461 pe = TEE_Malloc(sizeof(struct prop_enumerator), 462 TEE_USER_MEM_HINT_NO_FILL_ZERO); 463 if (pe == NULL) { 464 res = TEE_ERROR_OUT_OF_MEMORY; 465 goto err; 466 } 467 468 *enumerator = (TEE_PropSetHandle) pe; 469 TEE_ResetPropertyEnumerator(*enumerator); 470 471 goto out; 472 473 err: 474 if (res == TEE_ERROR_OUT_OF_MEMORY) 475 return res; 476 TEE_Panic(0); 477 out: 478 return TEE_SUCCESS; 479 } 480 481 void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator) 482 { 483 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 484 485 pe->idx = PROP_ENUMERATOR_NOT_STARTED; 486 } 487 488 void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator) 489 { 490 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 491 492 TEE_Free(pe); 493 } 494 495 void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator, 496 TEE_PropSetHandle propSet) 497 { 498 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 499 500 if (pe == NULL) 501 return; 502 503 pe->idx = 0; 504 pe->prop_set = propSet; 505 } 506 507 TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator, 508 void *nameBuffer, uint32_t *nameBufferLen) 509 { 510 TEE_Result res; 511 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 512 const struct user_ta_property *eps; 513 size_t eps_len; 514 const char *str; 515 size_t bufferlen; 516 517 if (pe == NULL || nameBuffer == NULL || nameBufferLen == NULL) { 518 res = TEE_ERROR_BAD_PARAMETERS; 519 goto err; 520 } 521 522 bufferlen = *nameBufferLen; 523 res = propset_get(pe->prop_set, &eps, &eps_len); 524 if (res != TEE_SUCCESS) 525 goto err; 526 527 if (pe->idx < eps_len) { 528 str = eps[pe->idx].name; 529 bufferlen = strlcpy(nameBuffer, str, *nameBufferLen); 530 if (bufferlen >= *nameBufferLen) 531 res = TEE_ERROR_SHORT_BUFFER; 532 *nameBufferLen = bufferlen; 533 } else { 534 res = utee_get_property((unsigned long)pe->prop_set, 535 pe->idx - eps_len, 536 nameBuffer, nameBufferLen, 537 0, 0, 0); 538 if (res != TEE_SUCCESS) 539 goto err; 540 } 541 542 err: 543 if (res != TEE_SUCCESS && 544 res != TEE_ERROR_ITEM_NOT_FOUND && 545 res != TEE_ERROR_SHORT_BUFFER) 546 TEE_Panic(0); 547 return res; 548 } 549 550 TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator) 551 { 552 TEE_Result res; 553 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 554 uint32_t next_idx; 555 const struct user_ta_property *eps; 556 size_t eps_len; 557 558 if (pe == NULL) { 559 res = TEE_ERROR_BAD_PARAMETERS; 560 goto out; 561 } 562 563 if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) { 564 res = TEE_ERROR_ITEM_NOT_FOUND; 565 goto out; 566 } 567 568 res = propset_get(pe->prop_set, &eps, &eps_len); 569 if (res != TEE_SUCCESS) 570 goto out; 571 572 next_idx = pe->idx + 1; 573 pe->idx = next_idx; 574 if (next_idx < eps_len) 575 res = TEE_SUCCESS; 576 else 577 res = utee_get_property((unsigned long)pe->prop_set, 578 next_idx - eps_len, 0, 0, 0, 0, 0); 579 580 out: 581 if (res != TEE_SUCCESS && 582 res != TEE_ERROR_ITEM_NOT_FOUND) 583 TEE_Panic(0); 584 return res; 585 } 586