3. ARM TrustZone硬件机制

TrustZone 并不是一颗独立的安全芯片,而是 ARM 处理器内部一套贯穿核心、总线、内存与外设的硬件隔离机制。理解它,关键要抓住一条主线:处理器在任一时刻只处于一个安全状态,而所有资源访问都要经过硬件层面的安全判定。本节围绕安全状态切换、监控模式、安全配置寄存器、内存保护单元与地址空间控制器五个硬件要素展开,帮助读者建立 TrustZone 的底层执行模型。

一、核心原理:两个世界与一次切换

ARM TrustZone 将整个 SoC 划分为安全世界(Secure World)与非安全世界(Normal World)。两者可以运行各自的操作系统,例如安全侧运行 OP-TEE 等可信执行环境,非安全侧运行 Linux 或 Android。处理器通过一个名为 NS 位(Non-Secure bit)的硬件信号标识当前状态:NS=0 表示安全状态,NS=1 表示非安全状态。这个位会随总线请求一起传播,成为内存控制器、外设和互连总线判断访问合法性的依据。

状态切换不是软件随意跳转,而是通过一条专用指令 SMC(Secure Monitor Call)触发异常,进入监控模式完成上下文保存与状态翻转。因此,安全世界与非安全世界之间始终隔着一层受控的“门”,而不是直接函数调用。

TrustZone 安全状态切换与硬件判定链 安全世界 Secure World NS = 0 OP-TEE / Trusted OS 安全服务、密钥、DRM 可访问安全+非安全资源 非安全世界 Normal World NS = 1 Linux / Android / Rich OS 普通应用与驱动 仅可访问非安全资源 监控模式 Monitor SMC 异常入口 / 上下文保存 SMC 进入 SMC 进入 返回安全态 返回非安全态 硬件安全判定链 NS 位 → SCR 安全配置 → MPU/SAU 内存保护 → TZASC 地址空间控制器 → TZPC 外设保护 → 总线/内存控制器放行或拒绝

二、监控模式:两个世界之间的唯一通道

监控模式(Monitor Mode)是 TrustZone 中权限最高的处理器模式,通常运行一段极小的安全监控代码(Secure Monitor)。它承担三项职责:保存当前世界上下文、根据 SMC 调用号决定服务对象、恢复目标世界上下文并执行 ERET 返回。由于监控模式代码量小、攻击面窄,它成为整个信任链的根。

典型切换流程如下:

  1. 非安全世界执行 SMC #0,处理器进入监控模式,NS 位仍为 1。
  2. 监控代码保存非安全侧通用寄存器、系统寄存器与返回地址。
  3. 监控代码将 SCR.NS 清零,切换到安全状态,恢复安全侧上下文。
  4. 安全侧处理请求,完成后再次通过 SMC 回到监控模式。
  5. 监控代码恢复非安全上下文,将 SCR.NS 置 1,执行 ERET 返回。
关键点:监控模式不是“第三个世界”,而是状态切换的中转站。它本身运行在安全侧,但可以访问两个世界的上下文。

三、安全配置寄存器 SCR 与安全配置

安全配置寄存器(Secure Configuration Register,SCR)是控制安全状态行为的核心寄存器之一。它决定了 NS 位、中断路由、SMC 使能等关键行为。常见字段包括:

字段 含义 典型配置
NS 当前安全状态位 0=安全,1=非安全
IRQ / FIQ 中断路由到哪个世界 安全中断路由到安全侧
AW 是否允许非安全侧执行 WFI/WFE 按功耗策略设置
SMD 是否禁用 SMC 指令 通常保持使能

除 SCR 外,安全配置还涉及 SPSR、VBAR 等异常向量基址寄存器,以及安全侧独有的系统寄存器。配置错误会导致中断误入非安全侧,或 SMC 调用被意外屏蔽。

四、内存保护单元与地址空间控制器

仅有状态位还不够,硬件必须对每一次内存访问做区域级判定。ARMv8-A 在安全侧引入 SAU(Security Attribution Unit),在非安全侧使用 MPU(Memory Protection Unit)或 TrustZone 地址空间控制器 TZASC。它们共同决定某段物理地址属于安全、非安全还是两者皆可。

  • SAU/IDAU:在处理器内部对地址进行安全属性划分,决定该地址在安全视角下是否可见。
  • TZASC:位于内存控制器前,对 DRAM 区域做安全/非安全分区,防止非安全主设备越权访问安全内存。
  • TZPC:对外设做安全属性配置,控制哪些外设只能被安全世界访问。

下面是一段典型的 TZASC 区域配置示意,用于把 DRAM 划分为安全区与非安全区:

/* TZASC 区域配置示例(伪代码) */
tzasc_write(REGION0_BASE,  0x80000000);   // 安全区起始
tzasc_write(REGION0_TOP,   0x81000000);   // 安全区结束
tzasc_write(REGION0_ATTR,  SEC_RW | NS_NO_ACCESS);

tzasc_write(REGION1_BASE,  0x81000000);   // 非安全区起始
tzasc_write(REGION1_TOP,   0xC0000000);   // 非安全区结束
tzasc_write(REGION1_ATTR,  NS_RW | SEC_RW);
常见误区:认为只要把代码放进安全世界就安全。实际上,如果 TZASC 未正确配置,非安全侧仍可能通过 DMA 或错误地址映射访问安全内存。硬件隔离必须“状态位 + 区域控制器 + 外设保护”三者同时生效。

五、案例场景:一次安全支付调用

以移动支付为例,非安全侧应用发起指纹验证请求。流程如下:

  1. 应用通过 TEE Client API 发起调用,最终触发 SMC 指令。
  2. 处理器进入监控模式,保存非安全上下文,SCR.NS 清零。
  3. 安全侧 OP-TEE 读取指纹传感器数据,密钥与比对逻辑均位于安全内存。
  4. SAU 与 TZASC 确保非安全侧无法读取该内存区域。
  5. 比对结果通过共享内存返回,监控模式恢复非安全上下文,SCR.NS 置 1。

整个过程中,非安全侧只能看到“请求”和“结果”,无法窥探密钥与比对过程。这正是 TrustZone 硬件隔离的价值所在。

六、复盘与检查清单

在调试 TrustZone 系统时,建议按以下清单逐项核对:

  • SCR.NS 是否在切换前后被正确保存与恢复?
  • SMC 调用号是否与监控模式分发表一致?
  • SAU/IDAU 区域是否覆盖全部安全内存,是否存在重叠或空洞?
  • TZASC 区域属性是否禁止非安全主设备访问安全区?
  • 中断路由是否与 SCR.IRQ/FIQ 配置匹配,避免安全中断落入非安全侧?
  • 共享内存是否显式标记为非安全,避免误判为安全区?

掌握这五个硬件要素后,读者就能从“状态切换—监控中转—寄存器控制—区域保护—外设隔离”这条完整链路理解 TrustZone 的工作方式,为后续性能优化与安全加固打下基础。