1b0104773SPascal Brand /* 2b0104773SPascal Brand * Copyright (c) 2014, STMicroelectronics International N.V. 3b0104773SPascal Brand * All rights reserved. 4b0104773SPascal Brand * 5b0104773SPascal Brand * Redistribution and use in source and binary forms, with or without 6b0104773SPascal Brand * modification, are permitted provided that the following conditions are met: 7b0104773SPascal Brand * 8b0104773SPascal Brand * 1. Redistributions of source code must retain the above copyright notice, 9b0104773SPascal Brand * this list of conditions and the following disclaimer. 10b0104773SPascal Brand * 11b0104773SPascal Brand * 2. Redistributions in binary form must reproduce the above copyright notice, 12b0104773SPascal Brand * this list of conditions and the following disclaimer in the documentation 13b0104773SPascal Brand * and/or other materials provided with the distribution. 14b0104773SPascal Brand * 15b0104773SPascal Brand * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16b0104773SPascal Brand * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17b0104773SPascal Brand * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18b0104773SPascal Brand * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19b0104773SPascal Brand * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20b0104773SPascal Brand * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21b0104773SPascal Brand * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22b0104773SPascal Brand * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23b0104773SPascal Brand * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24b0104773SPascal Brand * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25b0104773SPascal Brand * POSSIBILITY OF SUCH DAMAGE. 26b0104773SPascal Brand */ 272eb765fcSJens Wiklander #include <util.h> 28b0104773SPascal Brand #include <kernel/tee_common_otp.h> 29b0104773SPascal Brand #include <kernel/tee_common.h> 30b0104773SPascal Brand #include <tee_api_types.h> 31b0104773SPascal Brand #include <kernel/tee_ta_manager.h> 32b0104773SPascal Brand #include <utee_types.h> 33b0104773SPascal Brand #include <tee/tee_svc.h> 34ffe04039SJerome Forissier #include <tee/tee_cryp_utl.h> 35b0104773SPascal Brand #include <mm/tee_mmu.h> 36b0104773SPascal Brand #include <mm/tee_mm.h> 37b0104773SPascal Brand #include <kernel/tee_rpc.h> 38b0104773SPascal Brand #include <kernel/tee_rpc_types.h> 39b0104773SPascal Brand #include <kernel/tee_time.h> 40b0104773SPascal Brand 41b0104773SPascal Brand #include <user_ta_header.h> 424de4bebcSJens Wiklander #include <trace.h> 434de4bebcSJens Wiklander #include <kernel/trace_ta.h> 44b0104773SPascal Brand #include <kernel/chip_services.h> 458684fde8SJens Wiklander #include <kernel/static_ta.h> 46b0104773SPascal Brand 47e86f1266SJens Wiklander #include <assert.h> 48e86f1266SJens Wiklander 49e86f1266SJens Wiklander vaddr_t tee_svc_uref_base; 50e86f1266SJens Wiklander 513276098dSJerome Forissier void syscall_log(const void *buf __maybe_unused, size_t len __maybe_unused) 52b0104773SPascal Brand { 537c876f12SPascal Brand #ifdef CFG_TEE_CORE_TA_TRACE 54b0104773SPascal Brand char *kbuf; 55b0104773SPascal Brand 56b0104773SPascal Brand if (len == 0) 57b0104773SPascal Brand return; 58b0104773SPascal Brand 59b0104773SPascal Brand kbuf = malloc(len); 60b0104773SPascal Brand if (kbuf == NULL) 61b0104773SPascal Brand return; 62c0346845SJens Wiklander *kbuf = '\0'; 63b0104773SPascal Brand 64b0104773SPascal Brand /* log as Info/Raw traces */ 65b0104773SPascal Brand if (tee_svc_copy_from_user(NULL, kbuf, buf, len) == TEE_SUCCESS) 664de4bebcSJens Wiklander TAMSG_RAW("%.*s", (int)len, kbuf); 67b0104773SPascal Brand 68b0104773SPascal Brand free(kbuf); 697c876f12SPascal Brand #endif 70b0104773SPascal Brand } 71b0104773SPascal Brand 72453a5030SJerome Forissier TEE_Result syscall_not_supported(void) 73197d17e7SSY Chiu { 74197d17e7SSY Chiu return TEE_ERROR_NOT_SUPPORTED; 75197d17e7SSY Chiu } 76197d17e7SSY Chiu 773276098dSJerome Forissier uint32_t syscall_dummy(uint32_t *a __maybe_unused) 78b0104773SPascal Brand { 79851aa858SJens Wiklander DMSG("tee_svc_sys_dummy: a 0x%" PRIxVA, (vaddr_t)a); 80b0104773SPascal Brand return 0; 81b0104773SPascal Brand } 82b0104773SPascal Brand 833276098dSJerome Forissier uint32_t syscall_dummy_7args(unsigned long a1 __maybe_unused, 843276098dSJerome Forissier unsigned long a2 __maybe_unused, 853276098dSJerome Forissier unsigned long a3 __maybe_unused, 863276098dSJerome Forissier unsigned long a4 __maybe_unused, 873276098dSJerome Forissier unsigned long a5 __maybe_unused, 883276098dSJerome Forissier unsigned long a6 __maybe_unused, 893276098dSJerome Forissier unsigned long a7 __maybe_unused) 90b0104773SPascal Brand { 91e86f1266SJens Wiklander DMSG("tee_svc_sys_dummy_7args: 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, %lx, %lx\n", 92b0104773SPascal Brand a1, a2, a3, a4, a5, a6, a7); 93b0104773SPascal Brand return 0; 94b0104773SPascal Brand } 95b0104773SPascal Brand 96453a5030SJerome Forissier uint32_t syscall_nocall(void) 97b0104773SPascal Brand { 98b0104773SPascal Brand DMSG("No syscall"); 99b0104773SPascal Brand return 0x1; 100b0104773SPascal Brand } 101b0104773SPascal Brand 102ab35d7adSCedric Chaumont /* Configuration properties */ 103ab35d7adSCedric Chaumont /* API implementation version */ 104ab35d7adSCedric Chaumont static const char api_vers[] = TO_STR(CFG_TEE_API_VERSION); 105ab35d7adSCedric Chaumont 106ab35d7adSCedric Chaumont /* Implementation description (implementation-dependent) */ 107ab35d7adSCedric Chaumont static const char descr[] = TO_STR(CFG_TEE_IMPL_DESCR); 108ab35d7adSCedric Chaumont 109b0104773SPascal Brand /* 110ab35d7adSCedric Chaumont * TA persistent time protection level 111ab35d7adSCedric Chaumont * 100: Persistent time based on an REE-controlled real-time clock 112ab35d7adSCedric Chaumont * and on the TEE Trusted Storage for the storage of origins (default). 113ab35d7adSCedric Chaumont * 1000: Persistent time based on a TEE-controlled real-time clock 114ab35d7adSCedric Chaumont * and the TEE Trusted Storage. 115ab35d7adSCedric Chaumont * The real-time clock MUST be out of reach of software attacks 116ab35d7adSCedric Chaumont * from the REE. 117ab35d7adSCedric Chaumont */ 118b0104773SPascal Brand static const uint32_t ta_time_prot_lvl = 100; 119ab35d7adSCedric Chaumont 12064a5011eSPascal Brand /* Elliptic Curve Cryptographic support */ 12164a5011eSPascal Brand #ifdef CFG_CRYPTO_ECC 12264a5011eSPascal Brand static const uint32_t crypto_ecc_en = 1; 12364a5011eSPascal Brand #else 12464a5011eSPascal Brand static const uint32_t crypto_ecc_en; 12564a5011eSPascal Brand #endif 12664a5011eSPascal Brand 12764a5011eSPascal Brand static const bool crypto_ecc_en_obsolete; 128ab35d7adSCedric Chaumont 129ab35d7adSCedric Chaumont /* 130ab35d7adSCedric Chaumont * Trusted storage anti rollback protection level 131ab35d7adSCedric Chaumont * 0 (or missing): No antirollback protection (default) 132ab35d7adSCedric Chaumont * 100: Antirollback enforced at REE level 133ab35d7adSCedric Chaumont * 1000: Antirollback TEE-controlled hardware 134ab35d7adSCedric Chaumont */ 135ab35d7adSCedric Chaumont static const uint32_t ts_antiroll_prot_lvl; 136ab35d7adSCedric Chaumont 137ab35d7adSCedric Chaumont /* Trusted OS implementation version */ 1384bf425c1SJens Wiklander static const char trustedos_impl_version[] = TO_STR(TEE_IMPL_VERSION); 139ab35d7adSCedric Chaumont 140ab35d7adSCedric Chaumont /* Trusted OS implementation version (binary value) */ 141ab35d7adSCedric Chaumont static const uint32_t trustedos_impl_bin_version; /* 0 by default */ 142ab35d7adSCedric Chaumont 143ab35d7adSCedric Chaumont /* Trusted OS implementation manufacturer name */ 144ab35d7adSCedric Chaumont static const char trustedos_manufacturer[] = TO_STR(CFG_TEE_MANUFACTURER); 145ab35d7adSCedric Chaumont 146ab35d7adSCedric Chaumont /* Trusted firmware version */ 147ab35d7adSCedric Chaumont static const char fw_impl_version[] = TO_STR(CFG_TEE_FW_IMPL_VERSION); 148ab35d7adSCedric Chaumont 149ab35d7adSCedric Chaumont /* Trusted firmware version (binary value) */ 150ab35d7adSCedric Chaumont static const uint32_t fw_impl_bin_version; /* 0 by default */ 151ab35d7adSCedric Chaumont 152ab35d7adSCedric Chaumont /* Trusted firmware manufacturer name */ 153ab35d7adSCedric Chaumont static const char fw_manufacturer[] = TO_STR(CFG_TEE_FW_MANUFACTURER); 154ab35d7adSCedric Chaumont 15564a5011eSPascal Brand struct tee_props_obsolete { 156ab35d7adSCedric Chaumont const void *data; 157ab35d7adSCedric Chaumont const size_t len; 158ab35d7adSCedric Chaumont }; 159ab35d7adSCedric Chaumont 160ab35d7adSCedric Chaumont /* Consistent with enum utee_property */ 16164a5011eSPascal Brand const struct tee_props_obsolete tee_props_lut[] = { 162ab35d7adSCedric Chaumont {api_vers, sizeof(api_vers)}, 163ab35d7adSCedric Chaumont {descr, sizeof(descr)}, 164ab35d7adSCedric Chaumont {0, 0}, /* dev_id */ 1652cdaaacbSJerome Forissier {0, 0}, /* system time protection level */ 166ab35d7adSCedric Chaumont {&ta_time_prot_lvl, sizeof(ta_time_prot_lvl)}, 16764a5011eSPascal Brand {&crypto_ecc_en_obsolete, sizeof(crypto_ecc_en_obsolete)}, 168ab35d7adSCedric Chaumont {&ts_antiroll_prot_lvl, sizeof(ts_antiroll_prot_lvl)}, 169ab35d7adSCedric Chaumont {trustedos_impl_version, sizeof(trustedos_impl_version)}, 170ab35d7adSCedric Chaumont {&trustedos_impl_bin_version, 171ab35d7adSCedric Chaumont sizeof(trustedos_impl_bin_version)}, 172ab35d7adSCedric Chaumont {trustedos_manufacturer, sizeof(trustedos_manufacturer)}, 173ab35d7adSCedric Chaumont {fw_impl_version, sizeof(fw_impl_version)}, 174ab35d7adSCedric Chaumont {&fw_impl_bin_version, sizeof(fw_impl_bin_version)}, 175ab35d7adSCedric Chaumont {fw_manufacturer, sizeof(fw_manufacturer)}, 176ab35d7adSCedric Chaumont {0, 0}, /* client_id */ 177ab35d7adSCedric Chaumont {0, 0}, /* ta_app_id */ 178ab35d7adSCedric Chaumont }; 179ab35d7adSCedric Chaumont 18064a5011eSPascal Brand enum utee_property_obsolete { 18164a5011eSPascal Brand UTEE_PROP_TEE_API_VERSION = 0, 18264a5011eSPascal Brand UTEE_PROP_TEE_DESCR, 18364a5011eSPascal Brand UTEE_PROP_TEE_DEV_ID, 18464a5011eSPascal Brand UTEE_PROP_TEE_SYS_TIME_PROT_LEVEL, 18564a5011eSPascal Brand UTEE_PROP_TEE_TA_TIME_PROT_LEVEL, 18664a5011eSPascal Brand UTEE_PROP_TEE_CRYPTOGRAPHY_ECC, 18764a5011eSPascal Brand UTEE_PROP_TEE_TS_ANTIROLL_PROT_LEVEL, 18864a5011eSPascal Brand UTEE_PROP_TEE_TRUSTEDOS_IMPL_VERSION, 18964a5011eSPascal Brand UTEE_PROP_TEE_TRUSTEDOS_IMPL_BIN_VERSION, 19064a5011eSPascal Brand UTEE_PROP_TEE_TRUSTEDOS_MANUFACTURER, 19164a5011eSPascal Brand UTEE_PROP_TEE_FW_IMPL_VERSION, 19264a5011eSPascal Brand UTEE_PROP_TEE_FW_IMPL_BIN_VERSION, 19364a5011eSPascal Brand UTEE_PROP_TEE_FW_MANUFACTURER, 19464a5011eSPascal Brand UTEE_PROP_CLIENT_ID, 19564a5011eSPascal Brand UTEE_PROP_TA_APP_ID, 19664a5011eSPascal Brand }; 19764a5011eSPascal Brand 19864a5011eSPascal Brand static TEE_Result get_prop_tee_dev_id(struct tee_ta_session *sess, 199ff857a3aSPascal Brand void *buf, size_t *blen) 200ab35d7adSCedric Chaumont { 201b0104773SPascal Brand TEE_Result res; 202b0104773SPascal Brand TEE_UUID uuid; 203ab35d7adSCedric Chaumont const size_t nslen = 5; 20464a5011eSPascal Brand uint8_t data[5 + FVR_DIE_ID_NUM_REGS * sizeof(uint32_t)] = { 205ab35d7adSCedric Chaumont 'O', 'P', 'T', 'E', 'E' }; 206b0104773SPascal Brand 207ff857a3aSPascal Brand if (*blen < sizeof(uuid)) { 208ff857a3aSPascal Brand *blen = sizeof(uuid); 209b0104773SPascal Brand return TEE_ERROR_SHORT_BUFFER; 210ff857a3aSPascal Brand } 211ff857a3aSPascal Brand *blen = sizeof(uuid); 212b0104773SPascal Brand 21364a5011eSPascal Brand if (tee_otp_get_die_id(data + nslen, sizeof(data) - nslen)) 214b0104773SPascal Brand return TEE_ERROR_BAD_STATE; 215b0104773SPascal Brand 21664a5011eSPascal Brand res = tee_hash_createdigest(TEE_ALG_SHA256, data, sizeof(data), 21764a5011eSPascal Brand (uint8_t *)&uuid, sizeof(uuid)); 218b0104773SPascal Brand if (res != TEE_SUCCESS) 219b0104773SPascal Brand return TEE_ERROR_BAD_STATE; 220b0104773SPascal Brand 221b0104773SPascal Brand /* 222b0104773SPascal Brand * Changes the random value into and UUID as specifiec 223b0104773SPascal Brand * in RFC 4122. The magic values are from the example 224b0104773SPascal Brand * code in the RFC. 225b0104773SPascal Brand * 226b0104773SPascal Brand * TEE_UUID is defined slightly different from the RFC, 227b0104773SPascal Brand * but close enough for our purpose. 228b0104773SPascal Brand */ 229b0104773SPascal Brand 230b0104773SPascal Brand uuid.timeHiAndVersion &= 0x0fff; 231b0104773SPascal Brand uuid.timeHiAndVersion |= 5 << 12; 232b0104773SPascal Brand 233b0104773SPascal Brand /* uuid.clock_seq_hi_and_reserved in the RFC */ 234b0104773SPascal Brand uuid.clockSeqAndNode[0] &= 0x3f; 235b0104773SPascal Brand uuid.clockSeqAndNode[0] |= 0x80; 236b0104773SPascal Brand 23764a5011eSPascal Brand return tee_svc_copy_to_user(sess, buf, &uuid, sizeof(TEE_UUID)); 238b0104773SPascal Brand } 239b0104773SPascal Brand 24064a5011eSPascal Brand static TEE_Result get_prop_tee_sys_time_prot_level(struct tee_ta_session *sess, 241ff857a3aSPascal Brand void *buf, size_t *blen) 2422cdaaacbSJerome Forissier { 2432cdaaacbSJerome Forissier uint32_t prot; 2442cdaaacbSJerome Forissier 245ff857a3aSPascal Brand if (*blen < sizeof(prot)) { 246ff857a3aSPascal Brand *blen = sizeof(prot); 2472cdaaacbSJerome Forissier return TEE_ERROR_SHORT_BUFFER; 248ff857a3aSPascal Brand } 249ff857a3aSPascal Brand *blen = sizeof(prot); 2502cdaaacbSJerome Forissier prot = tee_time_get_sys_time_protection_level(); 25164a5011eSPascal Brand return tee_svc_copy_to_user(sess, (void *)buf, &prot, sizeof(prot)); 2522cdaaacbSJerome Forissier } 2532cdaaacbSJerome Forissier 25464a5011eSPascal Brand static TEE_Result get_prop_client_id(struct tee_ta_session *sess, 255ff857a3aSPascal Brand void *buf, size_t *blen) 25664a5011eSPascal Brand { 257ff857a3aSPascal Brand if (*blen < sizeof(TEE_Identity)) { 258ff857a3aSPascal Brand *blen = sizeof(TEE_Identity); 259b0104773SPascal Brand return TEE_ERROR_SHORT_BUFFER; 260ff857a3aSPascal Brand } 261ff857a3aSPascal Brand *blen = sizeof(TEE_Identity); 262e86f1266SJens Wiklander return tee_svc_copy_to_user(sess, buf, &sess->clnt_id, 263ab35d7adSCedric Chaumont sizeof(TEE_Identity)); 26464a5011eSPascal Brand } 26537d6ae92SPascal Brand 26664a5011eSPascal Brand static TEE_Result get_prop_ta_app_id(struct tee_ta_session *sess, 267ff857a3aSPascal Brand void *buf, size_t *blen) 26864a5011eSPascal Brand { 269ff857a3aSPascal Brand if (*blen < sizeof(TEE_UUID)) { 270ff857a3aSPascal Brand *blen = sizeof(TEE_UUID); 271b0104773SPascal Brand return TEE_ERROR_SHORT_BUFFER; 272ff857a3aSPascal Brand } 273ff857a3aSPascal Brand *blen = sizeof(TEE_UUID); 274e86f1266SJens Wiklander return tee_svc_copy_to_user(sess, buf, &sess->ctx->uuid, 275ab35d7adSCedric Chaumont sizeof(TEE_UUID)); 27664a5011eSPascal Brand } 27764a5011eSPascal Brand 27864a5011eSPascal Brand TEE_Result syscall_get_property_obsolete(unsigned long prop, 27964a5011eSPascal Brand void *buf, size_t blen) 28064a5011eSPascal Brand { 28164a5011eSPascal Brand struct tee_ta_session *sess; 28264a5011eSPascal Brand TEE_Result res; 28364a5011eSPascal Brand 28464a5011eSPascal Brand if (prop > ARRAY_SIZE(tee_props_lut)-1) 28564a5011eSPascal Brand return TEE_ERROR_NOT_IMPLEMENTED; 28664a5011eSPascal Brand 28764a5011eSPascal Brand res = tee_ta_get_current_session(&sess); 28864a5011eSPascal Brand if (res != TEE_SUCCESS) 28964a5011eSPascal Brand return res; 29064a5011eSPascal Brand 29164a5011eSPascal Brand switch (prop) { 29264a5011eSPascal Brand case UTEE_PROP_TEE_DEV_ID: 293ff857a3aSPascal Brand return get_prop_tee_dev_id(sess, buf, &blen); 29464a5011eSPascal Brand 29564a5011eSPascal Brand case UTEE_PROP_TEE_SYS_TIME_PROT_LEVEL: 296ff857a3aSPascal Brand return get_prop_tee_sys_time_prot_level(sess, buf, &blen); 29764a5011eSPascal Brand 29864a5011eSPascal Brand case UTEE_PROP_CLIENT_ID: 299ff857a3aSPascal Brand return get_prop_client_id(sess, buf, &blen); 30064a5011eSPascal Brand 30164a5011eSPascal Brand case UTEE_PROP_TA_APP_ID: 302ff857a3aSPascal Brand return get_prop_ta_app_id(sess, buf, &blen); 30364a5011eSPascal Brand 304b0104773SPascal Brand default: 305ab35d7adSCedric Chaumont if (blen < tee_props_lut[prop].len) 306ab35d7adSCedric Chaumont return TEE_ERROR_SHORT_BUFFER; 307e86f1266SJens Wiklander return tee_svc_copy_to_user(sess, buf, tee_props_lut[prop].data, 308ab35d7adSCedric Chaumont tee_props_lut[prop].len); 309b0104773SPascal Brand } 310b0104773SPascal Brand } 311b0104773SPascal Brand 31264a5011eSPascal Brand /* Properties of the set TEE_PROPSET_CURRENT_CLIENT */ 31364a5011eSPascal Brand const struct tee_props tee_propset_client[] = { 31464a5011eSPascal Brand { 31564a5011eSPascal Brand .name = "gpd.client.identity", 31664a5011eSPascal Brand .prop_type = USER_TA_PROP_TYPE_IDENTITY, 31764a5011eSPascal Brand .get_prop_func = get_prop_client_id 31864a5011eSPascal Brand }, 31964a5011eSPascal Brand }; 32064a5011eSPascal Brand 32164a5011eSPascal Brand /* Properties of the set TEE_PROPSET_CURRENT_TA */ 32264a5011eSPascal Brand const struct tee_props tee_propset_ta[] = { 32364a5011eSPascal Brand { 32464a5011eSPascal Brand .name = "gpd.ta.appID", 32564a5011eSPascal Brand .prop_type = USER_TA_PROP_TYPE_UUID, 32664a5011eSPascal Brand .get_prop_func = get_prop_ta_app_id 32764a5011eSPascal Brand }, 32864a5011eSPascal Brand 32964a5011eSPascal Brand /* 33064a5011eSPascal Brand * Following properties are processed directly in libutee: 33164a5011eSPascal Brand * TA_PROP_STR_SINGLE_INSTANCE 33264a5011eSPascal Brand * TA_PROP_STR_MULTI_SESSION 33364a5011eSPascal Brand * TA_PROP_STR_KEEP_ALIVE 33464a5011eSPascal Brand * TA_PROP_STR_DATA_SIZE 33564a5011eSPascal Brand * TA_PROP_STR_STACK_SIZE 33664a5011eSPascal Brand * TA_PROP_STR_VERSION 33764a5011eSPascal Brand * TA_PROP_STR_DESCRIPTION 33864a5011eSPascal Brand * USER_TA_PROP_TYPE_STRING, 33964a5011eSPascal Brand * TA_DESCRIPTION 34064a5011eSPascal Brand */ 34164a5011eSPascal Brand }; 34264a5011eSPascal Brand 34364a5011eSPascal Brand /* Properties of the set TEE_PROPSET_TEE_IMPLEMENTATION */ 34464a5011eSPascal Brand const struct tee_props tee_propset_tee[] = { 34564a5011eSPascal Brand { 34664a5011eSPascal Brand .name = "gpd.tee.apiversion", 34764a5011eSPascal Brand .prop_type = USER_TA_PROP_TYPE_STRING, 34864a5011eSPascal Brand .data = api_vers, 34964a5011eSPascal Brand .len = sizeof(api_vers), 35064a5011eSPascal Brand }, 35164a5011eSPascal Brand { 35264a5011eSPascal Brand .name = "gpd.tee.description", 35364a5011eSPascal Brand .prop_type = USER_TA_PROP_TYPE_STRING, 35464a5011eSPascal Brand .data = descr, .len = sizeof(descr) 35564a5011eSPascal Brand }, 35664a5011eSPascal Brand { 35764a5011eSPascal Brand .name = "gpd.tee.deviceID", 35864a5011eSPascal Brand .prop_type = USER_TA_PROP_TYPE_UUID, 35964a5011eSPascal Brand .get_prop_func = get_prop_tee_dev_id 36064a5011eSPascal Brand }, 36164a5011eSPascal Brand { 36264a5011eSPascal Brand .name = "gpd.tee.systemTime.protectionLevel", 36364a5011eSPascal Brand .prop_type = USER_TA_PROP_TYPE_U32, 36464a5011eSPascal Brand .get_prop_func = get_prop_tee_sys_time_prot_level 36564a5011eSPascal Brand }, 36664a5011eSPascal Brand { 36764a5011eSPascal Brand .name = "gpd.tee.TAPersistentTime.protectionLevel", 36864a5011eSPascal Brand .prop_type = USER_TA_PROP_TYPE_U32, 36964a5011eSPascal Brand .data = &ta_time_prot_lvl, 37064a5011eSPascal Brand .len = sizeof(ta_time_prot_lvl) 37164a5011eSPascal Brand }, 37264a5011eSPascal Brand { 37364a5011eSPascal Brand .name = "gpd.tee.cryptography.ecc", 37464a5011eSPascal Brand .prop_type = USER_TA_PROP_TYPE_BOOL, 37564a5011eSPascal Brand .data = &crypto_ecc_en, 37664a5011eSPascal Brand .len = sizeof(crypto_ecc_en) 37764a5011eSPascal Brand }, 37864a5011eSPascal Brand { 37964a5011eSPascal Brand .name = "gpd.tee.trustedStorage.antiRollback.protectionLevel", 38064a5011eSPascal Brand .prop_type = USER_TA_PROP_TYPE_U32, 38164a5011eSPascal Brand .data = &ts_antiroll_prot_lvl, 38264a5011eSPascal Brand .len = sizeof(ts_antiroll_prot_lvl) 38364a5011eSPascal Brand }, 38464a5011eSPascal Brand { 38564a5011eSPascal Brand .name = "gpd.tee.trustedos.implementation.version", 38664a5011eSPascal Brand .prop_type = USER_TA_PROP_TYPE_STRING, 38764a5011eSPascal Brand .data = trustedos_impl_version, 38864a5011eSPascal Brand .len = sizeof(trustedos_impl_version) 38964a5011eSPascal Brand }, 39064a5011eSPascal Brand { 39164a5011eSPascal Brand .name = "gpd.tee.trustedos.implementation.binaryversion", 39264a5011eSPascal Brand .prop_type = USER_TA_PROP_TYPE_U32, 39364a5011eSPascal Brand .data = &trustedos_impl_bin_version, 39464a5011eSPascal Brand .len = sizeof(trustedos_impl_bin_version) 39564a5011eSPascal Brand }, 39664a5011eSPascal Brand { 39764a5011eSPascal Brand .name = "gpd.tee.trustedos.manufacturer", 39864a5011eSPascal Brand .prop_type = USER_TA_PROP_TYPE_STRING, 39964a5011eSPascal Brand .data = trustedos_manufacturer, 40064a5011eSPascal Brand .len = sizeof(trustedos_manufacturer) 40164a5011eSPascal Brand }, 40264a5011eSPascal Brand { 40364a5011eSPascal Brand .name = "gpd.tee.firmware.implementation.version", 40464a5011eSPascal Brand .prop_type = USER_TA_PROP_TYPE_STRING, 40564a5011eSPascal Brand .data = fw_impl_version, 40664a5011eSPascal Brand .len = sizeof(fw_impl_version) 40764a5011eSPascal Brand }, 40864a5011eSPascal Brand { 40964a5011eSPascal Brand .name = "gpd.tee.firmware.implementation.binaryversion", 41064a5011eSPascal Brand .prop_type = USER_TA_PROP_TYPE_U32, 41164a5011eSPascal Brand .data = &fw_impl_bin_version, 41264a5011eSPascal Brand .len = sizeof(fw_impl_bin_version) 41364a5011eSPascal Brand }, 41464a5011eSPascal Brand { 41564a5011eSPascal Brand .name = "gpd.tee.firmware.manufacturer", 41664a5011eSPascal Brand .prop_type = USER_TA_PROP_TYPE_STRING, 41764a5011eSPascal Brand .data = fw_manufacturer, 41864a5011eSPascal Brand .len = sizeof(fw_manufacturer) 41964a5011eSPascal Brand }, 42064a5011eSPascal Brand 42164a5011eSPascal Brand /* 42264a5011eSPascal Brand * Following properties are processed directly in libutee: 42364a5011eSPascal Brand * gpd.tee.arith.maxBigIntSize 42464a5011eSPascal Brand */ 42564a5011eSPascal Brand }; 42664a5011eSPascal Brand 427*41d71430SPascal Brand __weak const struct tee_vendor_props vendor_props_client; 428*41d71430SPascal Brand __weak const struct tee_vendor_props vendor_props_ta; 429*41d71430SPascal Brand __weak const struct tee_vendor_props vendor_props_tee; 430*41d71430SPascal Brand 43164a5011eSPascal Brand static void get_prop_set(unsigned long prop_set, 43264a5011eSPascal Brand const struct tee_props **props, 433*41d71430SPascal Brand size_t *size, 434*41d71430SPascal Brand const struct tee_props **vendor_props, 435*41d71430SPascal Brand size_t *vendor_size) 43664a5011eSPascal Brand { 43764a5011eSPascal Brand if ((TEE_PropSetHandle)prop_set == TEE_PROPSET_CURRENT_CLIENT) { 43864a5011eSPascal Brand *props = tee_propset_client; 43964a5011eSPascal Brand *size = ARRAY_SIZE(tee_propset_client); 440*41d71430SPascal Brand *vendor_props = vendor_props_client.props; 441*41d71430SPascal Brand *vendor_size = vendor_props_client.len; 44264a5011eSPascal Brand } else if ((TEE_PropSetHandle)prop_set == TEE_PROPSET_CURRENT_TA) { 44364a5011eSPascal Brand *props = tee_propset_ta; 44464a5011eSPascal Brand *size = ARRAY_SIZE(tee_propset_ta); 445*41d71430SPascal Brand *vendor_props = vendor_props_ta.props; 446*41d71430SPascal Brand *vendor_size = vendor_props_ta.len; 44764a5011eSPascal Brand } else if ((TEE_PropSetHandle)prop_set == 44864a5011eSPascal Brand TEE_PROPSET_TEE_IMPLEMENTATION) { 44964a5011eSPascal Brand *props = tee_propset_tee; 45064a5011eSPascal Brand *size = ARRAY_SIZE(tee_propset_tee); 451*41d71430SPascal Brand *vendor_props = vendor_props_tee.props; 452*41d71430SPascal Brand *vendor_size = vendor_props_tee.len; 45364a5011eSPascal Brand } else { 454*41d71430SPascal Brand *props = NULL; 45564a5011eSPascal Brand *size = 0; 456*41d71430SPascal Brand *vendor_props = NULL; 457*41d71430SPascal Brand *vendor_size = 0; 45864a5011eSPascal Brand } 45964a5011eSPascal Brand } 46064a5011eSPascal Brand 46164a5011eSPascal Brand static const struct tee_props *get_prop_struct(unsigned long prop_set, 46264a5011eSPascal Brand unsigned long index) 46364a5011eSPascal Brand { 46464a5011eSPascal Brand const struct tee_props *props; 465*41d71430SPascal Brand const struct tee_props *vendor_props; 466*41d71430SPascal Brand size_t size; 467*41d71430SPascal Brand size_t vendor_size; 46864a5011eSPascal Brand 469*41d71430SPascal Brand get_prop_set(prop_set, &props, &size, &vendor_props, &vendor_size); 47064a5011eSPascal Brand 471*41d71430SPascal Brand if (index < size) 47264a5011eSPascal Brand return &(props[index]); 473*41d71430SPascal Brand index -= size; 474*41d71430SPascal Brand 475*41d71430SPascal Brand if (index < vendor_size) 476*41d71430SPascal Brand return &(vendor_props[index]); 477*41d71430SPascal Brand 47864a5011eSPascal Brand return NULL; 47964a5011eSPascal Brand } 48064a5011eSPascal Brand 48164a5011eSPascal Brand /* 48264a5011eSPascal Brand * prop_set is part of TEE_PROPSET_xxx 48364a5011eSPascal Brand * index is the index in the Property Set to retrieve 48464a5011eSPascal Brand * if name is not NULL, the name of "index" property is returned 48564a5011eSPascal Brand * if buf is not NULL, the property is returned 48664a5011eSPascal Brand */ 48764a5011eSPascal Brand TEE_Result syscall_get_property(unsigned long prop_set, 48864a5011eSPascal Brand unsigned long index, 48964a5011eSPascal Brand void *name, uint32_t *name_len, 49064a5011eSPascal Brand void *buf, uint32_t *blen, 49164a5011eSPascal Brand uint32_t *prop_type) 49264a5011eSPascal Brand { 49364a5011eSPascal Brand struct tee_ta_session *sess; 49464a5011eSPascal Brand TEE_Result res; 49564a5011eSPascal Brand TEE_Result res2; 49664a5011eSPascal Brand const struct tee_props *prop; 49764a5011eSPascal Brand uint32_t klen; 498ff857a3aSPascal Brand size_t klen_size; 49964a5011eSPascal Brand uint32_t elen; 50064a5011eSPascal Brand 50164a5011eSPascal Brand prop = get_prop_struct(prop_set, index); 50264a5011eSPascal Brand if (!prop) 50364a5011eSPascal Brand return TEE_ERROR_ITEM_NOT_FOUND; 50464a5011eSPascal Brand 50564a5011eSPascal Brand res = tee_ta_get_current_session(&sess); 50664a5011eSPascal Brand if (res != TEE_SUCCESS) 50764a5011eSPascal Brand return res; 50864a5011eSPascal Brand 509ff857a3aSPascal Brand /* Get the property type */ 510ff857a3aSPascal Brand if (prop_type) { 511ff857a3aSPascal Brand res = tee_svc_copy_to_user(sess, prop_type, &prop->prop_type, 512ff857a3aSPascal Brand sizeof(*prop_type)); 513ff857a3aSPascal Brand if (res != TEE_SUCCESS) 514ff857a3aSPascal Brand return res; 515ff857a3aSPascal Brand } 516ff857a3aSPascal Brand 51764a5011eSPascal Brand /* Get the property */ 51864a5011eSPascal Brand if (buf && blen) { 51964a5011eSPascal Brand res = tee_svc_copy_from_user(sess, &klen, blen, sizeof(klen)); 52064a5011eSPascal Brand if (res != TEE_SUCCESS) 52164a5011eSPascal Brand return res; 52264a5011eSPascal Brand 52364a5011eSPascal Brand if (prop->get_prop_func) { 524ff857a3aSPascal Brand klen_size = klen; 525ff857a3aSPascal Brand res = prop->get_prop_func(sess, buf, &klen_size); 526ff857a3aSPascal Brand klen = klen_size; 527ff857a3aSPascal Brand res2 = tee_svc_copy_to_user(sess, blen, 528ff857a3aSPascal Brand &klen, sizeof(*blen)); 52964a5011eSPascal Brand } else { 53064a5011eSPascal Brand if (klen < prop->len) 53164a5011eSPascal Brand res = TEE_ERROR_SHORT_BUFFER; 53264a5011eSPascal Brand else 53364a5011eSPascal Brand res = tee_svc_copy_to_user(sess, buf, 53464a5011eSPascal Brand prop->data, 53564a5011eSPascal Brand prop->len); 53664a5011eSPascal Brand res2 = tee_svc_copy_to_user(sess, blen, 537ff857a3aSPascal Brand &prop->len, sizeof(*blen)); 538ff857a3aSPascal Brand } 53964a5011eSPascal Brand if (res2 != TEE_SUCCESS) 54064a5011eSPascal Brand return res2; 54164a5011eSPascal Brand if (res != TEE_SUCCESS) 54264a5011eSPascal Brand return res; 54364a5011eSPascal Brand } 54464a5011eSPascal Brand 54564a5011eSPascal Brand /* Get the property name */ 54664a5011eSPascal Brand if (name && name_len) { 54764a5011eSPascal Brand res = tee_svc_copy_from_user(sess, &klen, 54864a5011eSPascal Brand name_len, sizeof(klen)); 54964a5011eSPascal Brand if (res != TEE_SUCCESS) 55064a5011eSPascal Brand return res; 55164a5011eSPascal Brand 55264a5011eSPascal Brand elen = strlen(prop->name) + 1; 55364a5011eSPascal Brand 55464a5011eSPascal Brand if (klen < elen) 55564a5011eSPascal Brand res = TEE_ERROR_SHORT_BUFFER; 55664a5011eSPascal Brand else 55764a5011eSPascal Brand res = tee_svc_copy_to_user(sess, name, 55864a5011eSPascal Brand prop->name, elen); 55964a5011eSPascal Brand res2 = tee_svc_copy_to_user(sess, name_len, 56064a5011eSPascal Brand &elen, sizeof(*name_len)); 56164a5011eSPascal Brand if (res2 != TEE_SUCCESS) 56264a5011eSPascal Brand return res2; 56364a5011eSPascal Brand if (res != TEE_SUCCESS) 56464a5011eSPascal Brand return res; 56564a5011eSPascal Brand } 56664a5011eSPascal Brand 56764a5011eSPascal Brand return res; 56864a5011eSPascal Brand } 56964a5011eSPascal Brand 57064a5011eSPascal Brand /* 57164a5011eSPascal Brand * prop_set is part of TEE_PROPSET_xxx 57264a5011eSPascal Brand */ 57364a5011eSPascal Brand TEE_Result syscall_get_property_name_to_index(unsigned long prop_set, 57464a5011eSPascal Brand void *name, 57564a5011eSPascal Brand unsigned long name_len, 57664a5011eSPascal Brand uint32_t *index) 57764a5011eSPascal Brand { 57864a5011eSPascal Brand TEE_Result res; 57964a5011eSPascal Brand struct tee_ta_session *sess; 58064a5011eSPascal Brand const struct tee_props *props; 581*41d71430SPascal Brand size_t size; 582*41d71430SPascal Brand const struct tee_props *vendor_props; 583*41d71430SPascal Brand size_t vendor_size; 58464a5011eSPascal Brand char *kname = 0; 58564a5011eSPascal Brand uint32_t i; 58664a5011eSPascal Brand 587*41d71430SPascal Brand get_prop_set(prop_set, &props, &size, &vendor_props, &vendor_size); 58864a5011eSPascal Brand if (!props) 58964a5011eSPascal Brand return TEE_ERROR_ITEM_NOT_FOUND; 59064a5011eSPascal Brand 59164a5011eSPascal Brand res = tee_ta_get_current_session(&sess); 59264a5011eSPascal Brand if (res != TEE_SUCCESS) 59364a5011eSPascal Brand goto out; 59464a5011eSPascal Brand 59564a5011eSPascal Brand if (!name || !name_len) { 59664a5011eSPascal Brand res = TEE_ERROR_BAD_PARAMETERS; 59764a5011eSPascal Brand goto out; 59864a5011eSPascal Brand } 59964a5011eSPascal Brand 60064a5011eSPascal Brand kname = malloc(name_len); 60164a5011eSPascal Brand if (!kname) 60264a5011eSPascal Brand return TEE_ERROR_OUT_OF_MEMORY; 60364a5011eSPascal Brand res = tee_svc_copy_from_user(sess, kname, name, name_len); 60464a5011eSPascal Brand if (res != TEE_SUCCESS) 60564a5011eSPascal Brand goto out; 60664a5011eSPascal Brand kname[name_len - 1] = 0; 60764a5011eSPascal Brand 60864a5011eSPascal Brand res = TEE_ERROR_ITEM_NOT_FOUND; 60964a5011eSPascal Brand for (i = 0; i < size; i++) { 61064a5011eSPascal Brand if (!strcmp(kname, props[i].name)) { 61164a5011eSPascal Brand res = tee_svc_copy_to_user(sess, index, &i, 61264a5011eSPascal Brand sizeof(*index)); 613*41d71430SPascal Brand goto out; 614*41d71430SPascal Brand } 615*41d71430SPascal Brand } 616*41d71430SPascal Brand for (i = size; i < size + vendor_size; i++) { 617*41d71430SPascal Brand if (!strcmp(kname, vendor_props[i - size].name)) { 618*41d71430SPascal Brand res = tee_svc_copy_to_user(sess, index, &i, 619*41d71430SPascal Brand sizeof(*index)); 620*41d71430SPascal Brand goto out; 62164a5011eSPascal Brand } 62264a5011eSPascal Brand } 62364a5011eSPascal Brand 62464a5011eSPascal Brand out: 62564a5011eSPascal Brand free(kname); 62664a5011eSPascal Brand return res; 62764a5011eSPascal Brand } 62864a5011eSPascal Brand 629e86f1266SJens Wiklander static void utee_param_to_param(struct tee_ta_param *p, struct utee_params *up) 630e86f1266SJens Wiklander { 631e86f1266SJens Wiklander size_t n; 632e86f1266SJens Wiklander uint32_t types = up->types; 633e86f1266SJens Wiklander 634e86f1266SJens Wiklander p->types = types; 635e86f1266SJens Wiklander for (n = 0; n < TEE_NUM_PARAMS; n++) { 636e86f1266SJens Wiklander uintptr_t a = up->vals[n * 2]; 637e86f1266SJens Wiklander size_t b = up->vals[n * 2 + 1]; 638e86f1266SJens Wiklander 639e86f1266SJens Wiklander switch (TEE_PARAM_TYPE_GET(types, n)) { 640e86f1266SJens Wiklander case TEE_PARAM_TYPE_MEMREF_INPUT: 641e86f1266SJens Wiklander case TEE_PARAM_TYPE_MEMREF_OUTPUT: 642e86f1266SJens Wiklander case TEE_PARAM_TYPE_MEMREF_INOUT: 643e86f1266SJens Wiklander p->params[n].memref.buffer = (void *)a; 644e86f1266SJens Wiklander p->params[n].memref.size = b; 645e86f1266SJens Wiklander break; 646e86f1266SJens Wiklander case TEE_PARAM_TYPE_VALUE_INPUT: 647e86f1266SJens Wiklander case TEE_PARAM_TYPE_VALUE_INOUT: 648e86f1266SJens Wiklander p->params[n].value.a = a; 649e86f1266SJens Wiklander p->params[n].value.b = b; 650e86f1266SJens Wiklander break; 651e86f1266SJens Wiklander default: 652e86f1266SJens Wiklander p->params[n].value.a = 0; 653e86f1266SJens Wiklander p->params[n].value.b = 0; 654e86f1266SJens Wiklander break; 655e86f1266SJens Wiklander } 656e86f1266SJens Wiklander } 657e86f1266SJens Wiklander } 658e86f1266SJens Wiklander 659b0104773SPascal Brand /* 660b0104773SPascal Brand * TA invokes some TA with parameter. 661b0104773SPascal Brand * If some parameters are memory references: 662b0104773SPascal Brand * - either the memref is inside TA private RAM: TA is not allowed to expose 663b0104773SPascal Brand * its private RAM: use a temporary memory buffer and copy the data. 664b0104773SPascal Brand * - or the memref is not in the TA private RAM: 665b0104773SPascal Brand * - if the memref was mapped to the TA, TA is allowed to expose it. 666b0104773SPascal Brand * - if so, converts memref virtual address into a physical address. 667b0104773SPascal Brand */ 668b0104773SPascal Brand static TEE_Result tee_svc_copy_param(struct tee_ta_session *sess, 669b0104773SPascal Brand struct tee_ta_session *called_sess, 670e86f1266SJens Wiklander struct utee_params *callee_params, 671b0104773SPascal Brand struct tee_ta_param *param, 672b0104773SPascal Brand tee_paddr_t tmp_buf_pa[TEE_NUM_PARAMS], 673b0104773SPascal Brand tee_mm_entry_t **mm) 674b0104773SPascal Brand { 675b0104773SPascal Brand size_t n; 676b0104773SPascal Brand TEE_Result res; 677b0104773SPascal Brand size_t req_mem = 0; 678b0104773SPascal Brand size_t s; 679b0104773SPascal Brand uint8_t *dst = 0; 680b0104773SPascal Brand tee_paddr_t dst_pa, src_pa = 0; 681b0104773SPascal Brand bool ta_private_memref[TEE_NUM_PARAMS]; 6828684fde8SJens Wiklander struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); 683b0104773SPascal Brand 684b7fc217fSPascal Brand /* fill 'param' input struct with caller params description buffer */ 685b7fc217fSPascal Brand if (!callee_params) { 686e86f1266SJens Wiklander memset(param, 0, sizeof(*param)); 687b0104773SPascal Brand } else { 6888684fde8SJens Wiklander res = tee_mmu_check_access_rights(utc, 689177603c7SJens Wiklander TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, 690e86f1266SJens Wiklander (tee_uaddr_t)callee_params, sizeof(struct utee_params)); 691177603c7SJens Wiklander if (res != TEE_SUCCESS) 692177603c7SJens Wiklander return res; 693e86f1266SJens Wiklander utee_param_to_param(param, callee_params); 694b0104773SPascal Brand } 695b0104773SPascal Brand 6968684fde8SJens Wiklander if (called_sess && is_static_ta_ctx(called_sess->ctx)) { 697b0104773SPascal Brand /* 6988684fde8SJens Wiklander * static TA, borrow the mapping of the calling 699b0104773SPascal Brand * during this call. 700b0104773SPascal Brand */ 701b0104773SPascal Brand called_sess->calling_sess = sess; 702b0104773SPascal Brand return TEE_SUCCESS; 703b0104773SPascal Brand } 704b0104773SPascal Brand 705b0104773SPascal Brand for (n = 0; n < TEE_NUM_PARAMS; n++) { 706b0104773SPascal Brand 707b0104773SPascal Brand ta_private_memref[n] = false; 708b0104773SPascal Brand 709b0104773SPascal Brand switch (TEE_PARAM_TYPE_GET(param->types, n)) { 710b0104773SPascal Brand case TEE_PARAM_TYPE_MEMREF_INPUT: 711b0104773SPascal Brand case TEE_PARAM_TYPE_MEMREF_OUTPUT: 712b0104773SPascal Brand case TEE_PARAM_TYPE_MEMREF_INOUT: 713b0104773SPascal Brand if (param->params[n].memref.buffer == NULL) { 714b0104773SPascal Brand if (param->params[n].memref.size != 0) 715b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS; 716b0104773SPascal Brand break; 717b0104773SPascal Brand } 718b0104773SPascal Brand /* uTA cannot expose its private memory */ 7198684fde8SJens Wiklander if (tee_mmu_is_vbuf_inside_ta_private(utc, 720106d8aa6SPascal Brand param->params[n].memref.buffer, 721b0104773SPascal Brand param->params[n].memref.size)) { 722b0104773SPascal Brand 723a17acc4cSSabrina Ni s = ROUNDUP(param->params[n].memref.size, 724b0104773SPascal Brand sizeof(uint32_t)); 725b0104773SPascal Brand /* Check overflow */ 726b0104773SPascal Brand if (req_mem + s < req_mem) 727b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS; 728b0104773SPascal Brand req_mem += s; 729b0104773SPascal Brand ta_private_memref[n] = true; 730b0104773SPascal Brand break; 731b0104773SPascal Brand } 7328684fde8SJens Wiklander if (tee_mmu_is_vbuf_intersect_ta_private(utc, 733106d8aa6SPascal Brand param->params[n].memref.buffer, 734b0104773SPascal Brand param->params[n].memref.size)) 735b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS; 736b0104773SPascal Brand 7378684fde8SJens Wiklander if (tee_mmu_user_va2pa(utc, 738b0104773SPascal Brand (void *)param->params[n].memref.buffer, 7390e692b78SJens Wiklander &src_pa) != TEE_SUCCESS) 740b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS; 741b0104773SPascal Brand 742b0104773SPascal Brand param->param_attr[n] = tee_mmu_user_get_cache_attr( 7438684fde8SJens Wiklander utc, (void *)param->params[n].memref.buffer); 744b0104773SPascal Brand 745b0104773SPascal Brand param->params[n].memref.buffer = (void *)src_pa; 746b0104773SPascal Brand break; 747b0104773SPascal Brand 748b0104773SPascal Brand default: 749b0104773SPascal Brand break; 750b0104773SPascal Brand } 751b0104773SPascal Brand } 752b0104773SPascal Brand 753b0104773SPascal Brand if (req_mem == 0) 754b0104773SPascal Brand return TEE_SUCCESS; 755b0104773SPascal Brand 756b0104773SPascal Brand /* Allocate section in secure DDR */ 757b0104773SPascal Brand *mm = tee_mm_alloc(&tee_mm_sec_ddr, req_mem); 758b0104773SPascal Brand if (*mm == NULL) { 759b0104773SPascal Brand DMSG("tee_mm_alloc TEE_ERROR_GENERIC"); 760b0104773SPascal Brand return TEE_ERROR_GENERIC; 761b0104773SPascal Brand } 762b0104773SPascal Brand 763b0104773SPascal Brand /* Get the virtual address for the section in secure DDR */ 764b0104773SPascal Brand res = tee_mmu_kmap(tee_mm_get_smem(*mm), req_mem, &dst); 765b0104773SPascal Brand if (res != TEE_SUCCESS) 766b0104773SPascal Brand return res; 767b0104773SPascal Brand dst_pa = tee_mm_get_smem(*mm); 768b0104773SPascal Brand 769b0104773SPascal Brand for (n = 0; n < 4; n++) { 770b0104773SPascal Brand 771b0104773SPascal Brand if (ta_private_memref[n] == false) 772b0104773SPascal Brand continue; 773b0104773SPascal Brand 774a17acc4cSSabrina Ni s = ROUNDUP(param->params[n].memref.size, sizeof(uint32_t)); 775b0104773SPascal Brand 776b0104773SPascal Brand switch (TEE_PARAM_TYPE_GET(param->types, n)) { 777b0104773SPascal Brand case TEE_PARAM_TYPE_MEMREF_INPUT: 778b0104773SPascal Brand case TEE_PARAM_TYPE_MEMREF_INOUT: 779b0104773SPascal Brand if (param->params[n].memref.buffer != NULL) { 780b0104773SPascal Brand res = tee_svc_copy_from_user(sess, dst, 781b7fc217fSPascal Brand param->params[n].memref.buffer, 782b7fc217fSPascal Brand param->params[n].memref.size); 783b0104773SPascal Brand if (res != TEE_SUCCESS) 784b0104773SPascal Brand return res; 785b0104773SPascal Brand param->param_attr[n] = 786b0104773SPascal Brand tee_mmu_kmap_get_cache_attr(dst); 787b0104773SPascal Brand param->params[n].memref.buffer = (void *)dst_pa; 788b0104773SPascal Brand tmp_buf_pa[n] = dst_pa; 789b0104773SPascal Brand dst += s; 790b0104773SPascal Brand dst_pa += s; 791b0104773SPascal Brand } 792b0104773SPascal Brand break; 793b0104773SPascal Brand 794b0104773SPascal Brand case TEE_PARAM_TYPE_MEMREF_OUTPUT: 795b0104773SPascal Brand if (param->params[n].memref.buffer != NULL) { 796b0104773SPascal Brand param->param_attr[n] = 797b0104773SPascal Brand tee_mmu_kmap_get_cache_attr(dst); 798b0104773SPascal Brand param->params[n].memref.buffer = (void *)dst_pa; 799b0104773SPascal Brand tmp_buf_pa[n] = dst_pa; 800b0104773SPascal Brand dst += s; 801b0104773SPascal Brand dst_pa += s; 802b0104773SPascal Brand } 803b0104773SPascal Brand break; 804b0104773SPascal Brand 805b0104773SPascal Brand default: 806b0104773SPascal Brand continue; 807b0104773SPascal Brand } 808b0104773SPascal Brand } 809b0104773SPascal Brand 810b0104773SPascal Brand tee_mmu_kunmap(dst, req_mem); 811b0104773SPascal Brand 812b0104773SPascal Brand return TEE_SUCCESS; 813b0104773SPascal Brand } 814b0104773SPascal Brand 815b0104773SPascal Brand /* 816b0104773SPascal Brand * Back from execution of service: update parameters passed from TA: 817b0104773SPascal Brand * If some parameters were memory references: 818b0104773SPascal Brand * - either the memref was temporary: copy back data and update size 819b0104773SPascal Brand * - or it was the original TA memref: update only the size value. 820b0104773SPascal Brand */ 821b0104773SPascal Brand static TEE_Result tee_svc_update_out_param( 822b0104773SPascal Brand struct tee_ta_session *sess, 823b0104773SPascal Brand struct tee_ta_session *called_sess, 824b0104773SPascal Brand struct tee_ta_param *param, 825b0104773SPascal Brand tee_paddr_t tmp_buf_pa[TEE_NUM_PARAMS], 826e86f1266SJens Wiklander struct utee_params *usr_param) 827b0104773SPascal Brand { 828b0104773SPascal Brand size_t n; 829e86f1266SJens Wiklander void *p; 8308684fde8SJens Wiklander struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); 8318684fde8SJens Wiklander bool have_private_mem_map = is_user_ta_ctx(called_sess->ctx); 832bc420748SJens Wiklander 833b0104773SPascal Brand tee_ta_set_current_session(sess); 834b0104773SPascal Brand 835b0104773SPascal Brand for (n = 0; n < TEE_NUM_PARAMS; n++) { 836b0104773SPascal Brand switch (TEE_PARAM_TYPE_GET(param->types, n)) { 837b0104773SPascal Brand case TEE_PARAM_TYPE_MEMREF_OUTPUT: 838b0104773SPascal Brand case TEE_PARAM_TYPE_MEMREF_INOUT: 839e86f1266SJens Wiklander p = (void *)(uintptr_t)usr_param->vals[n * 2]; 840b0104773SPascal Brand 841b0104773SPascal Brand /* outside TA private => memref is valid, update size */ 8428684fde8SJens Wiklander if (!tee_mmu_is_vbuf_inside_ta_private(utc, p, 843b0104773SPascal Brand param->params[n].memref.size)) { 844e86f1266SJens Wiklander usr_param->vals[n * 2 + 1] = 845b0104773SPascal Brand param->params[n].memref.size; 846b0104773SPascal Brand break; 847b0104773SPascal Brand } 848b0104773SPascal Brand 849b0104773SPascal Brand /* 850b0104773SPascal Brand * If we called a kernel TA the parameters are in shared 851b0104773SPascal Brand * memory and no copy is needed. 852b0104773SPascal Brand */ 853b0104773SPascal Brand if (have_private_mem_map && 854b0104773SPascal Brand param->params[n].memref.size <= 855e86f1266SJens Wiklander usr_param->vals[n * 2 + 1]) { 856b0104773SPascal Brand uint8_t *src = 0; 857b0104773SPascal Brand TEE_Result res; 858b0104773SPascal Brand 859b0104773SPascal Brand /* FIXME: TA_RAM is already mapped ! */ 860b0104773SPascal Brand res = tee_mmu_kmap(tmp_buf_pa[n], 861b0104773SPascal Brand param->params[n].memref.size, &src); 862b0104773SPascal Brand if (res != TEE_SUCCESS) 863b0104773SPascal Brand return TEE_ERROR_GENERIC; 864b0104773SPascal Brand 865e86f1266SJens Wiklander res = tee_svc_copy_to_user(sess, p, src, 866e86f1266SJens Wiklander param->params[n].memref.size); 867b0104773SPascal Brand if (res != TEE_SUCCESS) 868b0104773SPascal Brand return res; 869b0104773SPascal Brand tee_mmu_kunmap(src, 870b0104773SPascal Brand param->params[n].memref.size); 871b0104773SPascal Brand 872b0104773SPascal Brand } 873e86f1266SJens Wiklander usr_param->vals[n * 2 + 1] = 874e86f1266SJens Wiklander param->params[n].memref.size; 875b0104773SPascal Brand break; 876b0104773SPascal Brand 877b0104773SPascal Brand case TEE_PARAM_TYPE_VALUE_OUTPUT: 878b0104773SPascal Brand case TEE_PARAM_TYPE_VALUE_INOUT: 879e86f1266SJens Wiklander usr_param->vals[n * 2] = param->params[n].value.a; 880e86f1266SJens Wiklander usr_param->vals[n * 2 + 1] = param->params[n].value.b; 881b0104773SPascal Brand break; 882b0104773SPascal Brand 883b0104773SPascal Brand default: 884b0104773SPascal Brand continue; 885b0104773SPascal Brand } 886b0104773SPascal Brand } 887b0104773SPascal Brand 888b0104773SPascal Brand return TEE_SUCCESS; 889b0104773SPascal Brand } 890b0104773SPascal Brand 891b0104773SPascal Brand /* Called when a TA calls an OpenSession on another TA */ 892453a5030SJerome Forissier TEE_Result syscall_open_ta_session(const TEE_UUID *dest, 893e86f1266SJens Wiklander unsigned long cancel_req_to, 894e86f1266SJens Wiklander struct utee_params *usr_param, uint32_t *ta_sess, 895b0104773SPascal Brand uint32_t *ret_orig) 896b0104773SPascal Brand { 897b0104773SPascal Brand TEE_Result res; 898b0104773SPascal Brand uint32_t ret_o = TEE_ORIGIN_TEE; 899b0104773SPascal Brand struct tee_ta_session *s = NULL; 900b0104773SPascal Brand struct tee_ta_session *sess; 901b0104773SPascal Brand tee_mm_entry_t *mm_param = NULL; 902b0104773SPascal Brand TEE_UUID *uuid = malloc(sizeof(TEE_UUID)); 903b0104773SPascal Brand struct tee_ta_param *param = malloc(sizeof(struct tee_ta_param)); 904b0104773SPascal Brand TEE_Identity *clnt_id = malloc(sizeof(TEE_Identity)); 905b0104773SPascal Brand tee_paddr_t tmp_buf_pa[TEE_NUM_PARAMS]; 9068684fde8SJens Wiklander struct user_ta_ctx *utc; 907b0104773SPascal Brand 908b0104773SPascal Brand if (uuid == NULL || param == NULL || clnt_id == NULL) { 909b0104773SPascal Brand res = TEE_ERROR_OUT_OF_MEMORY; 910b0104773SPascal Brand goto out_free_only; 911b0104773SPascal Brand } 912b0104773SPascal Brand 913b0104773SPascal Brand memset(param, 0, sizeof(struct tee_ta_param)); 914b0104773SPascal Brand 915b0104773SPascal Brand res = tee_ta_get_current_session(&sess); 916b0104773SPascal Brand if (res != TEE_SUCCESS) 917b0104773SPascal Brand goto out_free_only; 9188684fde8SJens Wiklander utc = to_user_ta_ctx(sess->ctx); 919b0104773SPascal Brand 920b0104773SPascal Brand res = tee_svc_copy_from_user(sess, uuid, dest, sizeof(TEE_UUID)); 921b0104773SPascal Brand if (res != TEE_SUCCESS) 922b0104773SPascal Brand goto function_exit; 923b0104773SPascal Brand 924b0104773SPascal Brand clnt_id->login = TEE_LOGIN_TRUSTED_APP; 925bc420748SJens Wiklander memcpy(&clnt_id->uuid, &sess->ctx->uuid, sizeof(TEE_UUID)); 926b0104773SPascal Brand 927e86f1266SJens Wiklander res = tee_svc_copy_param(sess, NULL, usr_param, param, tmp_buf_pa, 928e86f1266SJens Wiklander &mm_param); 929b0104773SPascal Brand if (res != TEE_SUCCESS) 930b0104773SPascal Brand goto function_exit; 931b0104773SPascal Brand 932b0104773SPascal Brand /* 933b0104773SPascal Brand * Find session of a multi session TA or a static TA 934b0104773SPascal Brand * In such a case, there is no need to ask the supplicant for the TA 935b0104773SPascal Brand * code 936b0104773SPascal Brand */ 9378684fde8SJens Wiklander res = tee_ta_open_session(&ret_o, &s, &utc->open_sessions, uuid, 93827cbcc57SJens Wiklander clnt_id, cancel_req_to, param); 939c0346845SJens Wiklander if (res != TEE_SUCCESS) 940b0104773SPascal Brand goto function_exit; 941b0104773SPascal Brand 9428684fde8SJens Wiklander res = tee_svc_update_out_param(sess, s, param, tmp_buf_pa, usr_param); 943b0104773SPascal Brand 944b0104773SPascal Brand function_exit: 945b0104773SPascal Brand tee_ta_set_current_session(sess); 9460dcea1a3SJens Wiklander sess->calling_sess = NULL; /* clear eventual borrowed mapping */ 947b0104773SPascal Brand 948b0104773SPascal Brand if (mm_param != NULL) { 949b0104773SPascal Brand TEE_Result res2; 950b0104773SPascal Brand void *va = 0; 951b0104773SPascal Brand 952b0104773SPascal Brand res2 = 953b0104773SPascal Brand tee_mmu_kmap_pa2va((void *)tee_mm_get_smem(mm_param), &va); 954b0104773SPascal Brand if (res2 == TEE_SUCCESS) 955b0104773SPascal Brand tee_mmu_kunmap(va, tee_mm_get_bytes(mm_param)); 956b0104773SPascal Brand } 957b0104773SPascal Brand tee_mm_free(mm_param); 9582dcb3d36SJerome Forissier if (res == TEE_SUCCESS) 959e86f1266SJens Wiklander tee_svc_copy_kaddr_to_uref(sess, ta_sess, s); 960b0104773SPascal Brand tee_svc_copy_to_user(sess, ret_orig, &ret_o, sizeof(ret_o)); 961b0104773SPascal Brand 962b0104773SPascal Brand out_free_only: 963b0104773SPascal Brand free(param); 964b0104773SPascal Brand free(uuid); 965b0104773SPascal Brand free(clnt_id); 966b0104773SPascal Brand return res; 967b0104773SPascal Brand } 968b0104773SPascal Brand 969e86f1266SJens Wiklander TEE_Result syscall_close_ta_session(unsigned long ta_sess) 970b0104773SPascal Brand { 971b0104773SPascal Brand TEE_Result res; 972b0104773SPascal Brand struct tee_ta_session *sess; 97360699957SPascal Brand TEE_Identity clnt_id; 974e86f1266SJens Wiklander struct tee_ta_session *s = tee_svc_uref_to_kaddr(ta_sess); 9758684fde8SJens Wiklander struct user_ta_ctx *utc; 976b0104773SPascal Brand 977b0104773SPascal Brand res = tee_ta_get_current_session(&sess); 978b0104773SPascal Brand if (res != TEE_SUCCESS) 979b0104773SPascal Brand return res; 9808684fde8SJens Wiklander utc = to_user_ta_ctx(sess->ctx); 981b0104773SPascal Brand 98260699957SPascal Brand clnt_id.login = TEE_LOGIN_TRUSTED_APP; 983bc420748SJens Wiklander memcpy(&clnt_id.uuid, &sess->ctx->uuid, sizeof(TEE_UUID)); 984b0104773SPascal Brand 98560699957SPascal Brand tee_ta_set_current_session(NULL); 9868684fde8SJens Wiklander res = tee_ta_close_session(s, &utc->open_sessions, &clnt_id); 987b0104773SPascal Brand tee_ta_set_current_session(sess); 988b0104773SPascal Brand return res; 989b0104773SPascal Brand } 990b0104773SPascal Brand 991e86f1266SJens Wiklander TEE_Result syscall_invoke_ta_command(unsigned long ta_sess, 992e86f1266SJens Wiklander unsigned long cancel_req_to, unsigned long cmd_id, 993e86f1266SJens Wiklander struct utee_params *usr_param, uint32_t *ret_orig) 994b0104773SPascal Brand { 995b0104773SPascal Brand TEE_Result res; 996b0104773SPascal Brand uint32_t ret_o = TEE_ORIGIN_TEE; 997b0104773SPascal Brand struct tee_ta_param param = { 0 }; 99860699957SPascal Brand TEE_Identity clnt_id; 999b0104773SPascal Brand struct tee_ta_session *sess; 1000b666b6f2SJens Wiklander struct tee_ta_session *called_sess; 1001b0104773SPascal Brand tee_mm_entry_t *mm_param = NULL; 1002b0104773SPascal Brand tee_paddr_t tmp_buf_pa[TEE_NUM_PARAMS]; 10038684fde8SJens Wiklander struct user_ta_ctx *utc; 1004b0104773SPascal Brand 1005b0104773SPascal Brand res = tee_ta_get_current_session(&sess); 1006b0104773SPascal Brand if (res != TEE_SUCCESS) 1007b0104773SPascal Brand return res; 10088684fde8SJens Wiklander utc = to_user_ta_ctx(sess->ctx); 1009b0104773SPascal Brand 1010e86f1266SJens Wiklander called_sess = tee_ta_get_session( 1011e86f1266SJens Wiklander (vaddr_t)tee_svc_uref_to_kaddr(ta_sess), true, 10128684fde8SJens Wiklander &utc->open_sessions); 1013b666b6f2SJens Wiklander if (!called_sess) 1014b666b6f2SJens Wiklander return TEE_ERROR_BAD_PARAMETERS; 1015b0104773SPascal Brand 101660699957SPascal Brand clnt_id.login = TEE_LOGIN_TRUSTED_APP; 1017bc420748SJens Wiklander memcpy(&clnt_id.uuid, &sess->ctx->uuid, sizeof(TEE_UUID)); 101860699957SPascal Brand 1019e86f1266SJens Wiklander res = tee_svc_copy_param(sess, called_sess, usr_param, ¶m, 1020e86f1266SJens Wiklander tmp_buf_pa, &mm_param); 1021b0104773SPascal Brand if (res != TEE_SUCCESS) 1022b0104773SPascal Brand goto function_exit; 1023b0104773SPascal Brand 102460699957SPascal Brand res = tee_ta_invoke_command(&ret_o, called_sess, &clnt_id, 102560699957SPascal Brand cancel_req_to, cmd_id, ¶m); 102660699957SPascal Brand 1027b0104773SPascal Brand if (res != TEE_SUCCESS) 1028b0104773SPascal Brand goto function_exit; 1029b0104773SPascal Brand 1030b0104773SPascal Brand res = tee_svc_update_out_param(sess, called_sess, ¶m, tmp_buf_pa, 1031177603c7SJens Wiklander usr_param); 1032b0104773SPascal Brand if (res != TEE_SUCCESS) 1033b0104773SPascal Brand goto function_exit; 1034b0104773SPascal Brand 1035b0104773SPascal Brand function_exit: 1036b0104773SPascal Brand tee_ta_set_current_session(sess); 1037b0104773SPascal Brand called_sess->calling_sess = NULL; /* clear eventual borrowed mapping */ 1038b666b6f2SJens Wiklander tee_ta_put_session(called_sess); 1039b0104773SPascal Brand 1040b0104773SPascal Brand if (mm_param != NULL) { 1041b0104773SPascal Brand TEE_Result res2; 1042b0104773SPascal Brand void *va = 0; 1043b0104773SPascal Brand 1044b0104773SPascal Brand res2 = 1045b0104773SPascal Brand tee_mmu_kmap_pa2va((void *)tee_mm_get_smem(mm_param), &va); 1046b0104773SPascal Brand if (res2 == TEE_SUCCESS) 1047b0104773SPascal Brand tee_mmu_kunmap(va, tee_mm_get_bytes(mm_param)); 1048b0104773SPascal Brand } 1049b0104773SPascal Brand tee_mm_free(mm_param); 1050b0104773SPascal Brand if (ret_orig) 1051b0104773SPascal Brand tee_svc_copy_to_user(sess, ret_orig, &ret_o, sizeof(ret_o)); 1052b0104773SPascal Brand return res; 1053b0104773SPascal Brand } 1054b0104773SPascal Brand 1055e86f1266SJens Wiklander TEE_Result syscall_check_access_rights(unsigned long flags, const void *buf, 1056b0104773SPascal Brand size_t len) 1057b0104773SPascal Brand { 1058b0104773SPascal Brand TEE_Result res; 1059b0104773SPascal Brand struct tee_ta_session *s; 1060b0104773SPascal Brand 1061b0104773SPascal Brand res = tee_ta_get_current_session(&s); 1062b0104773SPascal Brand if (res != TEE_SUCCESS) 1063b0104773SPascal Brand return res; 1064b0104773SPascal Brand 10658684fde8SJens Wiklander return tee_mmu_check_access_rights(to_user_ta_ctx(s->ctx), flags, 10668684fde8SJens Wiklander (tee_uaddr_t)buf, len); 1067b0104773SPascal Brand } 1068b0104773SPascal Brand 1069b0104773SPascal Brand TEE_Result tee_svc_copy_from_user(struct tee_ta_session *sess, void *kaddr, 1070b0104773SPascal Brand const void *uaddr, size_t len) 1071b0104773SPascal Brand { 1072b0104773SPascal Brand TEE_Result res; 1073b0104773SPascal Brand struct tee_ta_session *s; 1074b0104773SPascal Brand 1075b0104773SPascal Brand if (sess == NULL) { 1076b0104773SPascal Brand res = tee_ta_get_current_session(&s); 1077b0104773SPascal Brand if (res != TEE_SUCCESS) 1078b0104773SPascal Brand return res; 1079b0104773SPascal Brand } else { 1080b0104773SPascal Brand s = sess; 1081b0104773SPascal Brand tee_ta_set_current_session(s); 1082b0104773SPascal Brand } 10838684fde8SJens Wiklander res = tee_mmu_check_access_rights(to_user_ta_ctx(s->ctx), 1084b0104773SPascal Brand TEE_MEMORY_ACCESS_READ | 1085b0104773SPascal Brand TEE_MEMORY_ACCESS_ANY_OWNER, 1086b0104773SPascal Brand (tee_uaddr_t)uaddr, len); 1087b0104773SPascal Brand if (res != TEE_SUCCESS) 1088b0104773SPascal Brand return res; 1089b0104773SPascal Brand 1090b0104773SPascal Brand memcpy(kaddr, uaddr, len); 1091b0104773SPascal Brand return TEE_SUCCESS; 1092b0104773SPascal Brand } 1093b0104773SPascal Brand 1094b0104773SPascal Brand TEE_Result tee_svc_copy_to_user(struct tee_ta_session *sess, void *uaddr, 1095b0104773SPascal Brand const void *kaddr, size_t len) 1096b0104773SPascal Brand { 1097b0104773SPascal Brand TEE_Result res; 1098b0104773SPascal Brand struct tee_ta_session *s; 1099b0104773SPascal Brand 1100b0104773SPascal Brand if (sess == NULL) { 1101b0104773SPascal Brand res = tee_ta_get_current_session(&s); 1102b0104773SPascal Brand if (res != TEE_SUCCESS) 1103b0104773SPascal Brand return res; 1104b0104773SPascal Brand } else { 1105b0104773SPascal Brand s = sess; 1106b0104773SPascal Brand tee_ta_set_current_session(s); 1107b0104773SPascal Brand } 1108b0104773SPascal Brand 11098684fde8SJens Wiklander res = tee_mmu_check_access_rights(to_user_ta_ctx(s->ctx), 1110b0104773SPascal Brand TEE_MEMORY_ACCESS_WRITE | 1111b0104773SPascal Brand TEE_MEMORY_ACCESS_ANY_OWNER, 1112b0104773SPascal Brand (tee_uaddr_t)uaddr, len); 1113b0104773SPascal Brand if (res != TEE_SUCCESS) 1114b0104773SPascal Brand return res; 1115b0104773SPascal Brand 1116b0104773SPascal Brand memcpy(uaddr, kaddr, len); 1117b0104773SPascal Brand return TEE_SUCCESS; 1118b0104773SPascal Brand } 1119b0104773SPascal Brand 1120e86f1266SJens Wiklander TEE_Result tee_svc_copy_kaddr_to_uref(struct tee_ta_session *sess, 1121e86f1266SJens Wiklander uint32_t *uref, void *kaddr) 11228707ec0fSJerome Forissier { 1123e86f1266SJens Wiklander uint32_t ref = tee_svc_kaddr_to_uref(kaddr); 11248707ec0fSJerome Forissier 1125e86f1266SJens Wiklander return tee_svc_copy_to_user(sess, uref, &ref, sizeof(ref)); 11268707ec0fSJerome Forissier } 11278707ec0fSJerome Forissier 1128b0104773SPascal Brand static bool session_is_cancelled(struct tee_ta_session *s, TEE_Time *curr_time) 1129b0104773SPascal Brand { 1130b0104773SPascal Brand TEE_Time current_time; 1131b0104773SPascal Brand 1132b0104773SPascal Brand if (s->cancel_mask) 1133b0104773SPascal Brand return false; 1134b0104773SPascal Brand 1135b0104773SPascal Brand if (s->cancel) 1136b0104773SPascal Brand return true; 1137b0104773SPascal Brand 1138b0104773SPascal Brand if (s->cancel_time.seconds == UINT32_MAX) 1139b0104773SPascal Brand return false; 1140b0104773SPascal Brand 1141b0104773SPascal Brand if (curr_time != NULL) 1142b0104773SPascal Brand current_time = *curr_time; 1143b0104773SPascal Brand else if (tee_time_get_sys_time(¤t_time) != TEE_SUCCESS) 1144b0104773SPascal Brand return false; 1145b0104773SPascal Brand 1146b0104773SPascal Brand if (current_time.seconds > s->cancel_time.seconds || 1147b0104773SPascal Brand (current_time.seconds == s->cancel_time.seconds && 1148b0104773SPascal Brand current_time.millis >= s->cancel_time.millis)) { 1149b0104773SPascal Brand return true; 1150b0104773SPascal Brand } 1151b0104773SPascal Brand 1152b0104773SPascal Brand return false; 1153b0104773SPascal Brand } 1154b0104773SPascal Brand 1155e86f1266SJens Wiklander TEE_Result syscall_get_cancellation_flag(uint32_t *cancel) 1156b0104773SPascal Brand { 1157b0104773SPascal Brand TEE_Result res; 1158b0104773SPascal Brand struct tee_ta_session *s = NULL; 1159e86f1266SJens Wiklander uint32_t c; 1160b0104773SPascal Brand 1161b0104773SPascal Brand res = tee_ta_get_current_session(&s); 1162b0104773SPascal Brand if (res != TEE_SUCCESS) 1163b0104773SPascal Brand return res; 1164b0104773SPascal Brand 1165b0104773SPascal Brand c = session_is_cancelled(s, NULL); 1166b0104773SPascal Brand 1167b0104773SPascal Brand return tee_svc_copy_to_user(s, cancel, &c, sizeof(c)); 1168b0104773SPascal Brand } 1169b0104773SPascal Brand 1170e86f1266SJens Wiklander TEE_Result syscall_unmask_cancellation(uint32_t *old_mask) 1171b0104773SPascal Brand { 1172b0104773SPascal Brand TEE_Result res; 1173b0104773SPascal Brand struct tee_ta_session *s = NULL; 1174e86f1266SJens Wiklander uint32_t m; 1175b0104773SPascal Brand 1176b0104773SPascal Brand res = tee_ta_get_current_session(&s); 1177b0104773SPascal Brand if (res != TEE_SUCCESS) 1178b0104773SPascal Brand return res; 1179b0104773SPascal Brand 1180b0104773SPascal Brand m = s->cancel_mask; 1181b0104773SPascal Brand s->cancel_mask = false; 1182b0104773SPascal Brand return tee_svc_copy_to_user(s, old_mask, &m, sizeof(m)); 1183b0104773SPascal Brand } 1184b0104773SPascal Brand 1185e86f1266SJens Wiklander TEE_Result syscall_mask_cancellation(uint32_t *old_mask) 1186b0104773SPascal Brand { 1187b0104773SPascal Brand TEE_Result res; 1188b0104773SPascal Brand struct tee_ta_session *s = NULL; 1189e86f1266SJens Wiklander uint32_t m; 1190b0104773SPascal Brand 1191b0104773SPascal Brand res = tee_ta_get_current_session(&s); 1192b0104773SPascal Brand if (res != TEE_SUCCESS) 1193b0104773SPascal Brand return res; 1194b0104773SPascal Brand 1195b0104773SPascal Brand m = s->cancel_mask; 1196b0104773SPascal Brand s->cancel_mask = true; 1197b0104773SPascal Brand return tee_svc_copy_to_user(s, old_mask, &m, sizeof(m)); 1198b0104773SPascal Brand } 1199b0104773SPascal Brand 1200e86f1266SJens Wiklander TEE_Result syscall_wait(unsigned long timeout) 1201b0104773SPascal Brand { 1202b0104773SPascal Brand TEE_Result res = TEE_SUCCESS; 1203b0104773SPascal Brand uint32_t mytime = 0; 1204b0104773SPascal Brand struct tee_ta_session *s; 1205b0104773SPascal Brand TEE_Time base_time; 1206b0104773SPascal Brand TEE_Time current_time; 1207b0104773SPascal Brand 1208b0104773SPascal Brand res = tee_ta_get_current_session(&s); 1209b0104773SPascal Brand if (res != TEE_SUCCESS) 1210b0104773SPascal Brand return res; 1211b0104773SPascal Brand 1212b0104773SPascal Brand res = tee_time_get_sys_time(&base_time); 1213b0104773SPascal Brand if (res != TEE_SUCCESS) 1214b0104773SPascal Brand return res; 1215b0104773SPascal Brand 1216b0104773SPascal Brand while (true) { 1217b0104773SPascal Brand res = tee_time_get_sys_time(¤t_time); 1218b0104773SPascal Brand if (res != TEE_SUCCESS) 1219b0104773SPascal Brand return res; 1220b0104773SPascal Brand 1221b0104773SPascal Brand if (session_is_cancelled(s, ¤t_time)) 1222b0104773SPascal Brand return TEE_ERROR_CANCEL; 1223b0104773SPascal Brand 1224b0104773SPascal Brand mytime = (current_time.seconds - base_time.seconds) * 1000 + 1225b0104773SPascal Brand (int)current_time.millis - (int)base_time.millis; 1226b0104773SPascal Brand if (mytime >= timeout) 1227b0104773SPascal Brand return TEE_SUCCESS; 1228b0104773SPascal Brand 1229d1aea08fSSY Chiu tee_time_wait(timeout - mytime); 1230b0104773SPascal Brand } 1231b0104773SPascal Brand 1232b0104773SPascal Brand return res; 1233b0104773SPascal Brand } 1234b0104773SPascal Brand 1235e86f1266SJens Wiklander TEE_Result syscall_get_time(unsigned long cat, TEE_Time *mytime) 1236b0104773SPascal Brand { 1237b0104773SPascal Brand TEE_Result res, res2; 1238b0104773SPascal Brand struct tee_ta_session *s = NULL; 1239b0104773SPascal Brand TEE_Time t; 1240b0104773SPascal Brand 1241b0104773SPascal Brand res = tee_ta_get_current_session(&s); 1242b0104773SPascal Brand if (res != TEE_SUCCESS) 1243b0104773SPascal Brand return res; 1244b0104773SPascal Brand 1245b0104773SPascal Brand switch (cat) { 1246b0104773SPascal Brand case UTEE_TIME_CAT_SYSTEM: 1247b0104773SPascal Brand res = tee_time_get_sys_time(&t); 1248b0104773SPascal Brand break; 1249b0104773SPascal Brand case UTEE_TIME_CAT_TA_PERSISTENT: 1250bc420748SJens Wiklander res = tee_time_get_ta_time((const void *)&s->ctx->uuid, &t); 1251b0104773SPascal Brand break; 1252b0104773SPascal Brand case UTEE_TIME_CAT_REE: 1253b0104773SPascal Brand res = tee_time_get_ree_time(&t); 1254b0104773SPascal Brand break; 1255b0104773SPascal Brand default: 1256b0104773SPascal Brand res = TEE_ERROR_BAD_PARAMETERS; 1257b0104773SPascal Brand break; 1258b0104773SPascal Brand } 1259b0104773SPascal Brand 1260b0104773SPascal Brand if (res == TEE_SUCCESS || res == TEE_ERROR_OVERFLOW) { 1261b0104773SPascal Brand res2 = tee_svc_copy_to_user(s, mytime, &t, sizeof(t)); 1262b0104773SPascal Brand if (res2 != TEE_SUCCESS) 1263b0104773SPascal Brand res = res2; 1264b0104773SPascal Brand } 1265b0104773SPascal Brand 1266b0104773SPascal Brand return res; 1267b0104773SPascal Brand } 1268b0104773SPascal Brand 1269453a5030SJerome Forissier TEE_Result syscall_set_ta_time(const TEE_Time *mytime) 1270b0104773SPascal Brand { 1271b0104773SPascal Brand TEE_Result res; 1272b0104773SPascal Brand struct tee_ta_session *s = NULL; 1273b0104773SPascal Brand TEE_Time t; 1274b0104773SPascal Brand 1275b0104773SPascal Brand res = tee_ta_get_current_session(&s); 1276b0104773SPascal Brand if (res != TEE_SUCCESS) 1277b0104773SPascal Brand return res; 1278b0104773SPascal Brand 1279b0104773SPascal Brand res = tee_svc_copy_from_user(s, &t, mytime, sizeof(t)); 1280b0104773SPascal Brand if (res != TEE_SUCCESS) 1281b0104773SPascal Brand return res; 1282b0104773SPascal Brand 1283bc420748SJens Wiklander return tee_time_set_ta_time((const void *)&s->ctx->uuid, &t); 1284b0104773SPascal Brand } 1285