PSA Firmware Framework(简称FF-M)是Arm提出的安全固件框架标准,专为构建可信执行环境(TEE)中的安全服务而设计。其核心架构基于Secure Partition(安全分区)概念,通过硬件辅助的隔离机制(如ARM TrustZone)实现资源保护。最新发布的v1.1版本在原有IPC模型基础上,引入了多项增强特性,显著提升了性能与开发灵活性。
FF-M的安全隔离机制通过以下三层实现:
典型的隔离级别配置示例如下:
c复制/* 在manifest中定义隔离级别 */
{
"psa_framework_version": 1.1,
"isolation_level": 2, // 级别1-3,数字越大隔离越严格
"mmio_regions": [
{
"name": "CRYPTO_ACCELERATOR",
"permission": "READ-WRITE"
}
]
}
v1.1版本的核心改进之一是引入SFN(Secure Function)模型,与原有IPC模型形成互补:
| 特性 | IPC模型 | SFN模型 |
|---|---|---|
| 调用方式 | 异步消息传递 | 同步函数调用 |
| 上下文切换 | 需要SPM调度 | 直接跳转 |
| 内存开销 | 每个连接需维护状态 | 无会话状态 |
| 延迟 | 较高(微秒级) | 极低(纳秒级) |
| 适用场景 | 复杂服务逻辑 | 高性能外设驱动 |
实测数据显示,在Cortex-M55平台上,SFN模型的调用延迟仅为IPC模型的1/20,这使得它特别适合实时性要求高的场景,如安全传感器数据采集或加密加速器驱动。
SFN模型的本质是将服务接口编译为可直接调用的函数。开发时需注意:
c复制psa_status_t my_service_sfn(const psa_msg_t* msg) {
// 处理请求并直接返回状态码
return PSA_SUCCESS;
}
c复制// v1.1新增的初始化函数(可选)
psa_status_t my_partition_init(void) {
if(peripheral_init() != SUCCESS) {
return PSA_ERROR_HARDWARE_FAILURE;
}
return PSA_SUCCESS;
}
__attribute__((section(".secure_data")))显式定位踩坑提醒:SFN函数内不可调用可能阻塞的API(如psa_delay),否则会导致整个分区挂起。
传统IPC通信需要两次数据拷贝(客户端→SPM→服务端),而MM-IOVEC通过内存映射实现零拷贝:
c复制// 客户端代码示例
psa_invec in_vecs[] = {
{buffer, sizeof(buffer)} // 直接映射此内存区域
};
// 服务端优化处理
const uint8_t* data = psa_map_invec(msg_handle, 0);
if(data) {
// 直接操作映射内存
process_data(data, msg->in_size[0]);
// 框架自动解除映射
}
性能测试表明,传输1KB数据时MM-IOVEC可降低80%的CPU开销。但使用时需注意:
无状态服务通过消除会话管理开销来优化短生命周期操作,其实现要点包括:
json复制{
"connection_based": false,
"stateless_handle": "auto" // 或指定固定索引
}
c复制// 无需psa_connect/psa_close
psa_call(CRYPTO_SERVICE_HANDLE, request_type, in_vecs, out_vecs);
典型应用场景包括:
从v1.0迁移到v1.1时,manifest需进行以下必要修改:
diff复制- "psa_framework_version": 1.0,
+ "psa_framework_version": 1.1,
json复制"model": "IPC" // 或"SFN"
json复制"irqs": [
{
"name": "TIMER_IRQ", // 替代旧版signal字段
"handling": "FLIH", // 新增处理类型
"source": "TIMER0"
}
]
v1.1对中断处理做出重大调整:
c复制// FLIH函数原型
psa_flih_result_t TIMER_IRQ_flih(void) {
if(registers & TIMEOUT_FLAG) {
clear_interrupt();
return PSA_FLIH_SIGNAL; // 需要后续处理
}
return PSA_FLIH_NO_SIGNAL;
}
// SLIH处理函数
void timer_slih(void) {
psa_reset_signal(TIMER_IRQ_SIGNAL);
// 执行耗时操作...
}
v1.1明确了错误码分配规则,开发者需遵循以下范围:
| 错误码范围 | 用途 |
|---|---|
| 1 ~ 255 | 服务自定义成功码 |
| -1 ~ -128 | 首要服务错误码范围 |
| -129 ~ -248 | 保留给PSA标准服务 |
| -249 ~ -256 | SPM实现专用 |
| ≤ -257 | 次要服务错误码范围 |
建议使用预定义宏保证兼容性:
c复制#define MY_SERVICE_ERROR_BASE PSA_ERROR_ROT_SERVICE_BASE
#define INVALID_PARAM (MY_SERVICE_ERROR_BASE - 1)
json复制"stack_size": "0x800", // 需考虑最深调用链
c复制__attribute__((always_inline))
static inline void crypto_round(uint32_t* state) {
// 高频操作函数
}
c复制void* vec = psa_map_outvec(handle, idx);
if(vec && msg->out_size[idx] >= required_len) {
// 安全操作区域
psa_unmap_outvec(handle, idx, used_len);
} else {
psa_unmap_outvec(handle, idx, 0); // 显式取消
}
__DSB()屏障SCB_CleanDCache_by_Addr对于复杂系统,可组合使用两种模型:
mermaid复制graph TD
A[高频传感器数据] -->|SFN调用| B(环形缓冲区)
B -->|IPC消息| C[数据处理服务]
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| SFN调用卡死 | 栈溢出 | 增大stack_size并检查递归 |
| MM-IOVEC映射失败 | 客户端内存未物理连续 | 使用psa_alloc分配对齐内存 |
| FLIH中触发异常 | 调用了阻塞API | 将耗时操作移至SLIH |
| 服务版本不兼容 | version_policy配置错误 | 设置为"RELAXED"或更新客户端 |
c复制// 在框架配置中启用
#define PSA_FRAMEWORK_LOG_LEVEL 3 // DEBUG级别
c复制uint32_t start = psa_cycle_count();
// 被测代码段
uint32_t cycles = psa_cycle_count() - start;
通过对比测试数据可以清晰看出设计动机:
| 指标 | IPC模型 (Cortex-M7) | SFN模型 (Cortex-M7) |
|---|---|---|
| 调用延迟 | 1.2μs | 58ns |
| 代码大小开销 | +8KB | +1.2KB |
| 最大吞吐量 | 820 calls/ms | 12,000 calls/ms |
这种性能提升使得以下场景成为可能:
MM-IOVEC设计时面临的核心挑战是如何平衡性能与安全。最终方案通过以下机制确保安全:
对于复杂服务,可采用"微分区"架构:
针对PSA Certified Level 2/3要求,需特别注意:
c复制// 示例:参数校验模板
if(type < PSA_CALL_TYPE_MIN || type > PSA_CALL_TYPE_MAX) {
psa_panic(INVALID_ARGUMENT);
}
推荐工具组合:
bash复制armclang --target=arm-arm-none-eabi -march=armv8-m.main+dsp
python复制def test_sfn_latency():
for i in range(1000):
start = get_cycle_count()
psa.call(SFN_SERVICE, REQUEST)
latency = get_cycle_count() - start
assert latency < MAX_ALLOWED
yaml复制fuzz_targets:
- name: crypto_service
api: psa_crypto_sfn
input_types: [random, edge_cases]
memory_protection: strict
某工业设备厂商采用v1.1特性重构其安全传感器处理流水线:
原始架构:
优化后架构:
优化结果:
关键实现片段:
c复制// 加速度计处理SFN
psa_status_t accel_sfn(const psa_msg_t* msg) {
const sensor_data_t* data = psa_map_invec(msg->handle, 0);
if(data && msg->in_size[0] == sizeof(sensor_data_t)) {
return process_accel(data);
}
return PSA_ERROR_INVALID_ARGUMENT;
}
根据Arm路线图,后续版本可能引入:
对于现有开发者,建议:
psa_framework_version()做版本检测PSA_HAS_DYNAMIC_LOAD)在实际项目中,我们团队发现SFN模型配合MM-IOVEC可将加密吞吐量提升3倍以上,但需要特别注意内存对齐问题——某些Cortex-M处理器要求128位对齐才能达到最佳性能。这提醒我们,性能优化必须结合具体硬件特性进行微调。