可信执行环境(安全编程篇)

安全应用编程模型

YoC OS的安全应用编程模型如下所示,YoC OS直接调用libcsiteeca.a库函数就可以完成对TEE OS里的可信应用的间接调用。libcsiteeca.a库基于TEE Client API接口实现,在利用TEE SDK开发可信应用的同时产生的,其接口是对可信应用调用的抽象封装,如需要进行个性化的可信应用的开发,具体详见Chapter 7-应用程序开发章节里的安全应用开发文档。

YoC安全应用开发

TEE OS和YoC OS是独立运行的,利用YoC SDK可以生成TEE OS镜像,再生成YoC OS镜像。随着YoC SDK发布的TEE OS里已经预置了一些可信应用,YoC安全应用直接调用libcsiteeca.a库函数就可以完成安全应用的调用。

1. 获取YoC SDK

获取SDK之前先安装yoctools工具。yoctools安装以及使用请看YoCTools

通过yoc命令安装:yoc install sdk_pangu,安装完毕之后,可以看到如下目录:

ls boards components solutions
boards:
pangu_cpu0

components:
amrnb  aui_cloud  ble_mesh  console    drivers           drv_snd_pangu       flac        ipc   ...

solutions:
pangu_demo  pangu_player  pangu_rec_demo  pangu_tee  pangu_tee_test

2. 系统启动镜像

YoC OS启动的流程有两种情况:包含TEE镜像和不包含TEE镜像。 我们可以在config.yaml脚本里为每一个镜像配置地址空间, 以pangu_cpu0为例, config.yaml位于

  ./boards/pangu_cpu0/configs/config.yaml

我们通过修改config.yaml脚本来修改TEE和PRIM的FLASH地址空间,并确保各镜像地址不重叠。

注意TEE和PRIM的RAM地址空间配置请参考后面章节。

  • 启动流程包含TEE

    partitions:
      - { name: bmtb,   address: 0x8000000, size: 0x001000 }
      - { name: boot,   address: 0x8001000, size: 0x010000 }
      - { name: tee,    address: 0x8011000, load_addr: 0x18000000, size: 0x010000 }
      - { name: imtb,   address: 0x8021000, size: 0x002000 }
      - { name: prim,   address: 0x8023000, load_addr: 0x18010000, size: 0x300000, verify: true, update: DIFF}
      - { name: cpu1,   address: 0x8323000, size: 0x080000, update: DIFF }
      - { name: cpu2,   address: 0x83A3000, size: 0x200000, update: DIFF }
      - { name: kv,     address: 0x8623000, size: 0x004000 }
      - { name: lpm,    address: 0x8627000, size: 0x020000 }
      - { name: misc,   address: 0x8647000, size: 0x400000 }
      - { name: kp,     address: 0x8FFF000, size: 0x001000 }
    
  • 启动流程包不含TEE

    partitions:
      - { name: bmtb,   address: 0x8000000, size: 0x001000 }
      - { name: boot,   address: 0x8001000, size: 0x010000 }
      - { name: imtb,   address: 0x8021000, size: 0x002000 }
      - { name: prim,   address: 0x8023000, load_addr: 0x18010000, size: 0x300000, verify: true, update: DIFF}
      - { name: cpu1,   address: 0x8323000, size: 0x080000, update: DIFF }
      - { name: cpu2,   address: 0x83A3000, size: 0x200000, update: DIFF }
      - { name: kv,     address: 0x8623000, size: 0x004000 }
      - { name: lpm,    address: 0x8627000, size: 0x020000 }
      - { name: misc,   address: 0x8647000, size: 0x400000 }
      - { name: kp,     address: 0x8FFF000, size: 0x001000 }
    

在编译生成YoC OS镜像的时候,每个镜像的地址空间从该脚本里读取,最终生成系统镜像

3. 编译生成TEE OS镜像

pangu_tee solution工程位于

./solutions/pangu_tee

TEE OS镜像的地址空间配置文件tee_addr_map.h,该文件位于

