4. TEE安全世界软件栈

在ARM TrustZone技术中,“安全世界”(Secure World)是一个与“非安全世界”(Normal World)完全隔离的执行环境。本章深入剖析安全世界软件栈的三层核心架构:安全监控器(Secure Monitor)、安全世界操作系统(Secure OS)以及运行于其上的安全应用(Trusted Application, TA)。理解这三层的职责与协作关系,是设计安全存储密钥方案的基础。

核心概念:安全世界软件栈通过硬件强制隔离与软件分层设计,确保敏感操作(如密钥生成、加解密)在受保护的环境中执行,即使非安全世界的操作系统(如Linux/Android)被攻破,也无法窃取安全世界内的秘密。

4.1 安全世界软件栈总体架构

下图展示了安全世界软件栈的典型分层结构,以及与非安全世界的交互关系。安全监控器作为唯一的桥梁,控制着两个世界之间的切换。

安全世界软件栈总体架构图 安全世界软件栈总体架构 非安全世界 (Normal World) 普通应用 (CA) 普通应用 (CA) 非安全世界操作系统 (Linux / Android / 其他RTOS) 安全世界 (Secure World) 安全应用 (TA) 安全应用 (TA) 安全世界操作系统 (OP-TEE / Trusty / QSEE) 安全监控器 (Secure Monitor) (ARM Monitor Mode / EL3) TrustZone 硬件安全扩展 (Core / MMU / GIC / DMA 安全位) 说明:安全监控器是唯一跨越两个世界的软件组件,负责上下文切换和中断路由。
架构要点:安全世界操作系统运行在比非安全世界操作系统更高的特权级别(EL1S vs EL1NS),而安全监控器运行在最高特权级别EL3。这种分层设计确保了安全世界无法被非安全世界直接访问。

4.2 安全监控器(Secure Monitor)

安全监控器是TrustZone架构中最关键的软件组件,运行在ARMv8-A架构的EL3异常级别(或ARMv7-A的Monitor模式)。它负责管理两个世界之间的安全上下文切换,是系统安全的“守门人”。

4.2.1 核心职责

  • 世界切换(World Switch):通过执行SMC(Secure Monitor Call)指令,触发从非安全世界到安全世界(或反向)的切换。安全监控器保存当前世界的寄存器状态,恢复目标世界的寄存器状态。
  • 中断路由:配置GIC(通用中断控制器),将安全中断(如安全定时器、安全外设中断)直接路由到安全世界,非安全中断路由到非安全世界。
  • 安全启动验证:在系统启动时,安全监控器负责验证安全世界操作系统镜像的签名和完整性,确保只有经过授权的安全OS才能加载执行。
  • 安全资源管理:控制对安全物理内存区域(TZASC/TrustZone Address Space Controller)和安全外设的访问权限。

4.2.2 世界切换流程

下表总结了从非安全世界调用安全世界服务时的典型切换步骤:

步骤 执行组件 操作描述
1 非安全世界OS 准备参数(如TA UUID、命令ID),执行SMC #0指令
2 安全监控器 捕获SMC异常,保存非安全世界上下文(寄存器、系统寄存器)
3 安全监控器 恢复安全世界上下文,设置SCR(Secure Configuration Register)切换到安全世界
4 安全世界OS 接收请求,解析参数,调用对应的TA处理
5 安全世界OS TA处理完成后,执行SMC #0返回安全监控器
6 安全监控器 保存安全世界上下文,恢复非安全世界上下文,返回非安全世界
安全风险提示:安全监控器本身的代码量应尽可能小(通常只有几千行),以减少攻击面。任何安全监控器中的漏洞都可能导致整个TrustZone安全机制失效。常见的攻击向量包括:SMC参数校验不严、上下文保存不完整、中断处理竞争条件。

4.3 安全世界操作系统(Secure OS)

安全世界操作系统运行在安全世界的EL1S异常级别,为安全应用提供运行环境和基础服务。与通用操作系统不同,安全OS的设计目标是最小化、确定性、高安全性。目前主流的开源安全OS包括OP-TEE和Trusty。

4.3.1 安全OS的核心功能

  • TA生命周期管理:负责安全应用的加载、验证、调度和销毁。TA通常以独立的镜像文件存储在安全文件系统中。
  • 安全内存管理:管理安全世界物理内存的分配与释放,确保TA之间以及TA与安全OS内核之间的内存隔离。
  • 安全通信服务:提供与非安全世界通信的机制,如共享内存和消息队列。非安全世界通过安全监控器调用安全OS的RPC(远程过程调用)服务。
  • 密码学服务:提供硬件加速的密码学操作接口(如AES、RSA、SHA、TRNG),TA可以直接调用这些接口,无需自行实现。
  • 安全存储服务:管理密钥和敏感数据的持久化存储,通常基于硬件唯一密钥(HUK)对数据进行加密后存储在非安全世界的文件系统中。

4.3.2 OP-TEE vs Trusty 对比

特性 OP-TEE Trusty
开源协议 BSD-2-Clause Apache 2.0
维护方 Linaro / 社区 Google
主要应用场景 通用嵌入式、IoT、移动设备 Android设备(Pixel系列)
TA开发语言 C / C++ C / C++
调度模型 基于优先级的抢占式调度 基于线程的抢占式调度
共享内存机制 动态共享内存(通过SMC注册) 预分配共享内存池
安全存储实现 基于RPMB或SQLite加密 基于RPMB或文件系统加密
安全世界操作系统内部架构图 安全世界操作系统(Secure OS)内部架构 TA 1 (密钥管理) TA 2 (支付认证) TA 3 (DRM解密) TA 4 (生物识别) 安全OS内核 (Secure Kernel) TA调度器 安全内存管理 密码学服务 安全存储引擎 硬件抽象层 (HAL) / 安全监控器接口 说明:安全OS内核为多个TA提供隔离的执行环境,每个TA拥有独立的虚拟地址空间。

