2. 理解TrustZone架构基础

任务目标

本案例要求通过阅读TrustZone架构文档并分析一段最小示例代码,理解TrustZone硬件隔离的核心机制:安全世界(Secure World)与非安全世界(Normal World)如何划分,以及两者之间通过Monitor模式完成世界切换的基本原理。完成本案例后,你应能解释TrustZone为何被视为硬件级隔离方案,而非纯软件沙箱。

TrustZone核心概念速览

TrustZone将CPU的物理硬件资源划分为两个虚拟世界,由硬件强制隔离:

  • 安全世界(Secure World):可访问安全内存、安全外设,运行可信代码(如TEE OS)。
  • 非安全世界(Normal World):运行普通操作系统(如Linux/Android),无法直接访问安全资源。
  • Monitor模式:位于EL3(ARMv8)或Monitor模式(ARMv7),是唯一能切换世界的软件入口。
  • 状态切换:通过执行SMC(Secure Monitor Call)指令主动陷入Monitor,由Monitor决定是否切换世界。

硬件隔离的关键在于:总线层面的地址空间过滤(NS位)确保非安全世界发出的访问请求在物理上无法到达安全资源,而非仅依赖软件权限检查。

最小示例代码:世界切换状态机

以下代码用C语言模拟TrustZone世界切换的核心状态流转,不依赖具体硬件,用于理解切换逻辑:

```c #include #include // 世界状态枚举 typedef enum { WORLD_NORMAL = 0, WORLD_SECURE = 1 } world_t; // Monitor模式下的世界切换请求类型 typedef enum { REQ_ENTER_SECURE = 0, // 非安全世界请求进入安全世界 REQ_RETURN_NORMAL = 1 // 安全世界请求返回非安全世界 } smc_request_t; // 当前所在世界(由硬件NS位决定,此处用变量模拟) static world_t current_world = WORLD_NORMAL; // 安全世界入口函数(实际场景中为TEE OS的入口) static void secure_world_entry(void) { printf("[Secure World] 已进入安全世界,可访问安全内存与外设\n"); // 执行安全服务... } // 非安全世界入口函数(实际场景中为普通OS的返回点) static void normal_world_entry(void) { printf("[Normal World] 已返回非安全世界,安全资源不可见\n"); } // Monitor模式处理SMC请求(核心切换逻辑) static void monitor_smc_handler(smc_request_t req) { printf("[Monitor] 收到SMC请求: %s\n", req == REQ_ENTER_SECURE ? "进入安全世界" : "返回非安全世界"); switch (req) { case REQ_ENTER_SECURE: if (current_world == WORLD_NORMAL) { // 保存非安全世界上下文(实际为寄存器组保存) // 切换SCR.NS位为0(安全状态) current_world = WORLD_SECURE; secure_world_entry(); } else { printf("[Monitor] 已在安全世界,忽略重复请求\n"); } break; case REQ_RETURN_NORMAL: if (current_world == WORLD_SECURE) { // 保存安全世界上下文 // 切换SCR.NS位为1(非安全状态) current_world = WORLD_NORMAL; normal_world_entry(); } else { printf("[Monitor] 已在非安全世界,忽略重复请求\n"); } break; default: printf("[Monitor] 未知请求\n"); break; } } // 模拟非安全世界发起SMC调用 static void normal_world_call_smc(smc_request_t req) { printf("[Normal World] 执行SMC指令请求切换...\n"); monitor_smc_handler(req); } // 模拟安全世界发起SMC调用 static void secure_world_call_smc(smc_request_t req) { printf("[Secure World] 执行SMC指令请求切换...\n"); monitor_smc_handler(req); } int main(void) { printf("=== TrustZone世界切换模拟 ===\n"); printf("初始状态: 非安全世界\n\n"); // 非安全世界请求进入安全世界 normal_world_call_smc(REQ_ENTER_SECURE); printf("\n"); // 安全世界处理完业务后返回非安全世界 secure_world_call_smc(REQ_RETURN_NORMAL); printf("\n"); // 验证:再次请求进入安全世界 normal_world_call_smc(REQ_ENTER_SECURE); printf("\n"); // 测试非法请求(已在非安全世界却请求返回非安全世界) normal_world_call_smc(REQ_RETURN_NORMAL); return 0; } ```

运行与验证

环境要求:仅需C编译器(gcc/clang),无额外依赖。

编译运行:

gcc -o tz_sim tz_sim.c && ./tz_sim

预期输出(与代码逻辑严格对应):

=== TrustZone世界切换模拟 ===
初始状态: 非安全世界

[Normal World] 执行SMC指令请求切换...
[Monitor] 收到SMC请求: 进入安全世界
[Secure World] 已进入安全世界,可访问安全内存与外设

[Secure World] 执行SMC指令请求切换...
[Monitor] 收到SMC请求: 返回非安全世界
[Normal World] 已返回非安全世界,安全资源不可见

[Normal World] 执行SMC指令请求切换...
[Monitor] 收到SMC请求: 进入安全世界
[Secure World] 已进入安全世界,可访问安全内存与外设

[Normal World] 执行SMC指令请求切换...
[Monitor] 收到SMC请求: 返回非安全世界
[Monitor] 已在非安全世界,忽略重复请求

判定标准:程序输出与上述顺序一致,且最后一条显示“忽略重复请求”,说明状态机正确拒绝了非法切换。观察输出中[Monitor]始终作为唯一切换决策点,即可验证“所有世界切换必须经过Monitor”这一TrustZone核心原则。

关键理解点

  • 代码中的current_world变量模拟硬件NS位;真实硬件中该位由SCR寄存器控制,非安全世界无法修改它。
  • monitor_smc_handler对应固件中的Monitor代码,实际场景中还需保存/恢复CPU上下文,本例省略以聚焦切换逻辑。
  • 安全世界入口secure_world_entry执行完毕后必须主动调用SMC返回,否则CPU将一直停留在安全世界——这对应真实TEE中“安全世界不能直接跳转回非安全世界,必须经Monitor”的规则。

常见误区澄清

  • TrustZone不是虚拟化技术:两个世界共享同一个物理CPU核心,通过时间片切换而非同时运行。
  • 安全中断(FIQ)可强制从非安全世界进入Monitor,本例未展示,但需知道这是除SMC外的第二种进入Monitor的途径。
  • 内存隔离由总线NS位过滤实现,非安全世界的DMA设备也无法访问安全内存——这是硬件保证,不依赖软件配置。