/solutions/pangu_tee/csi_arch/ck804t/tw/inc/hobbit4/tee_addr_map.h
  • 更新TEE OS地址空间 打开tee_addr_map.h后, 修改以下四个配置宏来更改TEE OS的地址空间,我们将config.yaml 里的TEE的FLASH的起始地址和大小配置到TW_RO_ADDR和TW_RO_SIZE, TEE OS的RAM地址空间通过修改TW_RW_ADDR和TW_RW_SIZE来实现(一般TEE OS的RAM使用系统RAM最靠前部分), 注意TEE OS使用的RAM地址空间不能和PRIM重叠, PRIM使用的RAM地址空间请在gcc_eflash.ld.S里查看, 防止地址重叠,gcc_eflash.ld.S位于:

    ./solutions/pangu_tee/gcc_flash.ld
    

    如果无需改动则调过此步骤。

    #define TW_RO_ADDR      0x18000000  // TEE OS FLASH start address
    #define TW_RO_SIZE      0x00008000  // TEE OS FLASH SIZE
    #define TW_RW_ADDR      0x18008000  // TEE OS RAM start address
    #define TW_RW_SIZE      0x00004000  // TEE OS RAM size
    
  • 编译生成TEE OS 在根目录下执行"make"来编译生成TEE OS, 最终生成tee文件和libcsiteeca.a文件

  • 安装TEE OS 将tee文件复制到下面目录,

    ./boards/pangu_cpu0/bootimgs
    

    将libcsiteeca.a文件复制到以下目录

    ./components/csi_pangu/tee
    

4. 开发YoC安全应用

YoC安全应用的开发直接调用libcsiteeca.a库函数即可以, 该库函数的函数申明在tee.h里。 其中libcsiteeca.a和tee.h分别位于

./components/csi_pangu/tee/libcsiteeca.a

./components/csi/include/drv/tee.h

具体接口使用说明请参考后续的章节。

利用libcsiteeca.a库函数实现安全应用的参考代码如下:

  • AES算法接口使用参考代码
    const uint8_t in[16] = "Hello, World!";
    uint8_t iv[16] = {0};
    const uint8_t key[32] = "Demo-Key";

    int32_t ret;
    uint8_t out[16] = {};
    uint8_t out2[16] = {};
    int i;

    TEE_LOGI("AES CBC source string:%s\n", in);
    TEE_HEX_DUMP("AES CBC IV:", iv, 16);
    TEE_HEX_DUMP("AES CBC KEY:", key, 32);

    for (i = 0; i < AES_CASE_NUM; i++) {
        memset(out, 0, 16);
        memset(out2, 0, 16);
        memset(iv, 0, 16);

        TEE_LOGI("%s TEST\n", aes_case[i].case_name);
        TEE_HEX_DUMP("expect out:", aes_case[i].expect_out, 16);

        ret = csi_tee_aes_encrypt(in, 16, key, aes_case[i].key_len, iv, out, aes_case[i].mode);

        if (0 == ret) {
            TEE_HEX_DUMP("encrypt:", out, 16);
            TEE_LOGE("%s encrypt test: %s\n", aes_case[i].case_name, memcmp(out, aes_case[i].expect_out, 16) ? "Fail" : "Pass");
        } else {
            TEE_LOGE("%s test: Fail, ret 0x%x\n",  aes_case[i].case_name, ret);
        }

        memset(iv, 0, 16);

        ret = csi_tee_aes_decrypt(out, 16, key, aes_case[i].key_len, iv, out2, aes_case[i].mode);

        if (0 == ret) {
            TEE_HEX_DUMP("decrypt:", out2, 16);
            TEE_LOGE("%s decrypt test: %s\n", aes_case[i].case_name, memcmp(out2, in, 16) ? "Fail" : "Pass");
        } else {
            TEE_LOGE("%s test: Fail, ret 0x%x\n", aes_case[i].case_name, ret);
        }
    }
  • SHA运算接口使用参考代码

      uint8_t digest[64] = {0};
      int i, ret;
    
      TEE_HEX_DUMP("SHA source", (uint8_t *)data_in, sizeof(data_in));
    
      for (i = 0; i < SHA_CASE_NUM; i++) {
          memset(digest, 0, sizeof(digest));
    
          TEE_LOGI("%s TEST\n", sha_case[i].case_name);
          TEE_HEX_DUMP("expect out:", sha_case[i].expect_out, sha_case[i].hash_len);
    
          ret = csi_tee_sha_digest((uint8_t *)data_in, sizeof(data_in), digest, sha_case[i].type);
    
          if (ret == 0) {
              TEE_HEX_DUMP("digest:", digest, sha_case[i].hash_len);
              TEE_LOGI("%s digest test: %s\n", sha_case[i].case_name, memcmp(digest, sha_case[i].expect_out, sha_case[i].hash_len) ? "Fail" : "Pass");
          } else {
              TEE_LOGI("%s digest test: Fail, ret 0x%x\n", sha_case[i].case_name, ret);
          }
      }
    
  • RSA算法接口使用参考代码

      ret = csi_tee_rsa_sign(Digest, 32,
                             rsa2048_key, sizeof(rsa2048_key),
                             dst_2048, &dst_size,
                             TEE_RSA_SHA256);
    
      TEE_HEX_DUMP("RSA2048 SHA256 sign:", dst_2048, dst_size);
    
      if (ret) {
          TEE_LOGI("RSA2048 sign Fail,ret %x", ret);
      }
    
      ret = csi_tee_rsa_verify(Digest, 32,
                               rsa2048_pub_key, sizeof(rsa2048_pub_key),
                               dst_2048, dst_size,
                               TEE_RSA_SHA256);
      TEE_LOGI("RSA2048 SHA256 sign and verify: %s\n", ret ? "Fail" : "Pass");
    
      ret =  csi_tee_rsa_encrypt(Digest, 32,
                                 rsa2048_pub_key, sizeof(rsa2048_pub_key),
                                 dst_2048, &dst_size,
                                 TEE_RSA_PKCS1_PADDING);
      TEE_HEX_DUMP("RSA2048 encrypt:", dst_2048, dst_size);
    
      if (ret) {
          TEE_LOGI("RSA2048 encrypt Fail,ret %x", ret);
      }
    
      ret = csi_tee_rsa_decrypt(dst_2048, dst_size,
                                rsa2048_key, sizeof(rsa2048_key),
                                dst_2048, &dst_size,
                                TEE_RSA_PKCS1_PADDING);
      TEE_HEX_DUMP("RSA2048 decrypt:", dst_2048, dst_size);
    
      if (ret == 0) {
          TEE_LOGI("RSA2048 encrypt and decrypt: %s\n", memcmp(dst_2048, Digest, 20) ? "Fail" : "Pass");
      } else {
          TEE_LOGI("RSA2048 decrypt Fail,ret %x", ret);
      }
    
  • 系统频率接口操作实例代码

      uint32_t sysclk;
    
      csi_tee_get_sys_freq(&sysclk);
      printf("current system clock is %d\n", sysclk);
    
      csi_tee_set_sys_freq(EHS_CLK, OSR_8M_CLK_24M);
      console_init_ree(24000000);
      printf("set system clock to %d\n", 24000000);
    
      csi_tee_get_sys_freq(&sysclk);
      printf("current system clock is %d\n", sysclk);
    

