多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

ARM Cortex-M23/M33/M35P安全内核解析:从TrustZone原理到物联网安全实战

ARM Cortex-M23/M33/M35P安全内核解析:从TrustZone原理到物联网安全实战 1. 从“裸奔”到“武装”为什么嵌入式系统需要Security如果你在嵌入式领域摸爬滚打超过五年大概率经历过这样的场景产品上市后突然发现某个功能可以被用户通过非正常手段绕过或者更糟固件被轻易提取、复制甚至被恶意篡改后重新刷入。早期基于Cortex-M0/M3的项目很多时候就像在“裸奔”我们关注的重点是性能、功耗和成本安全往往被放在“Nice to have”的清单末尾。但随着物联网设备的爆炸式增长设备联网成为标配安全从一个可选项变成了生存的底线。攻击者不再需要物理接触设备一个暴露的调试接口、一个未加密的固件升级包、甚至一段存在缓冲区溢出的网络数据解析代码都可能成为整个系统被攻破的入口。ARM公司显然深刻洞察了这一趋势。在传统的Cortex-M系列如M0, M3, M4取得了巨大的市场成功后他们推出了一个全新的产品线分支——Cortex-M23、Cortex-M33以及后来的Cortex-M35P。这些内核名字里没有延续简单的数字递增而是带上了“Security”的鲜明标签。这不仅仅是营销话术其内核架构从设计之初就为应对现代嵌入式安全威胁而重塑。理解M23/33/35P本质上是在理解ARM为物联网时代嵌入式设备构建的一套“内生安全”体系。这套体系不是简单地在外围加一个加密芯片而是将安全能力如同血管和神经一样深植于处理器的最核心。2. 安全基石TrustZone for Armv8-M 架构精解要搞懂M23/M33/M35P必须彻底理解其核心安全技术——TrustZone for Armv8-M。它脱胎于应用处理器如Cortex-A系列上成熟的TrustZone技术但针对资源受限的微控制器场景做了极致的精简和优化。2.1 两个世界一道“防火墙”你可以把TrustZone for Armv8-M想象成在单一的物理CPU核心内部划分出两个完全逻辑隔离的“世界”安全世界Secure World和非安全世界Non-secure World或称为正常世界。这两个世界有各自独立的内存空间、外设视图、甚至中断处理逻辑。关键在于“隔离”的粒度。传统的“特权级”如ARM的Handler/Thread模式是软件层面的权限控制一个恶意的高权限任务可以访问所有资源。而TrustZone的隔离是硬件强制的。CPU在执行时会处于安全状态S或非安全状态NS。当CPU处于NS状态时它试图访问被标记为安全的内存或外设硬件会直接产生一个错误异常SecureFault访问被坚决阻止软件无法绕过。这就像在一栋大楼里不仅用门禁卡软件权限区分区域更是在关键区域砌上了物理承重墙硬件隔离。这种硬件隔离的实现依赖于一个名为安全属性单元SAU Secure Attribution Unit的组件。在Cortex-M23/M33中SAU允许开发者将内存地址空间比如Flash和SRAM的某些区域静态地配置为安全或非安全。例如你可以将存放加密密钥、安全启动代码、认证算法的部分Flash配置为安全区域而将应用程序、用户数据、网络协议栈放在非安全区域。2.2 安全与非安全的交互网关与服务完全隔离意味着无法协作而系统需要安全世界为非安全世界提供服务如加解密、密钥管理、安全存储。为此ARM定义了安全网关Secure Gateway, SG指令和非安全可调用Non-Secure Callable, NSC内存区域。NSC区域这是安全内存中一块特殊的区域。非安全世界的代码只能跳转到这个区域内的入口点。SG指令这条特殊指令必须位于NSC区域的入口点。当非安全代码调用至此并执行SG指令后CPU会进行一个“世界切换”从非安全状态切换到安全状态并跳转到指定的安全函数称为安全服务去执行。执行完安全服务后通过一条特殊的返回指令BXNS再切换回非安全世界。这个过程是唯一被允许的、受控的跨界通道。安全服务的入口即NSC区域就像银行的服务窗口你只能通过窗口特定入口递交请求调用而无法进入柜台内部安全世界内存。这种设计确保了即使非安全世界的应用完全被恶意代码控制它也无法直接读取或篡改安全世界内部的敏感数据和代码逻辑只能通过预定义的安全接口来请求服务并且服务的内容和权限由安全世界完全掌控。2.3 外设的“站队”PPC与MPC内存隔离了外设呢一个UART或SPI接口可能既需要打印非安全的调试信息又需要传输安全的关键数据。TrustZone for Armv8-M通过外设保护控制器PPC, Peripheral Protection Controller来解决这个问题。PPC通常由芯片厂商实现它允许将每个外设或外设分组配置为安全特权仅安全世界可访问。非安全特权仅非安全世界可访问。非安全用户非安全世界只有在用户模式下不可访问在特权模式下可访问用于驱动。配置错误任何访问都会触发错误。例如可以将真随机数生成器TRNG、加密加速器、存储根密钥的OTP存储器配置为“安全特权”仅供安全世界使用。而将用户界面的LED、按键、普通定时器配置为“非安全特权”。对于共享外设如DMA可以配置其控制寄存器为安全而数据缓冲区寄存器为非安全从而实现安全世界控制数据流向非安全世界提供数据缓冲的复杂协作。对于需要更精细控制的内存区域如某块共享RAM则可能由内存保护控制器MPC, Memory Protection Controller来管理其原理与PPC类似但控制对象是内存地址区间。3. Cortex-M23/M33/M35P 的差异化定位与选型虽然都基于TrustZone for Armv8-M但M23、M33、M35P面向不同的细分市场选择哪一款取决于你对性能、功能和安全的综合要求。3.1 Cortex-M23极致能效与成本敏感的安全入口M23可以看作是Cortex-M0的“安全升级版”。它继承了M0的极简设计理念两级流水线、低中断延迟、超低功耗。M23的核心使命是在保持M0级别成本和功耗的前提下为最广泛的入门级物联网设备提供基础的安全硬件隔离能力。核心特点Armv8-M基线架构Mainline支持Thumb-1/2指令集通常最高主频在几十MHz到100MHz左右。安全特性完整支持TrustZone for Armv8-M具备SAU通常3-8个可配置区域。注意M23不支持MPU内存保护单元。这意味着在非安全世界内部无法再像M3/M4那样通过MPU进行任务间的内存保护。它的安全隔离完全依赖于TrustZone的世界划分。这对于运行简单裸机程序或轻量RTOS的非安全侧应用是足够的。典型应用智能门锁、传感器节点、可穿戴设备、小型家电等。这些设备需要防止固件被克隆、升级包被篡改并对功耗和成本极为敏感。M23让这类产品能以最小的代价获得硬件级安全基石。3.2 Cortex-M33性能与功能的平衡大师M33则是Cortex-M4的“全面安全增强版”并引入了部分M7的特性。它瞄准中高端物联网和工业应用在提供可观计算性能的同时提供完整的安全和调试功能集。核心特点Armv8-M主线架构Mainline支持DSP扩展单周期乘加MAC、可选单精度浮点单元FPU。采用三级流水线性能可达1.5 DMIPS/MHz以上主频可达200MHz。安全与保护完整TrustZone且同时具备SAU和MPU。这是与M23的关键区别。非安全世界可以利用MPU实现RTOS中多任务间的内存保护、栈溢出检测等实现“世界间隔离TrustZone 世界内保护MPU”的双重保险。安全世界也可以有自己的MPU可选。增强特性支持协处理器接口用于扩展自定义指令增强的调试和追踪功能如ETM微追踪可选的内存纠错码ECC。典型应用智能家居中枢、工业网关、支付终端、高端消费电子。这些应用场景复杂非安全侧可能运行Linux-like的轻量系统或功能丰富的RTOS需要MPU进行任务管理同时安全侧负责支付认证、设备入网认证、密钥管理等关键任务。3.3 Cortex-M35P物理安全防御的终极形态M35P在M33的基础上增加了一个“P”——物理安全防护Physical Security。它的目标客户是那些面临高强度物理攻击威胁的领域如金融IC卡、汽车电子、身份认证令牌。核心抗篡改特性传感器网络集成电压、温度、频率传感器。当检测到电压毛刺Glitch、温度异常或时钟频率突变时可以立即触发安全擦除或进入锁定状态。存储加密对片上Flash和SRAM的数据进行实时加密存储即使通过物理探针获取到存储内容也是密文。主动屏蔽层芯片顶层覆盖金属网格一旦被物理穿刺试图探测内部信号网格断裂即触发清零。设计考量使用M35P的芯片其布局布线、封装都会采用特殊设计以增强物理防护。因此基于M35P的MCU价格昂贵仅用于安全需求极高的特种场景。对于绝大多数物联网设备M33甚至M23已足够。选型速查表特性Cortex-M23Cortex-M33Cortex-M35P架构基线Armv8-M BaselineArmv8-M MainlineArmv8-M Mainline (P)性能类比M0 升级版M4 安全增强版M33 物理加固版TrustZone支持支持支持MPU不支持支持非安全侧必选安全侧可选支持DSP/FPU无 / 无有 / 可选有 / 可选典型主频 100 MHz100 - 200 MHz100 - 200 MHz核心价值低成本引入硬件安全性能与安全的平衡抵御物理攻击适用场景成本敏感型IoT终端中高端IoT、工业控制金融支付、汽车、高安全认证4. 开发模式转变从单一片区到双世界协同采用带TrustZone的芯片开发模式会发生根本性变化。你不再是在编写一个单一的应用程序而是在协同开发两个逻辑上独立、物理上共存的“子系统”。4.1 项目分区与链接脚本重定义首先你需要在内存映射上明确划分安全与非安全区域。这通常在链接脚本.ld文件中定义。例如MEMORY { FLASH_SECURE (rx) : ORIGIN 0x0, LENGTH 128K /* 安全启动 安全服务 */ FLASH_NSC (rx) : ORIGIN 0x20000, LENGTH 4K /* 非安全可调用区域 */ FLASH_NONSECURE (rx): ORIGIN 0x21000, LENGTH 384K /* 用户应用 */ RAM_SECURE (rwx) : ORIGIN 0x30000000, LENGTH 32K RAM_NONSECURE (rwx): ORIGIN 0x30008000, LENGTH 96K }你需要创建两个独立的工程或编译目标一个安全项目编译生成安全镜像一个非安全项目编译生成非安全镜像。安全项目会包含所有安全世界的代码并负责初始化SAU、PPC定义NSC区域并实现安全服务函数。非安全项目则像传统开发一样但它只能访问非安全的内存和外设调用安全服务需要通过NSC入口。4.2 启动流程安全先行芯片上电后首先运行的是安全世界的代码通常从0地址开始。安全启动代码需要按顺序完成硬件初始化配置时钟、必要的外设。初始化SAU/PPC划定安全与非安全的边界。这是最关键的一步一旦配置完成隔离墙就建立起来了。设置NSC区域将包含SG指令的安全服务入口函数所在的Flash区域标记为NSC。验证非安全镜像可选但推荐在跳转到非安全世界之前使用密码学方法验证非安全应用程序固件的完整性和真实性防止被篡改的固件运行。执行SG指令并跳转最后安全启动代码通过执行一个特殊的序列通常是设置非安全世界的初始PC和SP然后执行SG跳转将CPU控制权移交到非安全世界的复位向量非安全应用程序开始运行。4.3 调试与追踪的复杂性调试带TrustZone的系统变得更具挑战。你需要一个支持TrustZone识别的调试器如J-Link Plus及以上版本Keil ULINKplus等。在调试视图中你需要能区分当前上下文是安全还是非安全并能分别加载安全和非安全镜像的符号表。ETM或MTB追踪也需要配置为能区分安全和非安全世界的执行流否则追踪数据会混杂不清。一些高级调试工具允许你设置“安全世界访问断点”即当非安全代码试图非法访问安全资源时触发这对于排查跨界访问错误非常有用。5. 实战中的安全策略设计与常见陷阱有了硬件不等于安全。如何设计安全世界的软件是项目成败的关键。5.1 最小权限原则与服务设计安全世界应遵循“最小权限”和“最小暴露”原则。不要把所有代码都放进安全世界。安全世界只应包含安全启动代码密码学原语AES, SHA, RSA等的实现或对硬件加速器的驱动封装密钥管理生成、存储、使用关键资产如设备唯一标识、认证证书的存储和访问接口安全升级验证逻辑每个安全服务函数都应设计得尽可能简单、功能单一。例如提供一个secure_aes_encrypt(buffer_in, buffer_out, key_id)服务而不是一个secure_crypto_operation(complex_op_struct)。复杂的参数解析可能引入漏洞。5.2 参数传递与边界检查非安全世界调用安全服务时参数通过寄存器或共享内存需配置为非安全传递。安全世界必须对所有输入参数进行严格的边界和有效性检查。因为非安全世界可能被攻陷传入的参数可能是恶意的。指针参数如果传入的是指向非安全内存的指针安全服务在通过该指针读写数据前必须确保该指针指向的是合法的非安全内存区域并且操作长度不会越界。这通常需要芯片提供额外的硬件机制如ARM的TT指令或由安全软件维护一个合法的共享缓冲区列表。整数参数检查是否在合理范围内。关键陷阱避免在安全服务内部进行动态内存分配malloc这可能导致不可预测的行为和侧信道攻击。5.3 应对侧信道攻击即使逻辑正确物理设备也可能通过功耗分析、电磁辐射、时序差异等方式泄露信息。M35P有专门的防护但M23/M33也需要在软件层面注意恒定时间算法确保密码学操作如比较密钥、模幂运算的执行时间不随数据变化而变化。随机化在可能的地方引入随机延迟或随机操作顺序。清理现场安全服务返回前务必清空用于临时存储敏感数据的寄存器栈内存。5.4 安全启动与固件更新这是TrustZone最能发挥价值的场景之一。一个典型的安全启动流程如下芯片ROM中的第一级引导加载程序ROM Bootloader验证安全世界引导程序Secure Bootloader的签名。安全世界引导程序启动初始化TrustZone然后验证非安全世界应用程序Application的签名。验证通过后才跳转到应用程序执行。固件更新时新固件包括安全和非安全部分被下载到临时区域。安全世界负责验证整个更新包的签名和版本。验证通过后再由安全世界负责将新固件安全地编程到正式存储区。这个过程确保了即使传输链路被监听、存储介质可能出错也只有经过认证的固件才能被运行。6. 生态工具链与未来展望开发基于Cortex-M23/33/35P的项目工具链的选择至关重要。编译器ARM Compiler 6Armclang或基于LLVM的GCC/Clang版本对Armv8-M架构和TrustZone有最好的支持。它们能理解__attribute__((cmse_nonsecure_entry))这样的函数属性用于自动生成NSC入口代码和安全函数清理代码。较老的ARM Compiler 5需要特殊的支持包和更复杂的手动处理。IDE/工具Keil MDK、IAR Embedded Workbench、SEGGER Embedded Studio等主流IDE都已提供对TrustZone项目的支持包括工程模板、双镜像管理、调试配置等。例如在Keil中你可以创建“Secure Project”和“Non-secure Project”并通过“Manage Project Items”将它们关联起来。软件库ARM提供了CMSIS-TZ Core API这是一套标准化接口用于在安全和非安全代码中配置和访问TrustZone相关功能如SAU初始化、状态查询等。芯片厂商如NXP、ST、Microchip等也会提供基于自家MCU的TrustZone软件包和示例这些是快速上手的关键。从我实际移植和开发多个项目的经验来看从传统MCU转向TrustZone MCU最大的挑战不在于硬件本身而在于思维模式的转变和软件架构的重构。初期在划分安全边界、设计服务接口时会花费较多时间但一旦架构清晰后续开发和维护的复杂度反而会降低因为安全和非安全世界的职责被强制分离了。未来随着物联网安全法规如欧盟的RED指令、中国的网络安全法对IoT设备的要求日益严格以及应用场景对数据隐私和系统完整性的要求越来越高内置硬件安全功能的MCU将成为默认选择。Cortex-M23/33/35P这类内核正推动着整个嵌入式行业从“事后补救”的安全外挂模式转向“设计即安全”的体系化模式。对于嵌入式开发者而言深入理解并掌握TrustZone技术不再是面向未来的技能储备而是应对当下产品开发挑战的必备能力。
返回列表