Skip to content

Commit

Permalink
tee: OCALL support
Browse files Browse the repository at this point in the history
Enable Trusted Applications (TAs) to invoke functions on their
corresponding Client Application (CA), both during session open and
function invocation. These function invocations from TA to CA are referred
to as "Out Calls", or OCALLs for short.

The fundamental mechanism is one whereby upon a function invocation from
the CA to the TA, the TEE returns prematurely from the invocation with an
RPC. This RPC is generated after a TA calls the TEEC_InvokeCommand
equivalent function in secure world. The RPC carries information describing
the OCALL as well as its parameters. When this happens, the driver saves
the state of the current call and returns to user-mode.

The TEE Client API will have invoked the TEE_IOC_INVOKE IOCTL with a
special parameter that carries OCALL information. When the IOCTL returns
prematurely, this parameter includes information about what the CA is
expected to do on behalf of the TA along with data to be used to reply to
the request. The TEE Client API dispatches the request accordingly to the
CA proper.

Once that is done, the TEE Client API calls the TEE_IOC_INVOKE IOCTL again
with the modified OCALL parameter and associated information (such as the
result of the OCALL, and the parameters, as requested by the TA). The
driver notices that this invocation is in fact a resumption as opposed to a
brand-new invocation, and resumes the secure world thread that sent the RPC
in the first place.

The same mechanism applies to OCALLs during session open.

This patch also minimally updates the OP-TEE and AMD TEE drivers to match
the new signatures for session open and invoke. If an OCALL is specified by
the CA, EOPNOTSUPP is returned.

Signed-off-by: Hernan Gatta <[email protected]>
  • Loading branch information
HernanGatta committed Apr 5, 2021
1 parent be70804 commit 647242c
Show file tree
Hide file tree
Showing 8 changed files with 439 additions and 81 deletions.
8 changes: 6 additions & 2 deletions drivers/tee/amdtee/amdtee_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,17 @@ static inline u32 get_session_index(u32 session)

int amdtee_open_session(struct tee_context *ctx,
struct tee_ioctl_open_session_arg *arg,
struct tee_param *param);
struct tee_param *normal_param,
u32 num_normal_params,
struct tee_param *ocall_param);

int amdtee_close_session(struct tee_context *ctx, u32 session);

int amdtee_invoke_func(struct tee_context *ctx,
struct tee_ioctl_invoke_arg *arg,
struct tee_param *param);
struct tee_param *normal_param,
u32 num_normal_params,
struct tee_param *ocall_param);

int amdtee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session);

Expand Down
23 changes: 19 additions & 4 deletions drivers/tee/amdtee/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,9 @@ static void destroy_session(struct kref *ref)

