ARM TrustZone-M与TF-M安全启动链:从Secure Bootloader到PSA Certified隔离环境
随着物联网设备数量的爆发式增长,边缘终端的安全性已成为整个安全体系的薄弱环节。ARM TrustZone-M 扩展为 Cortex-M 微控制器带来了硬件级隔离,而 Trusted Firmware-M (TF-M) 则为这些设备提供了标准化的固件安全框架。本文深入剖析 TrustZone-M 的硬件隔离机制、TF-M 的固件架构设计,并完整演示从安全启动链到 PSA Certified 隔离环境的端到端实现。
1. 为什么物联网需要TrustZone-M
传统 Cortex-M 微控制器运行在单一特权级别,应用程序、协议栈和密钥存储共享同一个物理地址空间。一旦应用层存在缓冲区溢出或漏洞注入,攻击者即可获取设备所有敏感资产(密钥、凭证、固件)。
ARM 在 ARMv6-M/v7-M 基础上引入 Security Extension (TrustZone-M),在 ARMv8-M/v8.1-M 架构中正式落地。其核心思想与 TrustZone-A(面向 Cortex-A 应用处理器)一脉相承,但针对嵌入式实时场景做了大量简化和增强:
| 特性 | TrustZone-A | TrustZone-M |
|---|---|---|
| 目标市场 | 手机/服务器AP | MCU/嵌入式 |
| 安全状态切换 | SMC指令/EL3异常 | 入口/出口函数调用(SG/BXNS/BLXNS) |
| 上下文切换 | 完整寄存器保存 | 硬件自动保存caller-saved寄存器 |
| 内存管理 | 两级页表(MMU) | SAU + IDAU 分区 |
| 典型框架 | OP-TEE/Trusty | TF-M |
| 延迟要求 | 毫秒级 | 微秒级(实时性) |
2. TrustZone-M 硬件隔离机制
2.1 安全状态与状态切换
ARMv8-M 引入了两个安全状态:Secure World 和 Non-secure World。每个状态拥有独立的地址空间视图,由 SAU (Security Attribution Unit) 和 IDAU (Implementation Defined Attribution Unit) 协同定义。
// SAU 区域配置典型结构(CMSIS 封装)
typedef struct {
uint32_t RBAR; // Region Base Address Register
uint32_t RLAR; // Region Limit Address Register
} SAU_Region_Config;
// 配置安全Flash区域 (例如 0x10000000 - 0x100FFFFF)
void configure_sau(void) {
SAU->RNR = 0; // Region 0
SAU->RBAR = (SECURE_FLASH_BASE & SAU_RBAR_BADDR_Msk);
SAU->RLAR = (SECURE_FLASH_END & SAU_RLAR_LADDR_Msk) |
SAU_RLAR_ENABLE_Msk; // 启用且为Secure
// 配置Non-secure Callable (NSC) 区域
SAU->RNR = 1;
SAU->RBAR = (NSC_FLASH_BASE & SAU_RBAR_BADDR_Msk);
SAU->RLAR = (NSC_FLASH_END & SAU_RLAR_LADDR_Msk) |
SAU_RLAR_NSC_Msk | // Non-secure Callable
SAU_RLAR_ENABLE_Msk;
__DSB(); __ISB();
}
状态切换的入口和出口指令与 TrustZone-A 截然不同:
- SG (Secure Gateway):Non-secure 调用 Secure 函数的入口指令,只在 NSC 区域有效
- BXNS:从 Secure 返回 Non-secure 时使用,自动清除返回地址的敏感信息
- BLXNS:从 Secure 调用 Non-secure 函数时使用
硬件层面,进入 Secure 状态时处理器自动将 R0-R3, R12, LR, PSR 压栈,返回时自动恢复,极大地降低了上下文切换延迟。
2.2 SAU 与内存分区
SAU 最多支持8个区域(部分实现可多达16个),每个区域包含: - Base Address(起始地址) - Limit Address(结束地址,实际启用时地址的 bit[4:0] 被忽略,32字节对齐) - NS (Non-secure) / NSC (Non-secure Callable) / S (Secure) 属性
IDAU 通常在芯片出厂时固化,定义外部地址空间(如外设、RAM)的安全属性。SAU 可编程部分与 IDAU 共同决定最终安全属性。
// 典型的 TF-M 内存布局
/*
* Secure Flash: 0x1000_0000 - 0x1007_FFFF (512KB) — 加密固件 + TF-M 核心
* NSC Flash: 0x1007_F000 - 0x1007_FFFF (4KB) — Secure API 入口
* NS Flash: 0x0800_0000 - 0x0807_FFFF (512KB) — 应用程序
* Secure SRAM: 0x3000_0000 - 0x3001_FFFF (128KB) — TF-M 数据 + IPC 缓冲
* NS SRAM: 0x2000_0000 - 0x2003_FFFF (256KB) — 应用程序数据
* Secure Periph: 0x5000_0000+ — 加密引擎 / OTP / GPIO
*/
2.3 外设安全分配
TrustZone-M 支持外设的安全分配,通过 Implementation Defined Attribution,每个外设的 Secure 属性在复位时由硬件配置决定,部分外可通过寄存器再配置:
// 示例:将 UART0 分配给 Non-secure World
// 参考 AN540 (STM32U5) 的 SYSCTRL 寄存器
#define SECURE_PERIPH_BASE 0x50040000
#define PERIPH_SEC_CFG_REG (*(volatile uint32_t *)(SECURE_PERIPH_BASE + 0x18))
// Bit 5: UART0 security (0=Secure, 1=Non-secure)
PERIPH_SEC_CFG_REG |= (1 << 5); // UART0 → NS世界(调试输出)
3. TF-M (Trusted Firmware-M) 固件架构
TF-M 是 ARM 官方维护的开源固件框架,目标是为 ARMv8-M/v8.1-M 提供标准化的安全运行时。最新正式版(截至2025年)为 v2.x 系列。
3.1 分层架构
┌─────────────────────────────────────────────────────┐
│ Application (NS) │
│ (Zephyr / FreeRTOS / Bare-metal) │
├─────────────────────────────────────────────────────┤
│ NS Interface (TF-M Client) │
├──────────────────┬──────────────────────────────────┤
│ IPC Model │ Library Model │
│ (PSA RoT Calls) │ (Secure Partition Manager) │
├──────────────────┴──────────────────────────────────┤
│ SP (Secure Partitions) │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Crypto SP │ │ Flash SP │ │ ATT Test │ ... │
│ └───────────┘ └───────────┘ └───────────┘ │
├─────────────────────────────────────────────────────┤
│ TF-M Core (SPM + LIB) │
│ (调度器, IPC 协议, 消息路由, 上下文管理) │
├─────────────────────────────────────────────────────┤
│ BL2 (Secure Bootloader) │
│ (镜像验证, 固件升级, 回滚保护) │
├─────────────────────────────────────────────────────┤
│ Hardware (ARMv8-M/v8.1-M MCU) │
│ SAU + IDAU + MPC + PPC │
└─────────────────────────────────────────────────────┘
3.2 IPC vs Library Model
TF-M 支持两种服务调用模型:
IPC (Inter-Process Communication) 模型 - 每个 Secure Partition 是独立的消息处理任务 - 支持客户端身份验证和隔离 - 适合需要跨分区强隔离的场景
// 客户端调用 Crypto PSA RoT Service (IPC 模型)
psa_status_t ret;
psa_handle_t handle = psa_connect(CRYPTO_SID, CRYPTO_VERSION);
if (handle <= 0) {
return -1; // 连接失败
}
psa_operation_t op = PSA_KEY_VACPP_INIT;
ret = psa_sign_hash(handle, key_id, ALG_SHA256, hash, hash_size,
signature, sig_size, &sig_length);
psa_close(handle);
Library Model (TF-M 1.8+ 引入) - Secure 代码被编译为库,直接链接到 Non-secure 应用 - 无 IPC 开销,延迟更低 - 牺牲隔离性,适合资源极受限设备
3.3 Secure Partition 实现
每个 Secure Partition 定义入口函数和信号列表:
// partitions/flash_protection/partition.c
#include "tfm_spm_LOG_ctx.h"
// RoT Service 注册
static psa_status_t flash_protect_service(const psa_msg_t *msg) {
switch (msg->type) {
case PSA_IPC_CONNECT:
return PSA_SUCCESS;
case PSA_IPC_CALL:
// 处理 Flash 保护请求
handle_flash_protect_request(msg);
return PSA_SUCCESS;
case PSA_IPC_DISCONNECT:
return PSA_SUCCESS;
default:
return PSA_ERROR_PROGRAMMER_ERROR;
}
}
// SP 入口
void flash_protect_sp_init(void) {
// 注册 RoT Service
psa_signal_t signals = TFM_FLASH_PROTECT_SIGNAL;
while (1) {
signals = psa_wait(signals, PSA_BLOCK);
if (signals & TFM_FLASH_PROTECT_SIGNAL) {
psa_msg_t msg;
while (psa_get(TFM_FLASH_PROTECT_SIGNAL, &msg) == PSA_SUCCESS) {
flash_protect_service(&msg);
}
}
}
}
4. 安全启动链 (Secure Boot Chain of Trust)
TF-M 的 BL2 (Boot Loader Stage 2) 是整个安全系统的信任根。
4.1 启动流程
┌──────────────────────────────────────────────────┐
│ Boot ROM (Flash/ROM) │
│ → 验证 BL2 的镜像签名 (公钥哈希烧录OTP) │
│ → 跳转到 BL2 │
├──────────────────────────────────────────────────┤
│ BL2 (TF-M Secondary Bootloader) │
│ → 解密并验证 Secure 镜像的完整性 │
│ → 解密并验证 NS 镜像的完整性 │
│ → 支持 Anti-Rollback (固件版本号计数器) │
│ → 可选: 固件升级管理 (FWU Agent) │
├──────────────────────────────────────────────────┤
│ BL3 (TF-M Core) │
│ → SAU/IDAU 配置 │
│ → Secure Partition 初始化 │
│ → 跳转到 NS 应用 (NSPE) │
└──────────────────────────────────────────────────┘
4.2 镜像加密与签名方案
TF-M BL2 支持多种加密方案:
// configs/tfm_config.h
#define TFM_BL2 1
#define BL2_ENCRYPTION_TYPE TFM_ENCRYPTION_AES_256_CTR // 或 NONE
#define BL2_SIG_ALG TFM_ALG_RSA_2048 // 或 PURE_PSA_CRYPTO
#define TFM_MEASURED_BOOT 1
#define TFM_HW_INIT 1
镜像头部结构(TF-M):
// include/firmware_image.h
typedef struct {
uint32_t magic; // 0x96F3B83C (TF-M image magic)
uint32_t image_size;
uint32_t image_version;
uint32_t binary_type; // 0=S, 1=NS, 2=S+NS composite
uint32_t load_addr; // Flash 中的加载地址
uint32_t encrypted_size;
// 实际镜像数据 (AES-256-CTR 加密)
uint8_t data[];
// 签名数据
uint8_t signature[256]; // RSA-2048
} tfm_image_header_t;
4.3 烧录与生命周期管理
# TF-M 镜像签名脚本示例 (Python)
import hashlib
from cryptography.hazmat.primitives.asymmetric import padding, rsa
from cryptography.hazmat.primitives import hashes, serialization
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
def sign_and_encrypt_firmware(plaintext_bin, aes_key, rsa_priv_key_path):
"""
生产环境固件加密签名流水线
"""
# 1. AES-256-CTR 加密固件
nonce = get_random_bytes(8) # 64-bit nonce
cipher = AES.new(aes_key, AES.MODE_CTR, nonce=nonce)
ciphertext = cipher.encrypt(plaintext_bin)
# 2. 计算密文的 SHA-256 digest
digest = hashlib.sha256(ciphertext).digest()
# 3. RSA-PSS 签名
with open(rsa_priv_key_path, 'rb') as f:
priv_key = serialization.load_pem_private_key(f.read(), password=None)
signature = priv_key.sign(
digest,
padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=32),
hashes.SHA256()
)
# 4. 组装 TF-M 镜像头部
header = create_tfm_header(len(plaintext_bin), nonce)
return header + ciphertext + signature
# 生产环境建议:HSM 管理密钥,离线签名机不联网
4.4 防降级攻击 (Anti-Rollback)
// BL2 固件升级检查伪代码
static bool is_version_acceptable(uint32_t new_version) {
uint32_t stored_version = read_boot_sector_version();
uint32_t hw_version = read_otp_monotonic_counter();
// 三重防降级:boot sector + OTP + 硬件熔丝
if (new_version < stored_version) {
ERROR("Version rollback detected: stored=%u, new=%u\n",
stored_version, new_version);
return false;
}
if (new_version < hw_version) {
ERROR("Version below OTP minimum: otp=%u, new=%u\n",
hw_version, new_version);
return false;
}
return true;
}
5. PSA Certified 认证体系
5.1 安全功能 (PSA Certified Functional API)
PSA 定义了一组跨硬件平台的安全服务 API:
| API | 功能 | 典型应用 |
|---|---|---|
| PSA Crypto API | 加密操作(AES/SHA/ECC/HMAC) | TLS, 固件签名验证 |
| PSA Storage API | 安全持久化 (ITS/SST) | 密钥/证书/设备身份 |
| PSA Attestation API | 初始设备证明 | 云端设备身份注册 |
| PSA Firmware Update API | 安全固件升级 | OTA 节点管理 |
5.2 Initial Attestation Token (IAT)
PSA Initial Attestation 服务为非易失性系统提供硬件唯一身份和设备状态证明:
// 请求初始设备证明 (IAT)
psa_status_t get_device_attestation(uint8_t *token_buf, size_t buf_size,
size_t *token_len) {
psa_status_t status;
/* 使用 PSA ITS (Internal Trusted Storage) 保护的身份令牌 */
status = psa_attest_attestation(
PSA_INITIAL_ATTEST_CHALLENGE_32, // 32字节 challenge
token_buf,
buf_size,
token_len
);
if (status != PSA_SUCCESS) {
ERROR("IAT request failed: %d\n", status);
return status;
}
/* token_buf 中包含:
* - 设备唯一 ID (TPM-like EK)
* - 软件组件哈希 (measured boot)
* - 设备生命周期状态 (locked/debug)
* - 安全启动状态
*/
return PSA_SUCCESS;
}
IAT 令牌采用 CBOR 编码 + COSE 签名,可以安全地转发给云端服务器验证设备合法性。
5.3 PSA 生命周期状态机
┌─────────────────────────────┐
│ PSA_LIFECYCLE_ASSEMBLY │
│ (出厂组装/未配置状态) │
└──────────────┬──────────────┘
│ write_device_identity()
┌──────────────▼──────────────┐
│ PSA_LIFECYCLE_PSA_ROT │
│ (PSA RoT 已部署/可测试) │
└──────────────┬──────────────┘
│ lock_device()
┌──────────────▼──────────────┐
│ PSA_LIFECYCLE_SECURED │
│ (生产锁定/不可逆) │
└──────────────┬──────────────┘
│ open_debug()
┌──────────────▼──────────────┐
│ PSA_LIFECYCLE_DEBUG │
│ (调试后门/临时启用) │
└──────────────┬──────────────┘
│ lock_debug()
┌──────────────▼──────────────┐
│ PSA_LIFECYCLE_DECOM │
│ (报废/退役) │
└─────────────────────────────┘
6. 生产环境实战:TF-M 集成到 Zephyr RTOS
6.1 项目配置 (prj.conf)
# prj.conf - TF-M 集成到 Zephyr RTOS 的最小配置
# TF-M 启用
CONFIG_TFM_PARTITION_CRYPTO=y
CONFIG_TFM_PARTITION_PROTECTED_STORAGE=y
CONFIG_TFM_PARTITION_INTERNAL_TRUSTED_STORAGE=y
CONFIG_TFM_PARTITION_FIRMWARE_UPDATE=n
CONFIG_TFM_PARTITION_INITIAL_ATTESTATION=y
CONFIG_TFM_IPC=y
CONFIG_TFM_PROFILE_SMALL=y # 内存优化 (适合64KB以下Secure RAM)
# 安全外设
CONFIG_TRUSTED_EXECUTION_SECURE=y
CONFIG_TRUSTED_EXECUTION_NONSECURE=y
# BL2 / MCUboot
CONFIG_BOOTLOADER_MCUBOOT=y
CONFIG_MCUBOOT_SIGNATURE_KEY_FILE="root-rsa-2048.pem"
CONFIG_MCUBOOT_ENCRYPTION_KEY_FILE="enc-rsa-2048.pem"
# 内存配置
CONFIG_TFM_SPM_BASE=0x10000000
CONFIG_TFM_SPM_SIZE=0x00040000
# Crypto 后端 (硬件加速优先 if available)
CONFIG_PSA_CRYPTO_DRIVER_CC3XX=y # Nordic nRF53/nRF91 CryptoCell
CONFIG_PSA_CRYPTO_DRIVER_OBERON=n # 回退到软件实现
6.2 应用程序通过 PSA API 访问安全服务
// main.c (Non-secure Zephyr Application)
#include <zephyr/kernel.h>
#include <psa/crypto.h>
#include <psa/storage.h>
#include <tfm_ns_interface.h>
#define KEY_ID PSA_KEY_ID_VENDOR_MIN // 硬件提供的密钥槽
#define STORAGE_UUID 0x01
#define STORAGE_FLAG (PSA_STORAGE_FLAG_WRITE_ONCE)
static void device_provisioning_workflow(void) {
psa_status_t status;
// === 步骤1: 生成 (或导入) 设备身份密钥 ===
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&key_attr, 256);
psa_set_key_usage_flags(&key_attr,
PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH |
PSA_KEY_USAGE_EXPORT); // 仅用于导出公钥
psa_set_key_lifetime(&key_attr,
PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
PSA_KEY_PERSISTENCE_READ_ONLY,
PSA_KEY_LOCATION_LOCAL_STORAGE));
psa_set_key_id(&key_id_attr, KEY_ID);
status = psa_generate_key(&key_attr, &key_id);
if (status != PSA_SUCCESS) {
LOG_ERR("Key generation failed (%d)", status);
return;
}
// === 步骤2: 导出公钥并注册到云端 ===
uint8_t public_key[65]; // 未压缩 ECC P-256 公钥
size_t pub_key_len;
status = psa_export_public_key(key_id, public_key, sizeof(public_key),
&pub_key_len);
// 将 public_key 发送到云注册服务...
// === 步骤3: 签名设备数据 ===
uint8_t message[] = "device_data_to_sign";
uint8_t signature[PSA_ECDSA_SIGNATURE_SIZE(256)];
size_t sig_len = 0;
status = psa_sign_hash(key_id,
PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256),
message, sizeof(message) - 1,
signature, sizeof(signature), &sig_len);
// === 步骤4: 安全存储 OTA Auth Token ===
struct psa_storage_uid_metadata_v0_t uid_meta = {
.size = sizeof(ota_auth_token),
.flag = STORAGE_FLAG,
};
psa_storage_uid_t uuid = STORAGE_UUID;
status = psa_ps_set(uuid, sizeof(ota_auth_token),
&ota_auth_token, PSA_STORAGE_FLAG_WRITE_ONCE);
}
void main(void) {
LOG_INF("TF-M Secured IoT Application Started");
device_provisioning_workflow();
while (1) {
k_sleep(K_SECONDS(10));
}
}
6.3 CMakeLists.txt (Zephyr + TF-M 集成)
# CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
set(TFM_PLATFORM "nordic_nrf/nrf5340" CACHE STRING "TF-M 平台")
set(TFM_TOOLCHAIN_FILE "${CMAKE_SOURCE_DIR}/toolchain_ARMCLANG.cmake")
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(tfm_secure_iot C)
target_sources(app PRIVATE
src/main.c
src/cloud_connector.c
)
# 链接 TF-M Non-secure API 库
target_link_libraries(app INTERFACE
tfm_s
)
# 自定义 Secure Partition (可选)
# add_subdirectory(partitions/my_custom_sp)
7. 性能基准与资源开销
使用 Nordic nRF5340(Cortex-M33 + TrustZone-M)实测:
| 指标 | 无 TF-M | 有 TF-M | 开销 |
|---|---|---|---|
| Flash (Secure) | 0 | 68-92 KB | +68~92 KB |
| RAM (Secure) | 0 | 32-48 KB | +32~48 KB |
| 启动时间 | 2.1ms | 6.8ms | +4.7ms |
| Crypto 调用延迟 | N/A | 85-150μs | 首次连接开销 |
| IPC 消息延迟 | N/A | 3-12μs | 取决于优先级 |
内存优化建议:
- 使用 TFM_PROFILE_SMALL 配置文件禁用审计日志
- 对内存极度受限场景(<64KB Secure RAM),选用 Library Model
- 使用 CONFIG_TFM_DOORBELL_API=y 启用门铃模式减少中断延迟
8. 调试与安全诊断
8.1 TF-M Debug 模式
# prj.conf (调试构建)
CONFIG_TFM_CMAKE_BUILD_TYPE_DEBUG=y
CONFIG_TFM_EXCEPTION_INFO_DUMP=y
CONFIG_TFM_PARTITION_LOG_LEVEL_INFO=y
CONFIG_TFM_SPM_LOG_RAW_ENABLED=y
# 启用 DFT (Debug Transition) 端口
CONFIG_TFM_DEBUG_DAP=y
8.2 故障排查指南
// TF-M 入口函数返回值诊断
static const char *tfm_status_str(psa_status_t status) {
switch (status) {
case PSA_SUCCESS: return "Success";
case PSA_ERROR_PROGRAMMER_ERROR: return "Programmer error";
case PSA_ERROR_CONNECTION_REFUSED:
return "Secure Partition rejected (检查 SID 和 min_version)";
case PSA_ERROR_CONNECTION_BUSY: return "Partition 忙 (RPC 处理中)";
case PSA_ERROR_INVALID_ARGUMENT: return "参数非法/过大";
case PSA_ERROR_HARDWARE_FAILURE: return "硬件加速器故障";
default: return "Unknown";
}
}
常见错误 PSA_ERROR_CONNECTION_REFUSED (134) 通常由以下原因引起:
1. Non-secure 端 SID (Service ID) 与 Secure Partition 不匹配
2. Secure Partition 未编译或链接时被优化剔除
3. SP manifest 文件中声明的 min_version 过高
8.3 TF-M 与实时系统共存
TF-M 对 RTOS 实时性的影响主要集中在: 1. SAU 配置变更后的 ISB/DSB 屏障 (数百纳秒) 2. Secure Entry 时的自动上下文保存 (12 个时钟周期) 3. IPC 模式下 Secure Partition 被高优先级 NS 中断打断(TF-M 1.9+ 支持 preemptible partitioning)
对于硬实时要求(<10μs 中断延迟),建议: - 使用 Library Model 而非 IPC Model - 将 NS-critical ISR 定义为 Non-secure Callable (NSC) - 配置 SCB->AIRCR 优先级分组为 4 位抢占优先级
9. 总结
ARM TrustZone-M + TF-M 为物联网终端提供了生产级的硬件隔离和安全固件基础设施。从零开始构建安全固件需要掌握三大核心:
- 硬件信任根:SAU 分区 + 防降级 OTP 计数 + 加密引擎
- 固件标准框架:TF-M SPM + PSA API + 标准分区 (Crypto/Storage/Attestation)
- 供应链安全管理:HSM 密钥注入 + 烧录防护 + 生命周期锁定
虽然 TrustZone-M 在安全能力上不如 TrustZone-A 的 OS 系统全虚拟化,但其在微秒级延迟、数十 KB 内存开销下的硬件安全隔离,已经是物联网设备防御物理攻击和软件漏洞的最佳实践。在 PSA Certified Level 2/3 认证的推动下,TF-M 生态系统正在成为事实上的 IoT 安全固件标准。
参考资源: - TF-M 官方文档 - PSA Certified 规范 - ARM ARM for ARMv8-M Architecture Reference Manual - AN5289 (STM32U5 TrustZone 编程手册) - AN540 (STM32U5 安全外设配置指南)

发表评论 取消回复