zoukankan      html  css  js  c++  java
  • <OPTEE>Trusted Application结构分析

      最近又开始和Trusted Zone打起了交道,需要把Linaro开发的开源安全系统optee os移植到实验室的老板子上。不过导师要求我先开发一个应用,在普通环境和安全环境分别有一个程序,称为host与trusted application(简称TA)。让我在这个过程中了解一下这个系统。

      optee os的github地址:https://github.com/OP-TEE/optee_os,一天几个commit,那几个大神真是勤劳。

      不管怎么说,我要先搞清楚这个应用的结构,幸好这个项目还带有一个测试工具集optee test ,这个测试肯定包含host和TA两端,所以可以从这里入手学习。

      host就是一个普通的可执行文件,除了调用了TEE的Api,没什么特别的。

      TA端是OPTEE中运行的程序,有他的要求,下面以一个简单的测试存储的TA——storage为例介绍他的基本结构。

      程序文件

      

      include目录下的头文件  

      

      可以看到所需的文件并不多。简要介绍一下,makefile和sub.mk自不必说,storage.c写的是一些简单的调用TEE存储API的逻辑。

      ta_entry.c比较重要,是TA的入口,里面主要是

      TA_CreateEntryPoint,

      TA_DestroyEntryPoint,

      TA_OpenSessionEntryPoint,

      TA_CloseSessionEntryPoint,

      TA_InvokeCommandEntryPoint

      几个函数,是作用通过名字即可看出,在<tee_ta_api.h>中早有定义,每一个TA都要各自实现这几个函数,不过代码量很小,一般不需要写逻辑,声明出来,处理参数不要报错就行。其中的TA_InvokeCommandEntryPoint主体是一个switch,用传入的命令ID判断和分发。

      Ta_storage.h

    #ifndef TA_STORAGE_H
    #define TA_STORAGE_H
    #define TA_STORAGE_UUID { 0xb689f2a7, 0x8adf, 0x477a, 
        { 0x9f, 0x99, 0x32, 0xe9, 0x0c, 0x0a, 0xd0, 0xa2 } }
    
    #define TA_STORAGE_CMD_OPEN           0
    #define TA_STORAGE_CMD_CLOSE          1
    #define TA_STORAGE_CMD_READ           2
    #define TA_STORAGE_CMD_WRITE          3
    #define TA_STORAGE_CMD_CREATE         4
    #define TA_STORAGE_CMD_SEEK           5
    #define TA_STORAGE_CMD_UNLINK         6
    #define TA_STORAGE_CMD_RENAME         7
    #define TA_STORAGE_CMD_TRUNC          8
    #define TA_STORAGE_CMD_ALLOC_ENUM     9
    #define TA_STORAGE_CMD_FREE_ENUM      10
    #define TA_STORAGE_CMD_RESET_ENUM     11
    #define TA_STORAGE_CMD_START_ENUM     12
    #define TA_STORAGE_CMD_NEXT_ENUM      13
    
    #endif /*TA_SKELETON_H */

      上面定义了该TA的UUID, 以及各个命令的宏。OPTEE通过UUID唯一标识系统里的TA,因此这个UUID不能重复,这里建议的是通过网站ITU-T UUID generator

    http://www.itu.int/ITU-T/asn1/uuid.html)来创建唯一的ID,而且生成的数据长度和OPTEE的要求是一致的,只要按格式拆分就可以了。

      上述命令在TA_InvokeCommandEntryPoint函数中用switch分发命令调用,处理请求的实现写在storage.c中。

    TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext,
                          uint32_t nCommandID, uint32_t nParamTypes,
                          TEE_Param pParams[4])
    {
        (void)pSessionContext;
    
        switch (nCommandID) {
        case TA_STORAGE_CMD_OPEN:
            return ta_storage_cmd_open(nParamTypes, pParams);
    
        case TA_STORAGE_CMD_CLOSE:
            return ta_storage_cmd_close(nParamTypes, pParams)
    
            //......
    }        

      

      user_ta_header_defines.h,TA的头部信息,主要是UUID和一些空间信息。 

    #ifndef USER_TA_HEADER_DEFINES_H
    #define USER_TA_HEADER_DEFINES_H
    
    #include <ta_storage.h>
    
    #define TA_UUID TA_STORAGE_UUID
    
    /*
     * This is important to have TA_FLAG_SINGLE_INSTANCE && !TA_FLAG_MULTI_SESSION
     * as it is used by the ytest
     */
    #define TA_FLAGS        (TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR | 
                    TA_FLAG_SINGLE_INSTANCE)
    #define TA_STACK_SIZE        (2 * 1024)
    #define TA_DATA_SIZE        (32 * 1024)  

      

      在optee_os/../kernel tee_ta_Manager.c里面,tee_ta_init_static_ta_session函数中定义TA头部结构体类型,在OPTEE收到Host端的请求,准备初始化会话,加载对应的TA时,会创建一个TA指针,在循环中从内存中定义的start到stop移动,依次比对UUID,从而获取所需的TA头部指针,然后调用tee_ta_load函数,检查签名,加载待运行的TA。

    static TEE_Result tee_ta_init_static_ta_session(const TEE_UUID *uuid,
                    struct tee_ta_session *s)
    {
        struct tee_ta_ctx *ctx = NULL;
        ta_static_head_t *ta = NULL;
    
        DMSG("   Lookup for Static TA %08x-%04x-%04x",
             uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion);
    
        ta = &__start_ta_head_section;
        while (true) {
            if (ta >= &__stop_ta_head_section)
                return TEE_ERROR_ITEM_NOT_FOUND;
            if (memcmp(&ta->uuid, uuid, sizeof(TEE_UUID)) == 0)
                break;
            ta++;
        }
            //......
    }

      所以新增的TA应该预先把自己的头部结构体放在区间内,经过分析,只要在编译完成后,把.ta文件预先放在rootfs下的lib/optee_armtz/目录内即可,运行时,系统将把这个目录下的TA的头部都加载到内存中以供查找。至于如何打包,最好的方式还是通过修改makefile中Root FS部分内容,这样每次编译完都会把.ta打包入镜像。
      以上就是一个简单的TA项目基本的结构介绍和分析,更详细的代码请自行到github查看。

      optee_os

      optee test

  • 相关阅读:
    一个web应用的诞生(4)
    一个web应用的诞生(7)
    一个web应用的诞生(6)
    HTTP状态码大全(转自wiki)
    十分钟搞懂什么是CGI
    HTTP真的很简单
    QT程序在发布的时候应注意的地方
    QT中获取选中的radioButton的两种方法
    WinEdit编辑器中中文乱码
    C++ lstrlen()
  • 原文地址:https://www.cnblogs.com/aureate-sunshine/p/5341967.html
Copyright © 2011-2022 走看看