☰
STM32安全启动实战:SBSFU信任链与固件更新全解析
2026/10/22 7:48:21 网站建设 项目流程

如果你去搜“安全启动”,大概率会先看到一屏的Windows 11升级提示,或者“主板Secure Boot怎么打开”这类求助帖。PC上的安全启动,本质是用一段固化在主板里的可信代码,先检查引导程序有没有合法签名,再决定要不要执行它。MCU里的安全启动,思路完全一样,但实现起来要难受得多:Flash以KB算、没有独立的TPM、程序直接在Flash里跑,还得同时处理升级失败、代码抄板、回滚攻击这些现实问题。ST给出的答案就是X_CUBE_SBSFU——一个整合了安全启动(Secure Boot)和安全固件更新(Secure Firmware Update)功能的软件扩展包,配套的UM2262应用笔记是绝大多数人进入这个领域的第一份文档。这篇文章不打算按UM2262的目录平铺,而是按我实际跑通SBSFU的经验,把这里面的信任链结构、CubeMX配置逻辑、完整升级链路和最容易翻车的几个点讲清楚。正在接触STM32安全启动、或者已经在用X_CUBE_SBSFU但被一堆配置项绕晕的工程师,读完应该能直接上手。

1. SBSFU要解决的不只是“不被偷代码”:安全启动和固件更新的真实场景

1.1 没有信任根的MCU产品,最怕哪几件事

很多工程师第一次看到SBSFU会想:我不就是需要一个bootloader吗?自己写一个跳转程序不就行了?这个问题其实问到了点子上——普通bootloader和SBSFU的区别,核心不在“跳转”,而在“校验”和“防回滚”。

普通bootloader做的事情是上电后直接跳到0x08008000之类的应用地址,最多加个CRC检查。但一个没有安全设计的升级系统,至少面临四类风险:

  • 固件被篡改:攻击者把恶意程序直接写进Flash,设备启动后执行的就是别人的代码。最典型的是抄板、注入后门、替换业务逻辑。
  • 固件被回滚:设备已经修复了漏洞,攻击者又把旧版本刷回去,让已知漏洞重新生效。这类攻击在金融、表计、车联网场景里尤其要命。
  • 代码被读取:调试接口没锁,J-Link/ST-Link直接连上,整份固件被读出来逆向分析。很多协议密钥、服务器地址就是这样泄露的。
  • 升级链路被劫持:OTA下载过程中数据包被替换,设备更新了一个“看起来正常”的恶意固件。

SBSFU之所以叫“Secure Boot + Secure Firmware Update”,就是同时解决启动和升级两条链路上的可信问题。它不只是做签名验证,还包含了加密、哈希校验、版本号管理、Flash读写保护,甚至能在升级失败时保证旧版本还能跑。这才是它和普通bootloader拉开差距的地方。

1.2 和PC Secure Boot、SoC平台Secure Boot的共通逻辑

如果你接触过Rockchip那类SoC平台的Secure Boot,或者研究过安卓的Verified Boot,会发现大家做的事情本质是一样的:从一颗不可篡改的信任根出发,逐级校验,最后才把控制权交给操作系统或应用。

PC的UEFI Secure Boot是签名库里的公钥校验引导加载器,安卓的Verified Boot是从BootROM开始的哈希链,而STM32的SBSFU是把Secure Engine当作信任根,再由它去校验后面的Secure Boot、Secure Firmware Update和应用镜像。抽象出来都是那条链:

信任根 -> 校验Bootloader -> 校验固件镜像 -> 运行

这也是为什么“安全启动”这个词在PC、手机、嵌入式MCU里反复出现。只不过MCU上的约束更多,实现也更底层——没有操作系统帮忙,连跳转地址写错都会直接进HardFault。理解了这条信任链,后面的所有配置项就都不难懂了。

2. 三重角色搭起信任链:SE、SB、SFU是怎么分工与协作的

2.1 从一条应用启动路径看懂整个流程

