TEE 架构基础:硬件隔离与软件栈

各位同学,咱们今天聊聊 TEE 的骨架——硬件隔离机制和软件栈。这部分内容,说白了就是搞清楚 TEE 到底是怎么“与世隔绝”的,以及它里面都住了哪些“居民”。

我刚开始接触 TEE 的时候,也觉得很抽象。什么安全世界、普通世界,听着像两个平行宇宙。但等你真正动手做过一次接口适配,就会发现这些概念其实很实在。咱们一步步来拆解。

硬件隔离机制:TrustZone 与 TEE 安全内核

先问大家一个问题:一个 CPU 核心,怎么同时运行两个完全隔离的系统?

答案就是硬件隔离。ARM 的 TrustZone 技术,把物理的 CPU 核心虚拟成了两个“世界”:普通世界(Normal World)和安全世界(Secure World)。这两个世界共享同一个物理核,但通过硬件逻辑彻底隔开。

核心要点:TrustZone 不是软件模拟的,是芯片设计时就固化在总线、内存控制器和 CPU 核里的。普通世界的程序,永远无法直接访问安全世界的内存和寄存器。

我个人习惯把 TrustZone 想象成一栋楼里的两部电梯。普通世界的电梯只能到 1-10 层,安全世界的电梯能到 11-20 层。两部电梯的钥匙(权限)完全不同。你想想看,就算普通世界的电梯里塞满了恶意软件,它也按不了 11 层的按钮——因为硬件上就没给它这个权限。

安全世界与普通世界的切换

这两个世界怎么切换呢?靠一个叫 Monitor Mode 的监控模式。它就像两个世界之间的安检门。当普通世界想调用安全世界的服务时,必须通过一条特殊的指令——SMC(Secure Monitor Call)。

流程大概是这样的:

  1. 普通世界的程序执行 SMC 指令。
  2. CPU 陷入 Monitor Mode,保存普通世界的上下文。
  3. Monitor 检查调用是否合法,然后切换到安全世界。
  4. 安全世界处理请求,返回结果。
  5. Monitor 恢复普通世界上下文,继续执行。

嗯,这里要注意:Monitor Mode 本身也是运行在安全世界的,但它是最底层的“看门人”。我在项目中遇到过一个问题,就是 SMC 调用太频繁,导致性能急剧下降。后来我们优化了调用频率,把多次小请求合并成一次大请求,才解决了问题。

TEE 安全内核

安全世界里跑的是什么?就是 TEE 安全内核。它不是一个完整的操作系统,而是一个精简的、专门为安全场景设计的微型内核。

常见的 TEE 安全内核有:

  • OP-TEE:开源,由 Linaro 维护,社区活跃,我用的最多的就是它。
  • Trusty:Google 为 Android 设计的 TEE 内核,闭源。
  • QSEE:高通的 TEE 实现,闭源,很多手机都在用。

这些内核的共同特点是:小、专、硬。它们只提供最基本的内存管理、中断处理和线程调度,不提供文件系统、网络协议栈这些“花哨”功能。为什么?因为功能越少,攻击面越小。

避坑指南:我曾经在移植 OP-TEE 到一款新芯片时,发现安全内核总是启动失败。查了三天,最后发现是芯片的 TrustZone 硬件配置寄存器没设置对。所以,做 TEE 适配的第一步,一定是仔细阅读芯片的 TRM(Technical Reference Manual),把 TrustZone 相关的硬件配置搞清楚。

TEE 的软件栈:OS、TA、CA

硬件隔离是地基,软件栈就是上面的房子。TEE 的软件栈分为三层:CA(Client Application)、TEE OS 和 TA(Trusted Application)。

我画了一张图,帮你直观理解这三层的关系:

TEE 软件栈架构图 TEE 软件栈架构 普通世界 (Normal World) 安全世界 (Secure World) CA (Client Application) 普通应用,如支付 App REE OS (Linux/Android) 文件系统、网络、UI TA (Trusted Application) 安全应用,如密钥管理 TEE OS (OP-TEE/Trusty) 微型内核、安全调度 硬件层 (TrustZone + 安全外设) CPU、内存控制器、加密引擎、安全存储 Monitor Mode SMC 调用 说明:CA 通过 TEE Client API 发起请求,REE OS 通过 SMC 陷入 Monitor Mode, 切换到安全世界后由 TEE OS 分发给对应的 TA 处理。

CA:普通世界的“使者”

CA 运行在普通世界,就是我们常见的 App。比如支付宝、支付的 App 本身就是一个 CA。它负责发起安全请求,但自己不处理敏感数据。

CA 通过 TEE Client API 与安全世界通信。这个 API 是标准化的,主要就几个函数:

  • TEEC_InitializeContext:初始化 TEE 上下文。
  • TEEC_OpenSession:打开与 TA 的会话。
  • TEEC_InvokeCommand:调用 TA 中的命令。
  • TEEC_CloseSession:关闭会话。

说白了,CA 就是个“跑腿的”。它把数据打包好,通过 SMC 送到安全世界,然后等结果。它自己看不到数据在安全世界里是怎么处理的。

TEE OS:安全世界的“管家”

TEE OS 是安全世界的操作系统内核。它负责管理安全世界里的所有资源:内存、中断、TA 的生命周期等。

TEE OS 的核心职责包括:

  • 内存隔离:确保每个 TA 只能访问自己的内存区域。
  • 中断管理:处理来自安全外设的中断,比如安全键盘、指纹传感器。
  • TA 加载与调度:从安全存储中加载 TA 镜像,并调度执行。
  • 密码学服务:提供硬件加速的加解密、签名、哈希等操作。

注意:TEE OS 不是 Linux!它没有进程的概念,只有“会话”和“线程”。一个 TA 可以同时处理多个会话,但每个会话是独立隔离的。我在做性能优化时,就踩过这个坑——以为可以像 Linux 一样开多线程并行处理,结果发现 TEE OS 的线程模型非常受限。

TA:安全世界的“打工人”

TA 是真正干活的。它运行在安全世界,处理敏感数据。比如指纹比对、密钥生成、支付令牌签名等。

TA 的特点:

  • 单一职责:一个 TA 通常只做一件事,比如“密钥管理 TA”只负责生成和存储密钥。
  • 无网络访问:TA 不能直接访问网络,所有数据必须通过 CA 中转。
  • 持久化存储:TA 可以将数据加密后存储到普通世界的文件系统中,但只有 TA 自己能解密。

TA 的开发接口是 TEE Internal API,它提供了:

API 类别 功能 常用函数
密码学 加解密、签名、哈希 TEE_AllocateOperation、TEE_AsymmetricSignDigest
存储 安全存储数据 TEE_OpenPersistentObject、TEE_WriteObjectData
时间 获取安全时间 TEE_GetSystemTime
内存管理 分配安全内存 TEE_Malloc、TEE_Free

嗯,这里要特别说一下安全存储。TA 不能直接写硬盘,它只能通过 TEE OS 提供的接口,把数据加密后存到普通世界的文件里。加密密钥由 TEE OS 管理,普通世界根本拿不到。我曾经帮一个客户排查问题,发现 TA 存储的数据在重启后丢失了。最后定位到是 TA 的存储对象 ID 冲突了——两个 TA 用了相同的 ID,导致数据被覆盖。所以,给 TA 分配存储 ID 时,一定要保证全局唯一。

小结

这一章我们聊了 TEE 的硬件隔离机制和软件栈。TrustZone 提供了物理级别的隔离,TEE 安全内核是安全世界的“大脑”,而 CA、TEE OS、TA 三层架构,则让普通世界和安全世界能够有序协作。

记住一句话:CA 负责“问”,TA 负责“做”,TEE OS 负责“管”,TrustZone 负责“隔”。把这四个角色搞清楚了,TEE 的架构你就掌握了八成。