4.4 安全应用(Trusted Application, TA)

安全应用是运行在安全世界操作系统之上的可信程序,负责执行具体的敏感业务逻辑,如密钥生成、数据加解密、身份认证等。TA运行在EL0S异常级别,是安全世界中权限最低的组件,即使单个TA被攻破,也无法直接访问其他TA或安全OS内核的数据。

4.4.1 TA的典型结构

一个标准的TA通常包含以下组件:

  • 入口函数:TA_CreateEntryPoint(初始化)、TA_DestroyEntryPoint(销毁)、TA_OpenSessionEntryPoint(打开会话)、TA_CloseSessionEntryPoint(关闭会话)、TA_InvokeCommandEntryPoint(处理命令)。
  • 命令处理逻辑:根据非安全世界传入的命令ID,执行对应的安全操作。
  • 安全存储接口:调用安全OS提供的API(如TEE_ReadObjectData、TEE_WriteObjectData)读写持久化密钥。
  • 密码学操作接口:调用安全OS提供的密码学API(如TEE_AllocateOperation、TEE_CipherInit)执行加解密。

4.4.2 TA与非安全世界通信

TA与非安全世界的客户端应用(CA)通过TEE Client API进行通信。通信流程如下:

  1. CA发起会话:CA调用TEEC_OpenSession,指定目标TA的UUID。
  2. 安全OS路由:安全OS根据UUID查找并加载对应的TA镜像,创建会话上下文。
  3. CA发送命令:CA调用TEEC_InvokeCommand,传入命令ID和参数(通过共享内存传递)。
  4. TA处理命令:TA在安全世界内执行命令,访问安全资源(如密钥、硬件密码学引擎)。
  5. TA返回结果:TA将处理结果写入共享内存,安全OS将控制权返回给CA。
安全设计原则:TA应遵循最小权限原则,每个TA只拥有完成其任务所需的最小权限集。例如,密钥管理TA不应具备加解密大数据的能力,而应仅负责密钥的生成和导出(加密后导出)。

4.4.3 TA开发示例(OP-TEE)

以下是一个简单的OP-TEE TA代码片段,演示如何实现一个密钥生成命令:

// TA入口函数:处理命令
TEE_Result TA_InvokeCommandEntryPoint(void *sessionContext,
                                      uint32_t commandID,
                                      uint32_t paramTypes,
                                      TEE_Param params[4])
{
    TEE_Result res = TEE_SUCCESS;

    switch (commandID) {
    case TA_CMD_GENERATE_KEY:
        // 检查参数类型
        if (paramTypes != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
                                          TEE_PARAM_TYPE_NONE,
                                          TEE_PARAM_TYPE_NONE,
                                          TEE_PARAM_TYPE_NONE)) {
            return TEE_ERROR_BAD_PARAMETERS;
        }
        // 调用安全OS密码学API生成AES-256密钥
        res = generate_aes_key(params[0].memref.buffer,
                               params[0].memref.size);
        break;
    default:
        res = TEE_ERROR_NOT_SUPPORTED;
        break;
    }
    return res;
}

// 密钥生成内部函数
static TEE_Result generate_aes_key(uint8_t *key_buffer, uint32_t key_size)
{
    TEE_OperationHandle op_handle = TEE_HANDLE_NULL;
    TEE_Result res;

    // 分配密钥生成操作
    res = TEE_AllocateOperation(&op_handle,
                                TEE_ALG_AES_256,
                                TEE_MODE_GENERATE_KEY,
                                0);
    if (res != TEE_SUCCESS)
        return res;

    // 生成随机密钥
    res = TEE_GenerateKey(op_handle, key_size, NULL, 0);
    if (res != TEE_SUCCESS) {
        TEE_FreeOperation(op_handle);
        return res;
    }

    // 导出密钥到输出缓冲区
    res = TEE_GetObjectBufferAttribute(op_handle,
                                       TEE_ATTR_SECRET_VALUE,
                                       key_buffer,
                                       &key_size);
    TEE_FreeOperation(op_handle);
    return res;
}
开发建议:TA中不应包含任何硬编码的密钥或敏感常量。所有密钥应通过安全存储API从安全文件系统中读取,或通过硬件唯一密钥(HUK)派生。TA的日志输出应谨慎,避免泄露敏感信息。

4.5 三层架构的安全保障

安全世界软件栈的三层架构通过以下机制提供纵深防御:

层级 安全机制 防护目标
安全监控器 (EL3) 上下文隔离、中断路由控制、启动验证 防止非安全世界直接访问安全世界资源,确保切换安全
安全OS (EL1S) TA隔离、内存保护、权限控制、安全存储 防止TA之间相互干扰,保护TA数据不被非安全世界窃取
安全应用 (EL0S) 最小权限、沙箱执行、API安全校验 限制单个TA被攻破后的影响范围

这种分层设计使得攻击者必须同时突破多个安全层才能获取敏感密钥,极大地提高了攻击成本。在实际的密钥存储设计中,密钥通常由TA在安全世界内生成,并通过安全OS的安全存储服务加密后持久化,确保密钥明文永远不会暴露给非安全世界。