11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 2b0104773SPascal Brand /* 3b0104773SPascal Brand * Copyright (c) 2014, STMicroelectronics International N.V. 4b0104773SPascal Brand */ 5b0104773SPascal Brand #include <stdlib.h> 6b0104773SPascal Brand #include <string.h> 765551e69SJerome Forissier #include <string_ext.h> 8b0104773SPascal Brand #include <tee_api.h> 996c1d8c5SJens Wiklander #include <tee_internal_api_extensions.h> 10ef305e54SJens Wiklander #include <types_ext.h> 11b0104773SPascal Brand #include <user_ta_header.h> 1296c1d8c5SJens Wiklander #include <utee_syscalls.h> 13e86f1266SJens Wiklander #include "tee_api_private.h" 14b0104773SPascal Brand 15a83ee50aSSadiq Hussain /* 16a83ee50aSSadiq Hussain * return a known non-NULL invalid pointer when the 17a83ee50aSSadiq Hussain * requested size is zero 18a83ee50aSSadiq Hussain */ 19a83ee50aSSadiq Hussain #define TEE_NULL_SIZED_VA ((void *)1) 20a83ee50aSSadiq Hussain 218f07fe6fSJerome Forissier static const void *tee_api_instance_data; 22b0104773SPascal Brand 23b0104773SPascal Brand /* System API - Internal Client API */ 24b0104773SPascal Brand 257509620bSJens Wiklander static void copy_param(struct utee_params *up, uint32_t param_types, 267509620bSJens Wiklander const TEE_Param params[TEE_NUM_PARAMS]) 277509620bSJens Wiklander { 287509620bSJens Wiklander size_t n = 0; 297509620bSJens Wiklander uint64_t a = 0; 307509620bSJens Wiklander uint64_t b = 0; 317509620bSJens Wiklander 327509620bSJens Wiklander up->types = param_types; 337509620bSJens Wiklander for (n = 0; n < TEE_NUM_PARAMS; n++) { 347509620bSJens Wiklander switch (TEE_PARAM_TYPE_GET(up->types, n)) { 357509620bSJens Wiklander case TEE_PARAM_TYPE_VALUE_INPUT: 367509620bSJens Wiklander case TEE_PARAM_TYPE_VALUE_INOUT: 377509620bSJens Wiklander a = params[n].value.a; 387509620bSJens Wiklander b = params[n].value.b; 397509620bSJens Wiklander break; 407509620bSJens Wiklander case TEE_PARAM_TYPE_MEMREF_OUTPUT: 417509620bSJens Wiklander case TEE_PARAM_TYPE_MEMREF_INOUT: 427509620bSJens Wiklander case TEE_PARAM_TYPE_MEMREF_INPUT: 437509620bSJens Wiklander a = (vaddr_t)params[n].memref.buffer; 447509620bSJens Wiklander b = params[n].memref.size; 457509620bSJens Wiklander break; 467509620bSJens Wiklander default: 477509620bSJens Wiklander a = 0; 487509620bSJens Wiklander b = 0; 497509620bSJens Wiklander } 507509620bSJens Wiklander up->vals[n * 2] = a; 517509620bSJens Wiklander up->vals[n * 2 + 1] = b; 527509620bSJens Wiklander } 537509620bSJens Wiklander } 547509620bSJens Wiklander 557509620bSJens Wiklander static void copy_gp11_param(struct utee_params *up, uint32_t param_types, 567509620bSJens Wiklander const __GP11_TEE_Param params[TEE_NUM_PARAMS]) 577509620bSJens Wiklander { 587509620bSJens Wiklander size_t n = 0; 597509620bSJens Wiklander uint64_t a = 0; 607509620bSJens Wiklander uint64_t b = 0; 617509620bSJens Wiklander 627509620bSJens Wiklander up->types = param_types; 637509620bSJens Wiklander for (n = 0; n < TEE_NUM_PARAMS; n++) { 647509620bSJens Wiklander switch (TEE_PARAM_TYPE_GET(up->types, n)) { 657509620bSJens Wiklander case TEE_PARAM_TYPE_VALUE_INPUT: 667509620bSJens Wiklander case TEE_PARAM_TYPE_VALUE_INOUT: 677509620bSJens Wiklander a = params[n].value.a; 687509620bSJens Wiklander b = params[n].value.b; 697509620bSJens Wiklander break; 707509620bSJens Wiklander case TEE_PARAM_TYPE_MEMREF_OUTPUT: 717509620bSJens Wiklander case TEE_PARAM_TYPE_MEMREF_INOUT: 727509620bSJens Wiklander case TEE_PARAM_TYPE_MEMREF_INPUT: 737509620bSJens Wiklander a = (vaddr_t)params[n].memref.buffer; 747509620bSJens Wiklander b = params[n].memref.size; 757509620bSJens Wiklander break; 767509620bSJens Wiklander default: 777509620bSJens Wiklander a = 0; 787509620bSJens Wiklander b = 0; 797509620bSJens Wiklander } 807509620bSJens Wiklander up->vals[n * 2] = a; 817509620bSJens Wiklander up->vals[n * 2 + 1] = b; 827509620bSJens Wiklander } 837509620bSJens Wiklander } 847509620bSJens Wiklander 857509620bSJens Wiklander static TEE_Result map_tmp_param(struct utee_params *up, void **tmp_buf, 867509620bSJens Wiklander size_t *tmp_len, void *tmp_va[TEE_NUM_PARAMS]) 87e86f1266SJens Wiklander { 88ef305e54SJens Wiklander size_t n = 0; 89ef305e54SJens Wiklander uint8_t *tb = NULL; 90ef305e54SJens Wiklander size_t tbl = 0; 91ef305e54SJens Wiklander size_t tmp_align = sizeof(vaddr_t) * 2; 92ef305e54SJens Wiklander bool is_tmp_mem[TEE_NUM_PARAMS] = { false }; 93ef305e54SJens Wiklander void *b = NULL; 94ef305e54SJens Wiklander size_t s = 0; 95ef305e54SJens Wiklander const uint32_t flags = TEE_MEMORY_ACCESS_READ; 96ef305e54SJens Wiklander 97ef305e54SJens Wiklander /* 98ef305e54SJens Wiklander * If a memory parameter points to TA private memory we need to 99ef305e54SJens Wiklander * allocate a temporary buffer to avoid exposing the memory 100ef305e54SJens Wiklander * directly to the called TA. 101ef305e54SJens Wiklander */ 102ef305e54SJens Wiklander 103ef305e54SJens Wiklander *tmp_buf = NULL; 104ef305e54SJens Wiklander *tmp_len = 0; 105ef305e54SJens Wiklander for (n = 0; n < TEE_NUM_PARAMS; n++) { 106ef305e54SJens Wiklander tmp_va[n] = NULL; 1077509620bSJens Wiklander switch (TEE_PARAM_TYPE_GET(up->types, n)) { 108ef305e54SJens Wiklander case TEE_PARAM_TYPE_MEMREF_INPUT: 109ef305e54SJens Wiklander case TEE_PARAM_TYPE_MEMREF_OUTPUT: 110ef305e54SJens Wiklander case TEE_PARAM_TYPE_MEMREF_INOUT: 1117509620bSJens Wiklander b = (void *)(vaddr_t)up->vals[n * 2]; 1127509620bSJens Wiklander s = up->vals[n * 2 + 1]; 113ef305e54SJens Wiklander /* 114ef305e54SJens Wiklander * We're only allocating temporary memory if the 115ef305e54SJens Wiklander * buffer is completely within TA memory. If it's 116ef305e54SJens Wiklander * NULL, empty, partially outside or completely 117ef305e54SJens Wiklander * outside TA memory there's nothing more we need 118ef305e54SJens Wiklander * to do here. If there's security/permissions 119ef305e54SJens Wiklander * problem we'll get an error in the 120ef305e54SJens Wiklander * invoke_command/open_session below. 121ef305e54SJens Wiklander */ 122ef305e54SJens Wiklander if (b && s && 123ef305e54SJens Wiklander !TEE_CheckMemoryAccessRights(flags, b, s)) { 124ef305e54SJens Wiklander is_tmp_mem[n] = true; 125ef305e54SJens Wiklander tbl += ROUNDUP(s, tmp_align); 126ef305e54SJens Wiklander } 127ef305e54SJens Wiklander break; 128ef305e54SJens Wiklander default: 129ef305e54SJens Wiklander break; 130ef305e54SJens Wiklander } 131ef305e54SJens Wiklander } 132ef305e54SJens Wiklander 133ef305e54SJens Wiklander if (tbl) { 134ef305e54SJens Wiklander tb = tee_map_zi(tbl, TEE_MEMORY_ACCESS_ANY_OWNER); 135ef305e54SJens Wiklander if (!tb) 136ef305e54SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 137ef305e54SJens Wiklander *tmp_buf = tb; 138ef305e54SJens Wiklander *tmp_len = tbl; 139ef305e54SJens Wiklander } 140e86f1266SJens Wiklander 141e86f1266SJens Wiklander for (n = 0; n < TEE_NUM_PARAMS; n++) { 1427509620bSJens Wiklander switch (TEE_PARAM_TYPE_GET(up->types, n)) { 143e86f1266SJens Wiklander case TEE_PARAM_TYPE_MEMREF_OUTPUT: 144e86f1266SJens Wiklander case TEE_PARAM_TYPE_MEMREF_INOUT: 145ef305e54SJens Wiklander case TEE_PARAM_TYPE_MEMREF_INPUT: 1467509620bSJens Wiklander if (!is_tmp_mem[n]) 1477509620bSJens Wiklander break; 1487509620bSJens Wiklander s = up->vals[n * 2 + 1]; 1497509620bSJens Wiklander b = (void *)(vaddr_t)up->vals[n * 2]; 150ef305e54SJens Wiklander tmp_va[n] = tb; 151ef305e54SJens Wiklander tb += ROUNDUP(s, tmp_align); 1527509620bSJens Wiklander up->vals[n * 2] = (vaddr_t)tmp_va[n]; 1537509620bSJens Wiklander if (TEE_PARAM_TYPE_GET(up->types, n) != 154ef305e54SJens Wiklander TEE_PARAM_TYPE_MEMREF_OUTPUT) 1557509620bSJens Wiklander memcpy(tmp_va[n], b, s); 156e86f1266SJens Wiklander break; 157e86f1266SJens Wiklander default: 158e86f1266SJens Wiklander break; 159e86f1266SJens Wiklander } 160e86f1266SJens Wiklander } 161ef305e54SJens Wiklander 162ef305e54SJens Wiklander return TEE_SUCCESS; 1637509620bSJens Wiklander 164e86f1266SJens Wiklander } 165e86f1266SJens Wiklander 166ef305e54SJens Wiklander static void update_out_param(TEE_Param params[TEE_NUM_PARAMS], 167ef305e54SJens Wiklander void *tmp_va[TEE_NUM_PARAMS], 168ef305e54SJens Wiklander const struct utee_params *up) 169e86f1266SJens Wiklander { 170e86f1266SJens Wiklander size_t n; 171e86f1266SJens Wiklander uint32_t types = up->types; 172e86f1266SJens Wiklander 173e86f1266SJens Wiklander for (n = 0; n < TEE_NUM_PARAMS; n++) { 174e86f1266SJens Wiklander uintptr_t a = up->vals[n * 2]; 175e86f1266SJens Wiklander uintptr_t b = up->vals[n * 2 + 1]; 176e86f1266SJens Wiklander 177e86f1266SJens Wiklander switch (TEE_PARAM_TYPE_GET(types, n)) { 178e86f1266SJens Wiklander case TEE_PARAM_TYPE_VALUE_OUTPUT: 179e86f1266SJens Wiklander case TEE_PARAM_TYPE_VALUE_INOUT: 180e86f1266SJens Wiklander params[n].value.a = a; 181e86f1266SJens Wiklander params[n].value.b = b; 182e86f1266SJens Wiklander break; 183e86f1266SJens Wiklander case TEE_PARAM_TYPE_MEMREF_OUTPUT: 184e86f1266SJens Wiklander case TEE_PARAM_TYPE_MEMREF_INOUT: 185ef305e54SJens Wiklander if (tmp_va[n]) 186ef305e54SJens Wiklander memcpy(params[n].memref.buffer, tmp_va[n], 187ef305e54SJens Wiklander MIN(b, params[n].memref.size)); 188e86f1266SJens Wiklander params[n].memref.size = b; 189e86f1266SJens Wiklander break; 190e86f1266SJens Wiklander default: 191e86f1266SJens Wiklander break; 192e86f1266SJens Wiklander } 193e86f1266SJens Wiklander } 194e86f1266SJens Wiklander } 195e86f1266SJens Wiklander 1967509620bSJens Wiklander static void update_out_gp11_param(__GP11_TEE_Param params[TEE_NUM_PARAMS], 1977509620bSJens Wiklander void *tmp_va[TEE_NUM_PARAMS], 1987509620bSJens Wiklander const struct utee_params *up) 1997509620bSJens Wiklander { 2007509620bSJens Wiklander size_t n = 0; 2017509620bSJens Wiklander uint32_t types = up->types; 2027509620bSJens Wiklander 2037509620bSJens Wiklander for (n = 0; n < TEE_NUM_PARAMS; n++) { 2047509620bSJens Wiklander uintptr_t a = up->vals[n * 2]; 2057509620bSJens Wiklander uintptr_t b = up->vals[n * 2 + 1]; 2067509620bSJens Wiklander 2077509620bSJens Wiklander switch (TEE_PARAM_TYPE_GET(types, n)) { 2087509620bSJens Wiklander case TEE_PARAM_TYPE_VALUE_OUTPUT: 2097509620bSJens Wiklander case TEE_PARAM_TYPE_VALUE_INOUT: 2107509620bSJens Wiklander params[n].value.a = a; 2117509620bSJens Wiklander params[n].value.b = b; 2127509620bSJens Wiklander break; 2137509620bSJens Wiklander case TEE_PARAM_TYPE_MEMREF_OUTPUT: 2147509620bSJens Wiklander case TEE_PARAM_TYPE_MEMREF_INOUT: 2157509620bSJens Wiklander if (tmp_va[n]) 2167509620bSJens Wiklander memcpy(params[n].memref.buffer, tmp_va[n], 2177509620bSJens Wiklander MIN(b, params[n].memref.size)); 2187509620bSJens Wiklander params[n].memref.size = b; 2197509620bSJens Wiklander break; 2207509620bSJens Wiklander default: 2217509620bSJens Wiklander break; 2227509620bSJens Wiklander } 2237509620bSJens Wiklander } 2247509620bSJens Wiklander } 2257509620bSJens Wiklander 226*c8bf6a25SJens Wiklander static bool bufs_intersect(void *buf1, size_t sz1, void *buf2, size_t sz2) 227*c8bf6a25SJens Wiklander { 228*c8bf6a25SJens Wiklander vaddr_t b1 = (vaddr_t)buf1; 229*c8bf6a25SJens Wiklander vaddr_t b2 = (vaddr_t)buf2; 230*c8bf6a25SJens Wiklander vaddr_t e1 = b1 + sz1 - 1; 231*c8bf6a25SJens Wiklander vaddr_t e2 = b2 + sz2 - 1; 232*c8bf6a25SJens Wiklander 233*c8bf6a25SJens Wiklander if (!sz1 || !sz2) 234*c8bf6a25SJens Wiklander return false; 235*c8bf6a25SJens Wiklander 236*c8bf6a25SJens Wiklander if (e1 < b2 || e2 < b1) 237*c8bf6a25SJens Wiklander return false; 238*c8bf6a25SJens Wiklander 239*c8bf6a25SJens Wiklander return true; 240*c8bf6a25SJens Wiklander } 241*c8bf6a25SJens Wiklander 242*c8bf6a25SJens Wiklander static TEE_Result check_mem_access_rights_params(uint32_t flags, void *buf, 243*c8bf6a25SJens Wiklander size_t len) 244*c8bf6a25SJens Wiklander { 245*c8bf6a25SJens Wiklander size_t n = 0; 246*c8bf6a25SJens Wiklander 247*c8bf6a25SJens Wiklander for (n = 0; n < TEE_NUM_PARAMS; n++) { 248*c8bf6a25SJens Wiklander uint32_t f = TEE_MEMORY_ACCESS_ANY_OWNER; 249*c8bf6a25SJens Wiklander 250*c8bf6a25SJens Wiklander switch (TEE_PARAM_TYPE_GET(ta_param_types, n)) { 251*c8bf6a25SJens Wiklander case TEE_PARAM_TYPE_MEMREF_OUTPUT: 252*c8bf6a25SJens Wiklander case TEE_PARAM_TYPE_MEMREF_INOUT: 253*c8bf6a25SJens Wiklander f |= TEE_MEMORY_ACCESS_WRITE; 254*c8bf6a25SJens Wiklander fallthrough; 255*c8bf6a25SJens Wiklander case TEE_PARAM_TYPE_MEMREF_INPUT: 256*c8bf6a25SJens Wiklander f |= TEE_MEMORY_ACCESS_READ; 257*c8bf6a25SJens Wiklander if (bufs_intersect(buf, len, 258*c8bf6a25SJens Wiklander ta_params[n].memref.buffer, 259*c8bf6a25SJens Wiklander ta_params[n].memref.size)) { 260*c8bf6a25SJens Wiklander if ((flags & f) != flags) 261*c8bf6a25SJens Wiklander return TEE_ERROR_ACCESS_DENIED; 262*c8bf6a25SJens Wiklander } 263*c8bf6a25SJens Wiklander break; 264*c8bf6a25SJens Wiklander default: 265*c8bf6a25SJens Wiklander break; 266*c8bf6a25SJens Wiklander } 267*c8bf6a25SJens Wiklander } 268*c8bf6a25SJens Wiklander 269*c8bf6a25SJens Wiklander return TEE_SUCCESS; 270*c8bf6a25SJens Wiklander } 271*c8bf6a25SJens Wiklander 272b0104773SPascal Brand TEE_Result TEE_OpenTASession(const TEE_UUID *destination, 273b0104773SPascal Brand uint32_t cancellationRequestTimeout, 27468540524SIgor Opaniuk uint32_t paramTypes, 27568540524SIgor Opaniuk TEE_Param params[TEE_NUM_PARAMS], 276b0104773SPascal Brand TEE_TASessionHandle *session, 277b0104773SPascal Brand uint32_t *returnOrigin) 278b0104773SPascal Brand { 279ef305e54SJens Wiklander TEE_Result res = TEE_SUCCESS; 2807509620bSJens Wiklander struct utee_params up = { }; 281ef305e54SJens Wiklander uint32_t s = 0; 282ef305e54SJens Wiklander void *tmp_buf = NULL; 283ef305e54SJens Wiklander size_t tmp_len = 0; 284ef305e54SJens Wiklander void *tmp_va[TEE_NUM_PARAMS] = { NULL }; 285b0104773SPascal Brand 2866915bbbbSJens Wiklander if (paramTypes) 2876915bbbbSJens Wiklander __utee_check_inout_annotation(params, 2886915bbbbSJens Wiklander sizeof(TEE_Param) * 2896915bbbbSJens Wiklander TEE_NUM_PARAMS); 2906915bbbbSJens Wiklander __utee_check_out_annotation(session, sizeof(*session)); 2916915bbbbSJens Wiklander 2927509620bSJens Wiklander copy_param(&up, paramTypes, params); 2937509620bSJens Wiklander res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); 294ef305e54SJens Wiklander if (res) 295ef305e54SJens Wiklander goto out; 2962c028fdeSJerome Forissier res = _utee_open_ta_session(destination, cancellationRequestTimeout, 297e86f1266SJens Wiklander &up, &s, returnOrigin); 298ef305e54SJens Wiklander update_out_param(params, tmp_va, &up); 299ef305e54SJens Wiklander if (tmp_buf) { 300ef305e54SJens Wiklander TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); 301ef305e54SJens Wiklander 302ef305e54SJens Wiklander if (res2) 303ef305e54SJens Wiklander TEE_Panic(res2); 304ef305e54SJens Wiklander } 305ef305e54SJens Wiklander 306ef305e54SJens Wiklander out: 307b0104773SPascal Brand /* 308b0104773SPascal Brand * Specification says that *session must hold TEE_HANDLE_NULL is 309b0104773SPascal Brand * TEE_SUCCESS isn't returned. Set it here explicitly in case 310b0104773SPascal Brand * the syscall fails before out parameters has been updated. 311b0104773SPascal Brand */ 312b0104773SPascal Brand if (res != TEE_SUCCESS) 313e86f1266SJens Wiklander s = TEE_HANDLE_NULL; 314b0104773SPascal Brand 315e86f1266SJens Wiklander *session = (TEE_TASessionHandle)(uintptr_t)s; 316b0104773SPascal Brand return res; 317b0104773SPascal Brand } 318b0104773SPascal Brand 3197509620bSJens Wiklander TEE_Result __GP11_TEE_OpenTASession(const TEE_UUID *destination, 3207509620bSJens Wiklander uint32_t cancellationRequestTimeout, 3217509620bSJens Wiklander uint32_t paramTypes, 3227509620bSJens Wiklander __GP11_TEE_Param params[TEE_NUM_PARAMS], 3237509620bSJens Wiklander TEE_TASessionHandle *session, 3247509620bSJens Wiklander uint32_t *returnOrigin) 3257509620bSJens Wiklander { 3267509620bSJens Wiklander TEE_Result res = TEE_SUCCESS; 3277509620bSJens Wiklander struct utee_params up = { }; 3287509620bSJens Wiklander uint32_t s = 0; 3297509620bSJens Wiklander void *tmp_buf = NULL; 3307509620bSJens Wiklander size_t tmp_len = 0; 3317509620bSJens Wiklander void *tmp_va[TEE_NUM_PARAMS] = { NULL }; 3327509620bSJens Wiklander 3337509620bSJens Wiklander if (paramTypes) 3347509620bSJens Wiklander __utee_check_inout_annotation(params, 3357509620bSJens Wiklander sizeof(__GP11_TEE_Param) * 3367509620bSJens Wiklander TEE_NUM_PARAMS); 3377509620bSJens Wiklander __utee_check_out_annotation(session, sizeof(*session)); 3387509620bSJens Wiklander 3397509620bSJens Wiklander copy_gp11_param(&up, paramTypes, params); 3407509620bSJens Wiklander res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); 3417509620bSJens Wiklander if (res) 3427509620bSJens Wiklander goto out; 3437509620bSJens Wiklander res = _utee_open_ta_session(destination, cancellationRequestTimeout, 3447509620bSJens Wiklander &up, &s, returnOrigin); 3457509620bSJens Wiklander update_out_gp11_param(params, tmp_va, &up); 3467509620bSJens Wiklander if (tmp_buf) { 3477509620bSJens Wiklander TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); 3487509620bSJens Wiklander 3497509620bSJens Wiklander if (res2) 3507509620bSJens Wiklander TEE_Panic(res2); 3517509620bSJens Wiklander } 3527509620bSJens Wiklander 3537509620bSJens Wiklander out: 3547509620bSJens Wiklander /* 3557509620bSJens Wiklander * Specification says that *session must hold TEE_HANDLE_NULL if 3567509620bSJens Wiklander * TEE_SUCCESS isn't returned. Set it here explicitly in case 3577509620bSJens Wiklander * the syscall fails before out parameters has been updated. 3587509620bSJens Wiklander */ 3597509620bSJens Wiklander if (res != TEE_SUCCESS) 3607509620bSJens Wiklander s = TEE_HANDLE_NULL; 3617509620bSJens Wiklander 3627509620bSJens Wiklander *session = (TEE_TASessionHandle)(uintptr_t)s; 3637509620bSJens Wiklander return res; 3647509620bSJens Wiklander } 3657509620bSJens Wiklander 366b0104773SPascal Brand void TEE_CloseTASession(TEE_TASessionHandle session) 367b0104773SPascal Brand { 368b0104773SPascal Brand if (session != TEE_HANDLE_NULL) { 3692c028fdeSJerome Forissier TEE_Result res = _utee_close_ta_session((uintptr_t)session); 370e86f1266SJens Wiklander 371b0104773SPascal Brand if (res != TEE_SUCCESS) 372b0104773SPascal Brand TEE_Panic(res); 373b0104773SPascal Brand } 374b0104773SPascal Brand } 375b0104773SPascal Brand 376b0104773SPascal Brand TEE_Result TEE_InvokeTACommand(TEE_TASessionHandle session, 377b0104773SPascal Brand uint32_t cancellationRequestTimeout, 378b0104773SPascal Brand uint32_t commandID, uint32_t paramTypes, 37968540524SIgor Opaniuk TEE_Param params[TEE_NUM_PARAMS], 38068540524SIgor Opaniuk uint32_t *returnOrigin) 381b0104773SPascal Brand { 382ef305e54SJens Wiklander TEE_Result res = TEE_SUCCESS; 383ef305e54SJens Wiklander uint32_t ret_origin = TEE_ORIGIN_TEE; 3847509620bSJens Wiklander struct utee_params up = { }; 385ef305e54SJens Wiklander void *tmp_buf = NULL; 386ef305e54SJens Wiklander size_t tmp_len = 0; 387ef305e54SJens Wiklander void *tmp_va[TEE_NUM_PARAMS] = { NULL }; 388c15e5835SCedric Chaumont 3896915bbbbSJens Wiklander if (paramTypes) 3906915bbbbSJens Wiklander __utee_check_inout_annotation(params, 3916915bbbbSJens Wiklander sizeof(TEE_Param) * 3926915bbbbSJens Wiklander TEE_NUM_PARAMS); 3936915bbbbSJens Wiklander if (returnOrigin) 3946915bbbbSJens Wiklander __utee_check_out_annotation(returnOrigin, 3956915bbbbSJens Wiklander sizeof(*returnOrigin)); 3966915bbbbSJens Wiklander 3977509620bSJens Wiklander copy_param(&up, paramTypes, params); 3987509620bSJens Wiklander res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); 399ef305e54SJens Wiklander if (res) 400ef305e54SJens Wiklander goto out; 4012c028fdeSJerome Forissier res = _utee_invoke_ta_command((uintptr_t)session, 402e86f1266SJens Wiklander cancellationRequestTimeout, 403e86f1266SJens Wiklander commandID, &up, &ret_origin); 404ef305e54SJens Wiklander update_out_param(params, tmp_va, &up); 405ef305e54SJens Wiklander if (tmp_buf) { 406ef305e54SJens Wiklander TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); 4076709c3eaSCedric Chaumont 408ef305e54SJens Wiklander if (res2) 409ef305e54SJens Wiklander TEE_Panic(res2); 410ef305e54SJens Wiklander } 411ef305e54SJens Wiklander 412ef305e54SJens Wiklander out: 4136709c3eaSCedric Chaumont if (returnOrigin != NULL) 4146709c3eaSCedric Chaumont *returnOrigin = ret_origin; 4156709c3eaSCedric Chaumont 4166709c3eaSCedric Chaumont if (ret_origin == TEE_ORIGIN_TRUSTED_APP) 4176709c3eaSCedric Chaumont return res; 4186709c3eaSCedric Chaumont 419c15e5835SCedric Chaumont if (res != TEE_SUCCESS && 420c15e5835SCedric Chaumont res != TEE_ERROR_OUT_OF_MEMORY && 421c15e5835SCedric Chaumont res != TEE_ERROR_TARGET_DEAD) 422c15e5835SCedric Chaumont TEE_Panic(res); 423c15e5835SCedric Chaumont 424c15e5835SCedric Chaumont return res; 425b0104773SPascal Brand } 426b0104773SPascal Brand 4277509620bSJens Wiklander TEE_Result __GP11_TEE_InvokeTACommand(TEE_TASessionHandle session, 4287509620bSJens Wiklander uint32_t cancellationRequestTimeout, 4297509620bSJens Wiklander uint32_t commandID, uint32_t paramTypes, 4307509620bSJens Wiklander __GP11_TEE_Param params[TEE_NUM_PARAMS], 4317509620bSJens Wiklander uint32_t *returnOrigin) 4327509620bSJens Wiklander { 4337509620bSJens Wiklander TEE_Result res = TEE_SUCCESS; 4347509620bSJens Wiklander uint32_t ret_origin = TEE_ORIGIN_TEE; 4357509620bSJens Wiklander struct utee_params up = { }; 4367509620bSJens Wiklander void *tmp_buf = NULL; 4377509620bSJens Wiklander size_t tmp_len = 0; 4387509620bSJens Wiklander void *tmp_va[TEE_NUM_PARAMS] = { NULL }; 4397509620bSJens Wiklander 4407509620bSJens Wiklander if (paramTypes) 4417509620bSJens Wiklander __utee_check_inout_annotation(params, 4427509620bSJens Wiklander sizeof(__GP11_TEE_Param) * 4437509620bSJens Wiklander TEE_NUM_PARAMS); 4447509620bSJens Wiklander if (returnOrigin) 4457509620bSJens Wiklander __utee_check_out_annotation(returnOrigin, 4467509620bSJens Wiklander sizeof(*returnOrigin)); 4477509620bSJens Wiklander 4487509620bSJens Wiklander copy_gp11_param(&up, paramTypes, params); 4497509620bSJens Wiklander res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); 4507509620bSJens Wiklander if (res) 4517509620bSJens Wiklander goto out; 4527509620bSJens Wiklander res = _utee_invoke_ta_command((uintptr_t)session, 4537509620bSJens Wiklander cancellationRequestTimeout, 4547509620bSJens Wiklander commandID, &up, &ret_origin); 4557509620bSJens Wiklander update_out_gp11_param(params, tmp_va, &up); 4567509620bSJens Wiklander if (tmp_buf) { 4577509620bSJens Wiklander TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); 4587509620bSJens Wiklander 4597509620bSJens Wiklander if (res2) 4607509620bSJens Wiklander TEE_Panic(res2); 4617509620bSJens Wiklander } 4627509620bSJens Wiklander 4637509620bSJens Wiklander out: 4647509620bSJens Wiklander if (returnOrigin) 4657509620bSJens Wiklander *returnOrigin = ret_origin; 4667509620bSJens Wiklander 4677509620bSJens Wiklander if (ret_origin == TEE_ORIGIN_TRUSTED_APP) 4687509620bSJens Wiklander return res; 4697509620bSJens Wiklander 4707509620bSJens Wiklander if (res != TEE_SUCCESS && 4717509620bSJens Wiklander res != TEE_ERROR_OUT_OF_MEMORY && 4727509620bSJens Wiklander res != TEE_ERROR_TARGET_DEAD) 4737509620bSJens Wiklander TEE_Panic(res); 4747509620bSJens Wiklander 4757509620bSJens Wiklander return res; 4767509620bSJens Wiklander } 4777509620bSJens Wiklander 478b0104773SPascal Brand /* System API - Cancellations */ 479b0104773SPascal Brand 480b0104773SPascal Brand bool TEE_GetCancellationFlag(void) 481b0104773SPascal Brand { 482e86f1266SJens Wiklander uint32_t c; 4832c028fdeSJerome Forissier TEE_Result res = _utee_get_cancellation_flag(&c); 484e86f1266SJens Wiklander 485b0104773SPascal Brand if (res != TEE_SUCCESS) 486e86f1266SJens Wiklander c = 0; 487e86f1266SJens Wiklander return !!c; 488b0104773SPascal Brand } 489b0104773SPascal Brand 490b0104773SPascal Brand bool TEE_UnmaskCancellation(void) 491b0104773SPascal Brand { 492e86f1266SJens Wiklander uint32_t old_mask; 4932c028fdeSJerome Forissier TEE_Result res = _utee_unmask_cancellation(&old_mask); 494b0104773SPascal Brand 495b0104773SPascal Brand if (res != TEE_SUCCESS) 496b0104773SPascal Brand TEE_Panic(res); 497e86f1266SJens Wiklander return !!old_mask; 498b0104773SPascal Brand } 499b0104773SPascal Brand 500b0104773SPascal Brand bool TEE_MaskCancellation(void) 501b0104773SPascal Brand { 502e86f1266SJens Wiklander uint32_t old_mask; 5032c028fdeSJerome Forissier TEE_Result res = _utee_mask_cancellation(&old_mask); 504b0104773SPascal Brand 505b0104773SPascal Brand if (res != TEE_SUCCESS) 506b0104773SPascal Brand TEE_Panic(res); 507e86f1266SJens Wiklander return !!old_mask; 508b0104773SPascal Brand } 509b0104773SPascal Brand 510b0104773SPascal Brand /* System API - Memory Management */ 511b0104773SPascal Brand 512b0104773SPascal Brand TEE_Result TEE_CheckMemoryAccessRights(uint32_t accessFlags, void *buffer, 513cd3a8caeSJens Wiklander size_t size) 514b0104773SPascal Brand { 515*c8bf6a25SJens Wiklander uint32_t flags = accessFlags; 516b0104773SPascal Brand 517*c8bf6a25SJens Wiklander if (!size) 518b0104773SPascal Brand return TEE_SUCCESS; 519b0104773SPascal Brand 520*c8bf6a25SJens Wiklander /* 521*c8bf6a25SJens Wiklander * Check access rights against memory mapping. If this check is 522*c8bf6a25SJens Wiklander * OK the size can't cause an overflow when added with buffer. 523*c8bf6a25SJens Wiklander */ 524*c8bf6a25SJens Wiklander if (_utee_check_access_rights(accessFlags, buffer, size)) 525*c8bf6a25SJens Wiklander return TEE_ERROR_ACCESS_DENIED; 526b0104773SPascal Brand 527b0104773SPascal Brand /* 528*c8bf6a25SJens Wiklander * Check access rights against input parameters. 529*c8bf6a25SJens Wiklander * 530*c8bf6a25SJens Wiklander * Clear eventual extension flags like TEE_MEMORY_ACCESS_NONSECURE 531*c8bf6a25SJens Wiklander * and TEE_MEMORY_ACCESS_SECURE. 532b0104773SPascal Brand */ 533*c8bf6a25SJens Wiklander flags &= TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE | 534*c8bf6a25SJens Wiklander TEE_MEMORY_ACCESS_ANY_OWNER; 535*c8bf6a25SJens Wiklander if (check_mem_access_rights_params(flags, buffer, size)) 536*c8bf6a25SJens Wiklander return TEE_ERROR_ACCESS_DENIED; 537b0104773SPascal Brand 538*c8bf6a25SJens Wiklander if (malloc_buffer_overlaps_heap(buffer, size) && 539*c8bf6a25SJens Wiklander !malloc_buffer_is_within_alloced(buffer, size)) 540*c8bf6a25SJens Wiklander return TEE_ERROR_ACCESS_DENIED; 541*c8bf6a25SJens Wiklander 542*c8bf6a25SJens Wiklander return TEE_SUCCESS; 543b0104773SPascal Brand } 544b0104773SPascal Brand 545cd3a8caeSJens Wiklander TEE_Result __GP11_TEE_CheckMemoryAccessRights(uint32_t accessFlags, 546cd3a8caeSJens Wiklander void *buffer, uint32_t size) 547cd3a8caeSJens Wiklander { 548cd3a8caeSJens Wiklander return TEE_CheckMemoryAccessRights(accessFlags, buffer, size); 549cd3a8caeSJens Wiklander } 550cd3a8caeSJens Wiklander 5518f07fe6fSJerome Forissier void TEE_SetInstanceData(const void *instanceData) 552b0104773SPascal Brand { 553b0104773SPascal Brand tee_api_instance_data = instanceData; 554b0104773SPascal Brand } 555b0104773SPascal Brand 5568f07fe6fSJerome Forissier const void *TEE_GetInstanceData(void) 557b0104773SPascal Brand { 558b0104773SPascal Brand return tee_api_instance_data; 559b0104773SPascal Brand } 560b0104773SPascal Brand 5611d0ed95aSJens Wiklander void *TEE_MemMove(void *dest, const void *src, size_t size) 562b0104773SPascal Brand { 563b0104773SPascal Brand return memmove(dest, src, size); 564b0104773SPascal Brand } 565b0104773SPascal Brand 5661d0ed95aSJens Wiklander void *__GP11_TEE_MemMove(void *dest, const void *src, uint32_t size) 5671d0ed95aSJens Wiklander { 5681d0ed95aSJens Wiklander return TEE_MemMove(dest, src, size); 5691d0ed95aSJens Wiklander } 5701d0ed95aSJens Wiklander 5711d0ed95aSJens Wiklander int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, size_t size) 572b0104773SPascal Brand { 57365551e69SJerome Forissier return consttime_memcmp(buffer1, buffer2, size); 574b0104773SPascal Brand } 575b0104773SPascal Brand 5761d0ed95aSJens Wiklander int32_t __GP11_TEE_MemCompare(const void *buffer1, const void *buffer2, 5771d0ed95aSJens Wiklander uint32_t size) 5781d0ed95aSJens Wiklander { 5791d0ed95aSJens Wiklander return TEE_MemCompare(buffer1, buffer2, size); 5801d0ed95aSJens Wiklander } 5811d0ed95aSJens Wiklander 5821d0ed95aSJens Wiklander void TEE_MemFill(void *buff, uint32_t x, size_t size) 583b0104773SPascal Brand { 58432c75600SJens Wiklander memset(buff, x, size); 585b0104773SPascal Brand } 586b0104773SPascal Brand 5871d0ed95aSJens Wiklander void __GP11_TEE_MemFill(void *buff, uint32_t x, uint32_t size) 5881d0ed95aSJens Wiklander { 5891d0ed95aSJens Wiklander TEE_MemFill(buff, x, size); 5901d0ed95aSJens Wiklander } 5911d0ed95aSJens Wiklander 592b0104773SPascal Brand /* Date & Time API */ 593b0104773SPascal Brand 594b0104773SPascal Brand void TEE_GetSystemTime(TEE_Time *time) 595b0104773SPascal Brand { 5962c028fdeSJerome Forissier TEE_Result res = _utee_get_time(UTEE_TIME_CAT_SYSTEM, time); 597b0104773SPascal Brand 598b0104773SPascal Brand if (res != TEE_SUCCESS) 599b36311adSJerome Forissier TEE_Panic(res); 600b0104773SPascal Brand } 601b0104773SPascal Brand 602b0104773SPascal Brand TEE_Result TEE_Wait(uint32_t timeout) 603b0104773SPascal Brand { 6042c028fdeSJerome Forissier TEE_Result res = _utee_wait(timeout); 605b0104773SPascal Brand 606b0104773SPascal Brand if (res != TEE_SUCCESS && res != TEE_ERROR_CANCEL) 607b0104773SPascal Brand TEE_Panic(res); 608b0104773SPascal Brand 609b0104773SPascal Brand return res; 610b0104773SPascal Brand } 611b0104773SPascal Brand 612b0104773SPascal Brand TEE_Result TEE_GetTAPersistentTime(TEE_Time *time) 613b0104773SPascal Brand { 614b64d6909SCedric Chaumont TEE_Result res; 615b64d6909SCedric Chaumont 6162c028fdeSJerome Forissier res = _utee_get_time(UTEE_TIME_CAT_TA_PERSISTENT, time); 617b64d6909SCedric Chaumont 618b64d6909SCedric Chaumont if (res != TEE_SUCCESS && res != TEE_ERROR_OVERFLOW) { 619b64d6909SCedric Chaumont time->seconds = 0; 620b64d6909SCedric Chaumont time->millis = 0; 621b64d6909SCedric Chaumont } 622b64d6909SCedric Chaumont 623b64d6909SCedric Chaumont if (res != TEE_SUCCESS && 624b64d6909SCedric Chaumont res != TEE_ERROR_TIME_NOT_SET && 625b64d6909SCedric Chaumont res != TEE_ERROR_TIME_NEEDS_RESET && 626b64d6909SCedric Chaumont res != TEE_ERROR_OVERFLOW && 627b64d6909SCedric Chaumont res != TEE_ERROR_OUT_OF_MEMORY) 628b64d6909SCedric Chaumont TEE_Panic(res); 629b64d6909SCedric Chaumont 630b64d6909SCedric Chaumont return res; 631b0104773SPascal Brand } 632b0104773SPascal Brand 633b0104773SPascal Brand TEE_Result TEE_SetTAPersistentTime(const TEE_Time *time) 634b0104773SPascal Brand { 635b64d6909SCedric Chaumont TEE_Result res; 636b64d6909SCedric Chaumont 6372c028fdeSJerome Forissier res = _utee_set_ta_time(time); 638b64d6909SCedric Chaumont 639b64d6909SCedric Chaumont if (res != TEE_SUCCESS && 640b64d6909SCedric Chaumont res != TEE_ERROR_OUT_OF_MEMORY && 641b64d6909SCedric Chaumont res != TEE_ERROR_STORAGE_NO_SPACE) 642b64d6909SCedric Chaumont TEE_Panic(res); 643b64d6909SCedric Chaumont 644b64d6909SCedric Chaumont return res; 645b0104773SPascal Brand } 646b0104773SPascal Brand 647b0104773SPascal Brand void TEE_GetREETime(TEE_Time *time) 648b0104773SPascal Brand { 6492c028fdeSJerome Forissier TEE_Result res = _utee_get_time(UTEE_TIME_CAT_REE, time); 650b0104773SPascal Brand 651b0104773SPascal Brand if (res != TEE_SUCCESS) 652b36311adSJerome Forissier TEE_Panic(res); 653b0104773SPascal Brand } 654b0104773SPascal Brand 65511285ebcSJens Wiklander void *TEE_Malloc(size_t len, uint32_t hint) 656b0104773SPascal Brand { 65711285ebcSJens Wiklander switch (hint) { 65811285ebcSJens Wiklander case TEE_MALLOC_FILL_ZERO: 659a83ee50aSSadiq Hussain if (!len) 660a83ee50aSSadiq Hussain return TEE_NULL_SIZED_VA; 66196c1d8c5SJens Wiklander return calloc(1, len); 66211285ebcSJens Wiklander 66311285ebcSJens Wiklander case TEE_MALLOC_NO_FILL: 66411285ebcSJens Wiklander TEE_Panic(0); 66511285ebcSJens Wiklander break; 66611285ebcSJens Wiklander 66711285ebcSJens Wiklander case TEE_MALLOC_NO_FILL | TEE_MALLOC_NO_SHARE: 66811285ebcSJens Wiklander return NULL; /* TEE_MALLOC_NO_SHARE is not yet supported */ 66911285ebcSJens Wiklander 67011285ebcSJens Wiklander case TEE_USER_MEM_HINT_NO_FILL_ZERO: 67111285ebcSJens Wiklander if (!len) 67211285ebcSJens Wiklander return TEE_NULL_SIZED_VA; 67396c1d8c5SJens Wiklander return malloc(len); 67496c1d8c5SJens Wiklander 67511285ebcSJens Wiklander default: 67611285ebcSJens Wiklander break; 67711285ebcSJens Wiklander } 67811285ebcSJens Wiklander 67996c1d8c5SJens Wiklander EMSG("Invalid hint %#" PRIx32, hint); 68096c1d8c5SJens Wiklander 68196c1d8c5SJens Wiklander return NULL; 682b0104773SPascal Brand } 683b0104773SPascal Brand 68411285ebcSJens Wiklander void *__GP11_TEE_Malloc(uint32_t size, uint32_t hint) 68511285ebcSJens Wiklander { 68611285ebcSJens Wiklander return TEE_Malloc(size, hint); 68711285ebcSJens Wiklander } 68811285ebcSJens Wiklander 68911285ebcSJens Wiklander void *TEE_Realloc(void *buffer, size_t newSize) 690b0104773SPascal Brand { 691a83ee50aSSadiq Hussain if (!newSize) { 692a83ee50aSSadiq Hussain TEE_Free(buffer); 693a83ee50aSSadiq Hussain return TEE_NULL_SIZED_VA; 694a83ee50aSSadiq Hussain } 695a83ee50aSSadiq Hussain 696a83ee50aSSadiq Hussain if (buffer == TEE_NULL_SIZED_VA) 697a83ee50aSSadiq Hussain return calloc(1, newSize); 698a83ee50aSSadiq Hussain 69996c1d8c5SJens Wiklander return realloc(buffer, newSize); 700b0104773SPascal Brand } 701b0104773SPascal Brand 70211285ebcSJens Wiklander void *__GP11_TEE_Realloc(void *buffer, uint32_t newSize) 70311285ebcSJens Wiklander { 70411285ebcSJens Wiklander return TEE_Realloc(buffer, newSize); 70511285ebcSJens Wiklander } 70611285ebcSJens Wiklander 707b0104773SPascal Brand void TEE_Free(void *buffer) 708b0104773SPascal Brand { 709a83ee50aSSadiq Hussain if (buffer != TEE_NULL_SIZED_VA) 71096c1d8c5SJens Wiklander free(buffer); 711b0104773SPascal Brand } 712fa530828SPascal Brand 713fa530828SPascal Brand /* Cache maintenance support (TA requires the CACHE_MAINTENANCE property) */ 714fa530828SPascal Brand TEE_Result TEE_CacheClean(char *buf, size_t len) 715fa530828SPascal Brand { 7162c028fdeSJerome Forissier return _utee_cache_operation(buf, len, TEE_CACHECLEAN); 717fa530828SPascal Brand } 718fa530828SPascal Brand TEE_Result TEE_CacheFlush(char *buf, size_t len) 719fa530828SPascal Brand { 7202c028fdeSJerome Forissier return _utee_cache_operation(buf, len, TEE_CACHEFLUSH); 721fa530828SPascal Brand } 722fa530828SPascal Brand 723fa530828SPascal Brand TEE_Result TEE_CacheInvalidate(char *buf, size_t len) 724fa530828SPascal Brand { 7252c028fdeSJerome Forissier return _utee_cache_operation(buf, len, TEE_CACHEINVALIDATE); 726fa530828SPascal Brand } 727