| /* |
| * Copyright (c) 2017, Linaro Limited |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include <inttypes.h> |
| #include <secure_storage_ta.h> |
| #include <tee_internal_api.h> |
| #include <tee_internal_api_extensions.h> |
| |
| static TEE_Result delete_object(uint32_t param_types, TEE_Param params[4]) |
| { |
| const uint32_t exp_param_types = |
| TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, |
| TEE_PARAM_TYPE_NONE, |
| TEE_PARAM_TYPE_NONE, |
| TEE_PARAM_TYPE_NONE); |
| TEE_ObjectHandle object; |
| TEE_Result res; |
| char *obj_id; |
| size_t obj_id_sz; |
| |
| /* |
| * Safely get the invocation parameters |
| */ |
| if (param_types != exp_param_types) |
| return TEE_ERROR_BAD_PARAMETERS; |
| |
| obj_id_sz = params[0].memref.size; |
| obj_id = TEE_Malloc(obj_id_sz, 0); |
| if (!obj_id) |
| return TEE_ERROR_OUT_OF_MEMORY; |
| |
| TEE_MemMove(obj_id, params[0].memref.buffer, obj_id_sz); |
| |
| /* |
| * Check object exists and delete it |
| */ |
| res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, |
| obj_id, obj_id_sz, |
| TEE_DATA_FLAG_ACCESS_READ | |
| TEE_DATA_FLAG_ACCESS_WRITE_META, /* we must be allowed to delete it */ |
| &object); |
| if (res != TEE_SUCCESS) { |
| EMSG("Failed to open persistent object, res=0x%08x", res); |
| TEE_Free(obj_id); |
| return res; |
| } |
| |
| TEE_CloseAndDeletePersistentObject1(object); |
| TEE_Free(obj_id); |
| |
| return res; |
| } |
| |
| static TEE_Result create_raw_object(uint32_t param_types, TEE_Param params[4]) |
| { |
| const uint32_t exp_param_types = |
| TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, |
| TEE_PARAM_TYPE_MEMREF_INPUT, |
| TEE_PARAM_TYPE_NONE, |
| TEE_PARAM_TYPE_NONE); |
| TEE_ObjectHandle object; |
| TEE_Result res; |
| char *obj_id; |
| size_t obj_id_sz; |
| char *data; |
| size_t data_sz; |
| uint32_t obj_data_flag; |
| |
| /* |
| * Safely get the invocation parameters |
| */ |
| if (param_types != exp_param_types) |
| return TEE_ERROR_BAD_PARAMETERS; |
| |
| obj_id_sz = params[0].memref.size; |
| obj_id = TEE_Malloc(obj_id_sz, 0); |
| if (!obj_id) |
| return TEE_ERROR_OUT_OF_MEMORY; |
| |
| TEE_MemMove(obj_id, params[0].memref.buffer, obj_id_sz); |
| |
| data = (char *)params[1].memref.buffer; |
| data_sz = params[1].memref.size; |
| |
| /* |
| * Create object in secure storage and fill with data |
| */ |
| obj_data_flag = TEE_DATA_FLAG_ACCESS_READ | /* we can later read the oject */ |
| TEE_DATA_FLAG_ACCESS_WRITE | /* we can later write into the object */ |
| TEE_DATA_FLAG_ACCESS_WRITE_META | /* we can later destroy or rename the object */ |
| TEE_DATA_FLAG_OVERWRITE; /* destroy existing object of same ID */ |
| |
| res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, |
| obj_id, obj_id_sz, |
| obj_data_flag, |
| TEE_HANDLE_NULL, |
| NULL, 0, /* we may not fill it right now */ |
| &object); |
| if (res != TEE_SUCCESS) { |
| EMSG("TEE_CreatePersistentObject failed 0x%08x", res); |
| TEE_Free(obj_id); |
| return res; |
| } |
| |
| res = TEE_WriteObjectData(object, data, data_sz); |
| if (res != TEE_SUCCESS) { |
| EMSG("TEE_WriteObjectData failed 0x%08x", res); |
| TEE_CloseAndDeletePersistentObject1(object); |
| } else { |
| TEE_CloseObject(object); |
| } |
| TEE_Free(obj_id); |
| return res; |
| } |
| |
| static TEE_Result read_raw_object(uint32_t param_types, TEE_Param params[4]) |
| { |
| const uint32_t exp_param_types = |
| TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, |
| TEE_PARAM_TYPE_MEMREF_OUTPUT, |
| TEE_PARAM_TYPE_NONE, |
| TEE_PARAM_TYPE_NONE); |
| TEE_ObjectHandle object; |
| TEE_ObjectInfo object_info; |
| TEE_Result res; |
| uint32_t read_bytes; |
| char *obj_id; |
| size_t obj_id_sz; |
| char *data; |
| size_t data_sz; |
| |
| /* |
| * Safely get the invocation parameters |
| */ |
| if (param_types != exp_param_types) |
| return TEE_ERROR_BAD_PARAMETERS; |
| |
| obj_id_sz = params[0].memref.size; |
| obj_id = TEE_Malloc(obj_id_sz, 0); |
| if (!obj_id) |
| return TEE_ERROR_OUT_OF_MEMORY; |
| |
| TEE_MemMove(obj_id, params[0].memref.buffer, obj_id_sz); |
| |
| data = (char *)params[1].memref.buffer; |
| data_sz = params[1].memref.size; |
| |
| /* |
| * Check the object exist and can be dumped into output buffer |
| * then dump it. |
| */ |
| res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, |
| obj_id, obj_id_sz, |
| TEE_DATA_FLAG_ACCESS_READ | |
| TEE_DATA_FLAG_SHARE_READ, |
| &object); |
| if (res != TEE_SUCCESS) { |
| EMSG("Failed to open persistent object, res=0x%08x", res); |
| TEE_Free(obj_id); |
| return res; |
| } |
| |
| res = TEE_GetObjectInfo1(object, &object_info); |
| if (res != TEE_SUCCESS) { |
| EMSG("Failed to create persistent object, res=0x%08x", res); |
| goto exit; |
| } |
| |
| if (object_info.dataSize > data_sz) { |
| /* |
| * Provided buffer is too short. |
| * Return the expected size together with status "short buffer" |
| */ |
| params[1].memref.size = object_info.dataSize; |
| res = TEE_ERROR_SHORT_BUFFER; |
| goto exit; |
| } |
| |
| res = TEE_ReadObjectData(object, data, object_info.dataSize, |
| &read_bytes); |
| if (res != TEE_SUCCESS || read_bytes != object_info.dataSize) { |
| EMSG("TEE_ReadObjectData failed 0x%08x, read %" PRIu32 " over %u", |
| res, read_bytes, object_info.dataSize); |
| goto exit; |
| } |
| |
| /* Return the number of byte effectively filled */ |
| params[1].memref.size = read_bytes; |
| exit: |
| TEE_CloseObject(object); |
| TEE_Free(obj_id); |
| return res; |
| } |
| |
| TEE_Result TA_CreateEntryPoint(void) |
| { |
| /* Nothing to do */ |
| return TEE_SUCCESS; |
| } |
| |
| void TA_DestroyEntryPoint(void) |
| { |
| /* Nothing to do */ |
| } |
| |
| TEE_Result TA_OpenSessionEntryPoint(uint32_t __unused param_types, |
| TEE_Param __unused params[4], |
| void __unused **session) |
| { |
| /* Nothing to do */ |
| return TEE_SUCCESS; |
| } |
| |
| void TA_CloseSessionEntryPoint(void __unused *session) |
| { |
| /* Nothing to do */ |
| } |
| |
| TEE_Result TA_InvokeCommandEntryPoint(void __unused *session, |
| uint32_t command, |
| uint32_t param_types, |
| TEE_Param params[4]) |
| { |
| switch (command) { |
| case TA_SECURE_STORAGE_CMD_WRITE_RAW: |
| return create_raw_object(param_types, params); |
| case TA_SECURE_STORAGE_CMD_READ_RAW: |
| return read_raw_object(param_types, params); |
| case TA_SECURE_STORAGE_CMD_DELETE: |
| return delete_object(param_types, params); |
| default: |
| EMSG("Command ID 0x%x is not supported", command); |
| return TEE_ERROR_NOT_SUPPORTED; |
| } |
| } |