STM32 安全启动教程:MCUBoot 固件签名验证与安全 OTA
背景:固件为什么需要签名
问十个做嵌入式产品的人「固件有签名验证吗」,七八个会答「量太小,没人会来攻击」。但真实的翻版案例是:设备在淘宝上出现翻版,连品牌名都没改,只改了远程服务器的 IP——读 Flash、改几行、烧回去,一个下午的事。
固件签名防的不是国家级攻击,而是这种成本极低的「读出来、改一改、烧回去」。本文介绍 MCUBoot——一个 STM32F4 就能跑的开源 secure bootloader,给出签名验证 + 双 Slot 安全 OTA 的完整配置。
环境:STM32F4(或 F7/H7/L4/U5);构建链 west(Zephyr)或裸机编译;imgtool 负责签名。
一、MCUBoot 做了什么
MCUBoot 最早来自 Apache Mynewt RTOS,后被 Zephyr 及多个 RTOS 采纳,ST 官方也从 SBSFU 迁到了「基于 MCUBoot 的 OEMiRoT」。核心流程三步:
上电 → MCUBoot → 检查 Slot 0 镜像
├── 签名有效 → 跳转应用
└── 签名无效/无固件 → 停住等待恢复
「签名有效」包含三层验证:
- 完整性:固件是否损坏(SHA-256 哈希)
- 真实性:是否用你的私钥签的(ECDSA-P256)
- 防回滚:版本号是否比上次烧的更低(版本计数器)
二、Flash 布局与镜像格式
以 STM32F407、512KB Flash 为例的双 Slot 布局:
+------------------+ 0x08000000
│ MCUBoot │ 64 KB —— 不可变引导代码
+------------------+ 0x08010000
│ 应用固件 A │ 192 KB —— Slot 0(运行版本)
+------------------+ 0x08040000
│ 应用固件 B │ 192 KB —— Slot 1(新版本先烧到这)
+------------------+ 0x08070000
│ 暂存区 │ 64 KB —— Swap 工作区
+------------------+ 0x08080000
双 Slot 是安全 OTA 的关键:新固件先烧 Slot 1,验证通过才换到 Slot 0,中途断电从暂存区恢复,不会「半旧半新」。镜像格式为 Header(512B,魔数+版本+签名算法)→ 应用固件 → TLV 区(哈希+签名+版本),imgtool.py 负责加 Header/TLV,签名是后处理步骤,应用代码零改动。
三、实操六步
Step 1:生成密钥对。
pip install imgtool
imgtool.py keygen -t ecdsa-p256 -k private.pem
公钥编译进 MCUBoot,私钥留在构建服务器。带安全硬件的 MCU(如 STM32U5 PKA + SAES)可把公钥哈希存 OTP 物理不可擦。
Step 2:编译 MCUBoot。
git clone https://github.com/mcu-tools/mcuboot.git
cd mcuboot/boot/zephyr
west build -b stm32f407_disco -- -DCONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y
无 Zephyr 可裸机编译(boot/mynewt)或参考 ST 官方 SBSFU by MCUboot 包。
Step 3:烧 MCUBoot 到 0x08000000。
Step 4:签名应用固件。
imgtool.py sign -k private.pem \
--header-size 0x200 --align 8 --version 1.0.0 \
--slot-size 0x30000 --pad \
your_app.bin signed_app.bin
--slot-size 必须匹配 Slot 0 实际大小;--version 每次 OTA 递增;--pad 填满 slot,未填充区域视为无效。
Step 5:烧签名固件到 Slot 0(0x08010000)。
Step 6:上电。 MCUBoot 读 Header → 提取公钥哈希 → 验证 ECDSA 签名 → 通过 → 跳转应用,应用固件不参与任何签名逻辑。
四、OTA 升级与自动回滚
升级流程:应用下载新版本到外部 Flash/SD → 写到 Slot 1 → 设「待测试」标记软复位 → MCUBoot 验证后 Swap(或 Overwrite)→ 启动新版本。
Swap 模式的核心价值是「不死之身」:新固件起不来(开机 30 秒没确认),MCUBoot 自动回滚旧版本。应用正常运行后要显式确认:
boot_write_img_confirmed(); // 告诉 MCUBoot:这版本没问题,别回滚
不调用则下次上电被判「未确认」触发回滚。Swap 需要 Scratch 区,Flash 紧张用 Overwrite(省 Scratch 但丢回滚)。
五、局限
- Flash 开销大:MCUBoot 自身 30-64KB,加双 Slot,总开销至少是原固件 2.2 倍,64KB Flash 的芯片基本告别双 Slot。
- 启动延迟:软件 ECDSA 验证 200KB 固件约 100-300ms,要求上电 10ms 内响应的设备需硬件加密引擎。
- 量产复杂度:产线多烧 MCUBoot、烧签名固件、写 OTP 公钥哈希,比「烧一个 hex」多两个工位。
- 永不 OTA 的设备别用:一次性烧录的产品,MCUBoot 开销大于价值,用 RDP 读保护 + WRP 写保护即可。
六、总结
判断是否上 MCUBoot 的自查:设备联网 → 大概率需要;固件含密钥/客户数据 → 需要;有 OTA → 强烈建议(没签名验证的 OTA 等于给攻击者开门);淘宝已出现「兼容版」→ 立刻上;电池供电、Flash<128KB、无网络 → 暂时不用。
MCUBoot 一个下午就能在开发板上跑起来,花这一个下午,换十年安心。
更多推荐



所有评论(0)