SBSFU里有三个缩写必须记住:SE、SB、SFU。

  • SE(Secure Engine):信任根。在STM32L5上由TrustZone硬件隔离,在F4/L4等不支持TrustZone的芯片上,是一段放在受保护Flash区域的代码。它负责密钥存储、密码学运算,以及对SB_SFU镜像的认证。应用代码无法读写SE区域。
  • SB(Secure Boot):安全启动模块。负责校验用户应用镜像的签名、版本号、完整性,校验通过后才跳转执行。
  • SFU(Secure Firmware Update):固件更新引擎。负责通过UART、USB、SPI、I2C、CAN等接口接收新固件,做验签、解密、版本检查,然后安装到应用区。

在工程实现上,SB和SFU通常打包成一个镜像,所以你在CubeMX里看到的工程是SB_SFU和Application两个。前者就是那个“带安全启动功能的更新器”,后者是你自己的业务程序。

一次完整的启动流程是这样的:

  1. MCU上电复位,CPU从0x08000000取指,进入SE。
  2. SE用Root Key校验SB_SFU的签名和哈希,确保SB_SFU没被换过。
  3. SB_SFU接管,读取应用区头部信息,取出版本号、签名、镜像长度。
  4. SB_SFU用SB公钥验证应用镜像签名,并检查版本号是否满足反回滚要求。
  5. 校验通过,配置好向量表,跳转执行Application。
  6. 任何一步失败,设备不会执行非法代码,而是停在安全状态或进入SFU升级模式等待恢复。

这就是“Secure Boot”的实际含义——它保证你设备上跑的每一段代码,都经过信任根逐级确认。

2.2 密钥层级和镜像格式:谁签名、谁加密、谁校验

SBSFU的密钥体系分三层,理解这层关系,后面换正式密钥时就不会乱:

密钥作用存哪里
Root Key(信任根密钥)认证SB_SFU,保护SB/SFU密钥SE受保护区域
SB Key签名和验证用户应用镜像公钥存SE,私钥由开发者/产线保管
SFU Key签名和加密待升级固件包公钥存SE,私钥由开发者/产线保管

开发阶段,ST会送你一套Development Keys,方便你直接跑通流程。但Development Keys的公钥是公开的,如果产品一直用这套密钥,攻击者也能生成一个合法签名的固件。所以量产前必须生成自己的密钥对,并重新烧录SE和SB_SFU——这一点后面踩坑部分还会细说。

加密算法方面,不同SBSFU版本和芯片型号略有差异,但主线基本是:ECDSA P-256做签名认证,AES-128-CBC或AES-GCM做固件加密,SHA-256做哈希校验。UM2262里有一张算法和密钥长度的对照表,真到要选型定制的时候,以你下载的版本为准。

生成的固件包不是裸的bin文件,而是一个带头部结构的镜像:头部包含魔数、固件版本、镜像长度、加载地址、标志位,后面是加密后的负载数据,最后是覆盖头部和负载的签名。SFU升级时先解析头部,再依次检查版本、验签、解密、安装。

2.3 Flash分区与读保护:信任根的物理底座

光有密码学还不够,信任根本身必须待在“别人改不了也读不出来”的地方。SBSFU会把一颗MCU的Flash分成几个固定区域,以常见的四分区布局为例:

区域存放内容说明
Slot 0Secure Engine信任根,受RDP/WRP/PCROP保护
Slot 1SB_SFU安全启动和固件更新引擎
Slot 2Application(Active)当前运行的用户应用
Slot 3Download(Update)新固件下载区,校验通过后再安装

芯片本身的Flash保护由选项字节(Option Bytes)控制,SBSFU最核心的几项是:

  • RDP(读保护)Level 0:无保护,任何调试器都能连,适合开发阶段。
  • RDP Level 1:禁止调试接口直接读Flash。可以通过选项字节回退到Level 0,但回退会触发全片擦除。
  • RDP Level 2:永久锁定,不可逆,调试口彻底关闭。在F4/L4等型号上,一旦设置基本等于这颗芯片只能换新。
  • WRP/PCROP:对指定Flash区域做写保护或代码读出保护,SE代码就是靠它们罩住的。

