tee-supplicant的作用是帮忙optee_linuxdriver 从userspace访问rishos的文件系统中的资源

tee-supplicant 是运行在user space,主要是optee_linuxdriver通过ioctl告诉上层,让其访问rich os文件系统中的资源。从其makefile中可以看到最终build出的可执行档就是tee-supplicant
包换的源文件:tee_supplicant.c/teec_ta_load.c/tee_supp_fs.c/rpmb.c/handle.c
all: tee-supplicant
################################################################################
# Teec configuration
################################################################################
PACKAGE_NAME    := tee-supplicant

TEES_SRCS    := tee_supplicant.c \
           teec_ta_load.c \
           tee_supp_fs.c \
           rpmb.c \
           handle.c
其入口函数在tee_supplicant.c 中
int main(int argc, char *argv[])
{
    struct thread_arg arg = { .fd = -1 };
    int e;

    e = pthread_mutex_init(&arg.mutex, NULL);
    if (e) {
        EMSG("pthread_mutex_init: %s", strerror(e));
        EMSG("terminating...");
        exit(EXIT_FAILURE);
    }

    if (argc > 2)
        return usage();
    if (argc == 2) {
        arg.fd = open_dev(argv[1]);
        if (arg.fd < 0) {
            EMSG("failed to open \"%s\"", argv[1]);
            exit(EXIT_FAILURE);
        }
    } else {
//打开tee 驱动对应的字符设备
        arg.fd = get_dev_fd();
        if (arg.fd < 0) {
            EMSG("failed to find an OP-TEE supplicant device");
            exit(EXIT_FAILURE);
        }
    }

    if (tee_supp_fs_init() != 0) {
        EMSG("error tee_supp_fs_init");
        exit(EXIT_FAILURE);
    }
//创建一个thread出来TA的请求
    while (!arg.abort) {
        if (!process_one_request(&arg))
            arg.abort = true;
    }

    close(arg.fd);

    return EXIT_FAILURE;
}
在main函数中最终要的就是process_one_request
static bool process_one_request(struct thread_arg *arg)
{
    union tee_rpc_invoke request;
    size_t num_params;
    size_t num_meta;
    struct tee_ioctl_param *params;
    uint32_t func;
    uint32_t ret;

    DMSG("looping");
    memset(&request, 0, sizeof(request));
    request.recv.num_params = RPC_NUM_PARAMS;

    /* Let it be known that we can deal with meta parameters */
    params = (struct tee_ioctl_param *)(&request.send + 1);
    params->attr = TEE_IOCTL_PARAM_ATTR_META;

    num_waiters_inc(arg);
//分析TA 发送过来的请求
    if (!read_request(arg->fd, &request))
        return false;
//解析TA的请求
    if (!find_params(&request, &func, &num_params, &params, &num_meta))
        return false;
//调用spawn_thread 创建一个新的thread,这个thread的处理函数thread_main。
    if (num_meta && !num_waiters_dec(arg) && !spawn_thread(arg))
        return false;
根据解析TA的命令执行不同的操作。假如是OPTEE_MSG_RPC_CMD_LOAD_TA 命令的话,则执行load_ta
    switch (func) {
    case OPTEE_MSG_RPC_CMD_LOAD_TA:
        ret = load_ta(num_params, params);
        break;
    }

    request.send.ret = ret;
//回复处理后的数据给TA
    return write_response(arg->fd, &request);
}
有几个重点函数read_request/find_params/spawn_thread/load_ta/write_response
先看read_request
static bool read_request(int fd, union tee_rpc_invoke *request)
{
    struct tee_ioctl_buf_data data;

    data.buf_ptr = (uintptr_t)request;
    data.buf_len = sizeof(*request);
    if (ioctl(fd, TEE_IOC_SUPPL_RECV, &data)) {
        EMSG("TEE_IOC_SUPPL_RECV: %s", strerror(errno));
        return false;
    }
    return true;
}
原来就是通过ioctl 从optee_linuxdriver 得到需求
static bool find_params(union tee_rpc_invoke *request, uint32_t *func,
            size_t *num_params, struct tee_ioctl_param **params,
            size_t *num_meta)
{
    struct tee_ioctl_param *p;
    size_t n;

    p = (struct tee_ioctl_param *)(&request->recv + 1);

    /* Skip meta parameters in the front */
    for (n = 0; n < request->recv.num_params; n++)
        if (!(p[n].attr & TEE_IOCTL_PARAM_ATTR_META))
            break;
//最重要的参数,tee_supplicant.c 中的process_one_request会根据func的值,执行不同的命令.
    *func = request->recv.func;
    *num_params = request->recv.num_params - n;
    *params = p + n;
    *num_meta = n;

    /* Make sure that no meta parameters follows a non-meta parameter */
    for (; n < request->recv.num_params; n++) {
        if (p[n].attr & TEE_IOCTL_PARAM_ATTR_META) {
            EMSG("Unexpected meta parameter");
            return false;
        }
    }

    return true;
}
在find_params 中会解析通过ioctl TEE_IOC_SUPPL_RECV得到的命令
static bool spawn_thread(struct thread_arg *arg)
{
    pthread_t tid;
    int e;

    DMSG("Spawning a new thread");

    /*
     * Increase number of waiters now to avoid starting another thread
     * before this thread has been scheduled.
     */
    num_waiters_inc(arg);

    e = pthread_create(&tid, NULL, thread_main, arg);
    if (e) {
        EMSG("pthread_create: %s", strerror(e));
        num_waiters_dec(arg);
        return false;
    }

    e = pthread_detach(tid);
    if (e)
        EMSG("pthread_detach: %s", strerror(e));

    return true;
}
spawn_thread 调用pthread_create 新建一个thread,其处理函数是thread_main
static void *thread_main(void *a)
{
    struct thread_arg *arg = a;

    /*
     * Now that this thread has been scheduled, compensate for the
     * initial increase in spawn_thread() before.
     */
    num_waiters_dec(arg);

    while (!arg->abort) {
        if (!process_one_request(arg))
            arg->abort = true;
    }

    return NULL;
}
在thread_main 中通过是调用process_one_request ,这个函数也就是我们正在分析的

