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