在STM32L5这类带TrustZone的MCU上,事情会更进一步:SE运行在安全世界,用户应用运行在非安全世界,界限由硬件强制隔离。安全边界的配置在CubeMX里做,比纯软件保护更彻底,但对配置的严谨度要求也更高。

开发阶段我强烈建议RDP保持在Level 0或Level 1,先把业务逻辑和升级流程完全跑通,最后批量烧录时再统一锁保护。千万别一上来就锁Level 2,后面会专门讲这个坑。

3. 入门实操:用CubeMX把第一个SBSFU工程跑起来

3.1 准备环境:软件、固件包和目标板

SBSFU入门最舒服的路径是拿一颗官方开发板起步。NUCLEO-L4R5ZI、NUCLEO-H743ZI2、B-L475E-IOT01A这些板子都有现成的例程支持,选NUCLEO系列就行,板载ST-Link可以省去一堆接线问题。

需要准备的软件就四样:

  • STM32CubeMX:带嵌入式软件包管理器,用来创建工程和安装X_CUBE_SBSFU。
  • STM32CubeIDE或其他支持GCC/ARMCC的IDE:用于编译生成的工程。
  • STM32CubeProgrammer:烧录SB_SFU、配置选项字节、查看Flash内容。
  • STM32CubeMonitor-SFU:ST官方提供的SFU固件升级可视化工具,入门阶段用它做升级测试非常省事。

打开STM32CubeMX,新建一个以目标板为基础的工程,然后在“Embedded Software Packages”里勾选X_CUBE_SBSFU。如果没有这个包,先去软件包管理器里安装,登录ST账号就能下载。不同版本的SBSFU生成的工程结构和配置项位置略有差异,建议下载和UM2262匹配的版本,少踩很多版本不一致的坑。

3.2 关键配置项逐个说明

工程创建后,CubeMX会出现在Middleware下的SBSFU配置界面。新手最容易被这一屏配置吓到,其实真正要关心的就四个部分。

第一是Memory Layout。这里定义了SE、SB_SFU、Application、Download四个区域的起始地址和大小。CubeMX会根据当前MCU的Flash大小给出一套默认值,大多数情况下直接用就行。如果你要调整,比如给应用区留更大空间,必须记住一个铁律:CubeMX里的区域地址、工程链接脚本里的起始地址、应用的向量表偏移,三者必须保持一致,只改一处必出问题。

第二是Key Management。开发阶段选择“Use Development Keys”即可,ST会把这些开发密钥打包到工程里。正式项目在这里要生成自己的密钥对,并且把私钥放到安全的地方,不要提交到Git仓库。建议一开始用开发密钥跑通,再做正式密钥切换,否则的问题会混在一起。

第三是Secure Boot配置。这里关注反回滚(Anti-rollback)和启动超时。反回滚开关打开后,SFU会拒绝版本号低于或等于当前版本的新固件。启动超时指的是SB_SFU在等待升级指令时的窗口时间,超时后如果没有收到升级命令,就正常启动应用。

第四是SFU配置。选择升级接口,最常用的是UART;然后确认波特率、引脚,以及升级触发引脚。多数官方例程会把升级触发引脚配置成板上的用户按键,实际操作就是“按住用户键再复位”,设备就会进入SFU升级模式。这块配置直接决定后面串口升级能不能连上,值得多看两眼。

最后生成代码。CubeMX会生成一个包含两个子工程的workspace:SB_SFU工程和Application工程。以后你每次改业务逻辑,都是在Application工程里改,SB_SFU基本不用动。

3.3 构建、烧录、首次运行

第一次构建时,编译顺序是固定的:先编译SB_SFU,再编译Application。因为Application的postbuild脚本要读取SB_SFU生成的密钥信息、地址配置等,如果先编译Application,生成的签名固件会很奇怪。具体原因倒不复杂——签名的密钥和校验用的公钥必须对应,脚本依赖特定的中间产物,所以必须按顺序来。

编译完成后,会得到几类产物:

  • SB_SFU

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询