static uint32_t load_ta(size_t num_params, struct tee_ioctl_param *params)
{
    int ta_found = 0;
    size_t size = 0;
    TEEC_UUID uuid;
    struct tee_ioctl_param_value *val_cmd;
    TEEC_SharedMemory shm_ta;

    memset(&shm_ta, 0, sizeof(shm_ta));

    if (num_params != 2 || get_value(num_params, params, 0, &val_cmd) ||
        get_param(num_params, params, 1, &shm_ta))
        return TEEC_ERROR_BAD_PARAMETERS;

    uuid_from_octets(&uuid, (void *)val_cmd);

    size = shm_ta.size;
    ta_found = TEECI_LoadSecureModule(ta_dir, &uuid, shm_ta.buffer, &size);
    if (ta_found != TA_BINARY_FOUND) {
        EMSG("  TA not found");
        return TEEC_ERROR_ITEM_NOT_FOUND;
    }

    params[1].u.memref.size = size;
    return TEEC_SUCCESS;
}
在load_ta 中通过TEECI_LoadSecureModule 开加载ta的binary
 {
 #ifdef TEEC_TEST_LOAD_PATH
     int res;
 
     res = try_load_secure_module(TEEC_TEST_LOAD_PATH,
                      dev_path, destination, ta, ta_size);
     if (res != TA_BINARY_NOT_FOUND)
         return res;
 #endif
 
     return try_load_secure_module(TEEC_LOAD_PATH,
                       dev_path, destination, ta, ta_size);
 }
正式版本不会定义TEEC_TEST_LOAD_PATH,因此调用try_load_secure_module
static int try_load_secure_module(const char* prefix,
                  const char* dev_path,
                  const TEEC_UUID *destination, void *ta,
                  size_t *ta_size)
{
    char fname[PATH_MAX];
    FILE *file = NULL;
    bool first_try = true;
    size_t s;
    int n;

    if (!ta_size || !destination) {
        printf("wrong inparameter to TEECI_LoadSecureModule\n");
        return TA_BINARY_NOT_FOUND;
    }

    /*
     * We expect the TA binary to be named after the UUID as per RFC4122,
     * that is: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.ta
     * If the file cannot be open, try the deprecated format:
     * xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx.ta
     */
again:
    n = snprintf(fname, PATH_MAX,
             "%s/%s/%08x-%04x-%04x-%02x%02x%s%02x%02x%02x%02x%02x%02x.ta",
             prefix, dev_path,
             destination->timeLow,
             destination->timeMid,
             destination->timeHiAndVersion,
             destination->clockSeqAndNode[0],
             destination->clockSeqAndNode[1],
             first_try ? "-" : "",
             destination->clockSeqAndNode[2],
             destination->clockSeqAndNode[3],
             destination->clockSeqAndNode[4],
             destination->clockSeqAndNode[5],
             destination->clockSeqAndNode[6],
             destination->clockSeqAndNode[7]);

    DMSG("Attempt to load %s", fname);

    if ((n < 0) || (n >= PATH_MAX)) {
        EMSG("wrong TA path [%s]", fname);
        return TA_BINARY_NOT_FOUND;
    }

    file = fopen(fname, "r");
    if (file == NULL) {
        DMSG("failed to open the ta %s TA-file", fname);
        if (first_try) {
            first_try = false;
            goto again;
        }
        return TA_BINARY_NOT_FOUND;
    }

    if (fseek(file, 0, SEEK_END) != 0) {
        fclose(file);
        return TA_BINARY_NOT_FOUND;
    }

    s = ftell(file);
    if (s > *ta_size || !ta) {
        /*
         * Buffer isn't large enough, return the required size to
         * let the caller increase the size of the buffer and try
         * again.
         */
        goto out;
    }

    if (fseek(file, 0, SEEK_SET) != 0) {
        fclose(file);
        return TA_BINARY_NOT_FOUND;
    }

    if (s != fread(ta, 1, s, file)) {
        printf("error fread TA file\n");
        fclose(file);
        return TA_BINARY_NOT_FOUND;
    }

out:
    *ta_size = s;
    fclose(file);
    return TA_BINARY_FOUND;
}
try_load_secure_module 也就是直接调用fread将binary读到内存中.
最后通过TEE_IOC_SUPPL_SEND 告诉optee_linuxdriver处理的结果
static bool write_response(int fd, union tee_rpc_invoke *request)
{
    struct tee_ioctl_buf_data data;

    data.buf_ptr = (uintptr_t)&request->send;
    data.buf_len = sizeof(struct tee_iocl_supp_send_arg) +
               sizeof(struct tee_ioctl_param) *
                request->send.num_params;
    if (ioctl(fd, TEE_IOC_SUPPL_SEND, &data)) {
        EMSG("TEE_IOC_SUPPL_SEND: %s", strerror(errno));
        return false;
    }
    return true;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值