diff options
author | Ilias Apalodimas <ilias.apalodimas@linaro.org> | 2020-03-31 22:00:05 +0300 |
---|---|---|
committer | Ilias Apalodimas <ilias.apalodimas@linaro.org> | 2020-04-06 23:57:31 +0300 |
commit | 27a22e38e2dd70005b548d90386a818319581133 (patch) | |
tree | 0c40a2c5c87477c3e2592a3f53b515702819ce1e | |
parent | 5e3ef32d241e4757977862cf477ac52ccf102a9f (diff) |
Write from StMM workingnew
Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
-rw-r--r-- | core/arch/arm/include/kernel/secure_partition.h | 2 | ||||
-rw-r--r-- | core/arch/arm/kernel/secure_partition.c | 30 | ||||
-rw-r--r-- | core/include/tee/tee_svc_storage.h | 11 | ||||
-rw-r--r-- | core/tee/tee_svc_storage.c | 185 |
4 files changed, 226 insertions, 2 deletions
diff --git a/core/arch/arm/include/kernel/secure_partition.h b/core/arch/arm/include/kernel/secure_partition.h index c00e3588..4990e677 100644 --- a/core/arch/arm/include/kernel/secure_partition.h +++ b/core/arch/arm/include/kernel/secure_partition.h @@ -37,6 +37,8 @@ #define SP_SVC_EVENT_COMPLETE_64 0xC4000061 #define SP_SVC_MEMORY_ATTRIBUTES_GET_64 0xC4000064 #define SP_SVC_MEMORY_ATTRIBUTES_SET_64 0xC4000065 +#define SP_SVC_RPMB_READ 0xC4000066 +#define SP_SVC_RPMB_WRITE 0xC4000067 /* Param header types */ #define SP_PARAM_EP UINT8_C(0x01) diff --git a/core/arch/arm/kernel/secure_partition.c b/core/arch/arm/kernel/secure_partition.c index d21a4a56..a01a6723 100644 --- a/core/arch/arm/kernel/secure_partition.c +++ b/core/arch/arm/kernel/secure_partition.c @@ -14,12 +14,15 @@ #include <zlib.h> #include "thread_private.h" +#include <tee/tee_svc_storage.h> +#include <crypto/crypto.h> +#include <tee_api_defines_extensions.h> static const TEE_UUID stmm_uuid = PTA_STMM_UUID; static const unsigned int stmm_entry; -static const unsigned int stmm_stack_size = 4 * SMALL_PAGE_SIZE; -static const unsigned int stmm_heap_size = 398 * SMALL_PAGE_SIZE; +static const unsigned int stmm_stack_size = 128 * SMALL_PAGE_SIZE; +static const unsigned int stmm_heap_size = 1024 * SMALL_PAGE_SIZE; static const unsigned int stmm_sec_buf_size = SMALL_PAGE_SIZE; static const unsigned int stmm_ns_comm_buf_size = SMALL_PAGE_SIZE; @@ -519,6 +522,13 @@ static void set_svc_retval(struct thread_svc_regs *regs, uint64_t ret_val) static bool stmm_handle_svc(struct thread_svc_regs *regs) { + uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_SHARE_READ | + TEE_DATA_FLAG_SHARE_WRITE | + TEE_DATA_FLAG_OVERWRITE; + TEE_Result res = TEE_SUCCESS; + switch (regs->x0) { case SP_SVC_VERSION: set_svc_retval(regs, SP_VERSION); @@ -534,6 +544,22 @@ static bool stmm_handle_svc(struct thread_svc_regs *regs) sp_svc_set_mem_attr(regs->x1, regs->x2, regs->x3)); return true; + case SP_SVC_RPMB_READ: + res = sec_storage_obj_read(TEE_STORAGE_PRIVATE_RPMB, + (void*)regs->x1, regs->x2, + (void*)regs->x3, regs->x4, + flags); + set_svc_retval(regs, res); + + return true; + case SP_SVC_RPMB_WRITE: + res = sec_storage_obj_write(TEE_STORAGE_PRIVATE_RPMB, + (void*)regs->x1, regs->x2, + (void*)regs->x3, regs->x4, regs->x5, + flags); + set_svc_retval(regs, res); + + return true; default: EMSG("Undefined syscall 0x%"PRIx32, (uint32_t)regs->x0); return return_helper(true, 0xbadfbadf, regs); diff --git a/core/include/tee/tee_svc_storage.h b/core/include/tee/tee_svc_storage.h index 33d94413..688c7022 100644 --- a/core/include/tee/tee_svc_storage.h +++ b/core/include/tee/tee_svc_storage.h @@ -18,6 +18,17 @@ const struct tee_file_operations *tee_svc_storage_file_ops(uint32_t storage_id); /* + * Combined read/write ops from secure partition running StnadAloneMM + */ +TEE_Result sec_storage_obj_read(unsigned long storage_id, void *object_id, + size_t object_id_len, void *data, size_t len, + unsigned long flags); + +TEE_Result sec_storage_obj_write(unsigned long storage_id, void *object_id, + size_t object_id_len, void *data, size_t len, + size_t offset, unsigned long flags); + +/* * Persistant Object Functions */ TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id, diff --git a/core/tee/tee_svc_storage.c b/core/tee/tee_svc_storage.c index 5602504a..fa9d28f3 100644 --- a/core/tee/tee_svc_storage.c +++ b/core/tee/tee_svc_storage.c @@ -6,6 +6,7 @@ #include <kernel/mutex.h> #include <kernel/tee_misc.h> #include <kernel/tee_ta_manager.h> +#include <kernel/secure_partition.h> #include <mm/tee_mmu.h> #include <string.h> #include <tee_api_defines_extensions.h> @@ -395,6 +396,190 @@ exit: return res; } +/* + * Combined read from secure partition, this will open, read and + * close the fh + */ +TEE_Result sec_storage_obj_read(unsigned long storage_id, void *object_id, + size_t object_id_len, void *data, size_t len, + unsigned long flags) + +{ + const struct tee_file_operations *fops = + tee_svc_storage_file_ops(storage_id); + struct tee_ta_session *sess = NULL; + TEE_Result res = TEE_ERROR_BAD_STATE; + struct tee_pobj *po = NULL; + size_t pos_tmp = 0; + /* + * We don't need to add an object here on the list we'll create the file + * and exit + */ + struct tee_obj o; + size_t bytes = 0; + + memset(&o, 0, sizeof(o)); + if (!fops) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (object_id_len > TEE_OBJECT_ID_MAX_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, + object_id_len, flags, false, fops, &po); + if (res != TEE_SUCCESS) + return res; + + o.info.handleFlags = + TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED | + TEE_DATA_FLAG_ACCESS_READ; + o.flags = flags; + o.pobj = po; + + res = tee_svc_storage_read_head(&o); + if (res != TEE_SUCCESS) { + if (res == TEE_ERROR_CORRUPT_OBJECT) { + EMSG("Object corrupt"); + goto err; + } + goto err; + } + + /* Always reading the full file */ + if (ADD_OVERFLOW(0, len, &pos_tmp)) { + res = TEE_ERROR_OVERFLOW; + goto err; + } + + /* + * FIXME @Jens, we don't need that since we always control the + * heap/stack of stmm right? + */ +#if 0 + res = tee_mmu_check_access_rights(&spc->uctx, + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)data, len); + if (res != TEE_SUCCESS) + goto err; +#endif + + /* + * Not needed but keep the check in case we want to read at an offset + * and change '0' with the offset value + */ + if (ADD_OVERFLOW(o.ds_pos, 0, &pos_tmp)) { + res = TEE_ERROR_OVERFLOW; + goto err; + } + + bytes = len; + res = o.pobj->fops->read(o.fh, pos_tmp, data, &bytes); + if (res != TEE_SUCCESS) { + if (res == TEE_ERROR_CORRUPT_OBJECT) { + EMSG("Object corrupt"); + o.pobj->fops->remove(o.pobj); + } + goto err; + } + o.pobj->fops->close(&o.fh); + + return res; + +err: + o.pobj->fops->close(&o.fh); + if (po) + tee_pobj_release(po); + if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) + res = TEE_ERROR_CORRUPT_OBJECT; + + return res; +} + +/* + * Combined write from secure partition, this will create/open, write and + * close the fh + */ +TEE_Result sec_storage_obj_write(unsigned long storage_id, void *object_id, + size_t object_id_len, void *data, size_t len, + size_t offset, unsigned long flags) + +{ + const struct tee_file_operations *fops = + tee_svc_storage_file_ops(storage_id); + struct tee_ta_session *sess = NULL; + TEE_Result res = TEE_SUCCESS; + struct tee_pobj *po = NULL; + size_t pos_tmp = 0; + /* + * We don't need to add an object here on the list we'll create the file + * and exit + */ + struct tee_obj o; + + memset(&o, 0, sizeof(o)); + if (!fops) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (object_id_len > TEE_OBJECT_ID_MAX_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_ta_get_current_session(&sess); + if (res != TEE_SUCCESS) + return res; + + res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, + object_id_len, flags, false, fops, &po); + if (res != TEE_SUCCESS) + return res; + + o.info.handleFlags = + TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED | + TEE_DATA_FLAG_ACCESS_WRITE; + o.flags = flags; + o.pobj = po; + + res = tee_svc_storage_init_file(&o, NULL, NULL, 0); + if (res != TEE_SUCCESS) + return res; + /* + * Guard o->info.dataPosition += bytes below from overflowing. + * The driver is expected to send the overall offset in the file for + * each write, so we can ignore dataPosition + */ + if (ADD_OVERFLOW(offset, len, &pos_tmp)) { + res = TEE_ERROR_OVERFLOW; + goto err; + } + + if (ADD_OVERFLOW(o.ds_pos, offset, &pos_tmp)) { + res = TEE_ERROR_ACCESS_CONFLICT; + goto err; + } + /* FIXME remove after tests */ + //pos_tmp += offset; + + res = o.pobj->fops->write(o.fh, pos_tmp, data, len); + if (res != TEE_SUCCESS) + goto err; + + o.pobj->fops->close(&o.fh); + + return TEE_SUCCESS; + +err: + if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) + res = TEE_ERROR_CORRUPT_OBJECT; + if (po) + tee_pobj_release(po); + + return res; +} + TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id, size_t object_id_len, unsigned long flags, unsigned long attr, void *data, size_t len, |