Armv8-M安全扩展为嵌入式系统提供了硬件级的安全隔离机制,其核心是TrustZone技术。该技术将处理器运行状态划分为安全(Secure)和非安全(Non-secure)两种执行环境,实现了物理隔离的安全域。
安全状态通过以下机制实现隔离:
SAU配置示例:
c复制#define SAU_REGIONS 3
void configure_sau(void) {
SAU->RNR = 0; // 配置区域0
SAU->RBAR = 0x00000000;
SAU->RLAR = 0x1FFFFFFF | SAU_RLAR_ENABLE_Msk;
SAU->RNR = 1; // 配置区域1
SAU->RBAR = 0x20000000;
SAU->RLAR = 0x3FFFFFFF | SAU_RLAR_ENABLE_Msk;
SAU->RNR = 2; // 配置区域2
SAU->RBAR = 0x60000000;
SAU->RLAR = 0x7FFFFFFF | SAU_RLAR_ENABLE_Msk;
SAU->CTRL = SAU_CTRL_ENABLE_Msk; // 启用SAU
}
关键提示:SAU配置必须在安全状态下完成,且通常作为系统启动初期的关键初始化步骤
非安全代码调用安全服务需通过严格定义的网关机制:
__attribute__((cmse_nonsecure_entry))标记典型调用序列的汇编实现:
assembly复制__acle_se_secure_function:
secure_function:
PUSH {R7, LR}
BL internal_secure_operation
POP {R7, LR}
BXNS LR ; 关键的安全返回指令
; 非安全侧调用
non_secure_caller:
BL secure_function ; 实际调用的是veneer
...
; Veneer实现
secure_function_veneer:
SG ; 安全网关指令
B.W __acle_se_secure_function
构建安全镜像需要特定工具链支持:
-mcmse启用安全扩展支持<arm_cmse.h>提供安全扩展 intrinsics基础编译命令示例:
bash复制armclang --target=arm-arm-none-eabi -march=armv8-m.main -mcmse -c secure_code.c
安全入口函数有特殊实现要求:
c复制#include <arm_cmse.h>
// 标准安全函数(仅安全域可调用)
int secure_operation(int x) {
return x * 2;
}
// 安全入口函数(允许非安全调用)
int __attribute__((cmse_nonsecure_entry)) secure_api(int x) {
// 参数自动进行安全检查
int result = secure_operation(x);
// 返回值自动清理敏感寄存器
return result;
}
关键注意事项:
安全系统需要特殊的存储器布局定义:
scatter复制LOAD_REGION 0x00000000 0x00200000 {
/* 安全执行区域 */
SECURE_EXEC 0x00000000 {
*(+RO,+RW,+ZI)
}
/* 非安全可调用区域(NSC) */
NSC_REGION 0x10000000 ALIGN 32 {
*(Veneer$$CMSE)
}
/* 非安全区域 */
NON_SECURE_EXEC 0x20000000 {
*.o(NON_SECURE)
}
}
内存布局要点:
生成导入库的关键步骤:
bash复制armlink secure.o --import-cmse-lib-out=secure_import.lib \
--scatter=secure.scatter \
--cpu=8-M.Main
导入库包含:
典型应用场景:
非安全侧开发要点:
c复制#include "secure_interface.h" // 来自安全团队
void non_secure_app(void) {
int result = secure_api(42); // 跨域调用
if(result != 84) {
handle_error();
}
}
对应的编译命令:
bash复制armclang --target=arm-arm-none-eabi -march=armv8-m.main -c non_secure.c
armlink non_secure.o secure_import.lib -o final.axf
混合架构下的特殊考量:
c复制// Armv8-M.Mainline支持浮点,需显式清理
void __attribute__((cmse_nonsecure_entry)) fp_operation(float x) {
__asm volatile("vpush {s0-s15}"); // 保存安全浮点上下文
float result = x * 1.5f;
__asm volatile("vpop {s0-s15}"); // 恢复上下文
return result;
}
重要警告:Armv8-M Baseline架构不支持浮点扩展,在此架构下编译的安全代码如果包含浮点操作,可能泄露安全域浮点寄存器内容
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 调用安全函数时进入HardFault | NSC区域配置错误 | 检查scatter文件中NSC区域是否正确定义和执行权限 |
| 安全函数返回值被篡改 | 寄存器清理不完整 | 确保使用-mcmse编译并检查反汇编中的寄存器清理代码 |
| 非安全调用导致系统锁定 | SAU/MPU配置冲突 | 验证SAU区域定义是否与MPU设置冲突 |
| 安全函数参数值异常 | 参数传递方式错误 | 确保参数均为基本类型且数量不超过寄存器承载能力 |
多版本安全镜像维护策略:
--import-cmse-lib-in保持入口地址稳定版本升级示例:
bash复制# 保持v1入口地址的同时生成v2
armlink secure_v2.o --import-cmse-lib-out=import_v2.lib \
--import-cmse-lib-in=import_v1.lib \
--scatter=secure.scat
实际工程中,我们发现安全边界处的栈处理需要特别注意。在某个支付终端项目中,由于非安全侧栈溢出破坏了安全调用帧,导致系统出现随机性故障。解决方案是:
这种深度防御机制最终使系统通过了CC EAL4+认证要求。