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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM