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设备也无法访问安全内存——这是硬件保证,不依赖软件配置。