1*5843bb75SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 2*5843bb75SJerome Forissier /* 3*5843bb75SJerome Forissier * Copyright (c) 2018-2019, Linaro Limited 4*5843bb75SJerome Forissier */ 5*5843bb75SJerome Forissier 6*5843bb75SJerome Forissier #include <assert.h> 7*5843bb75SJerome Forissier #include <crypto/crypto.h> 8*5843bb75SJerome Forissier #include <kernel/handle.h> 9*5843bb75SJerome Forissier #include <kernel/huk_subkey.h> 10*5843bb75SJerome Forissier #include <kernel/misc.h> 11*5843bb75SJerome Forissier #include <kernel/msg_param.h> 12*5843bb75SJerome Forissier #include <kernel/pseudo_ta.h> 13*5843bb75SJerome Forissier #include <kernel/user_ta.h> 14*5843bb75SJerome Forissier #include <kernel/user_ta_store.h> 15*5843bb75SJerome Forissier #include <ldelf.h> 16*5843bb75SJerome Forissier #include <mm/file.h> 17*5843bb75SJerome Forissier #include <mm/fobj.h> 18*5843bb75SJerome Forissier #include <mm/tee_mmu.h> 19*5843bb75SJerome Forissier #include <pta_system.h> 20*5843bb75SJerome Forissier #include <string.h> 21*5843bb75SJerome Forissier #include <tee_api_defines_extensions.h> 22*5843bb75SJerome Forissier #include <tee_api_defines.h> 23*5843bb75SJerome Forissier #include <util.h> 24*5843bb75SJerome Forissier 25*5843bb75SJerome Forissier #define MAX_ENTROPY_IN 32u 26*5843bb75SJerome Forissier 27*5843bb75SJerome Forissier struct bin_handle { 28*5843bb75SJerome Forissier const struct user_ta_store_ops *op; 29*5843bb75SJerome Forissier struct user_ta_store_handle *h; 30*5843bb75SJerome Forissier struct file *f; 31*5843bb75SJerome Forissier size_t offs_bytes; 32*5843bb75SJerome Forissier size_t size_bytes; 33*5843bb75SJerome Forissier }; 34*5843bb75SJerome Forissier 35*5843bb75SJerome Forissier struct system_ctx { 36*5843bb75SJerome Forissier struct handle_db db; 37*5843bb75SJerome Forissier const struct user_ta_store_ops *store_op; 38*5843bb75SJerome Forissier }; 39*5843bb75SJerome Forissier 40*5843bb75SJerome Forissier static unsigned int system_pnum; 41*5843bb75SJerome Forissier 42*5843bb75SJerome Forissier static TEE_Result system_rng_reseed(struct tee_ta_session *s __unused, 43*5843bb75SJerome Forissier uint32_t param_types, 44*5843bb75SJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 45*5843bb75SJerome Forissier { 46*5843bb75SJerome Forissier size_t entropy_sz; 47*5843bb75SJerome Forissier uint8_t *entropy_input; 48*5843bb75SJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 49*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE, 50*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE, 51*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE); 52*5843bb75SJerome Forissier 53*5843bb75SJerome Forissier if (exp_pt != param_types) 54*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 55*5843bb75SJerome Forissier entropy_input = params[0].memref.buffer; 56*5843bb75SJerome Forissier entropy_sz = params[0].memref.size; 57*5843bb75SJerome Forissier 58*5843bb75SJerome Forissier /* Fortuna PRNG requires seed <= 32 bytes */ 59*5843bb75SJerome Forissier if (!entropy_sz) 60*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 61*5843bb75SJerome Forissier 62*5843bb75SJerome Forissier entropy_sz = MIN(entropy_sz, MAX_ENTROPY_IN); 63*5843bb75SJerome Forissier 64*5843bb75SJerome Forissier crypto_rng_add_event(CRYPTO_RNG_SRC_NONSECURE, &system_pnum, 65*5843bb75SJerome Forissier entropy_input, entropy_sz); 66*5843bb75SJerome Forissier return TEE_SUCCESS; 67*5843bb75SJerome Forissier } 68*5843bb75SJerome Forissier 69*5843bb75SJerome Forissier static TEE_Result system_derive_ta_unique_key(struct tee_ta_session *s, 70*5843bb75SJerome Forissier uint32_t param_types, 71*5843bb75SJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 72*5843bb75SJerome Forissier { 73*5843bb75SJerome Forissier size_t data_len = sizeof(TEE_UUID); 74*5843bb75SJerome Forissier TEE_Result res = TEE_ERROR_GENERIC; 75*5843bb75SJerome Forissier uint8_t *data = NULL; 76*5843bb75SJerome Forissier uint32_t access_flags = 0; 77*5843bb75SJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 78*5843bb75SJerome Forissier TEE_PARAM_TYPE_MEMREF_OUTPUT, 79*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE, 80*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE); 81*5843bb75SJerome Forissier struct user_ta_ctx *utc = NULL; 82*5843bb75SJerome Forissier 83*5843bb75SJerome Forissier if (exp_pt != param_types) 84*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 85*5843bb75SJerome Forissier 86*5843bb75SJerome Forissier if (params[0].memref.size > TA_DERIVED_EXTRA_DATA_MAX_SIZE || 87*5843bb75SJerome Forissier params[1].memref.size < TA_DERIVED_KEY_MIN_SIZE || 88*5843bb75SJerome Forissier params[1].memref.size > TA_DERIVED_KEY_MAX_SIZE) 89*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 90*5843bb75SJerome Forissier 91*5843bb75SJerome Forissier utc = to_user_ta_ctx(s->ctx); 92*5843bb75SJerome Forissier 93*5843bb75SJerome Forissier /* 94*5843bb75SJerome Forissier * The derived key shall not end up in non-secure memory by 95*5843bb75SJerome Forissier * mistake. 96*5843bb75SJerome Forissier * 97*5843bb75SJerome Forissier * Note that we're allowing shared memory as long as it's 98*5843bb75SJerome Forissier * secure. This is needed because a TA always uses shared memory 99*5843bb75SJerome Forissier * when communicating with another TA. 100*5843bb75SJerome Forissier */ 101*5843bb75SJerome Forissier access_flags = TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER | 102*5843bb75SJerome Forissier TEE_MEMORY_ACCESS_SECURE; 103*5843bb75SJerome Forissier res = tee_mmu_check_access_rights(utc, access_flags, 104*5843bb75SJerome Forissier (uaddr_t)params[1].memref.buffer, 105*5843bb75SJerome Forissier params[1].memref.size); 106*5843bb75SJerome Forissier if (res != TEE_SUCCESS) 107*5843bb75SJerome Forissier return TEE_ERROR_SECURITY; 108*5843bb75SJerome Forissier 109*5843bb75SJerome Forissier /* Take extra data into account. */ 110*5843bb75SJerome Forissier if (ADD_OVERFLOW(data_len, params[0].memref.size, &data_len)) 111*5843bb75SJerome Forissier return TEE_ERROR_SECURITY; 112*5843bb75SJerome Forissier 113*5843bb75SJerome Forissier data = calloc(data_len, 1); 114*5843bb75SJerome Forissier if (!data) 115*5843bb75SJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 116*5843bb75SJerome Forissier 117*5843bb75SJerome Forissier memcpy(data, &s->ctx->uuid, sizeof(TEE_UUID)); 118*5843bb75SJerome Forissier 119*5843bb75SJerome Forissier /* Append the user provided data */ 120*5843bb75SJerome Forissier memcpy(data + sizeof(TEE_UUID), params[0].memref.buffer, 121*5843bb75SJerome Forissier params[0].memref.size); 122*5843bb75SJerome Forissier 123*5843bb75SJerome Forissier res = huk_subkey_derive(HUK_SUBKEY_UNIQUE_TA, data, data_len, 124*5843bb75SJerome Forissier params[1].memref.buffer, 125*5843bb75SJerome Forissier params[1].memref.size); 126*5843bb75SJerome Forissier free(data); 127*5843bb75SJerome Forissier 128*5843bb75SJerome Forissier return res; 129*5843bb75SJerome Forissier } 130*5843bb75SJerome Forissier 131*5843bb75SJerome Forissier static TEE_Result system_map_zi(struct tee_ta_session *s, uint32_t param_types, 132*5843bb75SJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 133*5843bb75SJerome Forissier { 134*5843bb75SJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 135*5843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_INOUT, 136*5843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_INPUT, 137*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE); 138*5843bb75SJerome Forissier struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); 139*5843bb75SJerome Forissier uint32_t prot = TEE_MATTR_URW | TEE_MATTR_PRW; 140*5843bb75SJerome Forissier uint32_t vm_flags = VM_FLAG_EXCLUSIVE_MOBJ; 141*5843bb75SJerome Forissier TEE_Result res = TEE_ERROR_GENERIC; 142*5843bb75SJerome Forissier struct mobj *mobj = NULL; 143*5843bb75SJerome Forissier uint32_t pad_begin = 0; 144*5843bb75SJerome Forissier struct fobj *f = NULL; 145*5843bb75SJerome Forissier uint32_t pad_end = 0; 146*5843bb75SJerome Forissier size_t num_bytes = 0; 147*5843bb75SJerome Forissier vaddr_t va = 0; 148*5843bb75SJerome Forissier 149*5843bb75SJerome Forissier if (exp_pt != param_types) 150*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 151*5843bb75SJerome Forissier if (params[0].value.b & ~PTA_SYSTEM_MAP_FLAG_SHAREABLE) 152*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 153*5843bb75SJerome Forissier 154*5843bb75SJerome Forissier if (params[0].value.b & PTA_SYSTEM_MAP_FLAG_SHAREABLE) 155*5843bb75SJerome Forissier vm_flags |= VM_FLAG_SHAREABLE; 156*5843bb75SJerome Forissier 157*5843bb75SJerome Forissier num_bytes = params[0].value.a; 158*5843bb75SJerome Forissier va = reg_pair_to_64(params[1].value.a, params[1].value.b); 159*5843bb75SJerome Forissier pad_begin = params[2].value.a; 160*5843bb75SJerome Forissier pad_end = params[2].value.b; 161*5843bb75SJerome Forissier 162*5843bb75SJerome Forissier f = fobj_ta_mem_alloc(ROUNDUP(num_bytes, SMALL_PAGE_SIZE) / 163*5843bb75SJerome Forissier SMALL_PAGE_SIZE); 164*5843bb75SJerome Forissier if (!f) 165*5843bb75SJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 166*5843bb75SJerome Forissier mobj = mobj_with_fobj_alloc(f, NULL); 167*5843bb75SJerome Forissier fobj_put(f); 168*5843bb75SJerome Forissier if (!mobj) 169*5843bb75SJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 170*5843bb75SJerome Forissier res = vm_map_pad(utc, &va, num_bytes, prot, vm_flags, 171*5843bb75SJerome Forissier mobj, 0, pad_begin, pad_end); 172*5843bb75SJerome Forissier if (res) 173*5843bb75SJerome Forissier mobj_free(mobj); 174*5843bb75SJerome Forissier else 175*5843bb75SJerome Forissier reg_pair_from_64(va, ¶ms[1].value.a, ¶ms[1].value.b); 176*5843bb75SJerome Forissier 177*5843bb75SJerome Forissier return res; 178*5843bb75SJerome Forissier } 179*5843bb75SJerome Forissier 180*5843bb75SJerome Forissier static TEE_Result system_unmap(struct tee_ta_session *s, uint32_t param_types, 181*5843bb75SJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 182*5843bb75SJerome Forissier { 183*5843bb75SJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 184*5843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_INPUT, 185*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE, 186*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE); 187*5843bb75SJerome Forissier 188*5843bb75SJerome Forissier if (exp_pt != param_types) 189*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 190*5843bb75SJerome Forissier 191*5843bb75SJerome Forissier if (params[0].value.b) 192*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 193*5843bb75SJerome Forissier 194*5843bb75SJerome Forissier return vm_unmap(to_user_ta_ctx(s->ctx), 195*5843bb75SJerome Forissier reg_pair_to_64(params[1].value.a, params[1].value.b), 196*5843bb75SJerome Forissier ROUNDUP(params[0].value.a, SMALL_PAGE_SIZE)); 197*5843bb75SJerome Forissier } 198*5843bb75SJerome Forissier 199*5843bb75SJerome Forissier static void ta_bin_close(void *ptr) 200*5843bb75SJerome Forissier { 201*5843bb75SJerome Forissier struct bin_handle *binh = ptr; 202*5843bb75SJerome Forissier 203*5843bb75SJerome Forissier if (binh) { 204*5843bb75SJerome Forissier if (binh->op && binh->h) 205*5843bb75SJerome Forissier binh->op->close(binh->h); 206*5843bb75SJerome Forissier file_put(binh->f); 207*5843bb75SJerome Forissier } 208*5843bb75SJerome Forissier free(binh); 209*5843bb75SJerome Forissier } 210*5843bb75SJerome Forissier 211*5843bb75SJerome Forissier static TEE_Result system_open_ta_binary(struct system_ctx *ctx, 212*5843bb75SJerome Forissier uint32_t param_types, 213*5843bb75SJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 214*5843bb75SJerome Forissier { 215*5843bb75SJerome Forissier TEE_Result res = TEE_SUCCESS; 216*5843bb75SJerome Forissier struct bin_handle *binh = NULL; 217*5843bb75SJerome Forissier int h = 0; 218*5843bb75SJerome Forissier TEE_UUID *uuid = NULL; 219*5843bb75SJerome Forissier uint8_t tag[FILE_TAG_SIZE] = { 0 }; 220*5843bb75SJerome Forissier unsigned int tag_len = sizeof(tag); 221*5843bb75SJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 222*5843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_OUTPUT, 223*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE, 224*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE); 225*5843bb75SJerome Forissier 226*5843bb75SJerome Forissier if (exp_pt != param_types) 227*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 228*5843bb75SJerome Forissier if (params[0].memref.size != sizeof(*uuid)) 229*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 230*5843bb75SJerome Forissier 231*5843bb75SJerome Forissier uuid = params[0].memref.buffer; 232*5843bb75SJerome Forissier 233*5843bb75SJerome Forissier binh = calloc(1, sizeof(*binh)); 234*5843bb75SJerome Forissier if (!binh) 235*5843bb75SJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 236*5843bb75SJerome Forissier 237*5843bb75SJerome Forissier SCATTERED_ARRAY_FOREACH(binh->op, ta_stores, struct user_ta_store_ops) { 238*5843bb75SJerome Forissier DMSG("Lookup user TA ELF %pUl (%s)", 239*5843bb75SJerome Forissier (void *)uuid, binh->op->description); 240*5843bb75SJerome Forissier 241*5843bb75SJerome Forissier res = binh->op->open(uuid, &binh->h); 242*5843bb75SJerome Forissier DMSG("res=0x%x", res); 243*5843bb75SJerome Forissier if (res != TEE_ERROR_ITEM_NOT_FOUND && 244*5843bb75SJerome Forissier res != TEE_ERROR_STORAGE_NOT_AVAILABLE) 245*5843bb75SJerome Forissier break; 246*5843bb75SJerome Forissier } 247*5843bb75SJerome Forissier if (res) 248*5843bb75SJerome Forissier goto err; 249*5843bb75SJerome Forissier 250*5843bb75SJerome Forissier res = binh->op->get_size(binh->h, &binh->size_bytes); 251*5843bb75SJerome Forissier if (res) 252*5843bb75SJerome Forissier goto err; 253*5843bb75SJerome Forissier res = binh->op->get_tag(binh->h, tag, &tag_len); 254*5843bb75SJerome Forissier if (res) 255*5843bb75SJerome Forissier goto err; 256*5843bb75SJerome Forissier binh->f = file_get_by_tag(tag, tag_len); 257*5843bb75SJerome Forissier if (!binh->f) 258*5843bb75SJerome Forissier goto err_oom; 259*5843bb75SJerome Forissier 260*5843bb75SJerome Forissier h = handle_get(&ctx->db, binh); 261*5843bb75SJerome Forissier if (h < 0) 262*5843bb75SJerome Forissier goto err_oom; 263*5843bb75SJerome Forissier 264*5843bb75SJerome Forissier return TEE_SUCCESS; 265*5843bb75SJerome Forissier err_oom: 266*5843bb75SJerome Forissier res = TEE_ERROR_OUT_OF_MEMORY; 267*5843bb75SJerome Forissier err: 268*5843bb75SJerome Forissier ta_bin_close(binh); 269*5843bb75SJerome Forissier return res; 270*5843bb75SJerome Forissier } 271*5843bb75SJerome Forissier 272*5843bb75SJerome Forissier static TEE_Result system_close_ta_binary(struct system_ctx *ctx, 273*5843bb75SJerome Forissier uint32_t param_types, 274*5843bb75SJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 275*5843bb75SJerome Forissier { 276*5843bb75SJerome Forissier TEE_Result res = TEE_SUCCESS; 277*5843bb75SJerome Forissier struct bin_handle *binh = NULL; 278*5843bb75SJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 279*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE, 280*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE, 281*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE); 282*5843bb75SJerome Forissier 283*5843bb75SJerome Forissier if (exp_pt != param_types) 284*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 285*5843bb75SJerome Forissier 286*5843bb75SJerome Forissier if (params[0].value.b) 287*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 288*5843bb75SJerome Forissier 289*5843bb75SJerome Forissier binh = handle_put(&ctx->db, params[0].value.a); 290*5843bb75SJerome Forissier if (!binh) 291*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 292*5843bb75SJerome Forissier 293*5843bb75SJerome Forissier if (binh->offs_bytes < binh->size_bytes) 294*5843bb75SJerome Forissier res = binh->op->read(binh->h, NULL, 295*5843bb75SJerome Forissier binh->size_bytes - binh->offs_bytes); 296*5843bb75SJerome Forissier 297*5843bb75SJerome Forissier ta_bin_close(binh); 298*5843bb75SJerome Forissier return res; 299*5843bb75SJerome Forissier } 300*5843bb75SJerome Forissier 301*5843bb75SJerome Forissier static TEE_Result binh_copy_to(struct bin_handle *binh, vaddr_t va, 302*5843bb75SJerome Forissier size_t offs_bytes, size_t num_bytes) 303*5843bb75SJerome Forissier { 304*5843bb75SJerome Forissier TEE_Result res = TEE_SUCCESS; 305*5843bb75SJerome Forissier size_t l = num_bytes; 306*5843bb75SJerome Forissier 307*5843bb75SJerome Forissier if (offs_bytes < binh->offs_bytes) 308*5843bb75SJerome Forissier return TEE_ERROR_BAD_STATE; 309*5843bb75SJerome Forissier if (offs_bytes > binh->offs_bytes) { 310*5843bb75SJerome Forissier res = binh->op->read(binh->h, NULL, 311*5843bb75SJerome Forissier offs_bytes - binh->offs_bytes); 312*5843bb75SJerome Forissier if (res) 313*5843bb75SJerome Forissier return res; 314*5843bb75SJerome Forissier binh->offs_bytes = offs_bytes; 315*5843bb75SJerome Forissier } 316*5843bb75SJerome Forissier 317*5843bb75SJerome Forissier if (binh->offs_bytes + l > binh->size_bytes) { 318*5843bb75SJerome Forissier size_t rb = binh->size_bytes - binh->offs_bytes; 319*5843bb75SJerome Forissier 320*5843bb75SJerome Forissier res = binh->op->read(binh->h, (void *)va, rb); 321*5843bb75SJerome Forissier if (res) 322*5843bb75SJerome Forissier return res; 323*5843bb75SJerome Forissier memset((uint8_t *)va + rb, 0, l - rb); 324*5843bb75SJerome Forissier binh->offs_bytes = binh->size_bytes; 325*5843bb75SJerome Forissier } else { 326*5843bb75SJerome Forissier res = binh->op->read(binh->h, (void *)va, l); 327*5843bb75SJerome Forissier if (res) 328*5843bb75SJerome Forissier return res; 329*5843bb75SJerome Forissier binh->offs_bytes += l; 330*5843bb75SJerome Forissier } 331*5843bb75SJerome Forissier 332*5843bb75SJerome Forissier return TEE_SUCCESS; 333*5843bb75SJerome Forissier } 334*5843bb75SJerome Forissier 335*5843bb75SJerome Forissier static TEE_Result system_map_ta_binary(struct system_ctx *ctx, 336*5843bb75SJerome Forissier struct tee_ta_session *s, 337*5843bb75SJerome Forissier uint32_t param_types, 338*5843bb75SJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 339*5843bb75SJerome Forissier { 340*5843bb75SJerome Forissier const uint32_t accept_flags = PTA_SYSTEM_MAP_FLAG_SHAREABLE | 341*5843bb75SJerome Forissier PTA_SYSTEM_MAP_FLAG_WRITEABLE | 342*5843bb75SJerome Forissier PTA_SYSTEM_MAP_FLAG_EXECUTABLE; 343*5843bb75SJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 344*5843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_INPUT, 345*5843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_INOUT, 346*5843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_INPUT); 347*5843bb75SJerome Forissier struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); 348*5843bb75SJerome Forissier struct bin_handle *binh = NULL; 349*5843bb75SJerome Forissier TEE_Result res = TEE_SUCCESS; 350*5843bb75SJerome Forissier struct file_slice *fs = NULL; 351*5843bb75SJerome Forissier bool file_is_locked = false; 352*5843bb75SJerome Forissier struct mobj *mobj = NULL; 353*5843bb75SJerome Forissier uint32_t offs_bytes = 0; 354*5843bb75SJerome Forissier uint32_t offs_pages = 0; 355*5843bb75SJerome Forissier uint32_t num_bytes = 0; 356*5843bb75SJerome Forissier uint32_t pad_begin = 0; 357*5843bb75SJerome Forissier uint32_t pad_end = 0; 358*5843bb75SJerome Forissier size_t num_pages = 0; 359*5843bb75SJerome Forissier uint32_t flags = 0; 360*5843bb75SJerome Forissier uint32_t prot = 0; 361*5843bb75SJerome Forissier vaddr_t va = 0; 362*5843bb75SJerome Forissier 363*5843bb75SJerome Forissier if (exp_pt != param_types) 364*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 365*5843bb75SJerome Forissier 366*5843bb75SJerome Forissier binh = handle_lookup(&ctx->db, params[0].value.a); 367*5843bb75SJerome Forissier if (!binh) 368*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 369*5843bb75SJerome Forissier flags = params[0].value.b; 370*5843bb75SJerome Forissier offs_bytes = params[1].value.a; 371*5843bb75SJerome Forissier num_bytes = params[1].value.b; 372*5843bb75SJerome Forissier va = reg_pair_to_64(params[2].value.a, params[2].value.b); 373*5843bb75SJerome Forissier pad_begin = params[3].value.a; 374*5843bb75SJerome Forissier pad_end = params[3].value.b; 375*5843bb75SJerome Forissier 376*5843bb75SJerome Forissier if ((flags & accept_flags) != flags) 377*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 378*5843bb75SJerome Forissier 379*5843bb75SJerome Forissier if ((flags & PTA_SYSTEM_MAP_FLAG_SHAREABLE) && 380*5843bb75SJerome Forissier (flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE)) 381*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 382*5843bb75SJerome Forissier 383*5843bb75SJerome Forissier if ((flags & PTA_SYSTEM_MAP_FLAG_EXECUTABLE) && 384*5843bb75SJerome Forissier (flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE)) 385*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 386*5843bb75SJerome Forissier 387*5843bb75SJerome Forissier if (offs_bytes & SMALL_PAGE_MASK) 388*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 389*5843bb75SJerome Forissier 390*5843bb75SJerome Forissier prot = TEE_MATTR_UR | TEE_MATTR_PR; 391*5843bb75SJerome Forissier if (flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE) 392*5843bb75SJerome Forissier prot |= TEE_MATTR_UW | TEE_MATTR_PW; 393*5843bb75SJerome Forissier if (flags & PTA_SYSTEM_MAP_FLAG_EXECUTABLE) 394*5843bb75SJerome Forissier prot |= TEE_MATTR_UX; 395*5843bb75SJerome Forissier 396*5843bb75SJerome Forissier offs_pages = offs_bytes >> SMALL_PAGE_SHIFT; 397*5843bb75SJerome Forissier num_pages = ROUNDUP(num_bytes, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE; 398*5843bb75SJerome Forissier 399*5843bb75SJerome Forissier if (!file_trylock(binh->f)) { 400*5843bb75SJerome Forissier /* 401*5843bb75SJerome Forissier * Before we can block on the file lock we must make all 402*5843bb75SJerome Forissier * our page tables available for reclaiming in order to 403*5843bb75SJerome Forissier * avoid a dead-lock with the other thread (which already 404*5843bb75SJerome Forissier * is holding the file lock) mapping lots of memory below. 405*5843bb75SJerome Forissier */ 406*5843bb75SJerome Forissier tee_mmu_set_ctx(NULL); 407*5843bb75SJerome Forissier file_lock(binh->f); 408*5843bb75SJerome Forissier tee_mmu_set_ctx(s->ctx); 409*5843bb75SJerome Forissier } 410*5843bb75SJerome Forissier file_is_locked = true; 411*5843bb75SJerome Forissier fs = file_find_slice(binh->f, offs_pages); 412*5843bb75SJerome Forissier if (fs) { 413*5843bb75SJerome Forissier /* If there's registered slice it has to match */ 414*5843bb75SJerome Forissier if (fs->page_offset != offs_pages || 415*5843bb75SJerome Forissier num_pages > fs->fobj->num_pages) { 416*5843bb75SJerome Forissier res = TEE_ERROR_BAD_PARAMETERS; 417*5843bb75SJerome Forissier goto err; 418*5843bb75SJerome Forissier } 419*5843bb75SJerome Forissier 420*5843bb75SJerome Forissier /* If there's a slice we must be mapping shareable */ 421*5843bb75SJerome Forissier if (!(flags & PTA_SYSTEM_MAP_FLAG_SHAREABLE)) { 422*5843bb75SJerome Forissier res = TEE_ERROR_BAD_PARAMETERS; 423*5843bb75SJerome Forissier goto err; 424*5843bb75SJerome Forissier } 425*5843bb75SJerome Forissier 426*5843bb75SJerome Forissier mobj = mobj_with_fobj_alloc(fs->fobj, binh->f); 427*5843bb75SJerome Forissier if (!mobj) { 428*5843bb75SJerome Forissier res = TEE_ERROR_OUT_OF_MEMORY; 429*5843bb75SJerome Forissier goto err; 430*5843bb75SJerome Forissier } 431*5843bb75SJerome Forissier res = vm_map_pad(utc, &va, num_pages * SMALL_PAGE_SIZE, prot, 432*5843bb75SJerome Forissier VM_FLAG_READONLY | VM_FLAG_EXCLUSIVE_MOBJ, 433*5843bb75SJerome Forissier mobj, 0, pad_begin, pad_end); 434*5843bb75SJerome Forissier if (res) 435*5843bb75SJerome Forissier goto err; 436*5843bb75SJerome Forissier } else { 437*5843bb75SJerome Forissier struct fobj *f = fobj_ta_mem_alloc(num_pages); 438*5843bb75SJerome Forissier struct file *file = NULL; 439*5843bb75SJerome Forissier uint32_t vm_flags = VM_FLAG_EXCLUSIVE_MOBJ; 440*5843bb75SJerome Forissier 441*5843bb75SJerome Forissier if (!f) { 442*5843bb75SJerome Forissier res = TEE_ERROR_OUT_OF_MEMORY; 443*5843bb75SJerome Forissier goto err; 444*5843bb75SJerome Forissier } 445*5843bb75SJerome Forissier if (!(flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE)) { 446*5843bb75SJerome Forissier file = binh->f; 447*5843bb75SJerome Forissier vm_flags |= VM_FLAG_READONLY; 448*5843bb75SJerome Forissier } 449*5843bb75SJerome Forissier 450*5843bb75SJerome Forissier mobj = mobj_with_fobj_alloc(f, file); 451*5843bb75SJerome Forissier fobj_put(f); 452*5843bb75SJerome Forissier if (!mobj) { 453*5843bb75SJerome Forissier res = TEE_ERROR_OUT_OF_MEMORY; 454*5843bb75SJerome Forissier goto err; 455*5843bb75SJerome Forissier } 456*5843bb75SJerome Forissier res = vm_map_pad(utc, &va, num_pages * SMALL_PAGE_SIZE, 457*5843bb75SJerome Forissier TEE_MATTR_PRW, vm_flags, mobj, 0, 458*5843bb75SJerome Forissier pad_begin, pad_end); 459*5843bb75SJerome Forissier if (res) 460*5843bb75SJerome Forissier goto err; 461*5843bb75SJerome Forissier res = binh_copy_to(binh, va, offs_bytes, num_bytes); 462*5843bb75SJerome Forissier if (res) 463*5843bb75SJerome Forissier goto err_unmap_va; 464*5843bb75SJerome Forissier res = vm_set_prot(utc, va, num_pages * SMALL_PAGE_SIZE, prot); 465*5843bb75SJerome Forissier if (res) 466*5843bb75SJerome Forissier goto err_unmap_va; 467*5843bb75SJerome Forissier 468*5843bb75SJerome Forissier /* 469*5843bb75SJerome Forissier * The context currently is active set it again to update 470*5843bb75SJerome Forissier * the mapping. 471*5843bb75SJerome Forissier */ 472*5843bb75SJerome Forissier tee_mmu_set_ctx(s->ctx); 473*5843bb75SJerome Forissier 474*5843bb75SJerome Forissier if (!(flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE)) { 475*5843bb75SJerome Forissier res = file_add_slice(binh->f, f, offs_pages); 476*5843bb75SJerome Forissier if (res) 477*5843bb75SJerome Forissier goto err_unmap_va; 478*5843bb75SJerome Forissier } 479*5843bb75SJerome Forissier } 480*5843bb75SJerome Forissier 481*5843bb75SJerome Forissier file_unlock(binh->f); 482*5843bb75SJerome Forissier 483*5843bb75SJerome Forissier reg_pair_from_64(va, ¶ms[2].value.a, ¶ms[2].value.b); 484*5843bb75SJerome Forissier return TEE_SUCCESS; 485*5843bb75SJerome Forissier 486*5843bb75SJerome Forissier err_unmap_va: 487*5843bb75SJerome Forissier if (vm_unmap(utc, va, num_pages * SMALL_PAGE_SIZE)) 488*5843bb75SJerome Forissier panic(); 489*5843bb75SJerome Forissier 490*5843bb75SJerome Forissier /* 491*5843bb75SJerome Forissier * The context currently is active set it again to update 492*5843bb75SJerome Forissier * the mapping. 493*5843bb75SJerome Forissier */ 494*5843bb75SJerome Forissier tee_mmu_set_ctx(s->ctx); 495*5843bb75SJerome Forissier 496*5843bb75SJerome Forissier err: 497*5843bb75SJerome Forissier mobj_free(mobj); 498*5843bb75SJerome Forissier if (file_is_locked) 499*5843bb75SJerome Forissier file_unlock(binh->f); 500*5843bb75SJerome Forissier 501*5843bb75SJerome Forissier return res; 502*5843bb75SJerome Forissier } 503*5843bb75SJerome Forissier 504*5843bb75SJerome Forissier static TEE_Result system_copy_from_ta_binary(struct system_ctx *ctx, 505*5843bb75SJerome Forissier uint32_t param_types, 506*5843bb75SJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 507*5843bb75SJerome Forissier { 508*5843bb75SJerome Forissier struct bin_handle *binh = NULL; 509*5843bb75SJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 510*5843bb75SJerome Forissier TEE_PARAM_TYPE_MEMREF_OUTPUT, 511*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE, 512*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE); 513*5843bb75SJerome Forissier 514*5843bb75SJerome Forissier if (exp_pt != param_types) 515*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 516*5843bb75SJerome Forissier 517*5843bb75SJerome Forissier binh = handle_lookup(&ctx->db, params[0].value.a); 518*5843bb75SJerome Forissier if (!binh) 519*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 520*5843bb75SJerome Forissier 521*5843bb75SJerome Forissier return binh_copy_to(binh, (vaddr_t)params[1].memref.buffer, 522*5843bb75SJerome Forissier params[0].value.b, params[1].memref.size); 523*5843bb75SJerome Forissier } 524*5843bb75SJerome Forissier 525*5843bb75SJerome Forissier static TEE_Result system_set_prot(struct tee_ta_session *s, 526*5843bb75SJerome Forissier uint32_t param_types, 527*5843bb75SJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 528*5843bb75SJerome Forissier { 529*5843bb75SJerome Forissier const uint32_t accept_flags = PTA_SYSTEM_MAP_FLAG_WRITEABLE | 530*5843bb75SJerome Forissier PTA_SYSTEM_MAP_FLAG_EXECUTABLE; 531*5843bb75SJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 532*5843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_INPUT, 533*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE, 534*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE); 535*5843bb75SJerome Forissier struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); 536*5843bb75SJerome Forissier uint32_t prot = TEE_MATTR_UR | TEE_MATTR_PR; 537*5843bb75SJerome Forissier TEE_Result res = TEE_SUCCESS; 538*5843bb75SJerome Forissier uint32_t vm_flags = 0; 539*5843bb75SJerome Forissier uint32_t flags = 0; 540*5843bb75SJerome Forissier vaddr_t va = 0; 541*5843bb75SJerome Forissier size_t sz = 0; 542*5843bb75SJerome Forissier 543*5843bb75SJerome Forissier if (exp_pt != param_types) 544*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 545*5843bb75SJerome Forissier 546*5843bb75SJerome Forissier flags = params[0].value.b; 547*5843bb75SJerome Forissier 548*5843bb75SJerome Forissier if ((flags & accept_flags) != flags) 549*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 550*5843bb75SJerome Forissier if (flags & PTA_SYSTEM_MAP_FLAG_WRITEABLE) 551*5843bb75SJerome Forissier prot |= TEE_MATTR_UW | TEE_MATTR_PW; 552*5843bb75SJerome Forissier if (flags & PTA_SYSTEM_MAP_FLAG_EXECUTABLE) 553*5843bb75SJerome Forissier prot |= TEE_MATTR_UX; 554*5843bb75SJerome Forissier 555*5843bb75SJerome Forissier va = reg_pair_to_64(params[1].value.a, params[1].value.b), 556*5843bb75SJerome Forissier sz = ROUNDUP(params[0].value.a, SMALL_PAGE_SIZE); 557*5843bb75SJerome Forissier 558*5843bb75SJerome Forissier res = vm_get_flags(utc, va, sz, &vm_flags); 559*5843bb75SJerome Forissier if (res) 560*5843bb75SJerome Forissier return res; 561*5843bb75SJerome Forissier 562*5843bb75SJerome Forissier /* 563*5843bb75SJerome Forissier * If the segment is a mapping of a part of a file (vm_flags & 564*5843bb75SJerome Forissier * VM_FLAG_READONLY) it cannot be made writeable as all mapped 565*5843bb75SJerome Forissier * files are mapped read-only. 566*5843bb75SJerome Forissier */ 567*5843bb75SJerome Forissier if ((vm_flags & VM_FLAG_READONLY) && 568*5843bb75SJerome Forissier (prot & (TEE_MATTR_UW | TEE_MATTR_PW))) 569*5843bb75SJerome Forissier return TEE_ERROR_ACCESS_DENIED; 570*5843bb75SJerome Forissier 571*5843bb75SJerome Forissier return vm_set_prot(utc, va, sz, prot); 572*5843bb75SJerome Forissier } 573*5843bb75SJerome Forissier 574*5843bb75SJerome Forissier static TEE_Result system_remap(struct tee_ta_session *s, uint32_t param_types, 575*5843bb75SJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 576*5843bb75SJerome Forissier { 577*5843bb75SJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 578*5843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_INPUT, 579*5843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_INOUT, 580*5843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_INPUT); 581*5843bb75SJerome Forissier struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); 582*5843bb75SJerome Forissier TEE_Result res = TEE_SUCCESS; 583*5843bb75SJerome Forissier uint32_t num_bytes = 0; 584*5843bb75SJerome Forissier uint32_t pad_begin = 0; 585*5843bb75SJerome Forissier uint32_t pad_end = 0; 586*5843bb75SJerome Forissier vaddr_t old_va = 0; 587*5843bb75SJerome Forissier vaddr_t new_va = 0; 588*5843bb75SJerome Forissier 589*5843bb75SJerome Forissier if (exp_pt != param_types) 590*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 591*5843bb75SJerome Forissier 592*5843bb75SJerome Forissier num_bytes = params[0].value.a; 593*5843bb75SJerome Forissier old_va = reg_pair_to_64(params[1].value.a, params[1].value.b); 594*5843bb75SJerome Forissier new_va = reg_pair_to_64(params[2].value.a, params[2].value.b); 595*5843bb75SJerome Forissier pad_begin = params[3].value.a; 596*5843bb75SJerome Forissier pad_end = params[3].value.b; 597*5843bb75SJerome Forissier 598*5843bb75SJerome Forissier res = vm_remap(utc, &new_va, old_va, num_bytes, pad_begin, pad_end); 599*5843bb75SJerome Forissier if (!res) 600*5843bb75SJerome Forissier reg_pair_from_64(new_va, ¶ms[2].value.a, 601*5843bb75SJerome Forissier ¶ms[2].value.b); 602*5843bb75SJerome Forissier 603*5843bb75SJerome Forissier return res; 604*5843bb75SJerome Forissier } 605*5843bb75SJerome Forissier 606*5843bb75SJerome Forissier /* ldelf has the same architecture/register width as the kernel */ 607*5843bb75SJerome Forissier #ifdef ARM32 608*5843bb75SJerome Forissier static const bool is_arm32 = true; 609*5843bb75SJerome Forissier #else 610*5843bb75SJerome Forissier static const bool is_arm32; 611*5843bb75SJerome Forissier #endif 612*5843bb75SJerome Forissier 613*5843bb75SJerome Forissier static TEE_Result call_ldelf_dlopen(struct user_ta_ctx *utc, TEE_UUID *uuid, 614*5843bb75SJerome Forissier uint32_t flags) 615*5843bb75SJerome Forissier { 616*5843bb75SJerome Forissier uaddr_t usr_stack = utc->ldelf_stack_ptr; 617*5843bb75SJerome Forissier TEE_Result res = TEE_ERROR_GENERIC; 618*5843bb75SJerome Forissier struct dl_entry_arg *arg = NULL; 619*5843bb75SJerome Forissier uint32_t panic_code = 0; 620*5843bb75SJerome Forissier uint32_t panicked = 0; 621*5843bb75SJerome Forissier 622*5843bb75SJerome Forissier assert(uuid); 623*5843bb75SJerome Forissier 624*5843bb75SJerome Forissier usr_stack -= ROUNDUP(sizeof(*arg), STACK_ALIGNMENT); 625*5843bb75SJerome Forissier arg = (struct dl_entry_arg *)usr_stack; 626*5843bb75SJerome Forissier 627*5843bb75SJerome Forissier res = tee_mmu_check_access_rights(utc, TEE_MEMORY_ACCESS_READ | 628*5843bb75SJerome Forissier TEE_MEMORY_ACCESS_WRITE | 629*5843bb75SJerome Forissier TEE_MEMORY_ACCESS_ANY_OWNER, 630*5843bb75SJerome Forissier (uaddr_t)arg, sizeof(*arg)); 631*5843bb75SJerome Forissier if (res) { 632*5843bb75SJerome Forissier EMSG("ldelf stack is inaccessible!"); 633*5843bb75SJerome Forissier return res; 634*5843bb75SJerome Forissier } 635*5843bb75SJerome Forissier 636*5843bb75SJerome Forissier memset(arg, 0, sizeof(*arg)); 637*5843bb75SJerome Forissier arg->cmd = LDELF_DL_ENTRY_DLOPEN; 638*5843bb75SJerome Forissier arg->dlopen.uuid = *uuid; 639*5843bb75SJerome Forissier arg->dlopen.flags = flags; 640*5843bb75SJerome Forissier 641*5843bb75SJerome Forissier res = thread_enter_user_mode((vaddr_t)arg, 0, 0, 0, 642*5843bb75SJerome Forissier usr_stack, utc->dl_entry_func, 643*5843bb75SJerome Forissier is_arm32, &panicked, &panic_code); 644*5843bb75SJerome Forissier if (panicked) { 645*5843bb75SJerome Forissier EMSG("ldelf dl_entry function panicked"); 646*5843bb75SJerome Forissier abort_print_current_ta(); 647*5843bb75SJerome Forissier res = TEE_ERROR_TARGET_DEAD; 648*5843bb75SJerome Forissier } 649*5843bb75SJerome Forissier if (!res) 650*5843bb75SJerome Forissier res = arg->ret; 651*5843bb75SJerome Forissier 652*5843bb75SJerome Forissier return res; 653*5843bb75SJerome Forissier } 654*5843bb75SJerome Forissier 655*5843bb75SJerome Forissier static TEE_Result call_ldelf_dlsym(struct user_ta_ctx *utc, TEE_UUID *uuid, 656*5843bb75SJerome Forissier const char *sym, size_t maxlen, vaddr_t *val) 657*5843bb75SJerome Forissier { 658*5843bb75SJerome Forissier uaddr_t usr_stack = utc->ldelf_stack_ptr; 659*5843bb75SJerome Forissier TEE_Result res = TEE_ERROR_GENERIC; 660*5843bb75SJerome Forissier struct dl_entry_arg *arg = NULL; 661*5843bb75SJerome Forissier uint32_t panic_code = 0; 662*5843bb75SJerome Forissier uint32_t panicked = 0; 663*5843bb75SJerome Forissier size_t len = strnlen(sym, maxlen); 664*5843bb75SJerome Forissier 665*5843bb75SJerome Forissier if (len == maxlen) 666*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 667*5843bb75SJerome Forissier 668*5843bb75SJerome Forissier usr_stack -= ROUNDUP(sizeof(*arg) + len + 1, STACK_ALIGNMENT); 669*5843bb75SJerome Forissier arg = (struct dl_entry_arg *)usr_stack; 670*5843bb75SJerome Forissier 671*5843bb75SJerome Forissier res = tee_mmu_check_access_rights(utc, TEE_MEMORY_ACCESS_READ | 672*5843bb75SJerome Forissier TEE_MEMORY_ACCESS_WRITE | 673*5843bb75SJerome Forissier TEE_MEMORY_ACCESS_ANY_OWNER, 674*5843bb75SJerome Forissier (uaddr_t)arg, 675*5843bb75SJerome Forissier sizeof(*arg) + len + 1); 676*5843bb75SJerome Forissier if (res) { 677*5843bb75SJerome Forissier EMSG("ldelf stack is inaccessible!"); 678*5843bb75SJerome Forissier return res; 679*5843bb75SJerome Forissier } 680*5843bb75SJerome Forissier 681*5843bb75SJerome Forissier memset(arg, 0, sizeof(*arg)); 682*5843bb75SJerome Forissier arg->cmd = LDELF_DL_ENTRY_DLSYM; 683*5843bb75SJerome Forissier arg->dlsym.uuid = *uuid; 684*5843bb75SJerome Forissier memcpy(arg->dlsym.symbol, sym, len); 685*5843bb75SJerome Forissier arg->dlsym.symbol[len + 1] = '\0'; 686*5843bb75SJerome Forissier 687*5843bb75SJerome Forissier res = thread_enter_user_mode((vaddr_t)arg, 0, 0, 0, 688*5843bb75SJerome Forissier usr_stack, utc->dl_entry_func, 689*5843bb75SJerome Forissier is_arm32, &panicked, &panic_code); 690*5843bb75SJerome Forissier if (panicked) { 691*5843bb75SJerome Forissier EMSG("ldelf dl_entry function panicked"); 692*5843bb75SJerome Forissier abort_print_current_ta(); 693*5843bb75SJerome Forissier res = TEE_ERROR_TARGET_DEAD; 694*5843bb75SJerome Forissier } 695*5843bb75SJerome Forissier if (!res) { 696*5843bb75SJerome Forissier res = arg->ret; 697*5843bb75SJerome Forissier if (!res) 698*5843bb75SJerome Forissier *val = arg->dlsym.val; 699*5843bb75SJerome Forissier } 700*5843bb75SJerome Forissier 701*5843bb75SJerome Forissier return res; 702*5843bb75SJerome Forissier } 703*5843bb75SJerome Forissier 704*5843bb75SJerome Forissier static TEE_Result system_dlopen(struct tee_ta_session *cs, uint32_t param_types, 705*5843bb75SJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 706*5843bb75SJerome Forissier { 707*5843bb75SJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 708*5843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_INPUT, 709*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE, 710*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE); 711*5843bb75SJerome Forissier TEE_Result res = TEE_ERROR_GENERIC; 712*5843bb75SJerome Forissier struct tee_ta_session *s = NULL; 713*5843bb75SJerome Forissier struct user_ta_ctx *utc = NULL; 714*5843bb75SJerome Forissier TEE_UUID *uuid = NULL; 715*5843bb75SJerome Forissier uint32_t flags = 0; 716*5843bb75SJerome Forissier 717*5843bb75SJerome Forissier if (exp_pt != param_types) 718*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 719*5843bb75SJerome Forissier 720*5843bb75SJerome Forissier uuid = params[0].memref.buffer; 721*5843bb75SJerome Forissier if (!uuid || params[0].memref.size != sizeof(*uuid)) 722*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 723*5843bb75SJerome Forissier 724*5843bb75SJerome Forissier flags = params[1].value.a; 725*5843bb75SJerome Forissier 726*5843bb75SJerome Forissier utc = to_user_ta_ctx(cs->ctx); 727*5843bb75SJerome Forissier 728*5843bb75SJerome Forissier s = tee_ta_pop_current_session(); 729*5843bb75SJerome Forissier res = call_ldelf_dlopen(utc, uuid, flags); 730*5843bb75SJerome Forissier tee_ta_push_current_session(s); 731*5843bb75SJerome Forissier 732*5843bb75SJerome Forissier return res; 733*5843bb75SJerome Forissier } 734*5843bb75SJerome Forissier 735*5843bb75SJerome Forissier static TEE_Result system_dlsym(struct tee_ta_session *cs, uint32_t param_types, 736*5843bb75SJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 737*5843bb75SJerome Forissier { 738*5843bb75SJerome Forissier uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 739*5843bb75SJerome Forissier TEE_PARAM_TYPE_MEMREF_INPUT, 740*5843bb75SJerome Forissier TEE_PARAM_TYPE_VALUE_OUTPUT, 741*5843bb75SJerome Forissier TEE_PARAM_TYPE_NONE); 742*5843bb75SJerome Forissier TEE_Result res = TEE_ERROR_GENERIC; 743*5843bb75SJerome Forissier struct tee_ta_session *s = NULL; 744*5843bb75SJerome Forissier struct user_ta_ctx *utc = NULL; 745*5843bb75SJerome Forissier const char *sym = NULL; 746*5843bb75SJerome Forissier TEE_UUID *uuid = NULL; 747*5843bb75SJerome Forissier size_t maxlen = 0; 748*5843bb75SJerome Forissier vaddr_t va = 0; 749*5843bb75SJerome Forissier 750*5843bb75SJerome Forissier if (exp_pt != param_types) 751*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 752*5843bb75SJerome Forissier 753*5843bb75SJerome Forissier uuid = params[0].memref.buffer; 754*5843bb75SJerome Forissier if (uuid && params[0].memref.size != sizeof(*uuid)) 755*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 756*5843bb75SJerome Forissier 757*5843bb75SJerome Forissier sym = params[1].memref.buffer; 758*5843bb75SJerome Forissier if (!sym) 759*5843bb75SJerome Forissier return TEE_ERROR_BAD_PARAMETERS; 760*5843bb75SJerome Forissier maxlen = params[1].memref.size; 761*5843bb75SJerome Forissier 762*5843bb75SJerome Forissier utc = to_user_ta_ctx(cs->ctx); 763*5843bb75SJerome Forissier 764*5843bb75SJerome Forissier s = tee_ta_pop_current_session(); 765*5843bb75SJerome Forissier res = call_ldelf_dlsym(utc, uuid, sym, maxlen, &va); 766*5843bb75SJerome Forissier tee_ta_push_current_session(s); 767*5843bb75SJerome Forissier 768*5843bb75SJerome Forissier if (!res) 769*5843bb75SJerome Forissier reg_pair_from_64(va, ¶ms[2].value.a, ¶ms[2].value.b); 770*5843bb75SJerome Forissier 771*5843bb75SJerome Forissier return res; 772*5843bb75SJerome Forissier } 773*5843bb75SJerome Forissier 774*5843bb75SJerome Forissier static TEE_Result open_session(uint32_t param_types __unused, 775*5843bb75SJerome Forissier TEE_Param params[TEE_NUM_PARAMS] __unused, 776*5843bb75SJerome Forissier void **sess_ctx) 777*5843bb75SJerome Forissier { 778*5843bb75SJerome Forissier struct tee_ta_session *s = NULL; 779*5843bb75SJerome Forissier struct system_ctx *ctx = NULL; 780*5843bb75SJerome Forissier 781*5843bb75SJerome Forissier /* Check that we're called from a user TA */ 782*5843bb75SJerome Forissier s = tee_ta_get_calling_session(); 783*5843bb75SJerome Forissier if (!s) 784*5843bb75SJerome Forissier return TEE_ERROR_ACCESS_DENIED; 785*5843bb75SJerome Forissier if (!is_user_ta_ctx(s->ctx)) 786*5843bb75SJerome Forissier return TEE_ERROR_ACCESS_DENIED; 787*5843bb75SJerome Forissier 788*5843bb75SJerome Forissier ctx = calloc(1, sizeof(*ctx)); 789*5843bb75SJerome Forissier if (!ctx) 790*5843bb75SJerome Forissier return TEE_ERROR_OUT_OF_MEMORY; 791*5843bb75SJerome Forissier 792*5843bb75SJerome Forissier *sess_ctx = ctx; 793*5843bb75SJerome Forissier 794*5843bb75SJerome Forissier return TEE_SUCCESS; 795*5843bb75SJerome Forissier } 796*5843bb75SJerome Forissier 797*5843bb75SJerome Forissier static void close_session(void *sess_ctx) 798*5843bb75SJerome Forissier { 799*5843bb75SJerome Forissier struct system_ctx *ctx = sess_ctx; 800*5843bb75SJerome Forissier 801*5843bb75SJerome Forissier handle_db_destroy(&ctx->db, ta_bin_close); 802*5843bb75SJerome Forissier free(ctx); 803*5843bb75SJerome Forissier } 804*5843bb75SJerome Forissier 805*5843bb75SJerome Forissier static TEE_Result invoke_command(void *sess_ctx, uint32_t cmd_id, 806*5843bb75SJerome Forissier uint32_t param_types, 807*5843bb75SJerome Forissier TEE_Param params[TEE_NUM_PARAMS]) 808*5843bb75SJerome Forissier { 809*5843bb75SJerome Forissier struct tee_ta_session *s = tee_ta_get_calling_session(); 810*5843bb75SJerome Forissier 811*5843bb75SJerome Forissier switch (cmd_id) { 812*5843bb75SJerome Forissier case PTA_SYSTEM_ADD_RNG_ENTROPY: 813*5843bb75SJerome Forissier return system_rng_reseed(s, param_types, params); 814*5843bb75SJerome Forissier case PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY: 815*5843bb75SJerome Forissier return system_derive_ta_unique_key(s, param_types, params); 816*5843bb75SJerome Forissier case PTA_SYSTEM_MAP_ZI: 817*5843bb75SJerome Forissier return system_map_zi(s, param_types, params); 818*5843bb75SJerome Forissier case PTA_SYSTEM_UNMAP: 819*5843bb75SJerome Forissier return system_unmap(s, param_types, params); 820*5843bb75SJerome Forissier case PTA_SYSTEM_OPEN_TA_BINARY: 821*5843bb75SJerome Forissier return system_open_ta_binary(sess_ctx, param_types, params); 822*5843bb75SJerome Forissier case PTA_SYSTEM_CLOSE_TA_BINARY: 823*5843bb75SJerome Forissier return system_close_ta_binary(sess_ctx, param_types, params); 824*5843bb75SJerome Forissier case PTA_SYSTEM_MAP_TA_BINARY: 825*5843bb75SJerome Forissier return system_map_ta_binary(sess_ctx, s, param_types, params); 826*5843bb75SJerome Forissier case PTA_SYSTEM_COPY_FROM_TA_BINARY: 827*5843bb75SJerome Forissier return system_copy_from_ta_binary(sess_ctx, param_types, 828*5843bb75SJerome Forissier params); 829*5843bb75SJerome Forissier case PTA_SYSTEM_SET_PROT: 830*5843bb75SJerome Forissier return system_set_prot(s, param_types, params); 831*5843bb75SJerome Forissier case PTA_SYSTEM_REMAP: 832*5843bb75SJerome Forissier return system_remap(s, param_types, params); 833*5843bb75SJerome Forissier case PTA_SYSTEM_DLOPEN: 834*5843bb75SJerome Forissier return system_dlopen(s, param_types, params); 835*5843bb75SJerome Forissier case PTA_SYSTEM_DLSYM: 836*5843bb75SJerome Forissier return system_dlsym(s, param_types, params); 837*5843bb75SJerome Forissier default: 838*5843bb75SJerome Forissier break; 839*5843bb75SJerome Forissier } 840*5843bb75SJerome Forissier 841*5843bb75SJerome Forissier return TEE_ERROR_NOT_IMPLEMENTED; 842*5843bb75SJerome Forissier } 843*5843bb75SJerome Forissier 844*5843bb75SJerome Forissier pseudo_ta_register(.uuid = PTA_SYSTEM_UUID, .name = "system.pta", 845*5843bb75SJerome Forissier .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT, 846*5843bb75SJerome Forissier .open_session_entry_point = open_session, 847*5843bb75SJerome Forissier .close_session_entry_point = close_session, 848*5843bb75SJerome Forissier .invoke_command_entry_point = invoke_command); 849