1 /* 2 * Copyright (c) 2014, STMicroelectronics International N.V. 3 * Copyright (c) 2017, Linaro Limited 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 #include <printk.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <tee_api_defines.h> 33 #include <tee_api.h> 34 #include <tee_api_types.h> 35 #include <tee_arith_internal.h> 36 #include <tee_internal_api_extensions.h> 37 #include <tee_isocket.h> 38 #include <user_ta_header.h> 39 #include <utee_syscalls.h> 40 #include <util.h> 41 42 #include "string_ext.h" 43 #include "base64.h" 44 45 #define PROP_STR_MAX 80 46 47 #define PROP_ENUMERATOR_NOT_STARTED 0xffffffff 48 49 struct prop_enumerator { 50 uint32_t idx; /* current index */ 51 TEE_PropSetHandle prop_set; /* part of TEE_PROPSET_xxx */ 52 }; 53 54 const struct user_ta_property tee_props[] = { 55 { 56 "gpd.tee.arith.maxBigIntSize", 57 USER_TA_PROP_TYPE_U32, 58 &(const uint32_t){TEE_MAX_NUMBER_OF_SUPPORTED_BITS} 59 }, 60 { 61 "gpd.tee.sockets.version", 62 USER_TA_PROP_TYPE_U32, 63 &(const uint32_t){TEE_ISOCKET_VERSION} 64 }, 65 { 66 "gpd.tee.sockets.tcp.version", 67 USER_TA_PROP_TYPE_U32, 68 &(const uint32_t){TEE_ISOCKET_VERSION} 69 }, 70 }; 71 72 static TEE_Result propset_get(TEE_PropSetHandle h, 73 const struct user_ta_property **eps, 74 size_t *eps_len) 75 { 76 if (h == TEE_PROPSET_CURRENT_TA) { 77 *eps = ta_props; 78 *eps_len = ta_num_props; 79 } else if (h == TEE_PROPSET_CURRENT_CLIENT) { 80 *eps = NULL; 81 *eps_len = 0; 82 } else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) { 83 *eps = tee_props; 84 *eps_len = ARRAY_SIZE(tee_props); 85 } else { 86 return TEE_ERROR_ITEM_NOT_FOUND; 87 } 88 89 return TEE_SUCCESS; 90 } 91 92 static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep, 93 enum user_ta_prop_type *type, 94 void *buf, uint32_t *len) 95 { 96 size_t l; 97 98 *type = ep->type; 99 switch (*type) { 100 case USER_TA_PROP_TYPE_BOOL: 101 l = sizeof(uint32_t); 102 break; 103 case USER_TA_PROP_TYPE_U32: 104 l = sizeof(uint32_t); 105 break; 106 case USER_TA_PROP_TYPE_UUID: 107 l = sizeof(TEE_UUID); 108 break; 109 case USER_TA_PROP_TYPE_IDENTITY: 110 l = sizeof(TEE_Identity); 111 break; 112 case USER_TA_PROP_TYPE_STRING: 113 /* take the leading 0 into account */ 114 l = strlen(ep->value) + 1; 115 break; 116 case USER_TA_PROP_TYPE_BINARY_BLOCK: 117 /* 118 * in case of TA property, a binary block is provided as a 119 * string, which is base64 encoded. We must first decode it, 120 * without taking into account the zero termination of the 121 * string 122 */ 123 l = *len; 124 if (!base64_dec(ep->value, strlen(ep->value), buf, &l) && 125 (l <= *len)) 126 return TEE_ERROR_GENERIC; 127 if (*len < l) { 128 *len = l; 129 return TEE_ERROR_SHORT_BUFFER; 130 } 131 132 *len = l; 133 return TEE_SUCCESS; 134 default: 135 return TEE_ERROR_GENERIC; 136 } 137 138 if (*len < l) { 139 *len = l; 140 return TEE_ERROR_SHORT_BUFFER; 141 } 142 143 *len = l; 144 memcpy(buf, ep->value, l); 145 return TEE_SUCCESS; 146 } 147 148 static TEE_Result propget_get_property(TEE_PropSetHandle h, const char *name, 149 enum user_ta_prop_type *type, 150 void *buf, uint32_t *len) 151 { 152 TEE_Result res; 153 const struct user_ta_property *eps; 154 size_t eps_len; 155 uint32_t prop_type; 156 uint32_t index; 157 158 if (h == TEE_PROPSET_CURRENT_TA || h == TEE_PROPSET_CURRENT_CLIENT || 159 h == TEE_PROPSET_TEE_IMPLEMENTATION) { 160 size_t n; 161 162 res = propset_get(h, &eps, &eps_len); 163 if (res != TEE_SUCCESS) 164 return res; 165 166 for (n = 0; n < eps_len; n++) { 167 if (!strcmp(name, eps[n].name)) 168 return propget_get_ext_prop(eps + n, type, 169 buf, len); 170 } 171 172 /* get the index from the name */ 173 res = utee_get_property_name_to_index((unsigned long)h, name, 174 strlen(name) + 1, &index); 175 if (res != TEE_SUCCESS) 176 return res; 177 res = utee_get_property((unsigned long)h, index, NULL, NULL, 178 buf, len, &prop_type); 179 } else { 180 struct prop_enumerator *pe = (struct prop_enumerator *)h; 181 uint32_t idx = pe->idx; 182 183 if (idx == PROP_ENUMERATOR_NOT_STARTED) 184 return TEE_ERROR_ITEM_NOT_FOUND; 185 186 res = propset_get(pe->prop_set, &eps, &eps_len); 187 if (res != TEE_SUCCESS) 188 return res; 189 190 if (idx < eps_len) 191 return propget_get_ext_prop(eps + idx, type, buf, len); 192 idx -= eps_len; 193 194 res = utee_get_property((unsigned long)pe->prop_set, idx, 195 NULL, NULL, buf, len, &prop_type); 196 if (res == TEE_ERROR_ITEM_NOT_FOUND) 197 res = TEE_ERROR_BAD_PARAMETERS; 198 } 199 200 *type = prop_type; 201 return res; 202 } 203 204 TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, 205 const char *name, char *value, 206 uint32_t *value_len) 207 { 208 TEE_Result res; 209 size_t l; 210 enum user_ta_prop_type type; 211 void *tmp_buf = 0; 212 uint32_t tmp_len; 213 uint32_t uint32_val; 214 TEE_Identity *p_identity_val; 215 216 if (!value || !value_len) { 217 res = TEE_ERROR_BAD_PARAMETERS; 218 goto out; 219 } 220 221 tmp_len = *value_len; 222 if (tmp_len < sizeof(TEE_Identity)) 223 tmp_len = sizeof(TEE_Identity); 224 tmp_buf = TEE_Malloc(tmp_len, TEE_USER_MEM_HINT_NO_FILL_ZERO); 225 if (!tmp_buf) { 226 res = TEE_ERROR_OUT_OF_MEMORY; 227 goto out; 228 } 229 230 res = propget_get_property(propsetOrEnumerator, name, &type, 231 tmp_buf, &tmp_len); 232 if (res != TEE_SUCCESS) { 233 if (res == TEE_ERROR_SHORT_BUFFER) { 234 if (type == USER_TA_PROP_TYPE_BINARY_BLOCK) { 235 /* 236 * in this case, we must enlarge the buffer 237 * with the size of the of the base64 encoded 238 * see base64_enc() function 239 */ 240 tmp_len = base64_enc_len(tmp_len); 241 } 242 *value_len = tmp_len; 243 } 244 goto out; 245 } 246 247 switch (type) { 248 case USER_TA_PROP_TYPE_BOOL: 249 uint32_val = *((uint32_t *)tmp_buf); 250 l = strlcpy(value, (uint32_val ? "true" : "false"), 251 *value_len); 252 break; 253 254 case USER_TA_PROP_TYPE_U32: 255 uint32_val = *((uint32_t *)tmp_buf); 256 l = snprintf(value, *value_len, "%u", uint32_val); 257 break; 258 259 case USER_TA_PROP_TYPE_UUID: 260 l = snprintk(value, *value_len, "%pUl", tmp_buf); 261 break; 262 263 case USER_TA_PROP_TYPE_IDENTITY: 264 p_identity_val = ((TEE_Identity *)tmp_buf); 265 l = snprintk(value, *value_len, "%u:%pUl", 266 p_identity_val->login, 267 (void *)(&(p_identity_val->uuid))); 268 break; 269 270 case USER_TA_PROP_TYPE_STRING: 271 l = strlcpy(value, tmp_buf, *value_len); 272 break; 273 274 case USER_TA_PROP_TYPE_BINARY_BLOCK: 275 l = *value_len; /* l includes the zero-termination */ 276 if (!base64_enc(tmp_buf, tmp_len, value, &l) && 277 (l <= *value_len)) { 278 res = TEE_ERROR_GENERIC; 279 goto out; 280 } 281 l--; /* remove the zero-termination that is added later */ 282 break; 283 284 default: 285 res = TEE_ERROR_BAD_FORMAT; 286 goto out; 287 } 288 289 l++; /* include zero termination */ 290 291 if (l > *value_len) 292 res = TEE_ERROR_SHORT_BUFFER; 293 *value_len = l; 294 295 out: 296 if (tmp_buf) 297 TEE_Free(tmp_buf); 298 if (res != TEE_SUCCESS && 299 res != TEE_ERROR_ITEM_NOT_FOUND && 300 res != TEE_ERROR_SHORT_BUFFER) 301 TEE_Panic(0); 302 303 return res; 304 } 305 306 TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator, 307 const char *name, bool *value) 308 { 309 TEE_Result res; 310 enum user_ta_prop_type type; 311 uint32_t uint32_val; 312 uint32_t uint32_len = sizeof(uint32_val); 313 if (value == NULL) { 314 res = TEE_ERROR_BAD_PARAMETERS; 315 goto out; 316 } 317 318 type = USER_TA_PROP_TYPE_BOOL; 319 res = propget_get_property(propsetOrEnumerator, name, &type, 320 &uint32_val, &uint32_len); 321 if (type != USER_TA_PROP_TYPE_BOOL) 322 res = TEE_ERROR_BAD_FORMAT; 323 if (res != TEE_SUCCESS) 324 goto out; 325 326 *value = !!uint32_val; 327 328 out: 329 if (res != TEE_SUCCESS && 330 res != TEE_ERROR_ITEM_NOT_FOUND && 331 res != TEE_ERROR_BAD_FORMAT) 332 TEE_Panic(0); 333 334 return res; 335 } 336 337 TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator, 338 const char *name, uint32_t *value) 339 { 340 TEE_Result res; 341 enum user_ta_prop_type type; 342 uint32_t uint32_len = sizeof(uint32_t); 343 344 if (!value) { 345 res = TEE_ERROR_BAD_PARAMETERS; 346 goto out; 347 } 348 349 type = USER_TA_PROP_TYPE_U32; 350 res = propget_get_property(propsetOrEnumerator, name, &type, 351 value, &uint32_len); 352 if (type != USER_TA_PROP_TYPE_U32) 353 res = TEE_ERROR_BAD_FORMAT; 354 355 out: 356 if (res != TEE_SUCCESS && 357 res != TEE_ERROR_ITEM_NOT_FOUND && 358 res != TEE_ERROR_BAD_FORMAT) 359 TEE_Panic(0); 360 361 return res; 362 } 363 364 TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, 365 const char *name, void *value, 366 uint32_t *value_len) 367 { 368 TEE_Result res; 369 enum user_ta_prop_type type; 370 371 if (!value || !value_len) { 372 res = TEE_ERROR_BAD_PARAMETERS; 373 goto out; 374 } 375 376 type = USER_TA_PROP_TYPE_BINARY_BLOCK; 377 res = propget_get_property(propsetOrEnumerator, name, &type, 378 value, value_len); 379 if (type != USER_TA_PROP_TYPE_BINARY_BLOCK) 380 res = TEE_ERROR_BAD_FORMAT; 381 382 out: 383 if (res != TEE_SUCCESS && 384 res != TEE_ERROR_ITEM_NOT_FOUND && 385 res != TEE_ERROR_BAD_FORMAT && 386 res != TEE_ERROR_SHORT_BUFFER) 387 TEE_Panic(0); 388 389 return res; 390 } 391 392 TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator, 393 const char *name, TEE_UUID *value) 394 { 395 TEE_Result res; 396 enum user_ta_prop_type type; 397 uint32_t uuid_len = sizeof(TEE_UUID); 398 399 if (!value) { 400 res = TEE_ERROR_BAD_PARAMETERS; 401 goto out; 402 } 403 404 type = USER_TA_PROP_TYPE_UUID; 405 res = propget_get_property(propsetOrEnumerator, name, &type, 406 value, &uuid_len); 407 if (type != USER_TA_PROP_TYPE_UUID) 408 res = TEE_ERROR_BAD_FORMAT; 409 410 out: 411 if (res != TEE_SUCCESS && 412 res != TEE_ERROR_ITEM_NOT_FOUND && 413 res != TEE_ERROR_BAD_FORMAT) 414 TEE_Panic(0); 415 416 return res; 417 } 418 419 TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator, 420 const char *name, TEE_Identity *value) 421 { 422 TEE_Result res; 423 enum user_ta_prop_type type; 424 uint32_t identity_len = sizeof(TEE_Identity); 425 426 if (!value) { 427 res = TEE_ERROR_BAD_PARAMETERS; 428 goto out; 429 } 430 431 type = USER_TA_PROP_TYPE_IDENTITY; 432 res = propget_get_property(propsetOrEnumerator, name, &type, 433 value, &identity_len); 434 if (type != USER_TA_PROP_TYPE_IDENTITY) 435 res = TEE_ERROR_BAD_FORMAT; 436 437 out: 438 if (res != TEE_SUCCESS && 439 res != TEE_ERROR_ITEM_NOT_FOUND && 440 res != TEE_ERROR_BAD_FORMAT) 441 TEE_Panic(0); 442 443 return res; 444 } 445 446 TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator) 447 { 448 TEE_Result res; 449 struct prop_enumerator *pe; 450 451 if (!enumerator) { 452 res = TEE_ERROR_BAD_PARAMETERS; 453 goto err; 454 } 455 456 pe = TEE_Malloc(sizeof(struct prop_enumerator), 457 TEE_USER_MEM_HINT_NO_FILL_ZERO); 458 if (pe == NULL) { 459 res = TEE_ERROR_OUT_OF_MEMORY; 460 goto err; 461 } 462 463 *enumerator = (TEE_PropSetHandle) pe; 464 TEE_ResetPropertyEnumerator(*enumerator); 465 466 goto out; 467 468 err: 469 if (res == TEE_ERROR_OUT_OF_MEMORY) 470 return res; 471 TEE_Panic(0); 472 out: 473 return TEE_SUCCESS; 474 } 475 476 void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator) 477 { 478 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 479 480 pe->idx = PROP_ENUMERATOR_NOT_STARTED; 481 } 482 483 void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator) 484 { 485 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 486 487 TEE_Free(pe); 488 } 489 490 void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator, 491 TEE_PropSetHandle propSet) 492 { 493 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 494 495 if (!pe) 496 return; 497 498 pe->idx = 0; 499 pe->prop_set = propSet; 500 } 501 502 TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator, 503 void *name, uint32_t *name_len) 504 { 505 TEE_Result res; 506 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 507 const struct user_ta_property *eps; 508 size_t eps_len; 509 const char *str; 510 size_t bufferlen; 511 512 if (!pe || !name || !name_len) { 513 res = TEE_ERROR_BAD_PARAMETERS; 514 goto err; 515 } 516 517 bufferlen = *name_len; 518 res = propset_get(pe->prop_set, &eps, &eps_len); 519 if (res != TEE_SUCCESS) 520 goto err; 521 522 if (pe->idx < eps_len) { 523 str = eps[pe->idx].name; 524 bufferlen = strlcpy(name, str, *name_len) + 1; 525 if (bufferlen > *name_len) 526 res = TEE_ERROR_SHORT_BUFFER; 527 *name_len = bufferlen; 528 } else { 529 res = utee_get_property((unsigned long)pe->prop_set, 530 pe->idx - eps_len, 531 name, name_len, NULL, NULL, NULL); 532 if (res != TEE_SUCCESS) 533 goto err; 534 } 535 536 err: 537 if (res != TEE_SUCCESS && 538 res != TEE_ERROR_ITEM_NOT_FOUND && 539 res != TEE_ERROR_SHORT_BUFFER) 540 TEE_Panic(0); 541 return res; 542 } 543 544 TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator) 545 { 546 TEE_Result res; 547 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 548 uint32_t next_idx; 549 const struct user_ta_property *eps; 550 size_t eps_len; 551 552 if (!pe) { 553 res = TEE_ERROR_BAD_PARAMETERS; 554 goto out; 555 } 556 557 if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) { 558 res = TEE_ERROR_ITEM_NOT_FOUND; 559 goto out; 560 } 561 562 res = propset_get(pe->prop_set, &eps, &eps_len); 563 if (res != TEE_SUCCESS) 564 goto out; 565 566 next_idx = pe->idx + 1; 567 pe->idx = next_idx; 568 if (next_idx < eps_len) 569 res = TEE_SUCCESS; 570 else 571 res = utee_get_property((unsigned long)pe->prop_set, 572 next_idx - eps_len, 573 NULL, NULL, NULL, NULL, NULL); 574 575 out: 576 if (res != TEE_SUCCESS && 577 res != TEE_ERROR_ITEM_NOT_FOUND) 578 TEE_Panic(0); 579 return res; 580 } 581