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, 153 &index); 154 if (res != TEE_SUCCESS) 155 return res; 156 res = _utee_get_property((unsigned long)h, index, NULL, NULL, 157 buf, len, &prop_type); 158 } else { 159 struct prop_enumerator *pe = (struct prop_enumerator *)h; 160 uint32_t idx = pe->idx; 161 162 if (idx == PROP_ENUMERATOR_NOT_STARTED) 163 return TEE_ERROR_ITEM_NOT_FOUND; 164 165 res = propset_get(pe->prop_set, &eps, &eps_len); 166 if (res != TEE_SUCCESS) 167 return res; 168 169 if (idx < eps_len) 170 return propget_get_ext_prop(eps + idx, type, buf, len); 171 idx -= eps_len; 172 173 res = _utee_get_property((unsigned long)pe->prop_set, idx, 174 NULL, NULL, buf, len, &prop_type); 175 if (res == TEE_ERROR_ITEM_NOT_FOUND) 176 res = TEE_ERROR_BAD_PARAMETERS; 177 } 178 179 *type = prop_type; 180 return res; 181 } 182 183 TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, 184 const char *name, char *value, 185 uint32_t *value_len) 186 { 187 TEE_Result res; 188 size_t l; 189 enum user_ta_prop_type type; 190 void *tmp_buf = 0; 191 uint32_t tmp_len; 192 uint32_t uint32_val; 193 bool bool_val; 194 TEE_Identity *p_identity_val; 195 196 if (!value || !value_len) { 197 res = TEE_ERROR_BAD_PARAMETERS; 198 goto out; 199 } 200 201 tmp_len = *value_len; 202 if (tmp_len < sizeof(TEE_Identity)) 203 tmp_len = sizeof(TEE_Identity); 204 tmp_buf = TEE_Malloc(tmp_len, TEE_USER_MEM_HINT_NO_FILL_ZERO); 205 if (!tmp_buf) { 206 res = TEE_ERROR_OUT_OF_MEMORY; 207 goto out; 208 } 209 210 res = propget_get_property(propsetOrEnumerator, name, &type, 211 tmp_buf, &tmp_len); 212 if (res != TEE_SUCCESS) { 213 if (res == TEE_ERROR_SHORT_BUFFER) { 214 if (type == USER_TA_PROP_TYPE_BINARY_BLOCK) { 215 /* 216 * in this case, we must enlarge the buffer 217 * with the size of the of the base64 encoded 218 * see base64_enc() function 219 */ 220 tmp_len = base64_enc_len(tmp_len); 221 } 222 *value_len = tmp_len; 223 } 224 goto out; 225 } 226 227 switch (type) { 228 case USER_TA_PROP_TYPE_BOOL: 229 bool_val = *((bool *)tmp_buf); 230 l = strlcpy(value, (bool_val ? "true" : "false"), *value_len); 231 break; 232 233 case USER_TA_PROP_TYPE_U32: 234 uint32_val = *((uint32_t *)tmp_buf); 235 l = snprintf(value, *value_len, "%u", uint32_val); 236 break; 237 238 case USER_TA_PROP_TYPE_UUID: 239 l = snprintk(value, *value_len, "%pUl", tmp_buf); 240 break; 241 242 case USER_TA_PROP_TYPE_IDENTITY: 243 p_identity_val = ((TEE_Identity *)tmp_buf); 244 l = snprintk(value, *value_len, "%u:%pUl", 245 p_identity_val->login, 246 (void *)(&(p_identity_val->uuid))); 247 break; 248 249 case USER_TA_PROP_TYPE_STRING: 250 l = strlcpy(value, tmp_buf, *value_len); 251 break; 252 253 case USER_TA_PROP_TYPE_BINARY_BLOCK: 254 l = *value_len; /* l includes the zero-termination */ 255 if (!base64_enc(tmp_buf, tmp_len, value, &l) && 256 (l <= *value_len)) { 257 res = TEE_ERROR_GENERIC; 258 goto out; 259 } 260 l--; /* remove the zero-termination that is added later */ 261 break; 262 263 default: 264 res = TEE_ERROR_BAD_FORMAT; 265 goto out; 266 } 267 268 l++; /* include zero termination */ 269 270 if (l > *value_len) 271 res = TEE_ERROR_SHORT_BUFFER; 272 *value_len = l; 273 274 out: 275 if (tmp_buf) 276 TEE_Free(tmp_buf); 277 if (res != TEE_SUCCESS && 278 res != TEE_ERROR_ITEM_NOT_FOUND && 279 res != TEE_ERROR_SHORT_BUFFER) 280 TEE_Panic(0); 281 282 return res; 283 } 284 285 TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator, 286 const char *name, bool *value) 287 { 288 TEE_Result res; 289 enum user_ta_prop_type type; 290 uint32_t bool_len = sizeof(bool); 291 if (value == NULL) { 292 res = TEE_ERROR_BAD_PARAMETERS; 293 goto out; 294 } 295 296 type = USER_TA_PROP_TYPE_BOOL; 297 res = propget_get_property(propsetOrEnumerator, name, &type, 298 value, &bool_len); 299 if (type != USER_TA_PROP_TYPE_BOOL) 300 res = TEE_ERROR_BAD_FORMAT; 301 if (res != TEE_SUCCESS) 302 goto out; 303 304 out: 305 if (res != TEE_SUCCESS && 306 res != TEE_ERROR_ITEM_NOT_FOUND && 307 res != TEE_ERROR_BAD_FORMAT) 308 TEE_Panic(0); 309 310 return res; 311 } 312 313 TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator, 314 const char *name, uint32_t *value) 315 { 316 TEE_Result res; 317 enum user_ta_prop_type type; 318 uint32_t uint32_len = sizeof(uint32_t); 319 320 if (!value) { 321 res = TEE_ERROR_BAD_PARAMETERS; 322 goto out; 323 } 324 325 type = USER_TA_PROP_TYPE_U32; 326 res = propget_get_property(propsetOrEnumerator, name, &type, 327 value, &uint32_len); 328 if (type != USER_TA_PROP_TYPE_U32) 329 res = TEE_ERROR_BAD_FORMAT; 330 331 out: 332 if (res != TEE_SUCCESS && 333 res != TEE_ERROR_ITEM_NOT_FOUND && 334 res != TEE_ERROR_BAD_FORMAT) 335 TEE_Panic(0); 336 337 return res; 338 } 339 340 TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, 341 const char *name, void *value, 342 uint32_t *value_len) 343 { 344 TEE_Result res; 345 enum user_ta_prop_type type; 346 347 if (!value_len) { 348 res = TEE_ERROR_BAD_PARAMETERS; 349 goto out; 350 } 351 352 type = USER_TA_PROP_TYPE_BINARY_BLOCK; 353 res = propget_get_property(propsetOrEnumerator, name, &type, 354 value, value_len); 355 if (type != USER_TA_PROP_TYPE_BINARY_BLOCK) 356 res = TEE_ERROR_BAD_FORMAT; 357 358 out: 359 if (res != TEE_SUCCESS && 360 res != TEE_ERROR_ITEM_NOT_FOUND && 361 res != TEE_ERROR_BAD_FORMAT && 362 res != TEE_ERROR_SHORT_BUFFER) 363 TEE_Panic(0); 364 365 return res; 366 } 367 368 TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator, 369 const char *name, TEE_UUID *value) 370 { 371 TEE_Result res; 372 enum user_ta_prop_type type; 373 uint32_t uuid_len = sizeof(TEE_UUID); 374 375 if (!value) { 376 res = TEE_ERROR_BAD_PARAMETERS; 377 goto out; 378 } 379 380 type = USER_TA_PROP_TYPE_UUID; 381 res = propget_get_property(propsetOrEnumerator, name, &type, 382 value, &uuid_len); 383 if (type != USER_TA_PROP_TYPE_UUID) 384 res = TEE_ERROR_BAD_FORMAT; 385 386 out: 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 (!value) { 403 res = TEE_ERROR_BAD_PARAMETERS; 404 goto out; 405 } 406 407 type = USER_TA_PROP_TYPE_IDENTITY; 408 res = propget_get_property(propsetOrEnumerator, name, &type, 409 value, &identity_len); 410 if (type != USER_TA_PROP_TYPE_IDENTITY) 411 res = TEE_ERROR_BAD_FORMAT; 412 413 out: 414 if (res != TEE_SUCCESS && 415 res != TEE_ERROR_ITEM_NOT_FOUND && 416 res != TEE_ERROR_BAD_FORMAT) 417 TEE_Panic(0); 418 419 return res; 420 } 421 422 TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator) 423 { 424 TEE_Result res; 425 struct prop_enumerator *pe; 426 427 if (!enumerator) { 428 res = TEE_ERROR_BAD_PARAMETERS; 429 goto err; 430 } 431 432 pe = TEE_Malloc(sizeof(struct prop_enumerator), 433 TEE_USER_MEM_HINT_NO_FILL_ZERO); 434 if (pe == NULL) { 435 res = TEE_ERROR_OUT_OF_MEMORY; 436 goto err; 437 } 438 439 *enumerator = (TEE_PropSetHandle) pe; 440 TEE_ResetPropertyEnumerator(*enumerator); 441 442 goto out; 443 444 err: 445 if (res == TEE_ERROR_OUT_OF_MEMORY) 446 return res; 447 TEE_Panic(0); 448 out: 449 return TEE_SUCCESS; 450 } 451 452 void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator) 453 { 454 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 455 456 pe->idx = PROP_ENUMERATOR_NOT_STARTED; 457 } 458 459 void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator) 460 { 461 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 462 463 TEE_Free(pe); 464 } 465 466 void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator, 467 TEE_PropSetHandle propSet) 468 { 469 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 470 471 if (!pe) 472 return; 473 474 pe->idx = 0; 475 pe->prop_set = propSet; 476 } 477 478 TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator, 479 void *name, uint32_t *name_len) 480 { 481 TEE_Result res; 482 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 483 const struct user_ta_property *eps; 484 size_t eps_len; 485 const char *str; 486 size_t bufferlen; 487 488 if (!pe || !name || !name_len) { 489 res = TEE_ERROR_BAD_PARAMETERS; 490 goto err; 491 } 492 493 bufferlen = *name_len; 494 res = propset_get(pe->prop_set, &eps, &eps_len); 495 if (res != TEE_SUCCESS) 496 goto err; 497 498 if (pe->idx < eps_len) { 499 str = eps[pe->idx].name; 500 bufferlen = strlcpy(name, str, *name_len) + 1; 501 if (bufferlen > *name_len) 502 res = TEE_ERROR_SHORT_BUFFER; 503 *name_len = bufferlen; 504 } else { 505 res = _utee_get_property((unsigned long)pe->prop_set, 506 pe->idx - eps_len, name, name_len, 507 NULL, NULL, NULL); 508 if (res != TEE_SUCCESS) 509 goto err; 510 } 511 512 err: 513 if (res != TEE_SUCCESS && 514 res != TEE_ERROR_ITEM_NOT_FOUND && 515 res != TEE_ERROR_SHORT_BUFFER) 516 TEE_Panic(0); 517 return res; 518 } 519 520 TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator) 521 { 522 TEE_Result res; 523 struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; 524 uint32_t next_idx; 525 const struct user_ta_property *eps; 526 size_t eps_len; 527 528 if (!pe) { 529 res = TEE_ERROR_BAD_PARAMETERS; 530 goto out; 531 } 532 533 if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) { 534 res = TEE_ERROR_ITEM_NOT_FOUND; 535 goto out; 536 } 537 538 res = propset_get(pe->prop_set, &eps, &eps_len); 539 if (res != TEE_SUCCESS) 540 goto out; 541 542 next_idx = pe->idx + 1; 543 pe->idx = next_idx; 544 if (next_idx < eps_len) 545 res = TEE_SUCCESS; 546 else 547 res = _utee_get_property((unsigned long)pe->prop_set, 548 next_idx - eps_len, NULL, NULL, NULL, 549 NULL, NULL); 550 551 out: 552 if (res != TEE_SUCCESS && 553 res != TEE_ERROR_ITEM_NOT_FOUND) 554 TEE_Panic(0); 555 return res; 556 } 557