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 226c8bf6a25SJens Wiklander static bool bufs_intersect(void *buf1, size_t sz1, void *buf2, size_t sz2) 227c8bf6a25SJens Wiklander { 228c8bf6a25SJens Wiklander vaddr_t b1 = (vaddr_t)buf1; 229c8bf6a25SJens Wiklander vaddr_t b2 = (vaddr_t)buf2; 230c8bf6a25SJens Wiklander vaddr_t e1 = b1 + sz1 - 1; 231c8bf6a25SJens Wiklander vaddr_t e2 = b2 + sz2 - 1; 232c8bf6a25SJens Wiklander 233c8bf6a25SJens Wiklander if (!sz1 || !sz2) 234c8bf6a25SJens Wiklander return false; 235c8bf6a25SJens Wiklander 236c8bf6a25SJens Wiklander if (e1 < b2 || e2 < b1) 237c8bf6a25SJens Wiklander return false; 238c8bf6a25SJens Wiklander 239c8bf6a25SJens Wiklander return true; 240c8bf6a25SJens Wiklander } 241c8bf6a25SJens Wiklander 242c8bf6a25SJens Wiklander static TEE_Result check_mem_access_rights_params(uint32_t flags, void *buf, 243c8bf6a25SJens Wiklander size_t len) 244c8bf6a25SJens Wiklander { 245c8bf6a25SJens Wiklander size_t n = 0; 246c8bf6a25SJens Wiklander 247c8bf6a25SJens Wiklander for (n = 0; n < TEE_NUM_PARAMS; n++) { 248c8bf6a25SJens Wiklander uint32_t f = TEE_MEMORY_ACCESS_ANY_OWNER; 249c8bf6a25SJens Wiklander 250c8bf6a25SJens Wiklander switch (TEE_PARAM_TYPE_GET(ta_param_types, n)) { 251c8bf6a25SJens Wiklander case TEE_PARAM_TYPE_MEMREF_OUTPUT: 252c8bf6a25SJens Wiklander case TEE_PARAM_TYPE_MEMREF_INOUT: 253c8bf6a25SJens Wiklander f |= TEE_MEMORY_ACCESS_WRITE; 254c8bf6a25SJens Wiklander fallthrough; 255c8bf6a25SJens Wiklander case TEE_PARAM_TYPE_MEMREF_INPUT: 256c8bf6a25SJens Wiklander f |= TEE_MEMORY_ACCESS_READ; 257c8bf6a25SJens Wiklander if (bufs_intersect(buf, len, 258c8bf6a25SJens Wiklander ta_params[n].memref.buffer, 259c8bf6a25SJens Wiklander ta_params[n].memref.size)) { 260c8bf6a25SJens Wiklander if ((flags & f) != flags) 261c8bf6a25SJens Wiklander return TEE_ERROR_ACCESS_DENIED; 262c8bf6a25SJens Wiklander } 263c8bf6a25SJens Wiklander break; 264c8bf6a25SJens Wiklander default: 265c8bf6a25SJens Wiklander break; 266c8bf6a25SJens Wiklander } 267c8bf6a25SJens Wiklander } 268c8bf6a25SJens Wiklander 269c8bf6a25SJens Wiklander return TEE_SUCCESS; 270c8bf6a25SJens Wiklander } 271c8bf6a25SJens Wiklander 272*30e5e0beSJens Wiklander static void check_invoke_param(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) 273*30e5e0beSJens Wiklander { 274*30e5e0beSJens Wiklander size_t n = 0; 275*30e5e0beSJens Wiklander 276*30e5e0beSJens Wiklander for (n = 0; n < TEE_NUM_PARAMS; n++) { 277*30e5e0beSJens Wiklander uint32_t f = TEE_MEMORY_ACCESS_ANY_OWNER; 278*30e5e0beSJens Wiklander void *buf = params[n].memref.buffer; 279*30e5e0beSJens Wiklander size_t size = params[n].memref.size; 280*30e5e0beSJens Wiklander 281*30e5e0beSJens Wiklander switch (TEE_PARAM_TYPE_GET(pt, n)) { 282*30e5e0beSJens Wiklander case TEE_PARAM_TYPE_MEMREF_OUTPUT: 283*30e5e0beSJens Wiklander case TEE_PARAM_TYPE_MEMREF_INOUT: 284*30e5e0beSJens Wiklander f |= TEE_MEMORY_ACCESS_WRITE; 285*30e5e0beSJens Wiklander fallthrough; 286*30e5e0beSJens Wiklander case TEE_PARAM_TYPE_MEMREF_INPUT: 287*30e5e0beSJens Wiklander f |= TEE_MEMORY_ACCESS_READ; 288*30e5e0beSJens Wiklander if (check_mem_access_rights_params(f, buf, size)) 289*30e5e0beSJens Wiklander TEE_Panic(0); 290*30e5e0beSJens Wiklander break; 291*30e5e0beSJens Wiklander default: 292*30e5e0beSJens Wiklander break; 293*30e5e0beSJens Wiklander } 294*30e5e0beSJens Wiklander } 295*30e5e0beSJens Wiklander } 296*30e5e0beSJens Wiklander 297b0104773SPascal Brand TEE_Result TEE_OpenTASession(const TEE_UUID *destination, 298b0104773SPascal Brand uint32_t cancellationRequestTimeout, 29968540524SIgor Opaniuk uint32_t paramTypes, 30068540524SIgor Opaniuk TEE_Param params[TEE_NUM_PARAMS], 301b0104773SPascal Brand TEE_TASessionHandle *session, 302b0104773SPascal Brand uint32_t *returnOrigin) 303b0104773SPascal Brand { 304ef305e54SJens Wiklander TEE_Result res = TEE_SUCCESS; 3057509620bSJens Wiklander struct utee_params up = { }; 306ef305e54SJens Wiklander uint32_t s = 0; 307ef305e54SJens Wiklander void *tmp_buf = NULL; 308ef305e54SJens Wiklander size_t tmp_len = 0; 309ef305e54SJens Wiklander void *tmp_va[TEE_NUM_PARAMS] = { NULL }; 310b0104773SPascal Brand 311*30e5e0beSJens Wiklander if (paramTypes) { 3126915bbbbSJens Wiklander __utee_check_inout_annotation(params, 3136915bbbbSJens Wiklander sizeof(TEE_Param) * 3146915bbbbSJens Wiklander TEE_NUM_PARAMS); 315*30e5e0beSJens Wiklander check_invoke_param(paramTypes, params); 316*30e5e0beSJens Wiklander } 3176915bbbbSJens Wiklander __utee_check_out_annotation(session, sizeof(*session)); 3186915bbbbSJens Wiklander 3197509620bSJens Wiklander copy_param(&up, paramTypes, params); 3207509620bSJens Wiklander res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); 321ef305e54SJens Wiklander if (res) 322ef305e54SJens Wiklander goto out; 3232c028fdeSJerome Forissier res = _utee_open_ta_session(destination, cancellationRequestTimeout, 324e86f1266SJens Wiklander &up, &s, returnOrigin); 325ef305e54SJens Wiklander update_out_param(params, tmp_va, &up); 326ef305e54SJens Wiklander if (tmp_buf) { 327ef305e54SJens Wiklander TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); 328ef305e54SJens Wiklander 329ef305e54SJens Wiklander if (res2) 330ef305e54SJens Wiklander TEE_Panic(res2); 331ef305e54SJens Wiklander } 332ef305e54SJens Wiklander 333ef305e54SJens Wiklander out: 334b0104773SPascal Brand /* 335b0104773SPascal Brand * Specification says that *session must hold TEE_HANDLE_NULL is 336b0104773SPascal Brand * TEE_SUCCESS isn't returned. Set it here explicitly in case 337b0104773SPascal Brand * the syscall fails before out parameters has been updated. 338b0104773SPascal Brand */ 339b0104773SPascal Brand if (res != TEE_SUCCESS) 340e86f1266SJens Wiklander s = TEE_HANDLE_NULL; 341b0104773SPascal Brand 342e86f1266SJens Wiklander *session = (TEE_TASessionHandle)(uintptr_t)s; 343b0104773SPascal Brand return res; 344b0104773SPascal Brand } 345b0104773SPascal Brand 3467509620bSJens Wiklander TEE_Result __GP11_TEE_OpenTASession(const TEE_UUID *destination, 3477509620bSJens Wiklander uint32_t cancellationRequestTimeout, 3487509620bSJens Wiklander uint32_t paramTypes, 3497509620bSJens Wiklander __GP11_TEE_Param params[TEE_NUM_PARAMS], 3507509620bSJens Wiklander TEE_TASessionHandle *session, 3517509620bSJens Wiklander uint32_t *returnOrigin) 3527509620bSJens Wiklander { 3537509620bSJens Wiklander TEE_Result res = TEE_SUCCESS; 3547509620bSJens Wiklander struct utee_params up = { }; 3557509620bSJens Wiklander uint32_t s = 0; 3567509620bSJens Wiklander void *tmp_buf = NULL; 3577509620bSJens Wiklander size_t tmp_len = 0; 3587509620bSJens Wiklander void *tmp_va[TEE_NUM_PARAMS] = { NULL }; 3597509620bSJens Wiklander 3607509620bSJens Wiklander if (paramTypes) 3617509620bSJens Wiklander __utee_check_inout_annotation(params, 3627509620bSJens Wiklander sizeof(__GP11_TEE_Param) * 3637509620bSJens Wiklander TEE_NUM_PARAMS); 3647509620bSJens Wiklander __utee_check_out_annotation(session, sizeof(*session)); 3657509620bSJens Wiklander 3667509620bSJens Wiklander copy_gp11_param(&up, paramTypes, params); 3677509620bSJens Wiklander res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); 3687509620bSJens Wiklander if (res) 3697509620bSJens Wiklander goto out; 3707509620bSJens Wiklander res = _utee_open_ta_session(destination, cancellationRequestTimeout, 3717509620bSJens Wiklander &up, &s, returnOrigin); 3727509620bSJens Wiklander update_out_gp11_param(params, tmp_va, &up); 3737509620bSJens Wiklander if (tmp_buf) { 3747509620bSJens Wiklander TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); 3757509620bSJens Wiklander 3767509620bSJens Wiklander if (res2) 3777509620bSJens Wiklander TEE_Panic(res2); 3787509620bSJens Wiklander } 3797509620bSJens Wiklander 3807509620bSJens Wiklander out: 3817509620bSJens Wiklander /* 3827509620bSJens Wiklander * Specification says that *session must hold TEE_HANDLE_NULL if 3837509620bSJens Wiklander * TEE_SUCCESS isn't returned. Set it here explicitly in case 3847509620bSJens Wiklander * the syscall fails before out parameters has been updated. 3857509620bSJens Wiklander */ 3867509620bSJens Wiklander if (res != TEE_SUCCESS) 3877509620bSJens Wiklander s = TEE_HANDLE_NULL; 3887509620bSJens Wiklander 3897509620bSJens Wiklander *session = (TEE_TASessionHandle)(uintptr_t)s; 3907509620bSJens Wiklander return res; 3917509620bSJens Wiklander } 3927509620bSJens Wiklander 393b0104773SPascal Brand void TEE_CloseTASession(TEE_TASessionHandle session) 394b0104773SPascal Brand { 395b0104773SPascal Brand if (session != TEE_HANDLE_NULL) { 3962c028fdeSJerome Forissier TEE_Result res = _utee_close_ta_session((uintptr_t)session); 397e86f1266SJens Wiklander 398b0104773SPascal Brand if (res != TEE_SUCCESS) 399b0104773SPascal Brand TEE_Panic(res); 400b0104773SPascal Brand } 401b0104773SPascal Brand } 402b0104773SPascal Brand 403b0104773SPascal Brand TEE_Result TEE_InvokeTACommand(TEE_TASessionHandle session, 404b0104773SPascal Brand uint32_t cancellationRequestTimeout, 405b0104773SPascal Brand uint32_t commandID, uint32_t paramTypes, 40668540524SIgor Opaniuk TEE_Param params[TEE_NUM_PARAMS], 40768540524SIgor Opaniuk uint32_t *returnOrigin) 408b0104773SPascal Brand { 409ef305e54SJens Wiklander TEE_Result res = TEE_SUCCESS; 410ef305e54SJens Wiklander uint32_t ret_origin = TEE_ORIGIN_TEE; 4117509620bSJens Wiklander struct utee_params up = { }; 412ef305e54SJens Wiklander void *tmp_buf = NULL; 413ef305e54SJens Wiklander size_t tmp_len = 0; 414ef305e54SJens Wiklander void *tmp_va[TEE_NUM_PARAMS] = { NULL }; 415c15e5835SCedric Chaumont 416*30e5e0beSJens Wiklander if (paramTypes) { 4176915bbbbSJens Wiklander __utee_check_inout_annotation(params, 4186915bbbbSJens Wiklander sizeof(TEE_Param) * 4196915bbbbSJens Wiklander TEE_NUM_PARAMS); 420*30e5e0beSJens Wiklander check_invoke_param(paramTypes, params); 421*30e5e0beSJens Wiklander } 4226915bbbbSJens Wiklander if (returnOrigin) 4236915bbbbSJens Wiklander __utee_check_out_annotation(returnOrigin, 4246915bbbbSJens Wiklander sizeof(*returnOrigin)); 4256915bbbbSJens Wiklander 4267509620bSJens Wiklander copy_param(&up, paramTypes, params); 4277509620bSJens Wiklander res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); 428ef305e54SJens Wiklander if (res) 429ef305e54SJens Wiklander goto out; 4302c028fdeSJerome Forissier res = _utee_invoke_ta_command((uintptr_t)session, 431e86f1266SJens Wiklander cancellationRequestTimeout, 432e86f1266SJens Wiklander commandID, &up, &ret_origin); 433ef305e54SJens Wiklander update_out_param(params, tmp_va, &up); 434ef305e54SJens Wiklander if (tmp_buf) { 435ef305e54SJens Wiklander TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); 4366709c3eaSCedric Chaumont 437ef305e54SJens Wiklander if (res2) 438ef305e54SJens Wiklander TEE_Panic(res2); 439ef305e54SJens Wiklander } 440ef305e54SJens Wiklander 441ef305e54SJens Wiklander out: 4426709c3eaSCedric Chaumont if (returnOrigin != NULL) 4436709c3eaSCedric Chaumont *returnOrigin = ret_origin; 4446709c3eaSCedric Chaumont 4456709c3eaSCedric Chaumont if (ret_origin == TEE_ORIGIN_TRUSTED_APP) 4466709c3eaSCedric Chaumont return res; 4476709c3eaSCedric Chaumont 448c15e5835SCedric Chaumont if (res != TEE_SUCCESS && 449c15e5835SCedric Chaumont res != TEE_ERROR_OUT_OF_MEMORY && 450c15e5835SCedric Chaumont res != TEE_ERROR_TARGET_DEAD) 451c15e5835SCedric Chaumont TEE_Panic(res); 452c15e5835SCedric Chaumont 453c15e5835SCedric Chaumont return res; 454b0104773SPascal Brand } 455b0104773SPascal Brand 4567509620bSJens Wiklander TEE_Result __GP11_TEE_InvokeTACommand(TEE_TASessionHandle session, 4577509620bSJens Wiklander uint32_t cancellationRequestTimeout, 4587509620bSJens Wiklander uint32_t commandID, uint32_t paramTypes, 4597509620bSJens Wiklander __GP11_TEE_Param params[TEE_NUM_PARAMS], 4607509620bSJens Wiklander uint32_t *returnOrigin) 4617509620bSJens Wiklander { 4627509620bSJens Wiklander TEE_Result res = TEE_SUCCESS; 4637509620bSJens Wiklander uint32_t ret_origin = TEE_ORIGIN_TEE; 4647509620bSJens Wiklander struct utee_params up = { }; 4657509620bSJens Wiklander void *tmp_buf = NULL; 4667509620bSJens Wiklander size_t tmp_len = 0; 4677509620bSJens Wiklander void *tmp_va[TEE_NUM_PARAMS] = { NULL }; 4687509620bSJens Wiklander 4697509620bSJens Wiklander if (paramTypes) 4707509620bSJens Wiklander __utee_check_inout_annotation(params, 4717509620bSJens Wiklander sizeof(__GP11_TEE_Param) * 4727509620bSJens Wiklander TEE_NUM_PARAMS); 4737509620bSJens Wiklander if (returnOrigin) 4747509620bSJens Wiklander __utee_check_out_annotation(returnOrigin, 4757509620bSJens Wiklander sizeof(*returnOrigin)); 4767509620bSJens Wiklander 4777509620bSJens Wiklander copy_gp11_param(&up, paramTypes, params); 4787509620bSJens Wiklander res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); 4797509620bSJens Wiklander if (res) 4807509620bSJens Wiklander goto out; 4817509620bSJens Wiklander res = _utee_invoke_ta_command((uintptr_t)session, 4827509620bSJens Wiklander cancellationRequestTimeout, 4837509620bSJens Wiklander commandID, &up, &ret_origin); 4847509620bSJens Wiklander update_out_gp11_param(params, tmp_va, &up); 4857509620bSJens Wiklander if (tmp_buf) { 4867509620bSJens Wiklander TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); 4877509620bSJens Wiklander 4887509620bSJens Wiklander if (res2) 4897509620bSJens Wiklander TEE_Panic(res2); 4907509620bSJens Wiklander } 4917509620bSJens Wiklander 4927509620bSJens Wiklander out: 4937509620bSJens Wiklander if (returnOrigin) 4947509620bSJens Wiklander *returnOrigin = ret_origin; 4957509620bSJens Wiklander 4967509620bSJens Wiklander if (ret_origin == TEE_ORIGIN_TRUSTED_APP) 4977509620bSJens Wiklander return res; 4987509620bSJens Wiklander 4997509620bSJens Wiklander if (res != TEE_SUCCESS && 5007509620bSJens Wiklander res != TEE_ERROR_OUT_OF_MEMORY && 5017509620bSJens Wiklander res != TEE_ERROR_TARGET_DEAD) 5027509620bSJens Wiklander TEE_Panic(res); 5037509620bSJens Wiklander 5047509620bSJens Wiklander return res; 5057509620bSJens Wiklander } 5067509620bSJens Wiklander 507b0104773SPascal Brand /* System API - Cancellations */ 508b0104773SPascal Brand 509b0104773SPascal Brand bool TEE_GetCancellationFlag(void) 510b0104773SPascal Brand { 511e86f1266SJens Wiklander uint32_t c; 5122c028fdeSJerome Forissier TEE_Result res = _utee_get_cancellation_flag(&c); 513e86f1266SJens Wiklander 514b0104773SPascal Brand if (res != TEE_SUCCESS) 515e86f1266SJens Wiklander c = 0; 516e86f1266SJens Wiklander return !!c; 517b0104773SPascal Brand } 518b0104773SPascal Brand 519b0104773SPascal Brand bool TEE_UnmaskCancellation(void) 520b0104773SPascal Brand { 521e86f1266SJens Wiklander uint32_t old_mask; 5222c028fdeSJerome Forissier TEE_Result res = _utee_unmask_cancellation(&old_mask); 523b0104773SPascal Brand 524b0104773SPascal Brand if (res != TEE_SUCCESS) 525b0104773SPascal Brand TEE_Panic(res); 526e86f1266SJens Wiklander return !!old_mask; 527b0104773SPascal Brand } 528b0104773SPascal Brand 529b0104773SPascal Brand bool TEE_MaskCancellation(void) 530b0104773SPascal Brand { 531e86f1266SJens Wiklander uint32_t old_mask; 5322c028fdeSJerome Forissier TEE_Result res = _utee_mask_cancellation(&old_mask); 533b0104773SPascal Brand 534b0104773SPascal Brand if (res != TEE_SUCCESS) 535b0104773SPascal Brand TEE_Panic(res); 536e86f1266SJens Wiklander return !!old_mask; 537b0104773SPascal Brand } 538b0104773SPascal Brand 539b0104773SPascal Brand /* System API - Memory Management */ 540b0104773SPascal Brand 541b0104773SPascal Brand TEE_Result TEE_CheckMemoryAccessRights(uint32_t accessFlags, void *buffer, 542cd3a8caeSJens Wiklander size_t size) 543b0104773SPascal Brand { 544c8bf6a25SJens Wiklander uint32_t flags = accessFlags; 545b0104773SPascal Brand 546c8bf6a25SJens Wiklander if (!size) 547b0104773SPascal Brand return TEE_SUCCESS; 548b0104773SPascal Brand 549c8bf6a25SJens Wiklander /* 550c8bf6a25SJens Wiklander * Check access rights against memory mapping. If this check is 551c8bf6a25SJens Wiklander * OK the size can't cause an overflow when added with buffer. 552c8bf6a25SJens Wiklander */ 553c8bf6a25SJens Wiklander if (_utee_check_access_rights(accessFlags, buffer, size)) 554c8bf6a25SJens Wiklander return TEE_ERROR_ACCESS_DENIED; 555b0104773SPascal Brand 556b0104773SPascal Brand /* 557c8bf6a25SJens Wiklander * Check access rights against input parameters. 558c8bf6a25SJens Wiklander * 559c8bf6a25SJens Wiklander * Clear eventual extension flags like TEE_MEMORY_ACCESS_NONSECURE 560c8bf6a25SJens Wiklander * and TEE_MEMORY_ACCESS_SECURE. 561b0104773SPascal Brand */ 562c8bf6a25SJens Wiklander flags &= TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE | 563c8bf6a25SJens Wiklander TEE_MEMORY_ACCESS_ANY_OWNER; 564c8bf6a25SJens Wiklander if (check_mem_access_rights_params(flags, buffer, size)) 565c8bf6a25SJens Wiklander return TEE_ERROR_ACCESS_DENIED; 566b0104773SPascal Brand 567c8bf6a25SJens Wiklander if (malloc_buffer_overlaps_heap(buffer, size) && 568c8bf6a25SJens Wiklander !malloc_buffer_is_within_alloced(buffer, size)) 569c8bf6a25SJens Wiklander return TEE_ERROR_ACCESS_DENIED; 570c8bf6a25SJens Wiklander 571c8bf6a25SJens Wiklander return TEE_SUCCESS; 572b0104773SPascal Brand } 573b0104773SPascal Brand 574cd3a8caeSJens Wiklander TEE_Result __GP11_TEE_CheckMemoryAccessRights(uint32_t accessFlags, 575cd3a8caeSJens Wiklander void *buffer, uint32_t size) 576cd3a8caeSJens Wiklander { 577cd3a8caeSJens Wiklander return TEE_CheckMemoryAccessRights(accessFlags, buffer, size); 578cd3a8caeSJens Wiklander } 579cd3a8caeSJens Wiklander 5808f07fe6fSJerome Forissier void TEE_SetInstanceData(const void *instanceData) 581b0104773SPascal Brand { 582b0104773SPascal Brand tee_api_instance_data = instanceData; 583b0104773SPascal Brand } 584b0104773SPascal Brand 5858f07fe6fSJerome Forissier const void *TEE_GetInstanceData(void) 586b0104773SPascal Brand { 587b0104773SPascal Brand return tee_api_instance_data; 588b0104773SPascal Brand } 589b0104773SPascal Brand 5901d0ed95aSJens Wiklander void *TEE_MemMove(void *dest, const void *src, size_t size) 591b0104773SPascal Brand { 592b0104773SPascal Brand return memmove(dest, src, size); 593b0104773SPascal Brand } 594b0104773SPascal Brand 5951d0ed95aSJens Wiklander void *__GP11_TEE_MemMove(void *dest, const void *src, uint32_t size) 5961d0ed95aSJens Wiklander { 5971d0ed95aSJens Wiklander return TEE_MemMove(dest, src, size); 5981d0ed95aSJens Wiklander } 5991d0ed95aSJens Wiklander 6001d0ed95aSJens Wiklander int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, size_t size) 601b0104773SPascal Brand { 60265551e69SJerome Forissier return consttime_memcmp(buffer1, buffer2, size); 603b0104773SPascal Brand } 604b0104773SPascal Brand 6051d0ed95aSJens Wiklander int32_t __GP11_TEE_MemCompare(const void *buffer1, const void *buffer2, 6061d0ed95aSJens Wiklander uint32_t size) 6071d0ed95aSJens Wiklander { 6081d0ed95aSJens Wiklander return TEE_MemCompare(buffer1, buffer2, size); 6091d0ed95aSJens Wiklander } 6101d0ed95aSJens Wiklander 6111d0ed95aSJens Wiklander void TEE_MemFill(void *buff, uint32_t x, size_t size) 612b0104773SPascal Brand { 61332c75600SJens Wiklander memset(buff, x, size); 614b0104773SPascal Brand } 615b0104773SPascal Brand 6161d0ed95aSJens Wiklander void __GP11_TEE_MemFill(void *buff, uint32_t x, uint32_t size) 6171d0ed95aSJens Wiklander { 6181d0ed95aSJens Wiklander TEE_MemFill(buff, x, size); 6191d0ed95aSJens Wiklander } 6201d0ed95aSJens Wiklander 621b0104773SPascal Brand /* Date & Time API */ 622b0104773SPascal Brand 623b0104773SPascal Brand void TEE_GetSystemTime(TEE_Time *time) 624b0104773SPascal Brand { 6252c028fdeSJerome Forissier TEE_Result res = _utee_get_time(UTEE_TIME_CAT_SYSTEM, time); 626b0104773SPascal Brand 627b0104773SPascal Brand if (res != TEE_SUCCESS) 628b36311adSJerome Forissier TEE_Panic(res); 629b0104773SPascal Brand } 630b0104773SPascal Brand 631b0104773SPascal Brand TEE_Result TEE_Wait(uint32_t timeout) 632b0104773SPascal Brand { 6332c028fdeSJerome Forissier TEE_Result res = _utee_wait(timeout); 634b0104773SPascal Brand 635b0104773SPascal Brand if (res != TEE_SUCCESS && res != TEE_ERROR_CANCEL) 636b0104773SPascal Brand TEE_Panic(res); 637b0104773SPascal Brand 638b0104773SPascal Brand return res; 639b0104773SPascal Brand } 640b0104773SPascal Brand 641b0104773SPascal Brand TEE_Result TEE_GetTAPersistentTime(TEE_Time *time) 642b0104773SPascal Brand { 643b64d6909SCedric Chaumont TEE_Result res; 644b64d6909SCedric Chaumont 6452c028fdeSJerome Forissier res = _utee_get_time(UTEE_TIME_CAT_TA_PERSISTENT, time); 646b64d6909SCedric Chaumont 647b64d6909SCedric Chaumont if (res != TEE_SUCCESS && res != TEE_ERROR_OVERFLOW) { 648b64d6909SCedric Chaumont time->seconds = 0; 649b64d6909SCedric Chaumont time->millis = 0; 650b64d6909SCedric Chaumont } 651b64d6909SCedric Chaumont 652b64d6909SCedric Chaumont if (res != TEE_SUCCESS && 653b64d6909SCedric Chaumont res != TEE_ERROR_TIME_NOT_SET && 654b64d6909SCedric Chaumont res != TEE_ERROR_TIME_NEEDS_RESET && 655b64d6909SCedric Chaumont res != TEE_ERROR_OVERFLOW && 656b64d6909SCedric Chaumont res != TEE_ERROR_OUT_OF_MEMORY) 657b64d6909SCedric Chaumont TEE_Panic(res); 658b64d6909SCedric Chaumont 659b64d6909SCedric Chaumont return res; 660b0104773SPascal Brand } 661b0104773SPascal Brand 662b0104773SPascal Brand TEE_Result TEE_SetTAPersistentTime(const TEE_Time *time) 663b0104773SPascal Brand { 664b64d6909SCedric Chaumont TEE_Result res; 665b64d6909SCedric Chaumont 6662c028fdeSJerome Forissier res = _utee_set_ta_time(time); 667b64d6909SCedric Chaumont 668b64d6909SCedric Chaumont if (res != TEE_SUCCESS && 669b64d6909SCedric Chaumont res != TEE_ERROR_OUT_OF_MEMORY && 670b64d6909SCedric Chaumont res != TEE_ERROR_STORAGE_NO_SPACE) 671b64d6909SCedric Chaumont TEE_Panic(res); 672b64d6909SCedric Chaumont 673b64d6909SCedric Chaumont return res; 674b0104773SPascal Brand } 675b0104773SPascal Brand 676b0104773SPascal Brand void TEE_GetREETime(TEE_Time *time) 677b0104773SPascal Brand { 6782c028fdeSJerome Forissier TEE_Result res = _utee_get_time(UTEE_TIME_CAT_REE, time); 679b0104773SPascal Brand 680b0104773SPascal Brand if (res != TEE_SUCCESS) 681b36311adSJerome Forissier TEE_Panic(res); 682b0104773SPascal Brand } 683b0104773SPascal Brand 68411285ebcSJens Wiklander void *TEE_Malloc(size_t len, uint32_t hint) 685b0104773SPascal Brand { 68611285ebcSJens Wiklander switch (hint) { 68711285ebcSJens Wiklander case TEE_MALLOC_FILL_ZERO: 688a83ee50aSSadiq Hussain if (!len) 689a83ee50aSSadiq Hussain return TEE_NULL_SIZED_VA; 69096c1d8c5SJens Wiklander return calloc(1, len); 69111285ebcSJens Wiklander 69211285ebcSJens Wiklander case TEE_MALLOC_NO_FILL: 69311285ebcSJens Wiklander TEE_Panic(0); 69411285ebcSJens Wiklander break; 69511285ebcSJens Wiklander 69611285ebcSJens Wiklander case TEE_MALLOC_NO_FILL | TEE_MALLOC_NO_SHARE: 69711285ebcSJens Wiklander return NULL; /* TEE_MALLOC_NO_SHARE is not yet supported */ 69811285ebcSJens Wiklander 69911285ebcSJens Wiklander case TEE_USER_MEM_HINT_NO_FILL_ZERO: 70011285ebcSJens Wiklander if (!len) 70111285ebcSJens Wiklander return TEE_NULL_SIZED_VA; 70296c1d8c5SJens Wiklander return malloc(len); 70396c1d8c5SJens Wiklander 70411285ebcSJens Wiklander default: 70511285ebcSJens Wiklander break; 70611285ebcSJens Wiklander } 70711285ebcSJens Wiklander 70896c1d8c5SJens Wiklander EMSG("Invalid hint %#" PRIx32, hint); 70996c1d8c5SJens Wiklander 71096c1d8c5SJens Wiklander return NULL; 711b0104773SPascal Brand } 712b0104773SPascal Brand 71311285ebcSJens Wiklander void *__GP11_TEE_Malloc(uint32_t size, uint32_t hint) 71411285ebcSJens Wiklander { 71511285ebcSJens Wiklander return TEE_Malloc(size, hint); 71611285ebcSJens Wiklander } 71711285ebcSJens Wiklander 71811285ebcSJens Wiklander void *TEE_Realloc(void *buffer, size_t newSize) 719b0104773SPascal Brand { 720a83ee50aSSadiq Hussain if (!newSize) { 721a83ee50aSSadiq Hussain TEE_Free(buffer); 722a83ee50aSSadiq Hussain return TEE_NULL_SIZED_VA; 723a83ee50aSSadiq Hussain } 724a83ee50aSSadiq Hussain 725a83ee50aSSadiq Hussain if (buffer == TEE_NULL_SIZED_VA) 726a83ee50aSSadiq Hussain return calloc(1, newSize); 727a83ee50aSSadiq Hussain 72896c1d8c5SJens Wiklander return realloc(buffer, newSize); 729b0104773SPascal Brand } 730b0104773SPascal Brand 73111285ebcSJens Wiklander void *__GP11_TEE_Realloc(void *buffer, uint32_t newSize) 73211285ebcSJens Wiklander { 73311285ebcSJens Wiklander return TEE_Realloc(buffer, newSize); 73411285ebcSJens Wiklander } 73511285ebcSJens Wiklander 736b0104773SPascal Brand void TEE_Free(void *buffer) 737b0104773SPascal Brand { 738a83ee50aSSadiq Hussain if (buffer != TEE_NULL_SIZED_VA) 73996c1d8c5SJens Wiklander free(buffer); 740b0104773SPascal Brand } 741fa530828SPascal Brand 742fa530828SPascal Brand /* Cache maintenance support (TA requires the CACHE_MAINTENANCE property) */ 743fa530828SPascal Brand TEE_Result TEE_CacheClean(char *buf, size_t len) 744fa530828SPascal Brand { 7452c028fdeSJerome Forissier return _utee_cache_operation(buf, len, TEE_CACHECLEAN); 746fa530828SPascal Brand } 747fa530828SPascal Brand TEE_Result TEE_CacheFlush(char *buf, size_t len) 748fa530828SPascal Brand { 7492c028fdeSJerome Forissier return _utee_cache_operation(buf, len, TEE_CACHEFLUSH); 750fa530828SPascal Brand } 751fa530828SPascal Brand 752fa530828SPascal Brand TEE_Result TEE_CacheInvalidate(char *buf, size_t len) 753fa530828SPascal Brand { 7542c028fdeSJerome Forissier return _utee_cache_operation(buf, len, TEE_CACHEINVALIDATE); 755fa530828SPascal Brand } 756