4. MCUboot 交换模式之覆盖升级(Overwrite)配置与验证
任务说明
本案例目标是在MCUboot中启用镜像签名验证功能:使用Python脚本或MCUboot提供的工具,为镜像生成RSA-2048签名,并配置MCUboot在启动时对该签名进行验证。完成本案例后,未签名的镜像或签名被篡改的镜像将被启动引导程序拒绝加载。
实现方案
MCUboot支持RSA-PSS和ECDSA-P256两种签名算法。本案例采用RSA-2048 + SHA-256方案,原因在于其工具链成熟、密钥生成简单,且适用于大多数MCU平台。整体流程分为三步:生成密钥对、签名镜像、配置MCUboot启用验证。
1. 生成RSA密钥对
使用MCUboot仓库中的imgtool脚本生成RSA-2048私钥(PEM格式):
# 克隆MCUboot仓库(如已克隆可跳过)
git clone https://github.com/mcu-tools/mcuboot.git
cd mcuboot
# 安装依赖(Python 3.6+)
pip3 install --user cryptography intelhex
# 生成RSA-2048私钥
./scripts/imgtool keygen -k rsa2048_private.pem -t rsa-2048
生成的rsa2048_private.pem为私钥文件,需妥善保管。对应的公钥将被编译进MCUboot bootloader中用于验证。
2. 签名镜像
假设已有一个待签名的应用固件app.bin(原始二进制,非hex),使用imgtool添加MCUboot头部并签名:
./scripts/imgtool sign \
--key rsa2048_private.pem \
--align 8 \
--header-size 0x400 \
--slot-size 0x80000 \
--version 1.0.0 \
--pad-header \
app.bin \
signed_app.bin
参数说明:--align 8为Flash对齐单位(需与目标MCU匹配);--header-size 0x400为镜像头部大小;--slot-size 0x80000为每个slot的容量(512KB);--pad-header表示头部不足时填充0xFF。输出signed_app.bin即为带签名的可引导镜像。
3. 配置MCUboot启用签名验证
在MCUboot的boot/zephyr/Kconfig或目标平台的prj.conf中启用以下配置:
# 启用签名验证
CONFIG_BOOT_SIGNATURE_TYPE_RSA=y
CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=n
# 指定公钥源文件(由私钥导出)
CONFIG_BOOT_SIGNATURE_KEY_FILE="rsa2048_public.pem"
公钥文件需从私钥导出:
./scripts/imgtool getpub -k rsa2048_private.pem -o rsa2048_public.pem
将生成的rsa2048_public.pem放入MCUboot的boot/zephyr/keys/目录,并在prj.conf中指定正确路径。若使用Zephyr构建系统,还需在CMakeLists.txt中确保公钥文件被编译为C数组。
4. 构建与烧录
以Zephyr+nRF52840 DK为例,构建带签名验证的bootloader:
west build -b nrf52840dk_nrf52840 -d build_boot boot/zephyr
west flash -d build_boot
烧录应用镜像时,需将签名后的signed_app.bin烧录到主slot(slot0)起始地址。使用nrfjprog或west flash均可,但必须确保烧录的是签名后的文件。
验证方法与判定标准
验证步骤:
- 正常启动:烧录bootloader和
signed_app.bin,复位后观察串口日志,应看到Image 0 loaded且应用正常运行。 - 篡改测试:使用十六进制编辑器修改
signed_app.bin中任意一个字节(例如偏移0x100处),重新烧录到slot0,复位后观察日志。 - 预期结果:篡改后的镜像启动时,串口输出
Image 0 signature check failed,随后MCUboot尝试从其他slot加载(若无有效镜像则进入恢复模式或停止)。
判定标准:满足以下条件即视为验证通过:
- 未篡改镜像能正常引导并运行;
- 篡改镜像被拒绝加载,且日志中出现明确的签名验证失败信息;
- 若配置了多slot,MCUboot能回退到备份镜像(如有)。
关键配置说明
若目标平台Flash对齐不是8字节,需同步调整--align参数和CONFIG_BOOT_SLOT_ALIGN配置。RSA-2048签名在Cortex-M4上验证耗时约50-100ms(取决于时钟频率),对启动时间敏感的场景可改用ECDSA-P256(验证更快,但签名工具链需额外安装ecdsa包)。
本案例使用RSA-2048方案,公钥以PEM格式编译进bootloader。若需防回滚保护,可额外启用CONFIG_BOOT_UPGRADE_ONLY和镜像版本号检查,但这不是本案例的必要条件。