5. 编译生成YoC OS镜像

所有的YoC安全应用开发完了以后,就可以通过在solutions下的应用目录进行编译,这里以pangu_demo为例,

在solutions/pangu_demo/目录下执行"make"指令来完成YoC OS镜像的生成。具体编译结果如下:

YoC SDK Done
[INFO] Create bin files
----------------------------------------------------------------
                bmtb, 0, 0, 0x08000000, 0x00001000, 0x08001000, bmtb
                boot, 0, 0, 0x08001000, 0x00010000, 0x08011000, boot
                 tee, 0, 0, 0x08011000, 0x00010000, 0x08021000, tee
                imtb, 0, 0, 0x08021000, 0x00002000, 0x08023000, imtb
                prim, 1, 1, 0x08023000, 0x00300000, 0x08323000, prim
                cpu1, 0, 1, 0x08323000, 0x00080000, 0x083a3000, cpu1
                cpu2, 0, 1, 0x083a3000, 0x00200000, 0x085a3000, cpu2
                  kv, 0, 0, 0x08623000, 0x00004000, 0x08627000
                 lpm, 0, 0, 0x08627000, 0x00020000, 0x08647000, lpm
                misc, 0, 0, 0x08647000, 0x00400000, 0x08a47000
                  kp, 0, 0, 0x08fff000, 0x00001000, 0x09000000, kp
    boot,    41516 bytes
     tee,    21604 bytes
    prim,  1312364 bytes
    cpu1,   427844 bytes
    cpu2,   347444 bytes
     lpm,    24484 bytes
      kp,      576 bytes
    bmtb,      192 bytes
    imtb,     8192 bytes
----------------------------------------------------------------

