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