1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2014, STMicroelectronics International N.V. 4 */ 5 #include <stdlib.h> 6 #include <string.h> 7 #include <string_ext.h> 8 #include <tee_api.h> 9 #include <tee_internal_api_extensions.h> 10 #include <types_ext.h> 11 #include <user_ta_header.h> 12 #include <utee_syscalls.h> 13 #include "tee_api_private.h" 14 15 /* 16 * return a known non-NULL invalid pointer when the 17 * requested size is zero 18 */ 19 #define TEE_NULL_SIZED_VA ((void *)1) 20 21 static const void *tee_api_instance_data; 22 23 /* System API - Internal Client API */ 24 25 static void copy_param(struct utee_params *up, uint32_t param_types, 26 const TEE_Param params[TEE_NUM_PARAMS]) 27 { 28 size_t n = 0; 29 uint64_t a = 0; 30 uint64_t b = 0; 31 32 up->types = param_types; 33 for (n = 0; n < TEE_NUM_PARAMS; n++) { 34 switch (TEE_PARAM_TYPE_GET(up->types, n)) { 35 case TEE_PARAM_TYPE_VALUE_INPUT: 36 case TEE_PARAM_TYPE_VALUE_INOUT: 37 a = params[n].value.a; 38 b = params[n].value.b; 39 break; 40 case TEE_PARAM_TYPE_MEMREF_OUTPUT: 41 case TEE_PARAM_TYPE_MEMREF_INOUT: 42 case TEE_PARAM_TYPE_MEMREF_INPUT: 43 a = (vaddr_t)params[n].memref.buffer; 44 b = params[n].memref.size; 45 break; 46 default: 47 a = 0; 48 b = 0; 49 } 50 up->vals[n * 2] = a; 51 up->vals[n * 2 + 1] = b; 52 } 53 } 54 55 static void copy_gp11_param(struct utee_params *up, uint32_t param_types, 56 const __GP11_TEE_Param params[TEE_NUM_PARAMS]) 57 { 58 size_t n = 0; 59 uint64_t a = 0; 60 uint64_t b = 0; 61 62 up->types = param_types; 63 for (n = 0; n < TEE_NUM_PARAMS; n++) { 64 switch (TEE_PARAM_TYPE_GET(up->types, n)) { 65 case TEE_PARAM_TYPE_VALUE_INPUT: 66 case TEE_PARAM_TYPE_VALUE_INOUT: 67 a = params[n].value.a; 68 b = params[n].value.b; 69 break; 70 case TEE_PARAM_TYPE_MEMREF_OUTPUT: 71 case TEE_PARAM_TYPE_MEMREF_INOUT: 72 case TEE_PARAM_TYPE_MEMREF_INPUT: 73 a = (vaddr_t)params[n].memref.buffer; 74 b = params[n].memref.size; 75 break; 76 default: 77 a = 0; 78 b = 0; 79 } 80 up->vals[n * 2] = a; 81 up->vals[n * 2 + 1] = b; 82 } 83 } 84 85 static TEE_Result map_tmp_param(struct utee_params *up, void **tmp_buf, 86 size_t *tmp_len, void *tmp_va[TEE_NUM_PARAMS]) 87 { 88 size_t n = 0; 89 uint8_t *tb = NULL; 90 size_t tbl = 0; 91 size_t tmp_align = sizeof(vaddr_t) * 2; 92 bool is_tmp_mem[TEE_NUM_PARAMS] = { false }; 93 void *b = NULL; 94 size_t s = 0; 95 const uint32_t flags = TEE_MEMORY_ACCESS_READ; 96 97 /* 98 * If a memory parameter points to TA private memory we need to 99 * allocate a temporary buffer to avoid exposing the memory 100 * directly to the called TA. 101 */ 102 103 *tmp_buf = NULL; 104 *tmp_len = 0; 105 for (n = 0; n < TEE_NUM_PARAMS; n++) { 106 tmp_va[n] = NULL; 107 switch (TEE_PARAM_TYPE_GET(up->types, n)) { 108 case TEE_PARAM_TYPE_MEMREF_INPUT: 109 case TEE_PARAM_TYPE_MEMREF_OUTPUT: 110 case TEE_PARAM_TYPE_MEMREF_INOUT: 111 b = (void *)(vaddr_t)up->vals[n * 2]; 112 s = up->vals[n * 2 + 1]; 113 /* 114 * We're only allocating temporary memory if the 115 * buffer is completely within TA memory. If it's 116 * NULL, empty, partially outside or completely 117 * outside TA memory there's nothing more we need 118 * to do here. If there's security/permissions 119 * problem we'll get an error in the 120 * invoke_command/open_session below. 121 */ 122 if (b && s && 123 !TEE_CheckMemoryAccessRights(flags, b, s)) { 124 is_tmp_mem[n] = true; 125 tbl += ROUNDUP(s, tmp_align); 126 } 127 break; 128 default: 129 break; 130 } 131 } 132 133 if (tbl) { 134 tb = tee_map_zi(tbl, TEE_MEMORY_ACCESS_ANY_OWNER); 135 if (!tb) 136 return TEE_ERROR_OUT_OF_MEMORY; 137 *tmp_buf = tb; 138 *tmp_len = tbl; 139 } 140 141 for (n = 0; n < TEE_NUM_PARAMS; n++) { 142 switch (TEE_PARAM_TYPE_GET(up->types, n)) { 143 case TEE_PARAM_TYPE_MEMREF_OUTPUT: 144 case TEE_PARAM_TYPE_MEMREF_INOUT: 145 case TEE_PARAM_TYPE_MEMREF_INPUT: 146 if (!is_tmp_mem[n]) 147 break; 148 s = up->vals[n * 2 + 1]; 149 b = (void *)(vaddr_t)up->vals[n * 2]; 150 tmp_va[n] = tb; 151 tb += ROUNDUP(s, tmp_align); 152 up->vals[n * 2] = (vaddr_t)tmp_va[n]; 153 if (TEE_PARAM_TYPE_GET(up->types, n) != 154 TEE_PARAM_TYPE_MEMREF_OUTPUT) 155 memcpy(tmp_va[n], b, s); 156 break; 157 default: 158 break; 159 } 160 } 161 162 return TEE_SUCCESS; 163 164 } 165 166 static void update_out_param(TEE_Param params[TEE_NUM_PARAMS], 167 void *tmp_va[TEE_NUM_PARAMS], 168 const struct utee_params *up) 169 { 170 size_t n; 171 uint32_t types = up->types; 172 173 for (n = 0; n < TEE_NUM_PARAMS; n++) { 174 uintptr_t a = up->vals[n * 2]; 175 uintptr_t b = up->vals[n * 2 + 1]; 176 177 switch (TEE_PARAM_TYPE_GET(types, n)) { 178 case TEE_PARAM_TYPE_VALUE_OUTPUT: 179 case TEE_PARAM_TYPE_VALUE_INOUT: 180 params[n].value.a = a; 181 params[n].value.b = b; 182 break; 183 case TEE_PARAM_TYPE_MEMREF_OUTPUT: 184 case TEE_PARAM_TYPE_MEMREF_INOUT: 185 if (tmp_va[n]) 186 memcpy(params[n].memref.buffer, tmp_va[n], 187 MIN(b, params[n].memref.size)); 188 params[n].memref.size = b; 189 break; 190 default: 191 break; 192 } 193 } 194 } 195 196 static void update_out_gp11_param(__GP11_TEE_Param params[TEE_NUM_PARAMS], 197 void *tmp_va[TEE_NUM_PARAMS], 198 const struct utee_params *up) 199 { 200 size_t n = 0; 201 uint32_t types = up->types; 202 203 for (n = 0; n < TEE_NUM_PARAMS; n++) { 204 uintptr_t a = up->vals[n * 2]; 205 uintptr_t b = up->vals[n * 2 + 1]; 206 207 switch (TEE_PARAM_TYPE_GET(types, n)) { 208 case TEE_PARAM_TYPE_VALUE_OUTPUT: 209 case TEE_PARAM_TYPE_VALUE_INOUT: 210 params[n].value.a = a; 211 params[n].value.b = b; 212 break; 213 case TEE_PARAM_TYPE_MEMREF_OUTPUT: 214 case TEE_PARAM_TYPE_MEMREF_INOUT: 215 if (tmp_va[n]) 216 memcpy(params[n].memref.buffer, tmp_va[n], 217 MIN(b, params[n].memref.size)); 218 params[n].memref.size = b; 219 break; 220 default: 221 break; 222 } 223 } 224 } 225 226 TEE_Result TEE_OpenTASession(const TEE_UUID *destination, 227 uint32_t cancellationRequestTimeout, 228 uint32_t paramTypes, 229 TEE_Param params[TEE_NUM_PARAMS], 230 TEE_TASessionHandle *session, 231 uint32_t *returnOrigin) 232 { 233 TEE_Result res = TEE_SUCCESS; 234 struct utee_params up = { }; 235 uint32_t s = 0; 236 void *tmp_buf = NULL; 237 size_t tmp_len = 0; 238 void *tmp_va[TEE_NUM_PARAMS] = { NULL }; 239 240 if (paramTypes) 241 __utee_check_inout_annotation(params, 242 sizeof(TEE_Param) * 243 TEE_NUM_PARAMS); 244 __utee_check_out_annotation(session, sizeof(*session)); 245 246 copy_param(&up, paramTypes, params); 247 res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); 248 if (res) 249 goto out; 250 res = _utee_open_ta_session(destination, cancellationRequestTimeout, 251 &up, &s, returnOrigin); 252 update_out_param(params, tmp_va, &up); 253 if (tmp_buf) { 254 TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); 255 256 if (res2) 257 TEE_Panic(res2); 258 } 259 260 out: 261 /* 262 * Specification says that *session must hold TEE_HANDLE_NULL is 263 * TEE_SUCCESS isn't returned. Set it here explicitly in case 264 * the syscall fails before out parameters has been updated. 265 */ 266 if (res != TEE_SUCCESS) 267 s = TEE_HANDLE_NULL; 268 269 *session = (TEE_TASessionHandle)(uintptr_t)s; 270 return res; 271 } 272 273 TEE_Result __GP11_TEE_OpenTASession(const TEE_UUID *destination, 274 uint32_t cancellationRequestTimeout, 275 uint32_t paramTypes, 276 __GP11_TEE_Param params[TEE_NUM_PARAMS], 277 TEE_TASessionHandle *session, 278 uint32_t *returnOrigin) 279 { 280 TEE_Result res = TEE_SUCCESS; 281 struct utee_params up = { }; 282 uint32_t s = 0; 283 void *tmp_buf = NULL; 284 size_t tmp_len = 0; 285 void *tmp_va[TEE_NUM_PARAMS] = { NULL }; 286 287 if (paramTypes) 288 __utee_check_inout_annotation(params, 289 sizeof(__GP11_TEE_Param) * 290 TEE_NUM_PARAMS); 291 __utee_check_out_annotation(session, sizeof(*session)); 292 293 copy_gp11_param(&up, paramTypes, params); 294 res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); 295 if (res) 296 goto out; 297 res = _utee_open_ta_session(destination, cancellationRequestTimeout, 298 &up, &s, returnOrigin); 299 update_out_gp11_param(params, tmp_va, &up); 300 if (tmp_buf) { 301 TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); 302 303 if (res2) 304 TEE_Panic(res2); 305 } 306 307 out: 308 /* 309 * Specification says that *session must hold TEE_HANDLE_NULL if 310 * TEE_SUCCESS isn't returned. Set it here explicitly in case 311 * the syscall fails before out parameters has been updated. 312 */ 313 if (res != TEE_SUCCESS) 314 s = TEE_HANDLE_NULL; 315 316 *session = (TEE_TASessionHandle)(uintptr_t)s; 317 return res; 318 } 319 320 void TEE_CloseTASession(TEE_TASessionHandle session) 321 { 322 if (session != TEE_HANDLE_NULL) { 323 TEE_Result res = _utee_close_ta_session((uintptr_t)session); 324 325 if (res != TEE_SUCCESS) 326 TEE_Panic(res); 327 } 328 } 329 330 TEE_Result TEE_InvokeTACommand(TEE_TASessionHandle session, 331 uint32_t cancellationRequestTimeout, 332 uint32_t commandID, uint32_t paramTypes, 333 TEE_Param params[TEE_NUM_PARAMS], 334 uint32_t *returnOrigin) 335 { 336 TEE_Result res = TEE_SUCCESS; 337 uint32_t ret_origin = TEE_ORIGIN_TEE; 338 struct utee_params up = { }; 339 void *tmp_buf = NULL; 340 size_t tmp_len = 0; 341 void *tmp_va[TEE_NUM_PARAMS] = { NULL }; 342 343 if (paramTypes) 344 __utee_check_inout_annotation(params, 345 sizeof(TEE_Param) * 346 TEE_NUM_PARAMS); 347 if (returnOrigin) 348 __utee_check_out_annotation(returnOrigin, 349 sizeof(*returnOrigin)); 350 351 copy_param(&up, paramTypes, params); 352 res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); 353 if (res) 354 goto out; 355 res = _utee_invoke_ta_command((uintptr_t)session, 356 cancellationRequestTimeout, 357 commandID, &up, &ret_origin); 358 update_out_param(params, tmp_va, &up); 359 if (tmp_buf) { 360 TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); 361 362 if (res2) 363 TEE_Panic(res2); 364 } 365 366 out: 367 if (returnOrigin != NULL) 368 *returnOrigin = ret_origin; 369 370 if (ret_origin == TEE_ORIGIN_TRUSTED_APP) 371 return res; 372 373 if (res != TEE_SUCCESS && 374 res != TEE_ERROR_OUT_OF_MEMORY && 375 res != TEE_ERROR_TARGET_DEAD) 376 TEE_Panic(res); 377 378 return res; 379 } 380 381 TEE_Result __GP11_TEE_InvokeTACommand(TEE_TASessionHandle session, 382 uint32_t cancellationRequestTimeout, 383 uint32_t commandID, uint32_t paramTypes, 384 __GP11_TEE_Param params[TEE_NUM_PARAMS], 385 uint32_t *returnOrigin) 386 { 387 TEE_Result res = TEE_SUCCESS; 388 uint32_t ret_origin = TEE_ORIGIN_TEE; 389 struct utee_params up = { }; 390 void *tmp_buf = NULL; 391 size_t tmp_len = 0; 392 void *tmp_va[TEE_NUM_PARAMS] = { NULL }; 393 394 if (paramTypes) 395 __utee_check_inout_annotation(params, 396 sizeof(__GP11_TEE_Param) * 397 TEE_NUM_PARAMS); 398 if (returnOrigin) 399 __utee_check_out_annotation(returnOrigin, 400 sizeof(*returnOrigin)); 401 402 copy_gp11_param(&up, paramTypes, params); 403 res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); 404 if (res) 405 goto out; 406 res = _utee_invoke_ta_command((uintptr_t)session, 407 cancellationRequestTimeout, 408 commandID, &up, &ret_origin); 409 update_out_gp11_param(params, tmp_va, &up); 410 if (tmp_buf) { 411 TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); 412 413 if (res2) 414 TEE_Panic(res2); 415 } 416 417 out: 418 if (returnOrigin) 419 *returnOrigin = ret_origin; 420 421 if (ret_origin == TEE_ORIGIN_TRUSTED_APP) 422 return res; 423 424 if (res != TEE_SUCCESS && 425 res != TEE_ERROR_OUT_OF_MEMORY && 426 res != TEE_ERROR_TARGET_DEAD) 427 TEE_Panic(res); 428 429 return res; 430 } 431 432 /* System API - Cancellations */ 433 434 bool TEE_GetCancellationFlag(void) 435 { 436 uint32_t c; 437 TEE_Result res = _utee_get_cancellation_flag(&c); 438 439 if (res != TEE_SUCCESS) 440 c = 0; 441 return !!c; 442 } 443 444 bool TEE_UnmaskCancellation(void) 445 { 446 uint32_t old_mask; 447 TEE_Result res = _utee_unmask_cancellation(&old_mask); 448 449 if (res != TEE_SUCCESS) 450 TEE_Panic(res); 451 return !!old_mask; 452 } 453 454 bool TEE_MaskCancellation(void) 455 { 456 uint32_t old_mask; 457 TEE_Result res = _utee_mask_cancellation(&old_mask); 458 459 if (res != TEE_SUCCESS) 460 TEE_Panic(res); 461 return !!old_mask; 462 } 463 464 /* System API - Memory Management */ 465 466 TEE_Result TEE_CheckMemoryAccessRights(uint32_t accessFlags, void *buffer, 467 uint32_t size) 468 { 469 TEE_Result res; 470 471 if (size == 0) 472 return TEE_SUCCESS; 473 474 /* Check access rights against memory mapping */ 475 res = _utee_check_access_rights(accessFlags, buffer, size); 476 if (res != TEE_SUCCESS) 477 goto out; 478 479 /* 480 * Check access rights against input parameters 481 * Previous legacy code was removed and will need to be restored 482 */ 483 484 res = TEE_SUCCESS; 485 out: 486 return res; 487 } 488 489 void TEE_SetInstanceData(const void *instanceData) 490 { 491 tee_api_instance_data = instanceData; 492 } 493 494 const void *TEE_GetInstanceData(void) 495 { 496 return tee_api_instance_data; 497 } 498 499 void *TEE_MemMove(void *dest, const void *src, uint32_t size) 500 { 501 return memmove(dest, src, size); 502 } 503 504 int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, uint32_t size) 505 { 506 return consttime_memcmp(buffer1, buffer2, size); 507 } 508 509 void TEE_MemFill(void *buff, uint32_t x, uint32_t size) 510 { 511 memset(buff, x, size); 512 } 513 514 /* Date & Time API */ 515 516 void TEE_GetSystemTime(TEE_Time *time) 517 { 518 TEE_Result res = _utee_get_time(UTEE_TIME_CAT_SYSTEM, time); 519 520 if (res != TEE_SUCCESS) 521 TEE_Panic(res); 522 } 523 524 TEE_Result TEE_Wait(uint32_t timeout) 525 { 526 TEE_Result res = _utee_wait(timeout); 527 528 if (res != TEE_SUCCESS && res != TEE_ERROR_CANCEL) 529 TEE_Panic(res); 530 531 return res; 532 } 533 534 TEE_Result TEE_GetTAPersistentTime(TEE_Time *time) 535 { 536 TEE_Result res; 537 538 res = _utee_get_time(UTEE_TIME_CAT_TA_PERSISTENT, time); 539 540 if (res != TEE_SUCCESS && res != TEE_ERROR_OVERFLOW) { 541 time->seconds = 0; 542 time->millis = 0; 543 } 544 545 if (res != TEE_SUCCESS && 546 res != TEE_ERROR_TIME_NOT_SET && 547 res != TEE_ERROR_TIME_NEEDS_RESET && 548 res != TEE_ERROR_OVERFLOW && 549 res != TEE_ERROR_OUT_OF_MEMORY) 550 TEE_Panic(res); 551 552 return res; 553 } 554 555 TEE_Result TEE_SetTAPersistentTime(const TEE_Time *time) 556 { 557 TEE_Result res; 558 559 res = _utee_set_ta_time(time); 560 561 if (res != TEE_SUCCESS && 562 res != TEE_ERROR_OUT_OF_MEMORY && 563 res != TEE_ERROR_STORAGE_NO_SPACE) 564 TEE_Panic(res); 565 566 return res; 567 } 568 569 void TEE_GetREETime(TEE_Time *time) 570 { 571 TEE_Result res = _utee_get_time(UTEE_TIME_CAT_REE, time); 572 573 if (res != TEE_SUCCESS) 574 TEE_Panic(res); 575 } 576 577 void *TEE_Malloc(uint32_t len, uint32_t hint) 578 { 579 if (!len) 580 return TEE_NULL_SIZED_VA; 581 582 if (hint == TEE_MALLOC_FILL_ZERO) 583 return calloc(1, len); 584 else if (hint == TEE_USER_MEM_HINT_NO_FILL_ZERO) 585 return malloc(len); 586 587 EMSG("Invalid hint %#" PRIx32, hint); 588 589 return NULL; 590 } 591 592 void *TEE_Realloc(void *buffer, uint32_t newSize) 593 { 594 if (!newSize) { 595 TEE_Free(buffer); 596 return TEE_NULL_SIZED_VA; 597 } 598 599 if (buffer == TEE_NULL_SIZED_VA) 600 return calloc(1, newSize); 601 602 return realloc(buffer, newSize); 603 } 604 605 void TEE_Free(void *buffer) 606 { 607 if (buffer != TEE_NULL_SIZED_VA) 608 free(buffer); 609 } 610 611 /* Cache maintenance support (TA requires the CACHE_MAINTENANCE property) */ 612 TEE_Result TEE_CacheClean(char *buf, size_t len) 613 { 614 return _utee_cache_operation(buf, len, TEE_CACHECLEAN); 615 } 616 TEE_Result TEE_CacheFlush(char *buf, size_t len) 617 { 618 return _utee_cache_operation(buf, len, TEE_CACHEFLUSH); 619 } 620 621 TEE_Result TEE_CacheInvalidate(char *buf, size_t len) 622 { 623 return _utee_cache_operation(buf, len, TEE_CACHEINVALIDATE); 624 } 625