其中prim镜像就是YoC OS镜像, tee镜像就是之前生成的TEE OS镜像,其他的镜像在默认情况下不用改动,如需要改动,请参考相应模块的章节。最终,所有的镜像都会打包成一个total_image.hex镜像, 直接利用烧录工具进行烧写即可,具体烧录步骤请参考相应章节,total_image.hex镜像位于

/solutions/pangu_demo/generated/total_image.hex

这里,YoC安全应用开发完毕。

6. 烧写YoC镜像

请参考镜像烧写章节。

7. 系统运行

按下启动按钮,系统开始运行,在串口控制台可以看到如下打印信息说明系统运行成功。

TEE v1.1 Initialize done.

由于TEE在系统运行过程中调试信息关闭,所以如果要确认可信安全应用是否正确执行,可以根据libcsiteeca.a库函数的返回值和参数来判断。

CSI TEE CA接口定义

返回值

#define TEEC_SUCCESS                    0x00000000
#define TEEC_ERROR_GENERIC              0xFFFF0000
#define TEEC_ERROR_ACCESS_DENIED        0xFFFF0001
#define TEEC_ERROR_CANCEL               0xFFFF0002
#define TEEC_ERROR_ACCESS_CONFLICT      0xFFFF0003
#define TEEC_ERROR_EXCESS_DATA          0xFFFF0004
#define TEEC_ERROR_BAD_FORMAT           0xFFFF0005
#define TEEC_ERROR_BAD_PARAMETERS       0xFFFF0006
#define TEEC_ERROR_BAD_STATE            0xFFFF0007
#define TEEC_ERROR_ITEM_NOT_FOUND       0xFFFF0008
#define TEEC_ERROR_NOT_IMPLEMENTED      0xFFFF0009
#define TEEC_ERROR_NOT_SUPPORTED        0xFFFF000A
#define TEEC_ERROR_NO_DATA              0xFFFF000B
#define TEEC_ERROR_OUT_OF_MEMORY        0xFFFF000C
#define TEEC_ERROR_BUSY                 0xFFFF000D
#define TEEC_ERROR_COMMUNICATION        0xFFFF000E
#define TEEC_ERROR_SECURITY             0xFFFF000F
#define TEEC_ERROR_SHORT_BUFFER         0xFFFF0010

数据结构

AES模式类型

typedef enum {
    TEE_AES_MODE_ECB = 0,    ///< TEE AES ECB mode
    TEE_AES_MODE_CBC = 1,    ///< TEE AES CBC mode
    TEE_AES_MODE_MAX,        ///< invaild mode
} tee_aes_mode_e;

低功耗操作类型

typedef enum {
    TEE_LPM_MODE_WAIT = 0,   ///< lpm wait
    TEE_LPM_MODE_DOZE = 1,   ///< lpm doze
    TEE_LPM_MODE_STOP = 2,   ///< lpm stop
    TEE_LPM_MODE_STANDBY = 3, ///< lpm standby
    TEE_LPM_MODE_CLOCK = 4,  ///< lpm clock gate
    TEE_LPM_MODE_MAX,
} tee_lpm_mode_e;

RSA签名类型

typedef enum {
    TEE_RSA_MD5    = 0,     ///< MD5
    TEE_RSA_SHA1   = 1,     ///< SHA1
    TEE_RSA_SHA256 = 3,     ///< SHA256
    TEE_RSA_SIGN_TYPE_MAX,  ///< invailed type
} tee_rsa_sign_type_e;

RSA 填充类型

typedef enum {
    TEE_RSA_PKCS1_PADDING = 0x01,     ///< RSA PKCS padding mode
    TEE_RSA_NO_PADDING    = 0x02,     ///< RSA no padding mode
} tee_rsa_padding_mode_e;

SHA 运算操作类型

typedef enum {
    TEE_HASH_OP_NONE = 0,     ///< No operation
    TEE_HASH_OP_START = 1,    ///< HASH init
    TEE_HASH_OP_UPDATA = 2,   ///< HASH update
    TEE_HASH_OP_FINISH = 3,   ///< HASH finish
    TEE_HASH_OP_MAX,          ///< invailed operation
} tee_hash_op_e;

SHA 运算模式类型

typedef enum {
    TEE_SHA1 = 0,   ///< SHA1
    TEE_SHA256 = 1, ///< SHA256
    TEE_SHA224 = 2, ///< SHA224
    TEE_SHA384 = 3, ///< SHA384
    TEE_SHA512 = 4, ///< SHA512
    TEE_SHA_MAX,    ///< invaild sha type
} tee_sha_type_t;