int amdtee_open_session(struct tee_context *ctx,
struct tee_ioctl_open_session_arg *arg,
struct tee_param *param)
struct tee_param *normal_param,
u32 num_normal_params,
struct tee_param *ocall_param)
{
struct amdtee_context_data *ctxdata = ctx->data;
struct amdtee_session *sess = NULL;
Expand All @@ -239,6 +241,11 @@ int amdtee_open_session(struct tee_context *ctx,
int rc, i;
void *ta;

if (ocall_param) {
pr_err("OCALLs not supported\n");
return -EOPNOTSUPP;
}

if (arg->clnt_login != TEE_IOCTL_LOGIN_PUBLIC) {
pr_err("unsupported client login method\n");
return -EINVAL;
Expand Down Expand Up @@ -279,7 +286,7 @@ int amdtee_open_session(struct tee_context *ctx,
}

/* Open session with loaded TA */
handle_open_session(arg, &session_info, param);
handle_open_session(arg, &session_info, normal_param);
if (arg->ret != TEEC_SUCCESS) {
pr_err("open_session failed %d\n", arg->ret);
spin_lock(&sess->lock);
Expand Down Expand Up @@ -391,12 +398,19 @@ void amdtee_unmap_shmem(struct tee_shm *shm)

int amdtee_invoke_func(struct tee_context *ctx,
struct tee_ioctl_invoke_arg *arg,
struct tee_param *param)
struct tee_param *normal_param,
u32 num_normal_params,
struct tee_param *ocall_param)
{
struct amdtee_context_data *ctxdata = ctx->data;
struct amdtee_session *sess;
u32 i, session_info;

if (ocall_param) {
pr_err("OCALLs not supported\n");
return -EOPNOTSUPP;
}

/* Check that the session is valid */
mutex_lock(&session_list_mutex);
sess = find_session(ctxdata, arg->session);
Expand All @@ -409,7 +423,7 @@ int amdtee_invoke_func(struct tee_context *ctx,
if (!sess)
return -EINVAL;

handle_invoke_cmd(arg, session_info, param);
handle_invoke_cmd(arg, session_info, normal_param);

return 0;
}
Expand All @@ -422,6 +436,7 @@ int amdtee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
static const struct tee_driver_ops amdtee_ops = {
.get_version = amdtee_get_version,
.open = amdtee_open,
.pre_release = NULL,
.release = amdtee_release,
.open_session = amdtee_open_session,
.close_session = amdtee_close_session,
Expand Down
28 changes: 22 additions & 6 deletions drivers/tee/optee/call.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@ static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,

int optee_open_session(struct tee_context *ctx,
struct tee_ioctl_open_session_arg *arg,
struct tee_param *param)
struct tee_param *normal_param,
u32 num_normal_params,
struct tee_param *ocall_param)
{
struct optee_context_data *ctxdata = ctx->data;
int rc;
Expand All @@ -136,6 +138,11 @@ int optee_open_session(struct tee_context *ctx,
phys_addr_t msg_parg;
struct optee_session *sess = NULL;

if (ocall_param) {
pr_err("OCALLs not supported\n");
return -EOPNOTSUPP;
}

/* +2 for the meta parameters added below */
shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg, &msg_parg);
if (IS_ERR(shm))
Expand All @@ -160,7 +167,8 @@ int optee_open_session(struct tee_context *ctx,
if (rc)
goto out;

rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param);
rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params,
normal_param);
if (rc)
goto out;

Expand All @@ -185,7 +193,8 @@ int optee_open_session(struct tee_context *ctx,
kfree(sess);
}

if (optee_from_msg_param(param, arg->num_params, msg_arg->params + 2)) {
if (optee_from_msg_param(normal_param, arg->num_params,
msg_arg->params + 2)) {
arg->ret = TEEC_ERROR_COMMUNICATION;
arg->ret_origin = TEEC_ORIGIN_COMMS;
/* Close session again to avoid leakage */
Expand Down Expand Up @@ -232,7 +241,8 @@ int optee_close_session(struct tee_context *ctx, u32 session)
}

int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
struct tee_param *param)
struct tee_param *normal_param, u32 num_normal_params,
struct tee_param *ocall_param)
{
struct optee_context_data *ctxdata = ctx->data;
struct tee_shm *shm;
Expand All @@ -241,6 +251,11 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
struct optee_session *sess;
int rc;

if (ocall_param) {
pr_err("OCALLs not supported\n");
return -EOPNOTSUPP;
}

/* Check that the session is valid */
mutex_lock(&ctxdata->mutex);
sess = find_session(ctxdata, arg->session);
Expand All @@ -256,7 +271,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
msg_arg->session = arg->session;
msg_arg->cancel_id = arg->cancel_id;

rc = optee_to_msg_param(msg_arg->params, arg->num_params, param);
rc = optee_to_msg_param(msg_arg->params, arg->num_params, normal_param);
if (rc)
goto out;

Expand All @@ -265,7 +280,8 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
}

if (optee_from_msg_param(param, arg->num_params, msg_arg->params)) {
if (optee_from_msg_param(normal_param, arg->num_params,
msg_arg->params)) {
msg_arg->ret = TEEC_ERROR_COMMUNICATION;
msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/tee/optee/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ static void optee_release(struct tee_context *ctx)
static const struct tee_driver_ops optee_ops = {
.get_version = optee_get_version,
.open = optee_open,
.pre_release = NULL,
.release = optee_release,
.open_session = optee_open_session,
.close_session = optee_close_session,
Expand Down
6 changes: 4 additions & 2 deletions drivers/tee/optee/optee_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,12 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg);
int optee_open_session(struct tee_context *ctx,
struct tee_ioctl_open_session_arg *arg,
struct tee_param *param);
struct tee_param *normal_param, u32 num_normal_params,
struct tee_param *ocall_param);
int optee_close_session(struct tee_context *ctx, u32 session);
int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
struct tee_param *param);
struct tee_param *normal_param, u32 num_normal_params,
struct tee_param *ocall_param);
int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session);

void optee_enable_shm_cache(struct optee *optee);
Expand Down
Loading

0 comments on commit 647242c

Please sign in to comment.