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 <printk.h> 33 #include <tee_api_defines.h> 34 #include <tee_api_types.h> 35 #include <user_ta_header.h> 36 #include <tee_internal_api_extensions.h> 37 #include <tee_arith_internal.h> 38 #include <util.h> 39 #include <utee_syscalls.h> 40 41 #include "string_ext.h" 42 #include "base64.h" 43 44 #define PROP_STR_MAX 80 45 46 #define PROP_ENUMERATOR_NOT_STARTED 0xffffffff 47 48 struct prop_enumerator { 49 uint32_t idx; /* current index */ 50 TEE_PropSetHandle prop_set; /* part of TEE_PROPSET_xxx */ 51 }; 52 53 const struct user_ta_property tee_props[] = { 54 { 55 "gpd.tee.arith.maxBigIntSize", 56 USER_TA_PROP_TYPE_U32, 57 &(const uint32_t){TEE_MAX_NUMBER_OF_SUPPORTED_BITS} 58 }, 59 }; 60 61 static TEE_Result propset_get(TEE_PropSetHandle h, 62 const struct user_ta_property **eps, 63 size_t *eps_len) 64 { 65 if (h == TEE_PROPSET_CURRENT_TA) { 66 *eps = ta_props; 67 *eps_len = ta_num_props; 68 } else if (h == TEE_PROPSET_CURRENT_CLIENT) { 69 *eps = NULL; 70 *eps_len = 0; 71 } else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) { 72 *eps = tee_props; 73 *eps_len = ARRAY_SIZE(tee_props); 74 } else { 75 return TEE_ERROR_ITEM_NOT_FOUND; 76 } 77 78 return TEE_SUCCESS; 79 } 80 81 static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep, 82 enum user_ta_prop_type *type, 83 void *buf, uint32_t *len) 84 { 85 size_t l; 86 87 *type = ep->type; 88 switch (*type) { 89 case USER_TA_PROP_TYPE_BOOL: 90 l = sizeof(uint32_t); 91 break; 92 case USER_TA_PROP_TYPE_U32: 93 l = sizeof(uint32_t); 94 break; 95 case USER_TA_PROP_TYPE_UUID: 96 l = sizeof(TEE_UUID); 97 break; 98 case USER_TA_PROP_TYPE_IDENTITY: 99 l = sizeof(TEE_Identity); 100 break; 101 case USER_TA_PROP_TYPE_STRING: 102 /* take the leading 0 into account */ 103 l = strlen(ep->value) + 1; 104 break; 105 case USER_TA_PROP_TYPE_BINARY_BLOCK: 106 /* 107 * in case of TA property, a binary block is provided as a 108 * string, which is base64 encoded. We must first decode it, 109 * without taking into account the zero termination of the 110 * string 111 */ 112 l = *len; 113 if (!base64_dec(ep->value, strlen(ep->value), buf, &l) && 114 (l <= *len)) 115 return TEE_ERROR_GENERIC; 116 if (*len < l) { 117 *len = l; 118 return TEE_ERROR_SHORT_BUFFER; 119 } 120 121 *len = l; 122 return TEE_SUCCESS; 123 default: 124 return TEE_ERROR_GENERIC; 125 } 126 127 if (*len < l) { 128 *len = l; 129 return TEE_ERROR_SHORT_BUFFER; 130 } 131 132 *len = l; 133 memcpy(buf, ep->value, l); 134 return TEE_SUCCESS; 135 } 136 137 static TEE_Result propget_get_property(TEE_PropSetHandle h, 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 (h == TEE_PROPSET_CURRENT_TA || h == TEE_PROPSET_CURRENT_CLIENT || 148 h == TEE_PROPSET_TEE_IMPLEMENTATION) { 149 size_t n; 150 151 res = propset_get(h, &eps, &eps_len); 152 if (res != TEE_SUCCESS) 153 return res; 154 155 for (n = 0; n < eps_len; n++) { 156 if (!strcmp(name, eps[n].name)) 157 return propget_get_ext_prop(eps + n, type, 158 buf, len); 159 } 160 161 /* get the index from the name */ 162 res = utee_get_property_name_to_index((unsigned long)h, name, 163 strlen(name) + 1, &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 char *name, char *value, 195 uint32_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 TEE_Identity *p_identity_val; 204 205 if (!value || !value_len) { 206 res = TEE_ERROR_BAD_PARAMETERS; 207 goto out; 208 } 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 uint32_val = *((uint32_t *)tmp_buf); 239 l = strlcpy(value, (uint32_val ? "true" : "false"), 240 *value_len); 241 break; 242 243 case USER_TA_PROP_TYPE_U32: 244 uint32_val = *((uint32_t *)tmp_buf); 245 l = snprintf(value, *value_len, "%u", uint32_val); 246 break; 247 248 case USER_TA_PROP_TYPE_UUID: 249 l = snprintk(value, *value_len, "%pUl", tmp_buf); 250 break; 251 252 case USER_TA_PROP_TYPE_IDENTITY: 253 p_identity_val = ((TEE_Identity *)tmp_buf); 254 l = snprintk(value, *value_len, "%u:%pUl", 255 p_identity_val->login, 256 (void *)(&(p_identity_val->uuid))); 257 break; 258 259 case USER_TA_PROP_TYPE_STRING: 260 l = strlcpy(value, tmp_buf, *value_len); 261 break; 262 263 case USER_TA_PROP_TYPE_BINARY_BLOCK: 264 l = *value_len; /* l includes the zero-termination */ 265 if (!base64_enc(tmp_buf, tmp_len, value, &l) && 266 (l <= *value_len)) { 267 res = TEE_ERROR_GENERIC; 268 goto out; 269 } 270 l--; /* remove the zero-termination that is added later */ 271 break; 272 273 default: 274 res = TEE_ERROR_BAD_FORMAT; 275 goto out; 276 } 277 278 l++; /* include zero termination */ 279 280 if (l > *value_len) 281 res = TEE_ERROR_SHORT_BUFFER; 282 *value_len = l; 283 284 out: 285 if (tmp_buf) 286 TEE_Free(tmp_buf); 287 if (res != TEE_SUCCESS && 288 res != TEE_ERROR_ITEM_NOT_FOUND && 289 res != TEE_ERROR_SHORT_BUFFER) 290 TEE_Panic(0); 291 292 return res; 293 } 294 295 TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator, 296 char *name, bool *value) 297 { 298 TEE_Result res; 299 enum user_ta_prop_type type; 300 uint32_t uint32_val; 301 uint32_t uint32_len = sizeof(uint32_val); 302 if (value == NULL) { 303 res = TEE_ERROR_BAD_PARAMETERS; 304 goto out; 305 } 306 307 type = USER_TA_PROP_TYPE_BOOL; 308 res = propget_get_property(propsetOrEnumerator, name, &type, 309 &uint32_val, &uint32_len); 310 if (type != USER_TA_PROP_TYPE_BOOL) 311 res = TEE_ERROR_BAD_FORMAT; 312 if (res != TEE_SUCCESS) 313 goto out; 314 315 *value = !!uint32_val; 316 317 out: 318 if (res != TEE_SUCCESS && 319 res != TEE_ERROR_ITEM_NOT_FOUND && 320 res != TEE_ERROR_BAD_FORMAT) 321 TEE_Panic(0); 322 323 return res; 324 } 325 326 TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator, 327 char *name, uint32_t *value) 328 { 329 TEE_Result res; 330 enum user_ta_prop_type type; 331 uint32_t uint32_len = sizeof(uint32_t); 332 333 if (!value) { 334 res = TEE_ERROR_BAD_PARAMETERS; 335 goto out; 336 } 337 338 type = USER_TA_PROP_TYPE_U32; 339 res = propget_get_property(propsetOrEnumerator, name, &type, 340 value, &uint32_len); 341 if (type != USER_TA_PROP_TYPE_U32) 342 res = TEE_ERROR_BAD_FORMAT; 343 344 out: 345 if (res != TEE_SUCCESS && 346 res != TEE_ERROR_ITEM_NOT_FOUND && 347 res != TEE_ERROR_BAD_FORMAT) 348 TEE_Panic(0); 349 350 return res; 351 } 352 353 TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, 354 char *name, void *value, 355 uint32_t *value_len) 356 { 357 TEE_Result res; 358 enum user_ta_prop_type type; 359 360 if (!value || !value_len) { 361 res = TEE_ERROR_BAD_PARAMETERS; 362 goto out; 363 } 364 365 type = USER_TA_PROP_TYPE_BINARY_BLOCK; 366 res = propget_get_property(propsetOrEnumerator, name, &type, 367 value, value_len); 368 if (type != USER_TA_PROP_TYPE_BINARY_BLOCK) 369 res = TEE_ERROR_BAD_FORMAT; 370 371 out: 372 if (res != TEE_SUCCESS && 373 res != TEE_ERROR_ITEM_NOT_FOUND && 374 res != TEE_ERROR_BAD_FORMAT && 375 res != TEE_ERROR_SHORT_BUFFER) 376 TEE_Panic(0); 377 378 return res; 379 } 380 381 TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator, 382 char *name, TEE_UUID *value) 383 { 384 TEE_Result res; 385 enum user_ta_prop_type type; 386 uint32_t uuid_len = sizeof(TEE_UUID); 387 388 if (!value) { 389 res = TEE_ERROR_BAD_PARAMETERS; 390 goto out; 391 } 392 393 type = USER_TA_PROP_TYPE_UUID; 394 res = propget_get_property(propsetOrEnumerator, name, &type, 395 value, &uuid_len); 396 if (type != USER_TA_PROP_TYPE_UUID) 397 res = TEE_ERROR_BAD_FORMAT; 398 399 out: 400 if (res != TEE_SUCCESS && 401 res != TEE_ERROR_ITEM_NOT_FOUND && 402 res != TEE_ERROR_BAD_FORMAT) 403 TEE_Panic(0); 404 405 return res; 406 } 407 408 TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator, 409 char *name, TEE_Identity *value) 410 { 411 TEE_Result res; 412 enum user_ta_prop_type type; 413 uint32_t identity_len = sizeof(TEE_Identity); 414 415 if (!value) { 416 res = TEE_ERROR_BAD_PARAMETERS; 417 goto out; 418 } 419 420 type = USER_TA_PROP_TYPE_IDENTITY; 421 res = propget_get_property(propsetOrEnumerator, name, &type, 422 value, &identity_len); 423 if (type != USER_TA_PROP_TYPE_IDENTITY) 424 res = TEE_ERROR_BAD_FORMAT; 425 426 out: 427 if (res != TEE_SUCCESS && 428 res != TEE_ERROR_ITEM_NOT_FOUND && 429 res != TEE_ERROR_BAD_FORMAT) 430 TEE_Panic(0); 431 432 return res; 433 } 434 435 TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator) 436 { 437 TEE_Result res; 438 struct prop_enumerator *pe; 439 440 if (!enumerator) { 441 res = TEE_ERROR_BAD_PARAMETERS; 442 goto err; 443 } 444 445 pe = TEE_Malloc(sizeof(struct prop_enumerator), 446 TEE_USER_MEM_HINT_NO_FILL_ZERO); 447 if (pe == NULL) { 448 res = TEE_ERROR_OUT_OF_MEMORY; 449 goto err; 450 } 451 452 *enumerator = (TEE_PropSetHandle) pe; 453 TEE_ResetPropertyEnumerator(*enumerator); 454 455 goto out; 456 457 err: 458 if (res == TEE_ERROR_OUT_OF_MEMORY) 459 return res; 460 TEE_Panic(0); 461 out: 462 return TEE_SUCCESS; 463 } 464 465 void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator) 466 { 467 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 468 469 pe->idx = PROP_ENUMERATOR_NOT_STARTED; 470 } 471 472 void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator) 473 { 474 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 475 476 TEE_Free(pe); 477 } 478 479 void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator, 480 TEE_PropSetHandle propSet) 481 { 482 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 483 484 if (!pe) 485 return; 486 487 pe->idx = 0; 488 pe->prop_set = propSet; 489 } 490 491 TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator, 492 void *name, uint32_t *name_len) 493 { 494 TEE_Result res; 495 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 496 const struct user_ta_property *eps; 497 size_t eps_len; 498 const char *str; 499 size_t bufferlen; 500 501 if (!pe || !name || !name_len) { 502 res = TEE_ERROR_BAD_PARAMETERS; 503 goto err; 504 } 505 506 bufferlen = *name_len; 507 res = propset_get(pe->prop_set, &eps, &eps_len); 508 if (res != TEE_SUCCESS) 509 goto err; 510 511 if (pe->idx < eps_len) { 512 str = eps[pe->idx].name; 513 bufferlen = strlcpy(name, str, *name_len) + 1; 514 if (bufferlen > *name_len) 515 res = TEE_ERROR_SHORT_BUFFER; 516 *name_len = bufferlen; 517 } else { 518 res = utee_get_property((unsigned long)pe->prop_set, 519 pe->idx - eps_len, 520 name, name_len, NULL, NULL, NULL); 521 if (res != TEE_SUCCESS) 522 goto err; 523 } 524 525 err: 526 if (res != TEE_SUCCESS && 527 res != TEE_ERROR_ITEM_NOT_FOUND && 528 res != TEE_ERROR_SHORT_BUFFER) 529 TEE_Panic(0); 530 return res; 531 } 532 533 TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator) 534 { 535 TEE_Result res; 536 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 537 uint32_t next_idx; 538 const struct user_ta_property *eps; 539 size_t eps_len; 540 541 if (!pe) { 542 res = TEE_ERROR_BAD_PARAMETERS; 543 goto out; 544 } 545 546 if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) { 547 res = TEE_ERROR_ITEM_NOT_FOUND; 548 goto out; 549 } 550 551 res = propset_get(pe->prop_set, &eps, &eps_len); 552 if (res != TEE_SUCCESS) 553 goto out; 554 555 next_idx = pe->idx + 1; 556 pe->idx = next_idx; 557 if (next_idx < eps_len) 558 res = TEE_SUCCESS; 559 else 560 res = utee_get_property((unsigned long)pe->prop_set, 561 next_idx - eps_len, 562 NULL, NULL, NULL, NULL, NULL); 563 564 out: 565 if (res != TEE_SUCCESS && 566 res != TEE_ERROR_ITEM_NOT_FOUND) 567 TEE_Panic(0); 568 return res; 569 } 570