821 lines
26 KiB
C
821 lines
26 KiB
C
|
|
#include <linux/slab.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/cdev.h>
|
|
#include <linux/uaccess.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/list.h>
|
|
#include <linux/mutex.h>
|
|
#include <asm/cacheflush.h>
|
|
#include <linux/kthread.h>
|
|
#include <linux/freezer.h>
|
|
#include <linux/kernel.h>
|
|
|
|
#include "teek_client_api.h"
|
|
#include "teek_client_id.h"
|
|
#include "teek_ns_client.h"
|
|
#include "teek_client_constants.h"
|
|
#include "tc_ns_log.h"
|
|
#include "securec.h"
|
|
#include "cfc.h"
|
|
|
|
static TEEC_Result TEEK_Encode(TC_NS_ClientContext *cli_context,
|
|
TEEC_UUID service_id,
|
|
uint32_t session_id,
|
|
uint32_t cmd_id,
|
|
TC_NS_ClientLogin *cli_login, TEEC_Operation *operation)
|
|
{
|
|
uint32_t param_type[4];
|
|
uint32_t param_cnt;
|
|
uint32_t diff;
|
|
errno_t sret;
|
|
|
|
if (!cli_context || !cli_login) {
|
|
tloge("cli_context or cli_login is null.\n");
|
|
return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
|
|
}
|
|
diff =
|
|
(uint32_t) TEEC_MEMREF_PARTIAL_INPUT -
|
|
(uint32_t) TEEC_MEMREF_TEMP_INPUT;
|
|
|
|
sret = memset_s(cli_context, sizeof(TC_NS_ClientContext),
|
|
0x00, sizeof(TC_NS_ClientContext));
|
|
if (EOK != sret) {
|
|
tloge("memset_s error sret is %d.\n", sret);
|
|
return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
|
|
}
|
|
sret = memcpy_s(cli_context->uuid, sizeof(cli_context->uuid),
|
|
(uint8_t *)&service_id, 16);
|
|
if (EOK != sret) {
|
|
tloge("memcpy_s error sret is %d.\n", sret);
|
|
return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
|
|
}
|
|
cli_context->session_id = session_id;
|
|
cli_context->cmd_id = cmd_id;
|
|
cli_context->returns.code = 0;
|
|
cli_context->returns.origin = 0;
|
|
|
|
cli_context->login.method = cli_login->method;
|
|
cli_context->login.mdata = cli_login->mdata;
|
|
|
|
/* support when operation is null */
|
|
if (!operation)
|
|
return TEEC_SUCCESS;
|
|
cli_context->started = operation->cancel_flag;
|
|
param_type[0] = TEEC_PARAM_TYPE_GET(operation->paramTypes, 0);
|
|
param_type[1] = TEEC_PARAM_TYPE_GET(operation->paramTypes, 1);
|
|
param_type[2] = TEEC_PARAM_TYPE_GET(operation->paramTypes, 2);
|
|
param_type[3] = TEEC_PARAM_TYPE_GET(operation->paramTypes, 3);
|
|
|
|
for (param_cnt = 0; param_cnt < 4; param_cnt++) {
|
|
if ((TEEC_MEMREF_TEMP_INPUT == param_type[param_cnt])
|
|
|| (TEEC_MEMREF_TEMP_OUTPUT == param_type[param_cnt])
|
|
|| (TEEC_MEMREF_TEMP_INOUT == param_type[param_cnt])) {
|
|
|
|
cli_context->params[param_cnt].memref.buffer
|
|
=
|
|
(__u64)operation->params[param_cnt].tmpref.buffer;
|
|
cli_context->params[param_cnt].memref.size_addr =
|
|
(__u64)&operation->params[param_cnt].tmpref.size;
|
|
} else if ((TEEC_MEMREF_WHOLE == param_type[param_cnt])
|
|
|| (TEEC_MEMREF_PARTIAL_INPUT == param_type[param_cnt])
|
|
|| (TEEC_MEMREF_PARTIAL_OUTPUT ==
|
|
param_type[param_cnt])
|
|
|| (TEEC_MEMREF_PARTIAL_INOUT ==
|
|
param_type[param_cnt])) {
|
|
|
|
/* buffer offset len */
|
|
if (TEEC_MEMREF_WHOLE == param_type[param_cnt]) {
|
|
cli_context->params[param_cnt].memref.offset =
|
|
0;
|
|
cli_context->params[param_cnt].memref.
|
|
size_addr =
|
|
(__u64)&operation->params[param_cnt].
|
|
memref.parent->size;
|
|
} else {
|
|
cli_context->params[param_cnt].memref.offset
|
|
=
|
|
operation->params[param_cnt].memref.offset;
|
|
cli_context->params[param_cnt].memref.
|
|
size_addr =
|
|
(__u64)&operation->params[param_cnt].
|
|
memref.size;
|
|
}
|
|
|
|
if (operation->params[param_cnt].memref.parent->
|
|
is_allocated) {
|
|
cli_context->params[param_cnt].memref.buffer =
|
|
(__u64)operation->params[param_cnt].memref.
|
|
parent->buffer;
|
|
} else {
|
|
cli_context->params[param_cnt].memref.buffer
|
|
=
|
|
(__u64)operation->params[param_cnt].memref.
|
|
parent->buffer +
|
|
operation->params[param_cnt].memref.offset;
|
|
cli_context->params[param_cnt].memref.offset =
|
|
0;
|
|
}
|
|
/* translate the paramType to know the driver */
|
|
if (TEEC_MEMREF_WHOLE == param_type[param_cnt]) {
|
|
switch (operation->params[param_cnt].memref.
|
|
parent->flags) {
|
|
case TEEC_MEM_INPUT:
|
|
param_type[param_cnt] =
|
|
TEEC_MEMREF_PARTIAL_INPUT;
|
|
break;
|
|
case TEEC_MEM_OUTPUT:
|
|
param_type[param_cnt] =
|
|
TEEC_MEMREF_PARTIAL_OUTPUT;
|
|
break;
|
|
case TEEC_MEM_INOUT:
|
|
param_type[param_cnt] =
|
|
TEEC_MEMREF_PARTIAL_INOUT;
|
|
break;
|
|
default:
|
|
param_type[param_cnt] =
|
|
TEEC_MEMREF_PARTIAL_INOUT;
|
|
break;
|
|
}
|
|
}
|
|
/* if is not allocated,
|
|
* translate TEEC_MEMREF_PARTIAL_XXX
|
|
* to TEEC_MEMREF_TEMP_XXX */
|
|
if (!operation->params[param_cnt].memref.parent->
|
|
is_allocated)
|
|
param_type[param_cnt] =
|
|
param_type[param_cnt] - diff;
|
|
} else if ((TEEC_VALUE_INPUT == param_type[param_cnt])
|
|
|| (TEEC_VALUE_OUTPUT == param_type[param_cnt])
|
|
|| (TEEC_VALUE_INOUT == param_type[param_cnt])) {
|
|
|
|
cli_context->params[param_cnt].value.a_addr =
|
|
(__u64 *)&operation->params[param_cnt].value.a;
|
|
cli_context->params[param_cnt].value.b_addr =
|
|
(__u64 *)&operation->params[param_cnt].value.b;
|
|
} else if (TEEC_ION_INPUT == param_type[param_cnt]) {
|
|
cli_context->params[param_cnt].value.a_addr
|
|
= (__u64 *)&operation->params[param_cnt].ionref.ion_share_fd;
|
|
cli_context->params[param_cnt].value.b_addr
|
|
= (__u64 *)&operation->params[param_cnt].ionref.ion_size;
|
|
} else if (TEEC_NONE == param_type[param_cnt]) {
|
|
/* do nothing */
|
|
} else {
|
|
tloge("param_type[%d]=%d not correct\n",
|
|
param_cnt, param_type[param_cnt]);
|
|
return TEEC_ERROR_BAD_PARAMETERS; /*lint !e570*/
|
|
}
|
|
}
|
|
cli_context->paramTypes =
|
|
TEEC_PARAM_TYPES(param_type[0], param_type[1], param_type[2],
|
|
param_type[3]);
|
|
tlogv("cli param type %d\n", cli_context->paramTypes);
|
|
return TEEC_SUCCESS;
|
|
}
|
|
|
|
static TEEC_Result TEEK_CheckTmpRef(TEEC_TempMemoryReference tmpref)
|
|
{
|
|
TEEC_Result ret;
|
|
|
|
if ((!tmpref.buffer) || (0 == tmpref.size)) {
|
|
tloge("tmpref buffer is null, or size is zero\n");
|
|
ret = (TEEC_Result) TEEC_ERROR_BAD_PARAMETERS;
|
|
} else {
|
|
ret = (TEEC_Result) TEEC_SUCCESS;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static TEEC_Result TEEK_CheckMemRef(TEEC_RegisteredMemoryReference memref,
|
|
uint32_t param_type)
|
|
{
|
|
if ((!memref.parent) || (!memref.parent->buffer)) {
|
|
tloge("parent of memref is null, or the buffer is zero\n");
|
|
return (TEEC_Result) TEEC_ERROR_BAD_PARAMETERS;
|
|
}
|
|
|
|
if (TEEC_MEMREF_PARTIAL_INPUT == param_type) {
|
|
if (!(memref.parent->flags & TEEC_MEM_INPUT))
|
|
return (TEEC_Result) TEEC_ERROR_BAD_PARAMETERS;
|
|
} else if (TEEC_MEMREF_PARTIAL_OUTPUT == param_type) {
|
|
if (!(memref.parent->flags & TEEC_MEM_OUTPUT))
|
|
return (TEEC_Result) TEEC_ERROR_BAD_PARAMETERS;
|
|
} else if (TEEC_MEMREF_PARTIAL_INOUT == param_type) {
|
|
if (!(memref.parent->flags & TEEC_MEM_INPUT))
|
|
return (TEEC_Result) TEEC_ERROR_BAD_PARAMETERS;
|
|
if (!(memref.parent->flags & TEEC_MEM_OUTPUT))
|
|
return (TEEC_Result) TEEC_ERROR_BAD_PARAMETERS;
|
|
} else if (TEEC_MEMREF_WHOLE == param_type) {
|
|
/* if type is TEEC_MEMREF_WHOLE, ignore it*/
|
|
} else {
|
|
return (TEEC_Result) TEEC_ERROR_BAD_PARAMETERS;
|
|
}
|
|
|
|
if ((param_type == TEEC_MEMREF_PARTIAL_INPUT)
|
|
|| (param_type == TEEC_MEMREF_PARTIAL_OUTPUT)
|
|
|| (param_type == TEEC_MEMREF_PARTIAL_INOUT)) {
|
|
if ((memref.offset + memref.size) > memref.parent->size
|
|
|| (memref.offset + memref.size) < memref.offset
|
|
|| (memref.offset + memref.size) < memref.size) {
|
|
tloge("offset + size exceed the parent size\n");
|
|
return (TEEC_Result) TEEC_ERROR_BAD_PARAMETERS;
|
|
}
|
|
}
|
|
|
|
return (TEEC_Result) TEEC_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Function: TEEC_CheckOperation
|
|
* Description: This function checks a operation is valid or not.
|
|
* Parameters: operation: a pointer to an Operation to be checked.
|
|
* Return: TEEC_SUCCESS: success
|
|
* other: failure
|
|
*/
|
|
TEEC_Result TEEK_CheckOperation(TEEC_Operation *operation)
|
|
{
|
|
uint32_t param_type[4];
|
|
uint32_t param_cnt;
|
|
TEEC_Result ret = TEEC_SUCCESS;
|
|
|
|
/* GP Support operation is NULL
|
|
* operation: a pointer to a Client Application initialized TEEC_Operation structure,
|
|
* or NULL if there is no payload to send or if the Command does not need to support
|
|
* cancellation.
|
|
* */
|
|
if (!operation)
|
|
return (TEEC_Result)TEEC_SUCCESS;
|
|
|
|
if (!operation->started) {
|
|
tloge("sorry, cancellation not support\n");
|
|
return (TEEC_Result) TEEC_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
param_type[0] = TEEC_PARAM_TYPE_GET(operation->paramTypes, 0);
|
|
param_type[1] = TEEC_PARAM_TYPE_GET(operation->paramTypes, 1);
|
|
param_type[2] = TEEC_PARAM_TYPE_GET(operation->paramTypes, 2);
|
|
param_type[3] = TEEC_PARAM_TYPE_GET(operation->paramTypes, 3);
|
|
|
|
for (param_cnt = 0; param_cnt < 4; param_cnt++) {
|
|
if ((TEEC_MEMREF_TEMP_INPUT == param_type[param_cnt])
|
|
|| (TEEC_MEMREF_TEMP_OUTPUT == param_type[param_cnt])
|
|
|| (TEEC_MEMREF_TEMP_INOUT == param_type[param_cnt])) {
|
|
|
|
ret = TEEK_CheckTmpRef(operation->params
|
|
[param_cnt].tmpref);
|
|
if (ret != TEEC_SUCCESS)
|
|
break;
|
|
} else if ((TEEC_MEMREF_WHOLE == param_type[param_cnt])
|
|
|| (TEEC_MEMREF_PARTIAL_INPUT ==
|
|
param_type[param_cnt])
|
|
|| (TEEC_MEMREF_PARTIAL_OUTPUT ==
|
|
param_type[param_cnt])
|
|
|| (TEEC_MEMREF_PARTIAL_INOUT ==
|
|
param_type[param_cnt])) {
|
|
|
|
ret = TEEK_CheckMemRef(operation->params
|
|
[param_cnt].memref,
|
|
param_type[param_cnt]);
|
|
if (ret != TEEC_SUCCESS)
|
|
break;
|
|
} else if ((TEEC_VALUE_INPUT == param_type[param_cnt])
|
|
|| (TEEC_VALUE_OUTPUT == param_type[param_cnt])
|
|
|| (TEEC_VALUE_INOUT == param_type[param_cnt])) {
|
|
/* if type is value, ignore it*/
|
|
} else if (TEEC_NONE == param_type[param_cnt]) {
|
|
/* if type is none, ignore it*/
|
|
} else if (TEEC_ION_INPUT == param_type[param_cnt]) {
|
|
if (operation->params[param_cnt].ionref.ion_share_fd < 0) {
|
|
tloge("operation check failed: ion_handle is invalid!\n");
|
|
ret = (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
|
|
break;
|
|
}
|
|
} else {
|
|
tloge("paramType[%d]=%x is not support\n",
|
|
param_cnt, param_type[param_cnt]);
|
|
ret = (TEEC_Result) TEEC_ERROR_BAD_PARAMETERS;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Function: TEEK_IsAgentAlive
|
|
* Description: This function check if the special agent
|
|
* is launched.Used For HDCP key.
|
|
* e.g. If sfs agent is not alive,
|
|
* you can not do HDCP key write to SRAM.
|
|
* Parameters: agent_id.
|
|
* Return: 1:agent is alive
|
|
* 0:agent not exsit.
|
|
*/
|
|
int TEEK_IsAgentAlive(unsigned int agent_id)
|
|
{
|
|
return is_agent_alive(agent_id);
|
|
}
|
|
EXPORT_SYMBOL(TEEK_IsAgentAlive);
|
|
|
|
/*
|
|
* Function: TEEC_InitializeContext
|
|
* Description: This function initializes a new TEE Context,
|
|
* forming a connection between this
|
|
* Client Application
|
|
* and the TEE identified by
|
|
* the string identifier name.
|
|
* Parameters: name: a zero-terminated string that describes
|
|
* the TEE to connect to.
|
|
* If this parameter is set to NULL,
|
|
* the Implementation MUST select a default TEE.
|
|
* context: a TEEC_Context structure that
|
|
* be initialized by the Implementation.
|
|
* Return: TEEC_SUCCESS: the initialization was successful.
|
|
* other: initialization was not successful.
|
|
*/
|
|
TEEC_Result TEEK_InitializeContext(const char *name, TEEC_Context *context)
|
|
{
|
|
int32_t ret;
|
|
|
|
/* name current not used */
|
|
(void)(name);
|
|
|
|
tlogd("TEEK_InitializeContext Started:\n");
|
|
|
|
/* First, check parameters is valid or not */
|
|
if (!context) {
|
|
tloge("context is null, not correct\n");
|
|
return (TEEC_Result) TEEC_ERROR_BAD_PARAMETERS;
|
|
}
|
|
|
|
context->dev = NULL;
|
|
/* Paramters right, start execution */
|
|
|
|
ret = TC_NS_ClientOpen((TC_NS_DEV_File **)&context->dev,
|
|
TEE_REQ_FROM_KERNEL_MODE);
|
|
|
|
if (TEEC_SUCCESS != ret) {
|
|
tloge("open device failed\n");
|
|
return (TEEC_Result) TEEC_ERROR_GENERIC;
|
|
}
|
|
|
|
tlogd("open device success\n");
|
|
INIT_LIST_HEAD((struct list_head *)&context->session_list);
|
|
INIT_LIST_HEAD((struct list_head *)&context->shrd_mem_list);
|
|
return TEEC_SUCCESS;
|
|
}
|
|
EXPORT_SYMBOL(TEEK_InitializeContext);
|
|
|
|
/*
|
|
* Function: TEEC_FinalizeContext
|
|
* Description: This function finalizes an initialized TEE Context.
|
|
* Parameters: context: an initialized TEEC_Context structure
|
|
* which is to be finalized.
|
|
* Return: NULL
|
|
*/
|
|
void TEEK_FinalizeContext(TEEC_Context *context)
|
|
{
|
|
struct list_node *ptr;
|
|
TEEC_Session *session;
|
|
/*TEEC_SharedMemory* shrdmem;*/
|
|
|
|
tlogd("TEEK_FinalizeContext started\n");
|
|
|
|
/* First, check parameters is valid or not */
|
|
if (!context) {
|
|
tloge("context is null, not correct\n");
|
|
return;
|
|
}
|
|
|
|
/* Paramters right, start execution */
|
|
if (!LIST_EMPTY(&context->session_list)) {
|
|
tlogi("context still has sessions opened, close it\n");
|
|
list_for_each(ptr, &context->session_list) {
|
|
session = list_entry(ptr, TEEC_Session, head);
|
|
TEEK_CloseSession(session);
|
|
}
|
|
}
|
|
|
|
tlogd("close device\n");
|
|
TC_NS_ClientClose(context->dev, 0);
|
|
context->dev = NULL;
|
|
}
|
|
EXPORT_SYMBOL(TEEK_FinalizeContext);
|
|
|
|
/*
|
|
* Function: TEEC_OpenSession
|
|
* Description: This function opens a new Session
|
|
* Parameters: context: a pointer to an initialized TEE Context.
|
|
* session: a pointer to a Session structure to open.
|
|
* destination: a pointer to a UUID structure.
|
|
* connectionMethod: the method of connection to use.
|
|
* connectionData: any necessary data required to
|
|
* support the connection method chosen.
|
|
* operation: a pointer to an Operation containing
|
|
* a set of Parameters.
|
|
* returnOrigin: a pointer to a variable which will
|
|
* contain the return origin.
|
|
* Return: TEEC_SUCCESS: success
|
|
* other: failure
|
|
*/
|
|
static TEEC_Result __TEEK_OpenSession(TEEC_Context *context,
|
|
TEEC_Session *session,
|
|
const TEEC_UUID *destination,
|
|
uint32_t connectionMethod,
|
|
const void *connectionData,
|
|
TEEC_Operation *operation,
|
|
uint32_t *returnOrigin)
|
|
{
|
|
int32_t ret;
|
|
TEEC_Result teec_ret = (TEEC_Result) TEEC_ERROR_BAD_PARAMETERS;
|
|
uint32_t origin = TEEC_ORIGIN_API;
|
|
TC_NS_ClientContext cli_context;
|
|
TC_NS_ClientLogin cli_login = { 0, 0 };
|
|
TC_NS_DEV_File *dev_file;
|
|
uint32_t param_type[4] = { 0 };
|
|
errno_t sret;
|
|
|
|
CFC_FUNC_ENTRY(TEEK_OpenSession);
|
|
|
|
tlogd("TEEK_OpenSession Started:\n");
|
|
/* connectionData current not used */
|
|
(void)(connectionData);
|
|
/* returnOrigin maybe null, so only when it is valid, we set
|
|
* origin(error come from which module)
|
|
* */
|
|
if (returnOrigin)
|
|
*returnOrigin = origin;
|
|
|
|
/* First, check parameters is valid or not */
|
|
if (!context || !session || !destination || !operation
|
|
|| TEEC_LOGIN_IDENTIFY != connectionMethod) {
|
|
tloge("invalid input params\n");
|
|
goto cfc_ret_fail;
|
|
}
|
|
param_type[3] = TEEC_PARAM_TYPE_GET(operation->paramTypes, 3);
|
|
param_type[2] = TEEC_PARAM_TYPE_GET(operation->paramTypes, 2);
|
|
if (TEEC_MEMREF_TEMP_INPUT != param_type[3]
|
|
|| TEEC_MEMREF_TEMP_INPUT != param_type[2]) {
|
|
tloge("invalid param type 0x%x\n", operation->paramTypes);
|
|
teec_ret = (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
|
|
goto cfc_ret_fail;
|
|
}
|
|
if (NULL == operation->params[3].tmpref.buffer
|
|
|| NULL == operation->params[2].tmpref.buffer
|
|
|| 0 == operation->params[3].tmpref.size
|
|
|| 0 == operation->params[2].tmpref.size) {
|
|
tloge("invalid operation params(NULL)\n");
|
|
teec_ret = (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
|
|
goto cfc_ret_fail;
|
|
}
|
|
cli_login.method = TEEC_LOGIN_IDENTIFY;
|
|
dev_file = (TC_NS_DEV_File *)(context->dev);
|
|
if (!dev_file) {
|
|
tloge("invalid context->dev (NULL)\n");
|
|
teec_ret = (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
|
|
goto cfc_ret_fail;
|
|
}
|
|
dev_file->pkg_name_len = operation->params[3].tmpref.size;
|
|
if (operation->params[3].tmpref.size > (MAX_PACKAGE_NAME_LEN - 1)) {
|
|
teec_ret = (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
|
|
goto cfc_ret_fail;
|
|
} else {
|
|
sret = memset_s(dev_file->pkg_name, sizeof(dev_file->pkg_name),
|
|
0, MAX_PACKAGE_NAME_LEN);
|
|
if (EOK != sret) {
|
|
tloge("memset_s error sret is %d.\n", sret);
|
|
teec_ret = (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
|
|
goto cfc_ret_fail;
|
|
}
|
|
sret = memcpy_s(dev_file->pkg_name, sizeof(dev_file->pkg_name),
|
|
operation->params[3].tmpref.buffer,
|
|
operation->params[3].tmpref.size);
|
|
if (EOK != sret) {
|
|
tloge("memcpy_s error sret is %d.\n", sret);
|
|
teec_ret = (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
|
|
goto cfc_ret_fail;
|
|
}
|
|
}
|
|
dev_file->pub_key_len = 0;
|
|
dev_file->login_setup = 1;
|
|
|
|
teec_ret = TEEK_CheckOperation(operation);
|
|
if (TEEC_SUCCESS != teec_ret) {
|
|
tloge("operation is invalid\n");
|
|
teec_ret = (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
|
|
goto cfc_ret_fail;
|
|
}
|
|
|
|
/* Paramters right, start execution */
|
|
/*
|
|
* note:before open session success,
|
|
* we should send session=0 as initial state.
|
|
*/
|
|
teec_ret = TEEK_Encode(&cli_context, *destination, 0 /*session->session_id */,
|
|
GLOBAL_CMD_ID_OPEN_SESSION, &cli_login, operation);
|
|
if (TEEC_SUCCESS != teec_ret) {
|
|
tloge("encode failed\n");
|
|
goto cfc_ret_fail;
|
|
}
|
|
|
|
#ifdef SECURITY_AUTH_ENHANCE
|
|
cli_context.token.teec_token = session->teec_token;
|
|
#endif
|
|
ret = TC_NS_OpenSession(context->dev, &cli_context);
|
|
if (0 == ret) {
|
|
tlogd("open session success\n");
|
|
session->session_id = cli_context.session_id;
|
|
session->service_id = *destination;
|
|
session->ops_cnt = 0;
|
|
INIT_LIST_HEAD((struct list_head *)&session->head);
|
|
list_insert_tail(&context->session_list, &session->head);
|
|
session->context = context;
|
|
teec_ret = TEEC_SUCCESS;
|
|
} else if (ret < 0) {
|
|
tloge("open session failed, ioctl errno = %d\n", ret);
|
|
if (-EFAULT == ret)
|
|
teec_ret = (TEEC_Result) TEEC_ERROR_ACCESS_DENIED;
|
|
else if (-ENOMEM == ret)
|
|
teec_ret = (TEEC_Result) TEEC_ERROR_OUT_OF_MEMORY;
|
|
else if (-EINVAL == ret)
|
|
teec_ret = (TEEC_Result) TEEC_ERROR_BAD_PARAMETERS;
|
|
else if (-ERESTARTSYS == ret)
|
|
teec_ret = (TEEC_Result) TEEC_CLIENT_INTR;
|
|
else
|
|
teec_ret = (TEEC_Result) TEEC_ERROR_GENERIC;
|
|
origin = TEEC_ORIGIN_COMMS;
|
|
} else {
|
|
tloge("open session failed, code=0x%x, origin=%d\n",
|
|
cli_context.returns.code,
|
|
cli_context.returns.origin);
|
|
teec_ret = (TEEC_Result) cli_context.returns.code;
|
|
origin = cli_context.returns.origin;
|
|
}
|
|
|
|
/* ONLY when ioctl returnCode!=0 and returnOrigin not NULL,
|
|
* set *returnOrigin
|
|
*/
|
|
if ((TEEC_SUCCESS != teec_ret) && (returnOrigin))
|
|
*returnOrigin = origin;
|
|
|
|
CFC_RETURN_SUCC(TEEK_OpenSession, 0, teec_ret);
|
|
|
|
cfc_ret_fail:
|
|
CFC_RETURN_FAIL(TEEK_OpenSession, 0, teec_ret);
|
|
}
|
|
|
|
TEEC_Result TEEK_OpenSession(TEEC_Context *context,
|
|
TEEC_Session *session,
|
|
const TEEC_UUID *destination,
|
|
uint32_t connectionMethod,
|
|
const void *connectionData,
|
|
TEEC_Operation *operation,
|
|
uint32_t *returnOrigin)
|
|
{
|
|
int i;
|
|
TEEC_Result ret;
|
|
|
|
/* Upvote for peripheral zone votage, needed by Coresight. */
|
|
cfc_prepare_clk_pm();
|
|
for (i = 0; i < 5; i++) {
|
|
ret = __TEEK_OpenSession(context, session, destination, connectionMethod,
|
|
connectionData, operation, returnOrigin);
|
|
if (ret != (TEEC_Result) TEEC_CLIENT_INTR) {
|
|
cfc_unprepare_pm_clk();
|
|
return ret;
|
|
}
|
|
}
|
|
cfc_unprepare_pm_clk();
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(TEEK_OpenSession);
|
|
|
|
/*
|
|
* Function: TEEC_CloseSession
|
|
* Description: This function closes an opened Session.
|
|
* Parameters: session: the session to close.
|
|
* Return: NULL
|
|
*/
|
|
void TEEK_CloseSession(TEEC_Session *session)
|
|
{
|
|
int32_t ret;
|
|
TC_NS_ClientContext cli_context;
|
|
TC_NS_ClientLogin cli_login = { 0, 0 };
|
|
struct list_node *ptr;
|
|
TEEC_Session *temp_sess;
|
|
bool found = false;
|
|
errno_t sret;
|
|
|
|
tlogd("TEEK_CloseSession started\n");
|
|
|
|
/* First, check parameters is valid or not */
|
|
if (!session || !session->context) {
|
|
tloge("input invalid session or session->context is null\n");
|
|
return;
|
|
}
|
|
|
|
list_for_each(ptr, &session->context->session_list) {
|
|
temp_sess = list_entry(ptr, TEEC_Session, head);
|
|
if (temp_sess == session) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
tloge("session isnot in the context list\n");
|
|
return;
|
|
}
|
|
|
|
/* Paramters all right, start execution */
|
|
if (session->ops_cnt)
|
|
tloge("session still has commands running\n");
|
|
|
|
if (TEEC_SUCCESS != TEEK_Encode(&cli_context, session->service_id, session->session_id,
|
|
GLOBAL_CMD_ID_CLOSE_SESSION, &cli_login, NULL)) {
|
|
tloge("encode failed, just return\n");
|
|
return;
|
|
}
|
|
|
|
#ifdef SECURITY_AUTH_ENHANCE
|
|
cli_context.token.teec_token = session->teec_token;
|
|
#endif
|
|
ret = TC_NS_CloseSession(session->context->dev, &cli_context);
|
|
|
|
if (0 == ret) {
|
|
tlogd("close session success\n");
|
|
session->session_id = 0;
|
|
sret = memset_s((uint8_t *)(&session->service_id), sizeof(session->service_id),
|
|
0x00, 16);
|
|
if (EOK != sret) {
|
|
tloge("memset_s error sret is %d.\n", sret);
|
|
/* TEEK_CloseSession is void so go on execute */
|
|
}
|
|
#ifdef SECURITY_AUTH_ENHANCE
|
|
sret = memset_s(session->teec_token, TOKEN_SAVE_LEN, 0x00, TOKEN_SAVE_LEN);
|
|
if (EOK != sret) {
|
|
tloge("memset_s teec_token error ret value is %d.\n", sret);
|
|
}
|
|
#endif
|
|
session->ops_cnt = 0;
|
|
list_remove(&session->head);
|
|
session->context = NULL;
|
|
} else {
|
|
tloge("close session failed\n");
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(TEEK_CloseSession);
|
|
|
|
/*
|
|
* Function: TEEC_InvokeCommand
|
|
* Description: This function invokes a Command within the specified Session.
|
|
* Parameters: session: the open Session in which the command will be invoked.
|
|
* commandID: the identifier of the Command.
|
|
* operation: a pointer to an Operation containing
|
|
* a set of Parameters.
|
|
* returnOrigin: a pointer to a variable which will
|
|
* contain the return origin.
|
|
* Return: TEEC_SUCCESS: success
|
|
* other: failure
|
|
*/
|
|
TEEC_Result TEEK_InvokeCommand(TEEC_Session *session,
|
|
uint32_t commandID,
|
|
TEEC_Operation *operation,
|
|
uint32_t *returnOrigin)
|
|
{
|
|
int32_t ret;
|
|
TEEC_Result teec_ret = (TEEC_Result) TEEC_ERROR_BAD_PARAMETERS;
|
|
uint32_t origin = TEEC_ORIGIN_API;
|
|
TC_NS_ClientContext cli_context;
|
|
TC_NS_ClientLogin cli_login = { 0, 0 };
|
|
|
|
tlogd("TEEK_InvokeCommand Started:\n");
|
|
|
|
/* First, check parameters is valid or not */
|
|
if (!session || !session->context) {
|
|
tloge("input invalid session or session->context is null\n");
|
|
if (returnOrigin)
|
|
*returnOrigin = origin;
|
|
return teec_ret;
|
|
}
|
|
|
|
teec_ret = TEEK_CheckOperation(operation);
|
|
if (TEEC_SUCCESS != teec_ret) {
|
|
tloge("operation is invalid\n");
|
|
if (returnOrigin)
|
|
*returnOrigin = origin;
|
|
return teec_ret;
|
|
}
|
|
|
|
/* Paramters all right, start execution */
|
|
session->ops_cnt++;
|
|
teec_ret = TEEK_Encode(&cli_context, session->service_id, session->session_id,
|
|
commandID, &cli_login, operation);
|
|
if (TEEC_SUCCESS != teec_ret) {
|
|
tloge("encode failed\n");
|
|
session->ops_cnt--;
|
|
if (returnOrigin)
|
|
*returnOrigin = origin;
|
|
return teec_ret;
|
|
}
|
|
|
|
#ifdef SECURITY_AUTH_ENHANCE
|
|
cli_context.token.teec_token = session->teec_token;
|
|
#endif
|
|
|
|
ret = TC_NS_Send_CMD(session->context->dev, &cli_context);
|
|
if (0 == ret) {
|
|
tlogd("invoke cmd success\n");
|
|
teec_ret = TEEC_SUCCESS;
|
|
} else if (ret < 0) {
|
|
tloge("invoke cmd failed, ioctl errno = %d\n", ret);
|
|
if (-EFAULT == ret)
|
|
teec_ret = (TEEC_Result) TEEC_ERROR_ACCESS_DENIED;
|
|
else if (-ENOMEM == ret)
|
|
teec_ret = (TEEC_Result) TEEC_ERROR_OUT_OF_MEMORY;
|
|
else if (-EINVAL == ret)
|
|
teec_ret = (TEEC_Result) TEEC_ERROR_BAD_PARAMETERS;
|
|
else
|
|
teec_ret = (TEEC_Result) TEEC_ERROR_GENERIC;
|
|
origin = TEEC_ORIGIN_COMMS;
|
|
} else {
|
|
tloge("invoke cmd failed, code=0x%x, origin=%d\n",
|
|
cli_context.returns.code,
|
|
cli_context.returns.origin);
|
|
teec_ret = (TEEC_Result) cli_context.returns.code;
|
|
origin = cli_context.returns.origin;
|
|
}
|
|
session->ops_cnt--;
|
|
|
|
/* ONLY when ioctl returnCode!=0 and returnOrigin not NULL,
|
|
* set *returnOrigin
|
|
*/
|
|
if ((TEEC_SUCCESS != teec_ret) && (returnOrigin))
|
|
*returnOrigin = origin;
|
|
return teec_ret;
|
|
}
|
|
EXPORT_SYMBOL(TEEK_InvokeCommand);
|
|
|
|
/*
|
|
* Function: TEEC_RegisterSharedMemory
|
|
* Description: This function registers a block of existing
|
|
* Client Application memory
|
|
* as a block of Shared Memory within the scope of
|
|
* the specified TEE Context.
|
|
* Parameters: context: a pointer to an initialized TEE Context.
|
|
* sharedMem: a pointer to a Shared Memory structure to register.
|
|
* Return: TEEC_SUCCESS: success
|
|
* other: failure
|
|
*/
|
|
TEEC_Result TEEK_RegisterSharedMemory(TEEC_Context *context,
|
|
TEEC_SharedMemory *sharedMem)
|
|
{
|
|
tloge("TEEK_RegisterSharedMemory not supported\n");
|
|
return TEEC_ERROR_NOT_SUPPORTED; /*lint !e570*/
|
|
}
|
|
EXPORT_SYMBOL(TEEK_RegisterSharedMemory);
|
|
|
|
/*
|
|
* Function: TEEC_AllocateSharedMemory
|
|
* Description: This function allocates a new block of memory as a block of
|
|
* Shared Memory within the scope of the specified TEE Context.
|
|
* Parameters: context: a pointer to an initialized TEE Context.
|
|
* sharedMem: a pointer to a Shared Memory structure to allocate.
|
|
* Return: TEEC_SUCCESS: success
|
|
* other: failure
|
|
*/
|
|
TEEC_Result TEEK_AllocateSharedMemory(TEEC_Context *context,
|
|
TEEC_SharedMemory *sharedMem)
|
|
{
|
|
tloge("TEEK_AllocateSharedMemory not supported\n");
|
|
return TEEC_ERROR_NOT_SUPPORTED; /*lint !e570*/
|
|
}
|
|
EXPORT_SYMBOL(TEEK_AllocateSharedMemory);
|
|
|
|
/*
|
|
* Function: TEEC_ReleaseSharedMemory
|
|
* Description: This function deregisters or deallocates
|
|
* a previously initialized block of Shared Memory..
|
|
* Parameters: sharedMem: a pointer to a valid Shared Memory structure.
|
|
* Return: NULL
|
|
*/
|
|
void TEEK_ReleaseSharedMemory(TEEC_SharedMemory *sharedMem)
|
|
{
|
|
tloge("TEEK_ReleaseSharedMemory not supported\n");
|
|
}
|
|
EXPORT_SYMBOL(TEEK_ReleaseSharedMemory);
|
|
|
|
|
|
/*
|
|
* Function: TEEC_RequestCancellation
|
|
* Description: This function requests the cancellation of
|
|
* a pending open Session operation or
|
|
* a Command invocation operation.
|
|
* Parameters: operation:a pointer to a Client Application
|
|
* instantiated Operation structure
|
|
* Return: NULL
|
|
*/
|
|
void TEEK_RequestCancellation(TEEC_Operation *operation)
|
|
{
|
|
tloge("TEEK_RequestCancellation not supported\n");
|
|
}
|