4. TrustZone技术原理

TinyML 项目部署到 MCU 后,面临的不仅是算力与功耗的约束,更严峻的是安全边界的模糊。传统上,开发者依赖 RTOS 的任务调度或软件 MPU 来隔离敏感数据,但在物理攻击、侧信道攻击和固件漏洞利用面前,纯软件隔离的强度远远不够。ARM TrustZone 技术从 Cortex-A 系列下沉到 Cortex-M23 与 Cortex-M33,为微控制器带来了基于硬件的、强制性的隔离架构。本章将深入拆解 TrustZone 在 MCU 上的核心原理:安全世界(Secure World)与普通世界(Normal World)如何划分、硬件如何强制隔离、以及这种隔离机制对 TinyML 模型、密钥和推理过程的具体保护方式。

Cortex-M33 TrustZone 硬件隔离架构 普通世界 (Normal World) 安全世界 (Secure World) 非安全应用 TinyML推理任务 RTOS / 调度器 FreeRTOS / Zephyr 非安全外设 UART / SPI / GPIO / 普通定时器 (通过SAU/IDAU配置为Non-Secure) 安全服务 密钥管理 / 安全存储 安全启动 信任根 (RoT) 安全外设 加密引擎 / 安全DMA / 防篡改GPIO (仅安全世界可访问) 硬件隔离边界 Cortex-M33 核心 支持 TrustZone 扩展 安全/非安全状态切换 SAU / IDAU 内存与外设安全属性配置 硬件强制访问控制 非安全中断 (Nonsecure IRQ) 可被安全固件屏蔽 安全中断 (Secure IRQ) 优先处理,不受普通世界影响 SGPI 信号控制总线访问权限 | 非安全代码无法直接读取安全内存或调用安全外设

上图展示了 Cortex-M33 中 TrustZone 的核心架构。左侧为普通世界,运行 RTOS 与 TinyML 推理任务;右侧为安全世界,存放密钥、安全启动代码与敏感外设控制。中间的隔离边界并非软件逻辑,而是由 CPU 总线层面的硬件信号(如 SAU、IDAU 配置)强制实施。任何跨域访问都会触发硬件异常,而非依赖操作系统的自觉性。这种设计从根本上改变了 MCU 安全模型——即使普通世界中的攻击者获得了任意代码执行权限,也无法直接触及安全世界中的模型参数或加密密钥。

4.1 核心原理:硬件强制隔离与状态切换

TrustZone 的隔离机制建立在 CPU 核心的两个虚拟状态之上:安全状态(Secure State)与非安全状态(Nonsecure State)。在 Cortex-M23/M33 中,这种状态由处理器内部的 安全属性单元(SAU) 和芯片厂商实现的 实现定义属性单元(IDAU) 共同决定。SAU 是 ARM 架构标准定义的编程接口,开发者可以通过寄存器配置内存区域的安全属性;IDAU 则由芯片厂商在硬件层面固定,用于定义芯片内部总线映射的安全边界。两者通过“与”逻辑生成最终的安全属性——只有 SAU 和 IDAU 都判定为安全,该地址才被允许在安全状态下访问。

状态切换并非简单的函数调用。当普通世界代码需要调用安全世界服务时,必须通过 安关(SG)指令 或 安全函数调用(SVC) 机制。Cortex-M33 提供了专用的 SG 指令,该指令只能在普通世界执行,且目标地址必须位于安全世界入口表(Vector Table)中标记为可调用区域。一旦执行 SG 指令,处理器硬件自动完成以下操作:保存普通世界上下文、切换到安全状态、跳转到安全入口地址。返回时通过 BXNS 指令回到普通世界,同时恢复上下文。整个过程不依赖软件标志位,硬件保证状态切换的原子性。