系统时钟类型

typedef enum {
    IHS_CLK       = 0,         /* internal high speed clock */
    EHS_CLK       = 1,         /* external high speed clock */
    ILS_CLK       = 2,         /* internal low speed clock */
    ELS_CLK       = 3          /* enternal low speed clock */
} clk_src_e;

系统时钟频率

typedef enum {
    OSR_8M_CLK_16M      = 0x80204, ///< register value for clock 16M
    OSR_8M_CLK_24M      = 0x80206, ///< register value for clock 24M
    OSR_8M_CLK_32M      = 0x80208, ///< register value for clock 32M
    OSR_8M_CLK_40M      = 0x8020a, ///< register value for clock 40M
    OSR_8M_CLK_48M      = 0x8020c  ///< register value for clock 48M
} clk_val_e;

AES ECB模式加密

int32_t csi_tee_aes_encrypt_ecb(const uint8_t *in, 
                                uint32_t in_len, 
                                uint8_t *key, 
                                uint32_t key_len, 
                                uint8_t *out);
  • 参数
    • in: 输入数据缓冲区指针
    • in_len: 输入数据长度
    • key: 输入加密密钥缓冲区指针
    • key_len: 输入加密密钥长度
    • out: 输出数据缓冲区指针
  • 返回值
    • ==TEEC_SUCCESS: 成功
    • !=TEEC_SUCCESS: 失败

AES ECB模式解密

int32_t csi_tee_aes_decrypt_ecb(const uint8_t *in, 
                                uint32_t in_len, 
                                uint8_t *key, 
                                uint32_t key_len, 
                                uint8_t *out);
  • 参数
    • in: 输入数据缓冲区指针
    • in_len: 输入数据长度
    • key: 输入解密密钥缓冲区指针
    • key_len: 输入解密密钥长度
    • out: 输出数据缓冲区指针
  • 返回值
    • ==TEEC_SUCCESS: 成功
    • !=TEEC_SUCCESS: 失败

AES CBC模式加密

int32_t csi_tee_aes_encrypt_cbc(const uint8_t *in, 
                                uint32_t in_len, 
                                uint8_t *key, 
                                uint32_t key_len, 
                                uint8_t *iv,
                                uint8_t *out);
  • 参数
    • in: 输入数据缓冲区指针
    • in_len: 输入数据长度
    • key: 输入加密密钥缓冲区指针
    • key_len: 输入加密密钥长度
    • iv: 输入的iv向量
    • out: 输出数据缓冲区指针
  • 返回值
    • ==TEEC_SUCCESS: 成功
    • !=TEEC_SUCCESS: 失败

AES CBC模式解密

int32_t csi_tee_aes_decrypt_cbc(const uint8_t *in, 
                                uint32_t in_len, 
                                uint8_t *key, 
                                uint32_t key_len, 
                                uint8_t *iv,
                                uint8_t *out);
  • 参数
    • in: 输入数据缓冲区指针
    • in_len: 输入数据长度
    • key: 输入解密密钥缓冲区指针
    • key_len: 输入解密密钥长度
    • iv: 输入的iv向量
    • out: 输出数据缓冲区指针
  • 返回值
    • ==TEEC_SUCCESS: 成功
    • !=TEEC_SUCCESS: 失败

RSA 签名

int32_t csi_tee_rsa_sign(const uint8_t *in, uint32_t in_len,
                         const uint8_t *key, uint32_t key_len,
                         uint8_t *sign, uint32_t *sign_len,
                         tee_rsa_sign_type_e type);
  • 参数
    • in: 输入数据缓冲区指针
    • in_len: 输入数据长度
    • key: 输入密钥缓冲区指针
    • key_len: 输入密钥长度
    • sign: 签名数据缓冲区指针
    • sign_len: 签名数据长度变量指针
    • type: 签名类型
  • 返回值
    • ==TEEC_SUCCESS: 成功
    • !=TEEC_SUCCESS: 失败

RSA 验签

