本文学习tee_supplicant的相关内容。以下是杂记,仅用做学习记录。学习代码均取自github和《手机安全和可信应用开发指南》(帅峰云,黄腾,宋洋)
进程间通信,是系统中进程或线程之间的通信机制,本文介绍OPTEE系统中的IPC机制
OPTEE的IPC机制主要满足OPTEE用户空间运行的线程调用其它线程,静态TA,安全驱动的需求。其核心原理是利用系统调用来访问其他线程或者安全驱动。当线程需要进行IPC时,首先会通过系统调用陷入到OPTEE内核态,然后执行类似CA调用TA的操作,建立会话并通过调用命令的方式让其他的TA来完成相应的操作。
TA调用TA
OPTEE定义了3个i二口,来完成TA和TA之间的调用
TEE_OpenTASession
TEE_Result TEE_OpenTASession(const TEE_UUID *destination,
uint32_t cancellationRequestTimeout,
uint32_t paramTypes,
TEE_Param params[TEE_NUM_PARAMS],
TEE_TASessionHandle *session,
uint32_t *returnOrigin)
{
TEE_Result res;
struct utee_params up;
uint32_t s;
__utee_from_param(&up, paramTypes, params);
res = utee_open_ta_session(destination, cancellationRequestTimeout,
&up, &s, returnOrigin);
__utee_to_param(params, NULL, &up);
/*
* Specification says that *session must hold TEE_HANDLE_NULL is
* TEE_SUCCESS isn't returned. Set it here explicitly in case
* the syscall fails before out parameters has been updated.
*/
if (res != TEE_SUCCESS)
s = TEE_HANDLE_NULL;
*session = (TEE_TASessionHandle)(uintptr_t)s;
return res;
}
/* utee_open_ta_session 会陷入内核然后调用syscall_open_ta_session */
/* Called when a TA calls an OpenSession on another TA */
TEE_Result syscall_open_ta_session(const TEE_UUID *dest,
unsigned long cancel_req_to,
struct utee_params *usr_param, uint32_t *ta_sess,
uint32_t *ret_orig)
{
TEE_Result res;
uint32_t ret_o = TEE_ORIGIN_TEE;
struct tee_ta_session *s = NULL;
struct tee_ta_session *sess;
struct mobj *mobj_param = NULL;
TEE_UUID *uuid = malloc(sizeof(TEE_UUID));
struct tee_ta_param *param = malloc(sizeof(struct tee_ta_param));
TEE_Identity *clnt_id = malloc(sizeof(TEE_Identity));
void *tmp_buf_va[TEE_NUM_PARAMS];
struct user_ta_ctx *utc;
if (uuid == NULL || param == NULL || clnt_id == NULL) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto out_free_only;
}
memset(param, 0, sizeof(struct tee_ta_param));
res = tee_ta_get_current_session(&sess); //这里的session是在open一个ta的时候创建的,一个ta对应一个session。这里获取的是本ta的session。
if (res != TEE_SUCCESS)
goto out_free_only;
utc = to_user_ta_ctx(sess->ctx);
res = tee_svc_copy_from_user(uuid, dest, sizeof(TEE_UUID));
if (res != TEE_SUCCESS)
goto function_exit;
clnt_id->login = TEE_LOGIN_TRUSTED_APP;
memcpy(&clnt_id->uuid, &sess->ctx->uuid, sizeof(TEE_UUID));
res = tee_svc_copy_param(sess, NULL, usr_param, param, tmp_buf_va,
&mobj_param);
if (res != TEE_SUCCESS)
goto function_exit;
/*
* Find session of a multi session TA or a static TA
* In such a case, there is no need to ask the supplicant for the TA
* code
*/
res = tee_ta_open_session(&ret_o, &s, &utc->open_sessions, uuid,
clnt_id, cancel_req_to, param); //调用内核的opensession函数打开对端ta的session
if (res != TEE_SUCCESS)
goto function_exit;
res = tee_svc_update_out_param(sess, s, param, tmp_buf_va, usr_param);
function_exit:
mobj_free(mobj_param);
if (res == TEE_SUCCESS)
tee_svc_copy_kaddr_to_uref(ta_sess, s);
tee_svc_copy_to_user(ret_orig, &ret_o, sizeof(ret_o));
out_free_only:
free(param);
free(uuid);
free(clnt_id);
return res;
}
TEE_InvokeTACommand
调用TEE_InvokeTACommand时带入命令ID就能调用TA中的具体命令,其过程与CA的命令调用操作几乎一致
TEE_CloseTASession
TEE_CloseTASession接口用于断开TA与其他TA之间的连接,其过程与CA的关闭会话操作几乎一致
TA调用系统服务和安全驱动
OPTEE中的TA调用系统服务和安全驱动和REE侧的userspace调用kernel space是类似的,都是通过触发软件中断然后陷入内核态,调用对应的系统服务来完成的,前文提到的open ta session,invoke ta command, close ta session其实也都是系统服务中的一项,下面罗列出OPTEE对外提供的系统服务函数
/*
* This array is ordered according to the SYSCALL ids TEE_SCN_xxx
*/
static const struct syscall_entry tee_svc_syscall_table[] = {
SYSCALL_ENTRY(syscall_sys_return),
SYSCALL_ENTRY(syscall_log),
SYSCALL_ENTRY(syscall_panic),
SYSCALL_ENTRY(syscall_get_property),
SYSCALL_ENTRY(syscall_get_property_name_to_index),
SYSCALL_ENTRY(syscall_open_ta_session),
SYSCALL_ENTRY(syscall_close_ta_session),
SYSCALL_ENTRY(syscall_invoke_ta_command),
SYSCALL_ENTRY(syscall_check_access_rights),
SYSCALL_ENTRY(syscall_get_cancellation_flag),
SYSCALL_ENTRY(syscall_unmask_cancellation),
SYSCALL_ENTRY(syscall_mask_cancellation),
SYSCALL_ENTRY(syscall_wait),
SYSCALL_ENTRY(syscall_get_time),
SYSCALL_ENTRY(syscall_set_ta_time),
SYSCALL_ENTRY(syscall_cryp_state_alloc),
SYSCALL_ENTRY(syscall_cryp_state_copy),
SYSCALL_ENTRY(syscall_cryp_state_free),
SYSCALL_ENTRY(syscall_hash_init),
SYSCALL_ENTRY(syscall_hash_update),
SYSCALL_ENTRY(syscall_hash_final),
SYSCALL_ENTRY(syscall_cipher_init),
SYSCALL_ENTRY(syscall_cipher_update),
SYSCALL_ENTRY(syscall_cipher_final),
SYSCALL_ENTRY(syscall_cryp_obj_get_info),
SYSCALL_ENTRY(syscall_cryp_obj_restrict_usage),
SYSCALL_ENTRY(syscall_cryp_obj_get_attr),
SYSCALL_ENTRY(syscall_cryp_obj_alloc),
SYSCALL_ENTRY(syscall_cryp_obj_close),
SYSCALL_ENTRY(syscall_cryp_obj_reset),
SYSCALL_ENTRY(syscall_cryp_obj_populate),
SYSCALL_ENTRY(syscall_cryp_obj_copy),
SYSCALL_ENTRY(syscall_cryp_derive_key),
SYSCALL_ENTRY(syscall_cryp_random_number_generate),
SYSCALL_ENTRY(syscall_authenc_init),
SYSCALL_ENTRY(syscall_authenc_update_aad),
SYSCALL_ENTRY(syscall_authenc_update_payload),
SYSCALL_ENTRY(syscall_authenc_enc_final),
SYSCALL_ENTRY(syscall_authenc_dec_final),
SYSCALL_ENTRY(syscall_asymm_operate),
SYSCALL_ENTRY(syscall_asymm_verify),
SYSCALL_ENTRY(syscall_storage_obj_open),
SYSCALL_ENTRY(syscall_storage_obj_create),
SYSCALL_ENTRY(syscall_storage_obj_del),
SYSCALL_ENTRY(syscall_storage_obj_rename),
SYSCALL_ENTRY(syscall_storage_alloc_enum),
SYSCALL_ENTRY(syscall_storage_free_enum),
SYSCALL_ENTRY(syscall_storage_reset_enum),
SYSCALL_ENTRY(syscall_storage_start_enum),
SYSCALL_ENTRY(syscall_storage_next_enum),
SYSCALL_ENTRY(syscall_storage_obj_read),
SYSCALL_ENTRY(syscall_storage_obj_write),
SYSCALL_ENTRY(syscall_storage_obj_trunc),
SYSCALL_ENTRY(syscall_storage_obj_seek),
SYSCALL_ENTRY(syscall_obj_generate_key),
SYSCALL_ENTRY(syscall_se_service_open),
SYSCALL_ENTRY(syscall_se_service_close),
SYSCALL_ENTRY(syscall_se_service_get_readers),
SYSCALL_ENTRY(syscall_se_reader_get_prop),
SYSCALL_ENTRY(syscall_se_reader_get_name),
SYSCALL_ENTRY(syscall_se_reader_open_session),
SYSCALL_ENTRY(syscall_se_reader_close_sessions),
SYSCALL_ENTRY(syscall_se_session_is_closed),
SYSCALL_ENTRY(syscall_se_session_get_atr),
SYSCALL_ENTRY(syscall_se_session_open_channel),
SYSCALL_ENTRY(syscall_se_session_close),
SYSCALL_ENTRY(syscall_se_channel_select_next),
SYSCALL_ENTRY(syscall_se_channel_get_select_resp),
SYSCALL_ENTRY(syscall_se_channel_transmit),
SYSCALL_ENTRY(syscall_se_channel_close),
SYSCALL_ENTRY(syscall_cache_operation),
};
以上函数在OPTEE userspace中对应型如utee_xxxx类的接口,例如syscall_open_ta_session对应utee_open_ta_session,只要调用utee_open_ta_session函数就会调用到内核准备的syscall_open_ta_session系统服务