TEE_Result tee_svc_invoke_ta_command(TEE_TASessionHandle ta_sess, uint32_t cancel_req_to, uint32_t cmd_id, uint32_t param_types, TEE_Param params[4], uint32_t *ret_orig) { TEE_Result res; uint32_t ret_o = TEE_ORIGIN_TEE; struct tee_ta_param param = { 0 }; TEE_Identity clnt_id; struct tee_ta_session *sess; struct tee_ta_session *called_sess = (struct tee_ta_session *)ta_sess; tee_mm_entry_t *mm_param = NULL; tee_paddr_t tmp_buf_pa[TEE_NUM_PARAMS]; res = tee_ta_get_current_session(&sess); if (res != TEE_SUCCESS) return res; res = tee_ta_verify_session_pointer(called_sess, &sess->ctx->open_sessions); if (res != TEE_SUCCESS) return res; res = tee_svc_copy_param(sess, called_sess, param_types, params, ¶m, tmp_buf_pa, &mm_param); if (res != TEE_SUCCESS) goto function_exit; res = tee_ta_invoke_command(&ret_o, called_sess, &clnt_id, cancel_req_to, cmd_id, ¶m); if (res != TEE_SUCCESS) goto function_exit; res = tee_svc_update_out_param(sess, called_sess, ¶m, tmp_buf_pa, params); if (res != TEE_SUCCESS) goto function_exit; function_exit: tee_ta_set_current_session(sess); called_sess->calling_sess = NULL; /* clear eventual borrowed mapping */ if (mm_param != NULL) { TEE_Result res2; void *va = 0; res2 = tee_mmu_kmap_pa2va((void *)tee_mm_get_smem(mm_param), &va); if (res2 == TEE_SUCCESS) tee_mmu_kunmap(va, tee_mm_get_bytes(mm_param)); } tee_mm_free(mm_param); if (ret_orig) tee_svc_copy_to_user(sess, ret_orig, &ret_o, sizeof(ret_o)); return res; }
static void buf_ta_close(struct user_ta_store_handle *h) { struct buf_ree_fs_ta_handle *handle = (struct buf_ree_fs_ta_handle *)h; if (!handle) return; tee_mm_free(handle->mm); free(handle); }
static TEE_Result buf_ta_open(const TEE_UUID *uuid, struct user_ta_store_handle **h) { struct buf_ree_fs_ta_handle *handle = NULL; TEE_Result res = TEE_SUCCESS; handle = calloc(1, sizeof(*handle)); if (!handle) return TEE_ERROR_OUT_OF_MEMORY; res = ree_fs_ta_open(uuid, &handle->h); if (res) goto err2; res = ree_fs_ta_get_size(handle->h, &handle->ta_size); if (res) goto err; res = ree_fs_ta_get_tag(handle->h, NULL, &handle->tag_len); if (res != TEE_ERROR_SHORT_BUFFER) { res = TEE_ERROR_GENERIC; goto err; } handle->tag = malloc(handle->tag_len); if (!handle->tag) { res = TEE_ERROR_OUT_OF_MEMORY; goto err; } res = ree_fs_ta_get_tag(handle->h, handle->tag, &handle->tag_len); if (res) goto err; handle->mm = tee_mm_alloc(&tee_mm_sec_ddr, handle->ta_size); if (!handle->mm) { res = TEE_ERROR_OUT_OF_MEMORY; goto err; } handle->buf = phys_to_virt(tee_mm_get_smem(handle->mm), MEM_AREA_TA_RAM); if (!handle->buf) { res = TEE_ERROR_OUT_OF_MEMORY; goto err; } res = ree_fs_ta_read(handle->h, handle->buf, handle->ta_size); if (res) goto err; *h = (struct user_ta_store_handle *)handle; err: ree_fs_ta_close(handle->h); err2: if (res) { tee_mm_free(handle->mm); free(handle->tag); free(handle); } return res; }
void tee_mmu_kunmap(void *va, size_t len) { size_t n; tee_mm_entry_t *mm; struct core_mmu_table_info tbl_info; size_t offs; if (!core_mmu_find_table(TEE_MMU_KMAP_START_VA, UINT_MAX, &tbl_info)) panic(); mm = tee_mm_find(&tee_mmu_virt_kmap, (vaddr_t)va); if (mm == NULL || len > tee_mm_get_bytes(mm)) return; /* Invalid range, not much to do */ /* Clear the mmu entries */ offs = (tee_mm_get_smem(mm) - tbl_info.va_base) >> tbl_info.shift; for (n = 0; n < tee_mm_get_size(mm); n++) core_mmu_set_entry(&tbl_info, n + offs, 0, 0); core_tlb_maintenance(TLBINV_UNIFIEDTLB, 0); tee_mm_free(mm); }
/* Called when a TA calls an OpenSession on another TA */ TEE_Result tee_svc_open_ta_session(const TEE_UUID *dest, uint32_t cancel_req_to, uint32_t param_types, TEE_Param params[4], TEE_TASessionHandle *ta_sess, uint32_t *ret_orig) { TEE_Result res; uint32_t ret_o = TEE_ORIGIN_TEE; struct tee_ta_session *s = NULL; struct tee_ta_session *sess; tee_mm_entry_t *mm_param = NULL; TEE_UUID *uuid = malloc(sizeof(TEE_UUID)); struct tee_ta_param *param = malloc(sizeof(struct tee_ta_param)); TEE_Identity *clnt_id = malloc(sizeof(TEE_Identity)); tee_paddr_t tmp_buf_pa[TEE_NUM_PARAMS]; if (uuid == NULL || param == NULL || clnt_id == NULL) { res = TEE_ERROR_OUT_OF_MEMORY; goto out_free_only; } memset(param, 0, sizeof(struct tee_ta_param)); res = tee_ta_get_current_session(&sess); if (res != TEE_SUCCESS) goto out_free_only; res = tee_svc_copy_from_user(sess, uuid, dest, sizeof(TEE_UUID)); if (res != TEE_SUCCESS) goto function_exit; clnt_id->login = TEE_LOGIN_TRUSTED_APP; memcpy(&clnt_id->uuid, &sess->ctx->head->uuid, sizeof(TEE_UUID)); res = tee_svc_copy_param(sess, NULL, param_types, params, param, tmp_buf_pa, &mm_param); if (res != TEE_SUCCESS) goto function_exit; /* * Find session of a multi session TA or a static TA * In such a case, there is no need to ask the supplicant for the TA * code */ res = tee_ta_open_session(&ret_o, &s, &sess->ctx->open_sessions, uuid, NULL, clnt_id, cancel_req_to, param); if (ret_o != TEE_ORIGIN_TEE || res != TEE_ERROR_ITEM_NOT_FOUND) goto function_exit; if (ret_o == TEE_ORIGIN_TEE && res == TEE_ERROR_ITEM_NOT_FOUND) { kta_signed_header_t *ta = NULL; struct tee_ta_nwumap lp; tee_mmu_set_ctx(NULL); /* Load TA */ res = tee_ta_rpc_load(uuid, &ta, &lp, &ret_o); if (res != TEE_SUCCESS) { tee_mmu_set_ctx(sess->ctx); goto function_exit; } res = tee_ta_open_session(&ret_o, &s, &sess->ctx->open_sessions, uuid, ta, clnt_id, cancel_req_to, param); tee_mmu_set_ctx(sess->ctx); if (res != TEE_SUCCESS) goto function_exit; s->ctx->nwumap = lp; } res = tee_svc_update_out_param(sess, NULL, param, tmp_buf_pa, params); if (res != TEE_SUCCESS) goto function_exit; function_exit: tee_ta_set_current_session(sess); if (mm_param != NULL) { TEE_Result res2; void *va = 0; res2 = tee_mmu_kmap_pa2va((void *)tee_mm_get_smem(mm_param), &va); if (res2 == TEE_SUCCESS) tee_mmu_kunmap(va, tee_mm_get_bytes(mm_param)); } tee_mm_free(mm_param); tee_svc_copy_to_user(sess, ta_sess, &s, sizeof(s)); tee_svc_copy_to_user(sess, ret_orig, &ret_o, sizeof(ret_o)); out_free_only: free(param); free(uuid); free(clnt_id); return res; }