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