session表示TA和CA之间的联系,从hello world程序中可以知道TA是有特定的UUID制定的。
TEEC_Result TEEC_OpenSession(TEEC_Context *ctx, TEEC_Session *session,
const TEEC_UUID *destination,
uint32_t connection_method, const void *connection_data,
TEEC_Operation *operation, uint32_t *ret_origin)
{
uint64_t buf[(sizeof(struct tee_ioctl_open_session_arg) +
TEEC_CONFIG_PAYLOAD_REF_COUNT *
sizeof(struct tee_ioctl_param)) /
sizeof(uint64_t)] = { 0 };
struct tee_ioctl_buf_data buf_data;
struct tee_ioctl_open_session_arg *arg;
struct tee_ioctl_param *params;
TEEC_Result res;
uint32_t eorig;
//TA和CA 之前是通过这个共享memory 传递数据
TEEC_SharedMemory shm[TEEC_CONFIG_PAYLOAD_REF_COUNT];
int rc;
(void)&connection_data;
if (!ctx || !session) {
eorig = TEEC_ORIGIN_API;
res = TEEC_ERROR_BAD_PARAMETERS;
goto out;
}
buf_data.buf_ptr = (uintptr_t)buf;
buf_data.buf_len = sizeof(buf);
arg = (struct tee_ioctl_open_session_arg *)buf;
arg->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT;
params = (struct tee_ioctl_param *)(arg + 1);
uuid_to_octets(arg->uuid, destination);
arg->clnt_login = connection_method;
//填充TEEC_Operation结构体变量
res = teec_pre_process_operation(ctx, operation, params, shm);
if (res != TEEC_SUCCESS) {
eorig = TEEC_ORIGIN_API;
goto out_free_temp_refs;
}
//通过ioctl向已经通过TEEC_InitializeContext 中赋值的fd 发送TEE_IOC_OPEN_SESSION 命令
rc = ioctl(ctx->fd, TEE_IOC_OPEN_SESSION, &buf_data);
if (rc) {
EMSG("TEE_IOC_OPEN_SESSION failed");
eorig = TEEC_ORIGIN_COMMS;
res = ioctl_errno_to_res(errno);
goto out_free_temp_refs;
}
res = arg->ret;
eorig = arg->ret_origin;
if (res == TEEC_SUCCESS) {
session->ctx = ctx;
session->session_id = arg->session;
}
//解析出TA中得到的数据
teec_post_process_operation(operation, params, shm);
out_free_temp_refs:
teec_free_temp_refs(operation, shm);
out:
if (ret_origin)
*ret_origin = eorig;
return res;
}
这里需要注意的是再通过ioctl向fd发送命令时候,之前会调用teec_pre_process_operation 准备参数,之后会调用teec_post_process_operation解析参数
与TEEC_OpenSession 对应的是TEEC_CloseSession,可见直接向fd发送TEE_IOC_CLOSE_SESSION
void TEEC_CloseSession(TEEC_Session *session)
{
struct tee_ioctl_close_session_arg arg;
if (!session)
return;
arg.session = session->session_id;
if (ioctl(session->ctx->fd, TEE_IOC_CLOSE_SESSION, &arg))
EMSG("Failed to close session 0x%x", session->session_id);
}
open session后就可以通过TEEC_InvokeCommand 来从CA向TA发送命令,这个函数的实现就和TEEC_OpenSession 类似同时通过ioctl下来同学的,与TEEC_InvokeCommand 对应的是TEEC_RequestCancellation 其作用是通过ioctl想TA 发送取消命令
TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, uint32_t cmd_id,
TEEC_Operation *operation, uint32_t *error_origin)
{
uint64_t buf[(sizeof(struct tee_ioctl_invoke_arg) +
TEEC_CONFIG_PAYLOAD_REF_COUNT *
sizeof(struct tee_ioctl_param)) /
sizeof(uint64_t)] = { 0 };
struct tee_ioctl_buf_data buf_data;
struct tee_ioctl_invoke_arg *arg;
struct tee_ioctl_param *params;
TEEC_Result res;
uint32_t eorig;
TEEC_SharedMemory shm[TEEC_CONFIG_PAYLOAD_REF_COUNT];
int rc;
if (!session) {
eorig = TEEC_ORIGIN_API;
res = TEEC_ERROR_BAD_PARAMETERS;
goto out;
}
buf_data.buf_ptr = (uintptr_t)buf;
buf_data.buf_len = sizeof(buf);
arg = (struct tee_ioctl_invoke_arg *)buf;
arg->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT;
params = (struct tee_ioctl_param *)(arg + 1);
arg->session = session->session_id;
arg->func = cmd_id;
if (operation) {
teec_mutex_lock(&teec_mutex);
operation->session = session;
teec_mutex_unlock(&teec_mutex);
}
res = teec_pre_process_operation(session->ctx, operation, params, shm);
if (res != TEEC_SUCCESS) {
eorig = TEEC_ORIGIN_API;
goto out_free_temp_refs;
}
rc = ioctl(session->ctx->fd, TEE_IOC_INVOKE, &buf_data);
if (rc) {
EMSG("TEE_IOC_INVOKE failed");
eorig = TEEC_ORIGIN_COMMS;
res = ioctl_errno_to_res(errno);
goto out_free_temp_refs;
}
res = arg->ret;
eorig = arg->ret_origin;
teec_post_process_operation(operation, params, shm);
out_free_temp_refs:
teec_free_temp_refs(operation, shm);
out:
if (error_origin)
*error_origin = eorig;
return res;
}
TEEC_Result TEEC_OpenSession(TEEC_Context *ctx, TEEC_Session *session,
const TEEC_UUID *destination,
uint32_t connection_method, const void *connection_data,
TEEC_Operation *operation, uint32_t *ret_origin)
{
uint64_t buf[(sizeof(struct tee_ioctl_open_session_arg) +
TEEC_CONFIG_PAYLOAD_REF_COUNT *
sizeof(struct tee_ioctl_param)) /
sizeof(uint64_t)] = { 0 };
struct tee_ioctl_buf_data buf_data;
struct tee_ioctl_open_session_arg *arg;
struct tee_ioctl_param *params;
TEEC_Result res;
uint32_t eorig;
//TA和CA 之前是通过这个共享memory 传递数据
TEEC_SharedMemory shm[TEEC_CONFIG_PAYLOAD_REF_COUNT];
int rc;
(void)&connection_data;
if (!ctx || !session) {
eorig = TEEC_ORIGIN_API;
res = TEEC_ERROR_BAD_PARAMETERS;
goto out;
}
buf_data.buf_ptr = (uintptr_t)buf;
buf_data.buf_len = sizeof(buf);
arg = (struct tee_ioctl_open_session_arg *)buf;
arg->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT;
params = (struct tee_ioctl_param *)(arg + 1);
uuid_to_octets(arg->uuid, destination);
arg->clnt_login = connection_method;
//填充TEEC_Operation结构体变量
res = teec_pre_process_operation(ctx, operation, params, shm);
if (res != TEEC_SUCCESS) {
eorig = TEEC_ORIGIN_API;
goto out_free_temp_refs;
}
//通过ioctl向已经通过TEEC_InitializeContext 中赋值的fd 发送TEE_IOC_OPEN_SESSION 命令
rc = ioctl(ctx->fd, TEE_IOC_OPEN_SESSION, &buf_data);
if (rc) {
EMSG("TEE_IOC_OPEN_SESSION failed");
eorig = TEEC_ORIGIN_COMMS;
res = ioctl_errno_to_res(errno);
goto out_free_temp_refs;
}
res = arg->ret;
eorig = arg->ret_origin;
if (res == TEEC_SUCCESS) {
session->ctx = ctx;
session->session_id = arg->session;
}
//解析出TA中得到的数据
teec_post_process_operation(operation, params, shm);
out_free_temp_refs:
teec_free_temp_refs(operation, shm);
out:
if (ret_origin)
*ret_origin = eorig;
return res;
}
这里需要注意的是再通过ioctl向fd发送命令时候,之前会调用teec_pre_process_operation 准备参数,之后会调用teec_post_process_operation解析参数
与TEEC_OpenSession 对应的是TEEC_CloseSession,可见直接向fd发送TEE_IOC_CLOSE_SESSION
void TEEC_CloseSession(TEEC_Session *session)
{
struct tee_ioctl_close_session_arg arg;
if (!session)
return;
arg.session = session->session_id;
if (ioctl(session->ctx->fd, TEE_IOC_CLOSE_SESSION, &arg))
EMSG("Failed to close session 0x%x", session->session_id);
}
open session后就可以通过TEEC_InvokeCommand 来从CA向TA发送命令,这个函数的实现就和TEEC_OpenSession 类似同时通过ioctl下来同学的,与TEEC_InvokeCommand 对应的是TEEC_RequestCancellation 其作用是通过ioctl想TA 发送取消命令
TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, uint32_t cmd_id,
TEEC_Operation *operation, uint32_t *error_origin)
{
uint64_t buf[(sizeof(struct tee_ioctl_invoke_arg) +
TEEC_CONFIG_PAYLOAD_REF_COUNT *
sizeof(struct tee_ioctl_param)) /
sizeof(uint64_t)] = { 0 };
struct tee_ioctl_buf_data buf_data;
struct tee_ioctl_invoke_arg *arg;
struct tee_ioctl_param *params;
TEEC_Result res;
uint32_t eorig;
TEEC_SharedMemory shm[TEEC_CONFIG_PAYLOAD_REF_COUNT];
int rc;
if (!session) {
eorig = TEEC_ORIGIN_API;
res = TEEC_ERROR_BAD_PARAMETERS;
goto out;
}
buf_data.buf_ptr = (uintptr_t)buf;
buf_data.buf_len = sizeof(buf);
arg = (struct tee_ioctl_invoke_arg *)buf;
arg->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT;
params = (struct tee_ioctl_param *)(arg + 1);
arg->session = session->session_id;
arg->func = cmd_id;
if (operation) {
teec_mutex_lock(&teec_mutex);
operation->session = session;
teec_mutex_unlock(&teec_mutex);
}
res = teec_pre_process_operation(session->ctx, operation, params, shm);
if (res != TEEC_SUCCESS) {
eorig = TEEC_ORIGIN_API;
goto out_free_temp_refs;
}
rc = ioctl(session->ctx->fd, TEE_IOC_INVOKE, &buf_data);
if (rc) {
EMSG("TEE_IOC_INVOKE failed");
eorig = TEEC_ORIGIN_COMMS;
res = ioctl_errno_to_res(errno);
goto out_free_temp_refs;
}
res = arg->ret;
eorig = arg->ret_origin;
teec_post_process_operation(operation, params, shm);
out_free_temp_refs:
teec_free_temp_refs(operation, shm);
out:
if (error_origin)
*error_origin = eorig;
return res;
}