3、TrustZone硬件架构:安全世界与普通世界的隔离机制、总线信号(NS位)、TrustZone地址空间控制器(TZASC)与TrustZone内存适配器(TZMA)
TrustZone技术的核心并非一个单一的安全模块,而是一套贯穿处理器内核、总线互联、内存控制器和外设的系统级安全架构。它通过将硬件资源划分为“安全世界”(Secure World)与“普通世界”(Normal World)两个相互隔离的执行环境,为高价值代码和数据提供可信执行空间。本章将深入剖析这套隔离机制的硬件基础,重点讲解NS位的传递规则、TZASC与TZMA的过滤原理,帮助您建立从SoC总线视角理解TrustZone的完整知识框架。
上图展示了TrustZone硬件隔离的核心架构。CPU核心通过NS位(Non-Secure)标记每一次总线访问的安全属性,该信号随AXI总线传递至TZASC和TZMA。TZASC负责对DDR等大容量内存进行区域划分,而TZMA则用于片上SRAM的简单隔离。TZPC(TrustZone Protection Controller)则控制外设的安全属性。整个机制的核心思想是:安全状态由硬件强制,而非软件约定——即使普通世界中的恶意软件试图访问安全内存,也会在总线层面被硬件拦截。
3.1 核心原理:NS位与总线信号扩展
TrustZone的隔离机制始于CPU核心内部。ARM处理器在运行时维护一个安全状态位(Secure State),该状态决定了当前执行的代码属于安全世界还是普通世界。这个状态并非仅影响CPU内部逻辑,更重要的是,它会通过总线接口扩展为一系列NS位信号,随每一次内存访问或外设访问一同发送到SoC的其他组件。
在ARM的AXI(Advanced eXtensible Interface)总线协议中,TrustZone扩展增加了以下关键信号:
- ARNS(Read Address Non-Secure):读地址通道的安全属性信号,高电平表示非安全读。
- AWNS(Write Address Non-Secure):写地址通道的安全属性信号,高电平表示非安全写。
- AxPROT:扩展的保护信号,其中bit[1]用于指示访问是否为安全访问(0为安全,1为非安全)。
这些信号由CPU核心根据当前运行状态自动生成。当CPU处于安全世界时,所有访问自动标记为安全;当处于普通世界时,所有访问自动标记为非安全。这种设计确保了安全属性与执行上下文强绑定,普通世界代码无法伪造安全访问标记。
关键理解:NS位并非一个简单的“开关”,而是一条贯穿SoC的“信任链”。从CPU发出,经过总线互联、内存控制器,最终到达存储介质,每一级硬件都会检查NS位并决定是否允许访问。任何一级的检查失败都会导致访问被拒绝(返回错误或挂起总线)。
3.2 判断方法与操作流程:TZASC区域配置
TZASC(TrustZone Address Space Controller)是TrustZone架构中用于隔离大容量内存(如DDR)的关键组件。它位于总线互联与内存控制器之间,充当“安全门卫”的角色。TZASC将物理内存划分为多个区域(Region),每个区域可以独立配置为安全或非安全属性。
配置TZASC通常遵循以下流程:
- 确定区域划分:根据系统需求,决定哪些内存地址范围属于安全世界(如TEE OS内核、安全数据缓冲区),哪些属于普通世界(如Linux内核、用户应用)。
- 设置区域基地址和大小:每个区域需要配置起始地址和长度,通常要求对齐到一定粒度(如64KB或1MB)。
- 配置安全属性:将每个区域标记为安全(Secure)或非安全(Non-Secure)。
- 使能区域:在配置完成后,使能相应的区域控制寄存器。
以下是一个典型的TZASC配置示例(基于ARM官方文档的寄存器操作):
// 假设TZASC基地址为 0x7C000000
#define TZASC_BASE 0x7C000000
#define TZASC_REGION_CTRL(base, n) (base + 0x100 + n * 0x10)
// 配置Region 0:安全区域,起始地址0x80000000,大小256MB
*(volatile uint32_t *)(TZASC_REGION_CTRL(TZASC_BASE, 0)) = 0x80000000 | (1 << 0); // 基地址+使能
*(volatile uint32_t *)(TZASC_REGION_CTRL(TZASC_BASE, 0) + 0x4) = 0xFF000000; // 大小掩码
*(volatile uint32_t *)(TZASC_REGION_CTRL(TZASC_BASE, 0) + 0x8) = 0x0; // 安全属性:全安全
// 配置Region 1:非安全区域,起始地址0x90000000,大小256MB
*(volatile uint32_t *)(TZASC_REGION_CTRL(TZASC_BASE, 1)) = 0x90000000 | (1 << 0);
*(volatile uint32_t *)(TZASC_REGION_CTRL(TZASC_BASE, 1) + 0x4) = 0xFF000000;
*(volatile uint32_t *)(TZASC_REGION_CTRL(TZASC_BASE, 1) + 0x8) = 0xFFFFFFFF; // 全非安全
需要注意的是,TZASC的配置操作必须在安全世界中进行,且通常由TEE(可信执行环境)的启动代码在早期完成。一旦配置完成,普通世界的软件无法修改这些寄存器。
3.3 案例拆解:TZMA在IoT设备中的SRAM隔离实践
与TZASC不同,TZMA(TrustZone Memory Adapter)是一种更简单的内存隔离机制,主要用于片上SRAM。它只支持将SRAM划分为两个区域:一个安全区域和一个非安全区域,且划分粒度通常较大(如4KB或8KB)。TZMA的典型应用场景是资源受限的IoT设备,这些设备可能没有DDR,只有片上SRAM。
以一个基于Cortex-M23的IoT安全设备为例:
| 项目 | 配置详情 |
|---|---|
| SRAM总容量 | 128KB(地址范围 0x20000000 - 0x2001FFFF) |
| 安全区域 | 0x20000000 - 0x2000FFFF(64KB),用于TEE运行时、安全密钥存储 |
| 非安全区域 | 0x20010000 - 0x2001FFFF(64KB),用于普通固件、应用数据 |
| TZMA配置 | 设置安全区域大小为64KB,其余自动为非安全 |
在这个案例中,TZMA的配置非常简单:只需设置一个寄存器指定安全区域的边界。当普通世界的代码尝试访问安全SRAM区域时,TZMA会直接阻止访问并返回总线错误。这种机制确保了即使普通世界固件被完全攻破,攻击者也无法读取或篡改安全区域中的敏感数据。
工程经验:TZMA适合对隔离粒度要求不高的场景。如果需要更细粒度的隔离(例如多个安全区域),应选择TZASC。此外,TZMA不支持动态重配置,必须在系统启动时确定划分方案。
3.4 常见误区与总结复盘
在TrustZone硬件架构的学习和实践中,以下误区值得特别关注:
- 误区一:认为TrustZone只保护内存。实际上,TrustZone还通过TZPC控制外设的安全属性,确保安全外设(如安全UART、安全Timer)只能被安全世界访问。
- 误区二:忽略总线互联的NS位传递。如果总线互联组件不支持TrustZone扩展,NS位信号会被丢弃,导致隔离失效。因此,SoC中的所有总线组件必须支持TrustZone。
- 误区三:混淆TZASC与TZMA的职责。TZASC用于大容量DDR内存,支持多个区域;TZMA用于片上SRAM,仅支持两个区域。两者不能互换使用。
- 误区四:认为安全世界可以随意访问普通世界内存。虽然安全世界通常具有更高的权限,但出于安全考虑,TEE OS也会对安全世界访问普通世界内存进行限制,防止安全世界代码漏洞导致普通世界数据泄露。
总结而言,TrustZone硬件隔离机制的核心在于NS位信号的全链路传递。从CPU发出安全属性标记,经过总线互联,最终由TZASC/TZMA执行强制访问控制。理解这一机制,是后续学习TEE软件栈(如OP-TEE、Trusty)的基础。在实际项目中,应根据内存类型和隔离需求选择合适的控制器,并在系统启动早期完成安全配置。
安全提醒:TZASC/TZMA的配置寄存器属于安全世界资源,普通世界任何访问都应被硬件拒绝。在调试过程中,如果发现普通世界可以读取这些寄存器,说明SoC的TrustZone实现存在缺陷,应立即联系芯片厂商确认。