关键硬件组件清单:

  • SAU (Security Attribution Unit):可编程的安全属性单元,最多支持 8 个区域配置,每个区域可独立设置起始地址、大小和安全属性。
  • IDAU (Implementation Defined Attribution Unit):芯片厂商固定的安全属性映射,通常将 Flash、SRAM 划分为安全与非安全区域,不可编程。
  • SGPI (Secure GPIO):安全 GPIO 控制器,可配置特定引脚为安全属性,防止普通世界通过 GPIO 侧信道窃取信息。
  • PPC (Peripheral Protection Controller):外设保护控制器,用于控制总线外设的安全访问权限。
  • MSC (Memory Security Controller):内存安全控制器,在 Flash/SRAM 接口层面实施安全过滤。

4.2 判断方法与操作流程:配置 TrustZone 隔离策略

在实际 TinyML 项目中,配置 TrustZone 需要遵循一套严谨的流程。首先,开发者需要明确哪些资源属于安全资产:通常包括模型加密密钥、设备唯一标识、安全启动代码、以及用于模型推理的敏感输入数据(如生物特征)。其次,需要根据芯片手册确定 IDAU 的固定划分,再通过 SAU 进行补充配置。以下是标准的配置流程:

  1. 步骤一:安全资产清单梳理 —— 列出所有需要保护的代码段、数据段、外设和中断。例如,将模型推理引擎放在非安全区,但将模型解密密钥放在安全区。
  2. 步骤二:内存映射规划 —— 在链接脚本中定义安全区域与非安全区域。Cortex-M33 通常将 Flash 分为安全区(如 0x10000000-0x1000FFFF)和非安全区(0x10010000-0x1001FFFF),SRAM 同理。
  3. 步骤三:SAU 寄存器配置 —— 通过 SAU_Setup() 函数设置区域属性。例如,将 0x20000000 开始的 32KB SRAM 配置为非安全,其余为安全。
  4. 步骤四:外设安全属性配置 —— 使用 PPC 将 UART、SPI 等外设设置为非安全,将加密引擎、安全存储控制器设置为安全。
  5. 步骤五:中断隔离配置 —— 在 NVIC 中设置中断的安全属性。安全中断可以抢占非安全中断,反之则不行。
  6. 步骤六:安全入口函数编写 —— 在安全世界实现服务函数,并通过 SG 指令暴露给普通世界调用。
// SAU 配置示例(基于 CMSIS):
void SAU_Setup(void) {
    SAU->CTRL = 0; // 禁用 SAU 进行配置
    // 区域 0: 0x10000000 - 0x1000FFFF (64KB Flash) 设为安全
    SAU->RNR = 0;
    SAU->RBAR = 0x10000000 & SAU_RBAR_BADDR_Msk;
    SAU->RLAR = (0x1000FFFF & SAU_RLAR_LADDR_Msk) | SAU_RLAR_ENABLE_Msk;
    // 区域 1: 0x20000000 - 0x20007FFF (32KB SRAM) 设为非安全
    SAU->RNR = 1;
    SAU->RBAR = 0x20000000 & SAU_RBAR_BADDR_Msk;
    SAU->RLAR = (0x20007FFF & SAU_RLAR_LADDR_Msk) | SAU_RLAR_ENABLE_Msk;
    SAU->CTRL = SAU_CTRL_ENABLE_Msk;
}

配置完成后,必须通过 安全启动验证 来确认隔离边界有效。测试方法包括:尝试从非安全代码直接读取安全内存地址(应触发 HardFault)、尝试调用安全外设寄存器(应返回总线错误)、以及验证安全中断能否正常抢占非安全中断。

4.3 案例拆解:TinyML 关键词识别中的模型保护

假设我们正在开发一个基于 Cortex-M33 的离线语音关键词识别设备,需要保护用户声纹特征和模型权重不被提取。设备约束为:1MB Flash、256KB SRAM、工作频率 100MHz,使用 TensorFlow Lite Micro 部署模型。

初始目标: 确保即使攻击者通过 UART 漏洞获取了普通世界代码执行权限,也无法读取存储在 Flash 中的模型权重或解密密钥。

关键输入数据: 模型权重约 300KB,密钥 16 字节 AES-128,声纹特征模板 1KB。