int32_t csi_tee_rsa_verify(const uint8_t *in, uint32_t in_len,
                         const uint8_t *key, uint32_t key_len,
                         uint8_t *sign, uint32_t sign_len,
                         tee_rsa_sign_type_e type);
  • 参数
    • in: 输入数据缓冲区指针
    • in_len: 输入数据长度
    • key: 输入密钥缓冲区指针
    • key_len: 输入密钥长度
    • sign: 签名数据缓冲区指针
    • sign_len: 签名数据长度变量指针
    • type: 签名类型
  • 返回值
    • ==TEEC_SUCCESS: 成功
    • !=TEEC_SUCCESS: 失败

RSA 加密

int32_t csi_tee_rsa_encrypt(const uint8_t *in, uint32_t in_len,
                            const uint8_t *key, uint32_t key_len,
                            uint8_t *out, uint32_t *out_len,
                            tee_rsa_padding_mode_e padding);
  • 参数
    • in: 输入数据缓冲区指针
    • in_len: 输入数据长度
    • key: 输入密钥缓冲区指针
    • key_len: 输入密钥长度
    • out: 密文数据缓冲区指针
    • out_len: 密文数据长度变量指针
    • padding: 填充算法类型
  • 返回值
    • ==TEEC_SUCCESS: 成功
    • !=TEEC_SUCCESS: 失败

RSA 解密

int32_t csi_tee_rsa_decrypt(const uint8_t *in, uint32_t in_len,
                            const uint8_t *key, uint32_t key_len,
                            uint8_t *out, uint32_t *out_len,
                            tee_rsa_padding_mode_e padding);
  • 参数
    • in: 输入数据缓冲区指针
    • in_len: 输入数据长度
    • key: 输入密钥缓冲区指针
    • key_len: 输入密钥长度
    • out: 明文数据缓冲区指针
    • out_len: 明文数据长度变量指针
    • padding: 填充算法类型
  • 返回值
    • ==TEEC_SUCCESS: 成功
    • !=TEEC_SUCCESS: 失败

SHA 运算操作启动


int32_t csi_tee_sha_start(tee_sha_type_t type, void *ctx);
  • 参数
    • type: 哈希运算类型
    • ctx: 哈希运算上下文指针
  • 返回值
    • ==TEEC_SUCCESS: 成功
    • !=TEEC_SUCCESS: 失败

SHA 运算操作更新

int32_t csi_tee_sha_update(const uint8_t *in, uint32_t in_len, void *ctx);
  • 参数
    • in: 输入数据缓冲区指针
    • in_len: 输入数据长度
    • ctx: 哈希运算上下文指针
  • 返回值
    • ==TEEC_SUCCESS: 成功
    • !=TEEC_SUCCESS: 失败

SHA 运算操作结束

int32_t csi_tee_sha_finish(uint8_t *out, vid *ctx);
  • 参数
    • out: 输出数据缓冲区指针
    • ctx: 哈希运算上下文指针
  • 返回值
    • ==TEEC_SUCCESS: 成功
    • !=TEEC_SUCCESS: 失败

SHA 摘要运算

int32_t csi_tee_sha_digest(const uint8_t *in, uint32_t in_len, uint8_t *out, tee-sha_type_t type);
  • 参数
    • in: 输入数据缓冲区指针
    • in_len: 输入数据长度
    • out: 输出数据缓冲区指针
    • type: 哈希运算类型
  • 返回值
    • ==TEEC_SUCCESS: 成功
    • !=TEEC_SUCCESS: 失败

低功耗操作

int32_t csi_tee_enter_lpm(uint32_t gate, uint32_t irqid, tee_lpm_mode_e mode);
  • 参数
    • gate: IP clk gate配置字,具体参考PMU 寄存器说明
    • irqid: 保留
    • mode: 索要进入低功耗的模式
  • 返回值
    • ==TEEC_SUCCESS: 成功
    • !=TEEC_SUCCESS: 失败

设置系统频率

int32_t csi_tee_set_sys_freq(uint32_t clk_src, uint32_t clk_val);
  • 参数
    • clk_src: 系统内部或者外部时钟源选择
    • clk_val: 需要设置的系统频率
  • 返回值
    • ==TEEC_SUCCESS: 成功
    • !=TEEC_SUCCESS: 失败

获取系统频率

int32_t csi_tee_get_sys_freq(uint32_t *clk_val);
  • 参数
    • clk_val: 存放系统频率的数据变量指针
  • 返回值
    • ==TEEC_SUCCESS: 成功
    • !=TEEC_SUCCESS: 失败

results matching ""

    No results matching ""