blob: 8821d613a08112c425dc863b3810d5fa8aa2b86b [file] [log] [blame]
/*
* 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;
}
}