4、TEE接口标准:GlobalPlatform TEE API、TEE Client API、TEE Internal Core API 概览

聊到TEE的接口标准,GlobalPlatform(GP)是绕不开的。说白了,它就是TEE世界的“普通话”。没有这套标准,各家芯片厂的TEE就像方言一样,你写个应用还得针对不同平台各搞一套,那运维成本就上去了。

我最早接触GP标准是在一个金融支付项目里。当时客户要求TEE必须通过GP兼容性认证,我心想不就是调几个API嘛,结果一翻规范文档——好家伙,光TEE Internal Core API就定义了上百个函数。嗯,今天咱们就把这三类API掰开揉碎,看看它们各自管什么、怎么用。

4.1 三层架构:谁在跟谁说话?

先看整体结构。GP把TEE的软件栈分成了三层,每一层都有对应的API:

  • TEE Client API:跑在REE侧(也就是Android/Linux等普通操作系统),供CA(Client Application)调用,用来跟TEE建立会话、传输数据。
  • TEE Internal Core API:跑在TEE侧,供TA(Trusted Application)调用,提供加解密、安全存储、时钟等核心能力。
  • TEE Sockets API / TEE DataStream API:扩展接口,用于网络通信和流式数据传输,咱们后面章节再细聊。

我习惯把这三层想象成“前台-后台-仓库”的关系:CA是前台接待,负责收单;TA是后台处理,负责干活;Internal Core API就是仓库里的工具,锤子扳手一应俱全。

核心要点:CA和TA永远不在同一个世界。CA在REE,TA在TEE,它们之间通过共享内存和SMC(安全监控调用)通信。Client API就是CA的“电话机”,Internal Core API是TA的“工具箱”。

TEE三层架构与API调用关系 REE(普通执行环境) CA (Client Application) TEE Client API → 建立会话、传输命令 ← TEE(可信执行环境) TA (Trusted Application) TEE Internal Core API → 加解密、安全存储 ← SMC / 共享内存 安全硬件(TrustZone / SE / Intel SGX) 硬件隔离、安全启动、内存加密 💡 说明 • Client API 是 CA 的“电话机”,负责拨号(建立会话)和挂断(关闭会话)。 • Internal Core API 是 TA 的“工具箱”,提供加解密、安全存储、时钟等。 • 两者通过 TEE 内核的通信机制(SMC + 共享内存)交换数据。

4.2 TEE Client API:CA的“电话机”

Client API是CA与TEE通信的唯一入口。它定义在GP的《TEE Client API Specification》里,核心就几个函数:

函数 作用 我踩过的坑
TEEC_InitializeContext 初始化TEE上下文,建立通信通道 忘记检查返回值,导致后续调用全挂
TEEC_OpenSession 打开与指定TA的会话 UUID写错一个字节,会话死活打不开
TEEC_InvokeCommand 向TA发送命令,携带参数 共享内存没对齐,TA读数据全是乱码
TEEC_CloseSession 关闭会话 忘了调用,导致TA资源泄漏
TEEC_FinalizeContext 释放TEE上下文 重复调用导致double-free崩溃

一个典型的CA调用流程是这样的:

// 1. 初始化上下文
TEEC_Context ctx;
result = TEEC_InitializeContext(NULL, &ctx);
if (result != TEEC_SUCCESS) {
    // 我曾经在这里吃过亏——没判断返回值就直接往下走
    return -1;
}

// 2. 打开会话
TEEC_Session session;
TEEC_UUID uuid = MY_TA_UUID;  // 注意:UUID必须与TA声明一致
result = TEEC_OpenSession(&ctx, &session, &uuid,
                          TEEC_LOGIN_PUBLIC, NULL, NULL, NULL);
if (result != TEEC_SUCCESS) {
    TEEC_FinalizeContext(&ctx);
    return -1;
}

// 3. 调用命令
TEEC_Operation op;
op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE,
                                  TEEC_NONE, TEEC_NONE);
op.params[0].value.a = 42;
result = TEEC_InvokeCommand(&session, CMD_HELLO, &op, NULL);