分析判断过程: 模型权重本身不一定是最高机密,但攻击者可以通过模型逆向推断训练数据特征。因此,我们将模型权重放在非安全 Flash 区,但使用 AES 加密存储。解密密钥存放在安全 Flash 区。推理时,普通世界将加密模型数据通过安全 API 传递给安全世界,由安全世界解密后执行推理,或者使用安全 DMA 将解密数据直接送入安全 SRAM 中的推理引擎。

实际操作步骤:

  1. 将 Flash 划分为:安全区 0x10000000-0x1000FFFF(64KB,存放密钥、安全启动代码)、非安全区 0x10010000-0x100FFFFF(960KB,存放加密模型和普通应用)。
  2. SRAM 划分:安全区 0x20000000-0x20003FFF(16KB,存放解密后的模型权重和声纹特征)、非安全区 0x20004000-0x2003FFFF(240KB,存放推理中间变量)。
  3. 在安全世界实现 Secure_ModelDecrypt() 函数,使用 AES 解密模型权重,并将结果放入安全 SRAM。
  4. 普通世界通过 SG 指令调用该函数,传入加密模型地址和长度,获取解密后的模型指针。
  5. 推理过程中,普通世界只能访问非安全 SRAM 中的中间结果,无法直接读取安全 SRAM 中的权重。

结果对比: 实施 TrustZone 后,通过 UART 漏洞获取代码执行权限的攻击者,尝试读取 0x20000000 地址时立即触发 HardFault,无法获取任何模型信息。而未实施 TrustZone 的对照组,攻击者可以轻松 dump 整个 SRAM 和 Flash。

风险与代价: 安全世界代码增加了约 8KB Flash 占用,每次模型加载需要额外的 AES 解密时间(约 15ms)。此外,安全 API 调用需要上下文切换,增加了约 2μs 的延迟。但相对于安全性提升,这些代价在大多数 TinyML 场景中是可接受的。

经验提醒: 在配置 TrustZone 时,务必注意 SAU 区域的对齐要求。SAU 区域大小必须是 32 字节的倍数,且起始地址必须对齐到区域大小。例如,配置 64KB 区域时,起始地址必须 64KB 对齐。否则,SAU 配置无效,可能导致安全漏洞。

4.4 常见误区与总结复盘

在 TrustZone 的实际应用中,开发者常陷入以下误区:

  • 误区一:认为 TrustZone 可以替代加密。 TrustZone 提供隔离,但不提供数据加密。如果安全 Flash 中的密钥被物理攻击(如探针)读取,隔离也无济于事。因此,TrustZone 应与硬件加密引擎结合使用。
  • 误区二:将所有外设都配置为非安全。 这会导致安全世界无法访问任何外设,使得安全服务无法实现。正确做法是仅将必要的通信外设(如 UART 调试口)设为非安全,而将安全关键外设(如 TRNG、加密引擎)保留为安全。
  • 误区三:忽略 IDAU 的固定限制。 某些芯片的 IDAU 将特定 Flash 区域固定为非安全,即使 SAU 配置为安全也无法覆盖。开发者必须查阅芯片参考手册,了解 IDAU 的固定映射。
  • 误区四:安全状态下的代码存在漏洞。 安全世界代码同样需要遵循安全编码规范。如果安全服务函数存在缓冲区溢出,攻击者可能通过普通世界传入恶意参数,在安全世界执行任意代码。

总结复盘: TrustZone 为 TinyML 提供了硬件级别的信任根,但它的有效性取决于正确的配置和严谨的安全世界代码实现。在项目初期,建议先使用开发板上的 TrustZone 示例工程进行验证,熟悉 SAU/IDAU 配置流程,再逐步将安全资产迁移到隔离区域。同时,建立安全启动链——从 BootROM 到安全世界固件,再到普通世界固件——确保整个系统的信任链完整。最后,定期进行渗透测试,尝试从普通世界发起攻击,验证隔离边界是否真正不可逾越。

风险提示: 切勿在生产环境中直接使用默认的 TrustZone 配置。每个芯片厂商的 IDAU 实现不同,且 SAU 配置需要根据具体应用场景定制。错误的配置可能导致安全世界被绕过,或者普通世界无法正常工作。务必在硬件在环测试中验证所有安全边界。