// 4. 清理
TEEC_CloseSession(&session);
TEEC_FinalizeContext(&ctx);

避坑指南:我曾经在一个项目里发现,CA调用TEEC_InvokeCommand后TA返回的数据总是错的。查了两天才发现——共享内存的物理地址没做cache一致性维护。嗯,ARM平台下记得用TEEC_RegisterSharedMemory注册内存,别自己malloc就传进去。

4.3 TEE Internal Core API:TA的“工具箱”

Internal Core API是TA开发者的主战场。它定义在GP的《TEE Internal Core API Specification》里,涵盖了TA需要的所有基础能力。我把它分成几大类:

4.3.1 加解密与哈希

  • TEE_AllocateOperation / TEE_FreeOperation:创建/销毁密码操作句柄
  • TEE_AEInit / TEE_AEDecryptFinal:对称加解密(AES、SM4等)
  • TEE_AsymmetricEncrypt / TEE_AsymmetricDecrypt:非对称加解密(RSA、ECC、SM2)
  • TEE_DigestUpdate / TEE_DigestDoFinal:哈希计算(SHA-256、SM3)

你想想看,TA里做加解密,最怕什么?密钥泄露。所以GP规定:密钥对象必须用TEE_GenerateKey或TEE_AllocateTransientObject创建,且存储在TEE安全内存中。CA永远拿不到密钥的明文。

4.3.2 安全存储

  • TEE_CreatePersistentObject:创建持久化对象(文件)
  • TEE_ReadObjectData / TEE_WriteObjectData:读写数据
  • TEE_OpenPersistentObject:打开已有对象

安全存储的数据是加密后写入flash的,密钥由TEE硬件派生。我记得有一次,客户要求TA存储的密钥必须能跨设备恢复——嗯,这就涉及到安全存储的“迁移”问题了,后面咱们专门讲。

4.3.3 时间与随机数

  • TEE_GetSystemTime:获取系统时间(注意:这个时间可能被REE篡改,不能用于安全校验)
  • TEE_GenerateRandom:生成真随机数(基于硬件熵源)

警告:千万不要在TA里用TEE_GetSystemTime做超时判断!我曾经在一个支付项目里,攻击者通过修改REE系统时间绕过了TA的支付超时检查。正确的做法是用TEE_GetTAPersistentTime或硬件计时器。

4.4 TEE Internal Core API 的“潜规则”

光看函数签名是不够的。我总结了几个实战中容易翻车的地方:

  1. 句柄必须显式释放:TEE_AllocateOperation、TEE_AllocateTransientObject返回的都是句柄,用完不释放就是内存泄漏。TA崩溃了TEE会帮你回收,但优雅退出时一定要自己清理。
  2. 参数类型要匹配:TEE_OperationMode有TEE_MODE_ENCRYPT和TEE_MODE_DECRYPT,搞反了加解密结果就是一团乱码。我见过有人把AES加密模式设成TEE_MODE_DECRYPT,然后debug了一整天。
  3. 共享内存大小有限:GP规范建议单次传输不超过4KB。大数据量要分片传输,或者用TEE_RegisterSharedMemory注册大块内存。
  4. 异常处理不能省:每个API都可能返回TEE_ERROR_OUT_OF_MEMORY、TEE_ERROR_SECURITY等错误码。不检查返回值,线上出问题连日志都找不到。

4.5 三类API的协作关系

最后用一张表总结它们的分工:

API类别 调用方 运行环境 核心职责 典型函数数
TEE Client API CA REE 建立会话、传输命令、管理共享内存 约20个
TEE Internal Core API TA TEE 加解密、安全存储、时间、随机数、对象管理 约120个
TEE Sockets API TA TEE 网络通信(可选扩展) 约15个

说白了,Client API是“门面”,Internal Core API是“内核”。CA通过Client API敲开TEE的门,TA用Internal Core API干活。两者配合好了,你的TEE应用才能既安全又高效。

我个人习惯在项目初期就把这三类API的调用链路画出来——CA调了哪个Client API、对应TA里哪个Internal Core API、数据怎么流。画清楚了,后面写代码基本不会跑偏。