|
前言 本文档介绍基于 MCUboot 的 AT32 MCU Secure Boot 和 SecureFirmware Upgrade 参考实现,围绕系统架构、安全机制、参考工程、平台移植、功能配置、密钥管理、Firmware Image 生成、USART IAP 升级、Application 适配以及调试测试等内容展开,旨在帮助开发人员快速理解和使用该参考方案。 本文档中的代码、Flash 地址、配置参数和工程结构均以 AT32 MCU 参考工程为基础。对于不同 Flash 容量、不同 Board 或不同产品配置,应根据实际硬件资源重新确认 Memory Layout、Slot Size、Linker Address 以及 Bootloader 和安全数据保护区域。 此外,本文还介绍 AT32 MCU 的 Security Library(sLib) 保护机制,并说明如何结合硬件保护功能对 Bootloader 代码、加密密钥及其他安全敏感数据进行保护,以降低关键安全资源被未授权读取或篡改的风险。 更多详细信息参考< AN0040_AT32F403A_407_Security_Library_Application_Note>。 支持型号列表:
备注:本文档仅供有需求的小伙伴们参考使用,更详细资料或视频,可访问雅特力官网获取https://www.arterytek.com/cn/support/index.jsp?index=1
目录
表目录 图目录 1 安全启动与安全固件升级概述1.1 安全启动背景随着 IoT、工业控制、消费电子以及嵌入式设备联网程度不断提高,Firmware 已成为产品安全的重要组成部分。传统 Bootloader 通常只负责硬件初始化和 Application 启动,无法确认即将运行的 Firmware 是否来自可信来源,也无法有效防止旧版本 Firmware 被重新安装。 Secure Boot(安全启动) 的目标是在 Application 启动之前对 Firmware Image 进行安全验证,确保只有通过完整性和真实性验证的 Firmware 才能够被加载和执行。 在此基础上,Secure Firmware Upgrade(安全固件升级) 进一步对 Firmware 更新过程进行安全保护,确保设备只能安装经过授权且符合版本要求的 Firmware,并能够在升级异常情况下保持设备的可恢复性。 安全启动主要实现以下安全功能: l Firmware Image完整性验证:确保 Firmware Image 在传输、存储和升级过程中未被篡改; l Firmware Image来源认证:通过数字签名验证Firmware是否来自可信的 Firmware 发布者; l Firmware Version / Security Counter 检查:检查Firmware版本及安全计数器是否满足升级要求; l 防止 Rollback:禁止设备重新安装低于当前安全版本的 Firmware; l 升级异常恢复:支持 Firmware Upgrade 过程中断电等异常情况的恢复; l 升级镜像验证:在新 Firmware 启动前完成必要的安全验证,验证失败时阻止其运行; l Bootloader 及安全关键区域保护:降低 Bootloader、密钥及其他安全关键数据被非法修改的风险。 1.2 安全启动与安全固件升级概述Secure Boot 与 Secure FirmwareUpgrade 是 Firmware 安全生命周期中的两个重要组成部分,两者分别解决设备启动阶段和 Firmware 更新阶段的安全问题。 Secure Boot 在设备正常启动时,Secure Boot首先运行,并对 Application Image 进行完整性和真实性验证。只有验证通过后,Secure Boot 才允许Application 执行,从而确保设备不会运行未经授权或被篡改的 Firmware。 Secure FirmwareUpgrade 在 Firmware Upgrade 过程中,新 Firmware 首先通过IAP 下载至 Secondary Slot。下载完成后,Application 设置 Upgrade Request,并执行系统复位。 设备复位后,Secure Boot检测到 Upgrade Request,并对 Secondary Slot 中的新 Firmware Image 进行验证。验证通过后,Secure Boot根据当前配置执行Image Swap,将新 Firmware 切换为待启动的 Image。新 Firmware 启动后,通过 Confirm 机制确认升级成功;如果升级过程中发生异常,Secure Boot可根据 Image 状态进行相应的恢复处理。 从功能上看,Secure Boot 和 Secure Firmware Upgrade 关注的问题有所不同: Secure Boot 主要解决「设备启动时运行什么Firmware」的问题,确保只有经过完整性和真实性验证的 Firmware 才能执行。 Secure FirmwareUpgrade 主要解决「如何安全地替换 Firmware」的问题,确保新 Firmware 在安装和运行前经过验证,并能够处理升级过程中的异常情况。 两者结合后,可以形成完整的 Firmware 安全生命周期 2 MCUboot安全启动与固件升级MCUboot 是一款面向 32 位微控制器(MCU)的开源安全启动引导程序(Secure Bootloader),可为嵌入式应用提供通用的安全启动和固件升级基础框架。 MCUboot 的主要功能包括: l 支持基于 ECDSA-P256 等数字签名算法的镜像验证,实现固件完整性和身份认证。 l 支持加密镜像功能,结合 ECIES-P256 等密钥封装机制和对称加密算法,提高固件的机密性。 l 支持多种镜像交换(Swap)策略,包括 Swap using Scratch、Swap usingMove 和 Swap using Offset。 l 支持镜像确认(Image Confirmation)机制,新固件可先以测试状态启动,并在确认运行正常后永久确认,从而支持升级失败后的回滚。 l 支持防回滚(Anti-rollback)机制,可基于安全计数器(Security Counter)拒绝安全版本等级较低的镜像。 l 采用硬件无关(Hardware-agnostic)的设计,并通过 Flash、启动和密码学等平台适配接口支持不同的 MCU 平台 2.1 MCUboot系统架构MCUboot 是一种面向嵌入式系统的安全启动引导程序,其核心架构通常由Bootloader、Primary Slot、Secondary Slot 以及镜像管理状态区域组成。 MCUboot 上电启动后,首先执行 Bootloader 中的安全启动流程,对待启动镜像进行状态检查和完整性验证。在镜像验证通过后,MCUboot 将控制权转移至可信的应用程序。 对于支持固件升级的系统,MCUboot 通常采用双镜像槽位(Dual ImageSlot)架构: l Bootloader:位于 Flash 的启动区域,负责 MCUboot 的启动流程、镜像状态管理、镜像完整性和签名验证,以及固件升级过程中的镜像交换或更新处理。 l Primary Slot(Slot 0):用于存放当前可启动的应用镜像。MCUboot 完成镜像验证后,通常从Primary Slot 启动应用程序。 l Secondary Slot(Slot 1):用于存放待升级的新镜像。新镜像下载完成后,由 MCUboot 根据镜像状态和配置的升级策略决定是否执行镜像交换。 l Image Trailer:位于镜像槽位末尾,用于保存镜像升级状态信息,例如镜像升级请求、测试状态、确认状态以及镜像交换过程中的状态信息。 MCUboot 系统架构的主要流程如下: 1. MCU 上电或复位后,从 Bootloader 开始执行。 2. MCUboot 检查 Primary Slot 和 Secondary Slot 中镜像的状态信息。 3. 如果存在待升级的有效镜像,则根据配置的升级策略执行镜像更新或交换操作。 4. 对待启动镜像执行完整性和数字签名验证。 5. 如果镜像验证通过,则启动 Primary Slot 中的应用程序。 6. 如果新镜像以测试状态启动,则应用程序在确认运行正常后对镜像进行确认;否则,在后续复位时 MCUboot 可根据镜像状态执行回滚。 MCUboot 的整体系统架构如图所示。 2.2 MCUboot Flash镜像架构 MCUboot 采用基于 Flash 分区的镜像管理机制,实现应用程序的安全启动和固件升级。一个典型的 MCUboot 系统通常包括 Bootloader 区域、Primary Slot(Slot 0)和 Secondary Slot(Slot 1)。 其中,Bootloader 负责镜像验证、升级状态管理以及镜像启动;Primary Slot 用于存放当前待启动或正在运行的应用镜像;Secondary Slot 用于存放待升级的新镜像。
在 MCUboot 中,Primary Slot 和 Secondary Slot 分别用于保存当前镜像和待升级镜像。每个镜像除了实际的应用程序代码外,还包含用于镜像验证和升级管理的元数据。 2.2.1 MCUboot Bootloader 区域Bootloader 位于 MCU 的启动 Flash 区域,是系统上电或复位后首先执行的软件模块。MCUboot 作为本系统的 Bootloader,负责在应用程序启动之前完成镜像检查、安全验证以及升级决策,并在确认目标镜像满足启动条件后,将控制权转移至应用程序。 MCUboot Bootloader 的主要功能包括: l 镜像状态检查:读取镜像 Header、Trailer 等元数据,判断镜像是否有效以及当前升级状态。 l 升级镜像检测:检查 Secondary Slot 中是否存在待升级镜像,并根据镜像状态决定是否执行升级。 l 镜像升级执行:根据配置的升级模式,对镜像执行相应的交换、复制或覆盖操作。 l 镜像完整性验证:通过 Hash 等机制检查镜像数据是否完整,确保镜像在存储或升级过程中未发生异常。 l 镜像数字签名验证:使用预置的公钥验证镜像签名,确认镜像来源可信且镜像内容未被非法篡改。 l 安全版本检查:根据系统安全策略检查镜像版本信息,防止设备回滚至低于安全版本要求的旧版本。 l 应用程序启动:完成镜像检查和安全验证后,将 MCU 的执行控制权转移至通过验证的应用程序。 上述功能共同构成 MCUboot 的镜像启动与安全升级机制,其基本关系如下。 Bootloader 属于系统启动链中的可信软件组件。如果 Bootloader 本身遭到未授权修改,攻击者可能绕过后续的镜像验证机制,因此需要对 Bootloader 代码及相关安全数据进行保护。 对于 AT32F403A/407,可结合 sLib 等硬件安全保护机制,对 Bootloader 代码以及公钥等安全敏感数据进行保护,降低 Bootloader 被未授权读取或修改的风险。 注:本节主要介绍 Bootloader 的功能及其在 MCUboot 系统中的作用。具体的 Flash 地址、区域大小以及 sLib 保护配置将在后续章节中详细介绍。 2.2.2 Primary Slot(Slot 0)Primary Slot,也称为 Slot 0,用于存放 MCUboot 当前准备启动的应用程序镜像。MCUboot 完成镜像升级处理后,会对 Primary Slot 中的镜像进行检查和验证,验证通过后将控制权转移至应用程序。 Primary Slot 是系统的主启动镜像区域。在正常启动过程中,MCUboot 最终需要从 Primary Slot 中选择有效的应用程序镜像并启动。 Primary Slot 与 Application 的关系 Primary Slot 的完整镜像结构已在 2.2 Flash 与镜像架构 中介绍,本节不再重复描述 Image Header、TLV 和 Image Trailer 的具体结构。 注:如果需要了解详细结构,可参考MCUboot官方信息https://docs.mcuboot.com/。 这里需要重点关注的是 Image Header 与 Application Vector Table 的地址关系。
由于 Image Header 位于 Primary Slot 起始位置,应用程序的 Vector Table 通常位于 Image Header 之后。因此,应用程序的实际启动地址通常为: Application Vector Table Address = Primary Slot Start Address + ImageHeader Size; 例如,当: Primary Slot Start Address = 0x08010000 Image Header Size =0x00000200 则:ApplicationVector Table Address = 0x08010200 此时,应用程序的 Vector Table 应位于 0x08010200,而不是 PrimarySlot 的起始地址 0x08010000。 Application Link Address 由于 ApplicationVector Table 位于 Image Header 之后,应用程序工程的 Link Address 需要与实际 Vector Table 地址保持一致。 因此,在 MCUboot 移植和应用程序配置过程中,需要重点确认以下参数: l Primary Slot StartAddress l Image Header Size l Application LinkAddress l Application VectorTable Address 这些地址和大小必须相互匹配,否则可能导致镜像验证通过后,应用程序无法正常启动。 注意: PrimarySlot 的实际起始地址、Image Header Size 以及 Application Link Address 取决于具体 MCUboot 配置和镜像生成方式。实际项目中应以最终的 MCUboot 配置和应用程序链接配置为准。 2.2.3 Secondary Slot(Slot 1)Secondary Slot,也称为 Slot 1,用于存放待升级的新应用程序镜像。 在升级过程中,新的固件镜像首先下载至 Secondary Slot,而不会直接覆盖当前 Primary Slot 中正在使用的有效镜像。这样可以在镜像下载过程中保留当前可正常运行的应用程序。
Secondary Slot 主要具有以下作用: l 暂存升级镜像:保存待升级的新应用程序镜像。 l 隔离当前镜像:镜像下载过程中不会直接修改 Primary Slot 中的当前运行镜像。 l 统一安全验证:镜像下载完成后,由 MCUboot 对待升级镜像进行完整性和安全验证。 l 支持升级恢复:升级过程中发生异常时,可根据 MCUboot 配置执行相应的恢复机制。 在本文的 AT32 MCU参考方案中,USART IAP 模块负责将升级镜像写入 Secondary Slot。镜像下载完成后,由应用程序设置升级请求状态,并通过系统复位进入 MCUboot。 MCUboot 启动后,首先检查 Secondary Slot 中的待升级镜像。镜像验证通过后,根据配置执行 Swap using Offset 升级流程,将新镜像更新至 Primary Slot,随后启动新的应用程序。 注意: SecondarySlot 的实际地址、大小以及升级方式取决于具体的 MCUboot FlashLayout 和配置。Primary Slot 与 Secondary Slot 通常需要满足足够的空间要求,以确保完整镜像能够正常存放和升级。 2.2.4 MCUboot Image镜像结构 MCUboot 管理的固件镜像并不是普通的裸 .bin 文件,而是按照 MCUboot Image Format 组织的镜像。MCUboot 通过 Image Header、Image Payload、TLV 以及 Image Trailer 等结构保存镜像信息,并在启动和升级过程中根据这些信息完成镜像识别、验证和状态管理。
注:详细信息可参考MCUboot官方信息https://docs.mcuboot.com/
各部分的主要作用如下: l Image Header 保存镜像基本信息,例如 Magic、Header Size、Image Size、Image Version 等 l Image Payload 保存实际的应用程序代码和数据 l Protected TLV 保存需要纳入镜像完整性保护范围的元数据 l TLV 保存镜像 Hash、数字签名等验证相关信息 l Image Trailer 保存镜像升级、Swap 以及 Confirm 等状态信息 2.2.4.1 Image Header Image Header 位于镜像起始位置,用于描述镜像的基本属性。MCUboot 在处理镜像时,会首先读取 Header 中的信息,以确定镜像格式、大小、版本等。 典型信息包括: l Magic l Header Size l Image Size l Image Version l Flags 等 需要特别注意的是,Image Header 不属于 Application Payload。 应用程序的 Vector Table 位于 Image Header 之后。具体地址关系已经在 1.2.2 PrimarySlot(Slot 0) 中说明,本节不再重复。 2.2.4.2 Image Payload Image Payload 是镜像的主体部分,主要包含应用程序实际执行所需的数据,例如: l Application VectorTable l Application Code l Read-only Data l Application Data 对于MCU,应用程序通常从 Payload 起始位置的 Vector Table 开始执行。 2.2.4.3 TLV与Protected TLV TLV 是 Type-Length-Value的缩写,用于保存镜像相关的元数据。 其基本结构如下: MCUboot 可以通过 TLV 保存镜像 Hash、数字签名、公钥相关信息以及安全版本等验证信息。 其中,Protected TLV 中的信息会被纳入镜像的完整性验证范围,用于确保相关安全元数据与镜像内容建立完整性绑定关系。 对于本文的安全启动方案,重点关注:HASH 和 Digital Signature ,用于MCUboot进行验证。 2.2.4.4 Image Trailer Image Trailer 位于 Slot 的尾部,用于保存 MCUboot 的镜像状态信息。 典型状态包括: l Image Magic l Image OK l Copy Done l Swap Status 这些状态用于记录镜像是否处于 Pending、Test、Confirm 以及 Swap 等状态。 例如一个升级流程: 1. Secondary Slot 2. New Image Download 3. Set Image Pending 4. Write Trailer State 5. System Reset 6. MCUboot Detect Upgrade MCUboot 在启动过程中读取 Trailer 状态,并结合 Primary Slot 和 Secondary Slot 中的镜像信息,决定是否执行升级操作。 2.3 MCUboot启动流程每次 MCU 上电或发生系统复位后,CPU 首先从Bootloader 区域开始执行。MCUboot 启动后,会检查Primary Slot 和 Secondary Slot 中的镜像状态,并根据镜像验证结果和升级状态决定是否执行升级以及最终启动哪个 Application。 在本系统中,新的 Firmware 可通过 IAP 下载至 Secondary Slot。下载完成后,系统设置升级请求并复位,MCUboot 检测到待升级镜像后进行验证。验证通过后,MCUboot 根据升级配置执行 Swap using Offset,完成镜像切换并启动新的Application。 注:上述流程用于描述本系统的整体启动逻辑。实际 MCUboot 执行路径还会受到 Image Trailer 状态、升级状态以及异常恢复状态等因素影响 2.3.1 MCUboot 启动MCUboot 启动阶段主要完成: l 初始化必要的运行环境; l 初始化 Flash 访问; l 获取 Primary Slot 和 Secondary Slot 的镜像状态; l 判断当前系统是否存在升级或恢复需求。 MCUboot 不会在启动后直接跳转至 Application,而是首先进行镜像和升级状态检查。 2.3.2 镜像状态检查MCUboot 对 Primary Slot 和 Secondary Slot 中的镜像进行检查。 l Primary Slot:保存当前主要启动镜像; l Secondary Slot:保存待升级的新镜像。 主要检查内容包括: l Image Header 是否有效; l 镜像状态是否正常; l 是否存在待升级镜像; l 镜像是否满足安全验证要求。 如果没有待升级镜像,则按照正常启动流程处理;如果存在待升级镜像,则进入镜像验证流程。 2.3.3 镜像验证对于待升级镜像,MCUboot 在执行升级前需要进行安全验证。 本系统主要通过以下机制保证镜像安全: l Hash:验证镜像数据完整性; l Digital Signature:验证镜像来源及完整性; l Security Counter:用于支持安全版本检查和 Anti-Rollback。 验证通过后,MCUboot 才会继续执行升级操作;验证失败则拒绝使用该镜像。 具体的 Hash、Digital Signature、Public Key 和 Anti-Rollback 机制将在后续镜像验证机制中详细介绍。 2.3.4 镜像升级镜像验证通过后,MCUboot 根据系统配置执行镜像升级。本系统采用 Swap using Offset 方式完成新旧镜像切换。 升级前: 升级后: 具体的 Swap 操作、Flash Sector 处理以及 Image Trailer 状态管理将在 1.5 镜像升级流程中详细介绍。 本应用笔记 MCUboot 采用 swap-using-offset 模式。Slot 1 的第一个扇区被预留为交换缓冲区,无需专用的 scratch 分区。升级过程以扇区为单位交换 Slot 0 和 Slot 1,并使用 Slot 1 的第一个扇区作为临时存储。 优点: l 无需单独的 scratch 分区,节省 Flash 空间 l 支持回滚:若新镜像未能完成确认,MCUboot 将在下次启动时恢复原镜像 l 掉电安全:swap 状态记录在 Flash 中,掉电后可续传 采用基于偏移量的交换(swap-using-offset)升级策略,无需专用的暂存分区。在升级过程中,Slot1 的第一个扇区用作交换缓冲区。 表1 Swap 模式对比 | 特性 | Swap-offset | 传统Swap(带SCRATCH) | | Scratch 分区 | 不需要 | 需要 | | Slot 1镜像起始位置 | 从第1个扇区开始 | 从第0个扇区开始 | | Slot 1 额外空间 | 加一个扇区作为swap缓冲区 | 无 | | 回滚能力 | 支持(未确认时自动恢复) | 支持 | | 掉电安全 | 支持(下次启动自动续传) | 支持 |
Slot1的首个扇区用作交换缓冲区,逐扇区进行交换,掉电安全,无需独立的暂存分区,若新镜像未确认则自动回滚。如下是Swap offset交换流程: 2.3.5 Application 启动完成镜像检查和必要的升级操作后,MCUboot 选择有效的 Primary Slot 镜像,并将 CPU 的执行控制权转移至 Application。 对于 Cortex-M MCU,Application 通常从 Vector Table 开始执行。由于 MCUboot Image 的 Image Header 位于 Vector Table 之前,因此 Application 工程的链接地址必须与实际 Vector Table 地址保持一致。具体地址应以最终 MCUboot 配置和 Application Linker 配置为准。 2.4 MCUboot安全特性 表2 安全特性总结 | 安全特性 | 实现方式 | 说明 | | 镜像签名(Image Signing) | ECDSA-P256 | 每个固件镜像必须使用私钥签名;bootloader 通过内嵌公钥进行验证 | | 镜像加密(Image Encryption) | ECIES-P256 + AES-128-CTR | 固件镜像可加密以实现安全 OTA;bootloader 使用内嵌私钥进行解密 | | 防回滚(Anti-Rollback) | 基于 Flash 的安全计数器 | 单调递增计数器存储在 Flash 第 15 扇区;防止降级到旧版本固件 | | Primary Validation | MCUBOOT_VALIDATE_PRIMARY_SLOT | 每次启动均验证主槽镜像,而非仅在升级后验证 | | 加密后端(Crypto Backend) | Mbed TLS 3.6.0 | 所有加密操作均采用业界标准 TLS 库 |
2.4.1 签名验证(ECDSA-P256)AT32 MCUboot 方案每个固件镜像都必须使用 ECDSA 算法签名,采用 NIST P-256 曲线和 SHA-256 哈希。bootloader 内置公钥,在启动或执行 swap 之前验证镜像签名。未签名或被篡改的镜像将被拒绝。 2.4.2 加密镜像(ECIES-P256)bootloader 同时支持明文和加密固件镜像。AT32MCUboot加密镜像采用 ECIES-P256,并使用 AES-128-CTR 进行批量加密。加密密钥通过 ECDH 密钥交换并结合 HKDF 派生生成。未修改任何配置时,明文签名镜像同样可以被接受。 2.4.3 镜像签名与验证流程
2.4.4 防回滚安全计数器 防回滚机制采用基于 Flash 存储的单调递增安全计数器,该计数器位于引导加载程序(bootloader)区域的第 15 扇区。每个计数器条目占用 8 字节:包含一个 32 位数值及其按位取反值(~value),从而实现断电检测功能。 3 AT32MCUboot实现本章介绍 MCUboot 在 AT32 MCU 上的具体实现,包括Flash 分区、MCUboot 工程结构、Application工程配置、MCUboot Image 配置、镜像签名以及 sLib 安全保护。 本方案采用 Swap using Offset 升级模式。Application 仅负责升级镜像的接收和存储,MCUboot 负责镜像验证、升级状态管理、镜像交换以及应用程序启动。 3.1 系统软件架构 主要软件模块功能如下: l MCUboot Bootloader:负责系统启动、Firmware Image 验证、固件升级、防回滚以及 Application 跳转。 l User Application:实现用户应用功能,并负责当前Firmware Image 的确认以及 USART IAP 升级处理。 l Flash Porting Layer:负责 MCUboot 与 AT32 内部 Flash 之间的适配,提供Flash 读、写、擦除及 Sector 管理接口。 l Mbed TLS Cryptographic Layer:提供SHA-256、ECDSA-P256、ECDH、AES-CTR、HKDF 等密码学算法,用于 Firmware Image 的完整性、真实性验证以及加密镜像解密。 l AT32 Security Library(sLib):提供 MCUboot 核心代码的安全库交付方式,用于产品集成场景下的核心代码保护。
MCUboot Bootloader MCUboot Bootloader 是系统的 Root of Trust 的主要执行组件,负责: l 镜像状态检查; l 镜像完整性验证; l ECDSA-P256 签名验证; l Security Counter 检查; l 加密镜像处理; l Swap using Offset 升级; l Test、Confirm 和 Revert 状态管理; l 跳转至可信应用程序。 User Application User Application 为用户实际运行的应用程序。 除了正常的业务功能外,本文参考工程还集成 USART IAP 功能,用于: l 接收 PC 发送的新固件; l 使用USART IAP l 擦除 Secondary Slot; l 将新的 MCUboot Image 写入 Secondary Slot; l 完成下载后设置 Pending 状态; l 触发系统复位。 注意:IAP升级协议参考AN0001_AT32_IAP_using_the_USART。 Flash Porting Layer Flash Porting Layer 用于将 MCUboot 的通用 Flash 接口映射至 AT32 MCU 的 Flash 控制接口。 Mbed TLS Mbed TLS 为 MCUboot 提供密码学算法支持,包括: l SHA-256; l ECDSA-P256; l ECIES-P256 相关密码学操作; l 其他 MCUboot 配置所需的密码学功能。 sLib AT32 Security Library 用于保护: l Bootloader; l 公钥; l 加密私密材料; l 安全配置数据。。 3.2 安全库(sLib)保护bootloaderAT32MCU 系列提供了一种硬件级代码保护机制——安全库(Security Library,sLib)。通过将 MCUboot bootloader 代码放置在 sLib 保护的 Flash 区域内,bootloader 固件——包括加密密钥和验证算法——可免受读取、篡改和未授权修改,即使同片 MCU 上运行的应用固件也无法访问。 关于 AT32 安全库机制的详细信息,请参阅: < AN0040_AT32F403A_407_Security_Library_Application_Note>. 3.3 Flash分区配置 MCUboot 系统需要根据 Bootloader、Application 以及 Firmware Upgrade 的需求,对 MCU 内部 Flash 进行合理划分。本系统采用 Swap using Offset 方式实现镜像升级,因此 Flash 主要划分为 MCUboot Bootloader、Primary Slot(Slot 0)和 Secondary Slot(Slot 1)。 其中,Secondary Slot(Slot 1)的空间比 Primary Slot(Slot 0)多一个 Flash Sector,该额外 Sector 位于 Slot 1 的起始位置,并包含在 Slot 1 的区域内,用于满足 Swap using Offset 的空间需求。 从 Flash Layout 可以看出,Slot 1 整体比 Slot 0 多一个 Flash Sector。该额外 Sector 位于 Slot 1 的起始位置,并作为 Swap using Offset 所需的 Offset 区域使用。 例如AT32F403A/407VGT7 FLASH 地址配置: 表3 Flash 地址配置 | 区域 | 起始地址 | 大小 | 描述 | | Bootloader | 0x08000000 | 64KB | MCUboot | | Primary Slot(Slot 0) | 0x08010000 | 448KB | 当前应用镜像 | | Secondary Slot(Slot 1) | 0x08080000 | 450KB | Swap offset+Upgrade image |
注:具体 Flash 地址、Sector Size 和 Slot Size 应以参考工程的实际 Flash Map 配置为准。 FLASH 分区设计应满足如下要求: 1. Bootloader、Slot 0 和 Slot 1 的地址范围不能重叠; 2. Slot 0 能够容纳完整的 MCUbootImage; 3. Slot 1 能够容纳完整的 UpgradeImage,并额外包含一个Swap Offset Sector; 4. Slot 1 的总大小必须比 Slot 0 多一个 Flash Sector; 5. Image Header、Payload、TLV 和 Trailer 所占空间均需要计入Slot 容量; 6. Flash 擦除和写入操作需要满足 AT32 MCU 对应型号 的 Flash 对齐要求; 7. MCUboot 的 Partition 配置必须与实际Flash Layout 保持一致。 3.4 Bootloader 工程介绍负责 MCU 上电后的启动控制、Firmware Image 验证、Firmware Upgrade 状态处理以及Application 跳转,Bootloader目前占用空间64KB,包括用于anti-rollbacksecurity counter的2KB,实际Bootoader最大可用空间为62KB. 为适应不同的产品集成和安全需求,参考工程提供两种 Bootloader 工程: l mcuboot Bootloader 工程: 包含完整 Bootloader 源码,可直接进行调试、修改和移植 l mcuboot Bootloader sLib 工程:将 Bootloader 核心功能以 sLib 形式集成,适用于需要保护 Bootloader 核心代码或减少源码暴露的产品 两个bootloader的工程结构都是相同的
3.4.1 Bootloader工程配置Bootloader 提供两个参考工程:mcuboot_bootloader工程和mcuboot_bootloader_slib 工程,两者功能基本一致, slib工程可启用sLib功能对bootloader的代码和key做一个保护。 如下是mcuboot Bootloader Keil 工程配置: 如下是mcuboot bootloader slib Keil 工程配置: 详细sLib 使用方式和配置参考< AN0040_AT32F403A_407_Security_Library_Application_Note >。
3.4.2 Bootloader 功能介绍这里重点mcuboot_port平台目录下的配置,包括如下内容: l MCUboot 功能配置文件(mcuboot_config.h) l FlashLayout / Flash Map配置 (sysflash.h) l MCUboot与Flash的Read/Write/Erase 接口(flash_map_backend.c) l MCUbootkey 管理 (key.c) l 防回滚计数security counter的操作(security_cnt.c) l MbedTLS 配置(mbedtls_config.h) 3.4.2.1 MCUboot 功能配置管理 MCUboot 的主要功能通过 mcuboot_config.h 进行配置。该文件用于选择Firmware Image 签名验证、加密 Image、Firmware Upgrade、Anti-Rollback等功能。 本参考工程当前采用的 MCUboot 配置如下: 图15 MCUboot 功能配置 - /* Signature: ECDSA-P256 */
- #define MCUBOOT_SIGN_EC256
- /* Crypto backend: Mbed TLS */
- #define MCUBOOT_USE_MBED_TLS
- /* Encrypted image support using ECIES-P256 */
- #define MCUBOOT_ENC_IMAGES
- #define MCUBOOT_ENCRYPT_EC256
- //#define NUM_ECC_BYTES (256 / 8)
- /* Swap using offset (no scratch partition needed) */
- #define MCUBOOT_SWAP_USING_OFFSET 1
- /* Anti-rollback: reject images with lower security counter */
- #define MCUBOOT_HW_ROLLBACK_PROT
- /* Validate primary slot on every boot */
- #define MCUBOOT_VALIDATE_PRIMARY_SLOT
- /* Flash area API supports get_sectors */
- #define MCUBOOT_USE_FLASH_AREA_GET_SECTORS
- /* Single image */
- #define MCUBOOT_IMAGE_NUMBER 1
- /* Max sectors per image slot: Slot 1 has 225 sectors (224 + 1 swap buffer) */
- #define MCUBOOT_MAX_IMG_SECTORS 225
- /* Write alignment for swap status tracking */
- #define MCUBOOT_BOOT_MAX_ALIGN 8
- /* Logging enabled */
- #define MCUBOOT_HAVE_LOGGING 1
复制代码 具体配置介绍如下: l Firmware Image 签名配置 #defineMCUBOOT_SIGN_EC256 启用 ECDSA-P256 Firmware Image 签名验证功能。Firmware Image 在生成阶段使用对应的签名私钥进行签名,Bootloader 内置签名公钥,并在启动或升级过程中对 Image 进行验证。 l Mbed TLS 加密后端 #defineMCUBOOT_USE_MBED_TLS 指定 MCUboot 使用 Mbed TLS 作为密码学算法实现后端。本参考工程中的 SHA、ECDSA、ECIES 等密码学功能由 Mbed TLS 提供支持。对应的具体算法模块通过 mbedtls_config.h 进行裁剪和配置。 l Firmware Image 加密配置 #defineMCUBOOT_ENC_IMAGES #defineMCUBOOT_ENCRYPT_EC256 用于启用 Firmware Image 加密功能,并使用 ECIES-P256 进行 Image 加密密钥保护。 其中: MCUBOOT_ENC_IMAGES:启用加密 Firmware Image 支持;MCUBOOT_ENCRYPT_EC256:选择 ECIES-P256 加密方式。 在使用 imgtool 生成加密 Image 时,实际 Firmware Payload 使用 AES-CTR 加密,AES 密钥通过 ECIES-P256 进行保护。Bootloader 使用设备侧保存的 ECIES 私钥恢复 AES 密钥并完成 Firmware 解密。 注意: imgtool 中的 --encrypt-keylen 128 用于指定 Firmware Payload 使用 AES-128,并不对应 MCUBOOT_ENCRYPT_EC256。MCUBOOT_ENCRYPT_EC256 表示的是 ECIES-P256 密钥保护机制。 l Firmware Swap 配置 #defineMCUBOOT_SWAP_USING_OFFSET 1配置 MCUboot 使用 Swap Using Offset 方式进行 Firmware Upgrade。该模式不需要独立的 Scratch Partition,可以利用 Primary Slot 和 Secondary Slot 的空间完成 Image Swap。 因此,Flash Layout 需要根据该 Upgrade Strategy 进行规划,并确保 Slot 大小及 Sector 数量满足 MCUboot 的要求。 l Anti-Rollback 配置 #defineMCUBOOT_HW_ROLLBACK_PROT启用 Firmware Image 的 Security Counter 防回滚机制。 Bootloader在验证 Firmware Image 时检查 Image 中的 Security Counter,拒绝安装低于设备当前 Security Counter 的旧版本 Firmware,从而防止攻击者通过重新安装旧版本 Firmware 绕过已经修复的安全漏洞。 FirmwareImage 的 Security Counter 在生成 Image 时通过 imgtool 设置,例如: pythonimgtool.py sign \ --security-counter 2 \ ... 设备侧 Security Counter 的读取、更新和存储由 security_cnt.c 实现。 l Primary Slot 启动验证 #defineMCUBOOT_VALIDATE_PRIMARY_SLOT配置 MCUboot 在每次启动时对 Primary Slot 中的 Firmware Image 进行验证。 只有 Firmware Image 验证通过后,Bootloader 才会跳转至 Application。 该配置可以确保 MCU 每次启动时都不会直接执行未经验证的 Application Firmware。 l Flash Sector 信息支持 #defineMCUBOOT_USE_FLASH_AREA_GET_SECTORS启用 Flash AreaSector 信息获取接口。 MCUboot可以通过该接口获取对应 Flash Area 的 Sector 信息,用于 Firmware Image 的读写、擦除以及 Swap 操作。 对于 AT32 平台,该功能需要与 flash_map_backend.c 中的 Flash 驱动实现保持一致。 l Image 数量配置 #defineMCUBOOT_IMAGE_NUMBER 1配置当前系统只使用 一个 FirmwareImage。 因此,本参考工程采用 Single Image 架构: Bootloader │ └── Image 0 ├── Primary Slot(Slot 0) └── Secondary Slot(Slot 1) 如果后续产品需要同时管理多个独立 Image,例如 Application + Secondary Firmware,则需要重新评估MCUboot Image 数量以及对应的 Flash Layout。 l Slot 最大 Sector 数量 #defineMCUBOOT_MAX_IMG_SECTORS 225定义 MCUboot 支持的单个 Image Slot 最大 Sector 数量。 本参考工程根据当前 Flash Layout 配置为224,其中需要考虑 Swap 操作所需的额外 Sector。 注意:当修改 Slot 大小、Flash Sector 大小或 Flash Layout 时,需要同步检查该参数,确保 MCUboot 能够覆盖实际 Slot 所包含的 Sector 数量。 l Swap 状态写入对齐 #defineMCUBOOT_BOOT_MAX_ALIGN 8配置 MCUboot Bootloader 的最大写入对齐要求为 8 Bytes。 该参数需要与 AT32 MCU Flash 的实际写入粒度以及 flash_map_backend.c 中的 Flash 写入实现保持一致。 l MCUboot 日志功能 #defineMCUBOOT_HAVE_LOGGING 1启用 MCUboot 日志输出功能,便于开发和调试阶段观察 Bootloader 的启动、Image 验证及 Firmware Upgrade 状态。 在量产版本中,可以根据产品需求关闭日志功能,以减少代码空间和运行时输出。 3.4.2.2 Flash Layout 管理 MCUboot 通过 sysflash.h 和 flash_map_backend.c 实现 Flash Layout 的定义与管理。其中,sysflash.h 负责定义各 Flash Area 的地址、大小及逻辑编号,flash_map_backend.c 负责将 MCUboot 的 Flash Area 操作映射到 AT32 MCU 的实际 Flash 读、写和擦除操作。 本参考工程采用 Primary Slot + Secondary Slot 的双镜像布局,并结合MCUBOOT_SWAP_USING_OFFSET 实现 FirmwareUpgrade。 如下是当前FLASH layout配置: 图16 AT32F403A/407 Flash Layout示例 - #define FLASH_DEVICE_INTERNAL_FLASH 0x7F
- #define FLASH_AREA_BOOTLOADER 0
- #define FLASH_AREA_IMAGE_0 1
- #define FLASH_AREA_IMAGE_1 2
- #define FLASH_AREA_IMAGE_SCRATCH 3
- /*
- * AT32F407VGT7 flash layout (1024KB total, sector size = 2KB):
- * Swap-using-offset mode: sector 0 of Slot 1 is the swap buffer,
- * so Slot 1 needs one extra sector compared to Slot 0.
- *
- * Bootloader: 0x08000000 - 0x0800FFFF (64KB, 32 sectors)
- * Slot 0: 0x08010000 - 0x0807FFFF (448KB, 224 sectors)
- * Slot 1: 0x08080000 - 0x080F0800 (450KB, 225 sectors)
- */
- #define AT32_FLASH_BASE ((uint32_t)0x08000000)
- #define AT32_BOOTLOADER_SIZE ((uint32_t)0x00010000) /* 64KB */
- #define AT32_SLOT0_SIZE ((uint32_t)0x00070000) /* 448KB, 224 sectors */
- #define AT32_SLOT1_SIZE ((uint32_t)0x00070800) /* 450KB, 225 sectors (224 + 1 swap buffer) */
- #define AT32_SECTOR_SIZE ((uint32_t)0x00000800) /* 2KB */
- #define AT32_IMG_HDR_SIZE 0x200
- #define FLASH_AREA_IMAGE_PRIMARY(x) (((x) == 0) ? FLASH_AREA_IMAGE_0 : FLASH_AREA_IMAGE_0)
- #define FLASH_AREA_IMAGE_SECONDARY(x) (((x) == 0) ? FLASH_AREA_IMAGE_1 : FLASH_AREA_IMAGE_1)
复制代码 如上配置解析,FLASH 总大小1024KB: l Bootloader Flash 区域 起始地址:0x08000000 大小:64KB l Slot 0区域 起始地址:0x08010000 大小:448KB l Slot 1区域 起始地址:0x08080000 大小:450KB Slot 1 比 Slot 0 多预留 1 个 Sector,用于 Swap Using Offset 模式下的 SwapOffset 操作 l Firmware Image Header 的大小 #define AT32_IMG_HDR_SIZE 0x200表示Image Header 大小512Byte flash_map_backend.c—— Flash 操作接口 flash_map_backend.c 负责实现 MCUboot Flash Area API 与 AT32 内部 Flash 驱动之间的适配,主要提供以下接口: l flash_device_base() 获取 Flash Device 基地址 l flash_area_open() 打开指定 FlashArea l flash_area_close() 关闭 Flash Area l flash_area_read() 读取 Flash 数据 l flash_area_write() 写入 Flash 数据 l flash_area_erase() 擦除 Flash Sector l flash_area_align() 获取 Flash 写入对齐要求 l flash_area_erased_val() 获取 Flash 擦除后的默认值 l flash_area_get_sectors() 获取 Flash Area 的 Sector 信息 l flash_area_get_sector() 获取指定偏移对应的 Sector 信息 l flash_area_read_is_empty() 检查指定 Flash 区域是否为空 l flash_area_id_from_multi_image_slot() 根据 Image Slot获取 Flash Area ID l flash_area_id_from_image_slot() 根据 Image Slot 获取 Flash Area ID 说明: 本参考工程提供的 Flash Layout 主要用于演示 MCUboot 的启动与固件升级功能。实际应用中,用户可根据 MCU Flash 容量、Bootloader 大小、Application 镜像大小以及升级策略等需求,对 Bootloader、Primary Slot、Secondary Slot 等区域的地址和大小进行调整。修改 Flash Layout 时,应确保 sysflash.h、flash_map_backend.c 以及 Application 的 Linker Script 配置保持一致,并满足 MCUboot 对 Sector 数量、镜像容量及地址对齐的要求。 3.4.2.3 key 管理 key.c 负责 MCUboot 中密钥的管理,主要用于 Firmware Image 签名验证及加密镜像解密。 1. 签名验证公钥 当使能 MCUBOOT_SIGN_EC256 时,通过 ecdsa_pub_key 保存 ECDSA-P256 公钥: const unsigned char ecdsa_pub_key[] = { /*ECDSA-P256 public key */ }; const unsigned int ecdsa_pub_key_len = 91; const struct bootutil_key bootutil_keys[] ={ { .key = ecdsa_pub_key, .len = &ecdsa_pub_key_len, }, }; const int bootutil_key_cnt = 1; ecdsa_pub_key[]:Firmware Image 签名验证公钥。 ecdsa_pub_key_len:公钥数据长度。 bootutil_keys[]:向 MCUboot 提供签名验证 Key。 bootutil_key_cnt:当前使用的 Key 数量。 替换方式:使用项目对应的 imgtool 根据签名私钥生成公钥,将生成的公钥数据替换 ecdsa_pub_key[] 中的内容,同时根据实际数据长度修改 ecdsa_pub_key_len。 2. 加密镜像解密私钥 当使能 MCUBOOT_ENCRYPT_EC256 时,通过 enc_priv_key 保存 ECIES-P256 私钥: const unsigned char enc_priv_key[] = { /*ECIES-P256 private key */ }; const unsigned int enc_priv_key_len = 138; const struct bootutil_key bootutil_enc_key ={ .key = enc_priv_key, .len = &enc_priv_key_len, }; enc_priv_key[]:用于解密Firmware Image 的私钥。 enc_priv_key_len:私钥数据长度。 bootutil_enc_key:向 MCUboot 提供加密镜像解密 Key。 替换方式:使用 imgtool 生成新的 ECIES-P256 加密 Key,并将对应的私钥数据替换 enc_priv_key[],同时更新 enc_priv_key_len。 注意:签名私钥用于 Firmware Image 签名,应由安全环境保存,不应放入 MCUboot;MCUboot 中仅保存用于验证签名的公钥。加密私钥则需要部署到设备端,用于启动时解密加密 Firmware Image。 3.4.2.4 Anti-rollback security counter 管理 security_cnt.c 负责 MCUboot Security Counter 的读取、更新和存储,用于实现 Firmware Image 的 Anti-rollback(防回滚)机制。 本参考工程将 Security Counter 存储在片上 Flash 的独立 Sector 中,通过多个固定大小的 Entry 顺序记录 Counter 值,并通过 value 与 inverse 的互补校验判断 Entry 是否有效。 主要配置和接口如下: l SEC_CNT_SECTOR_ADDR Security Counter 存储 Sector 起始地址 l SEC_CNT_SECTOR_SIZE Security Counter 存储 Sector 大小 l SEC_CNT_ENTRY_SIZE 单个 CounterEntry 大小 l SEC_CNT_MAX_ENTRIES 当前 Sector 最大可存储 Entry 数量 l boot_nv_security_counter_init() 初始化并读取当前Security Counter l boot_nv_security_counter_get() 获取当前 SecurityCounter l boot_nv_security_counter_update() 更新 SecurityCounter l flash_write_entry() 将新的 Counter 写入 Flash l flash_erase_sector() Security Counter Sector 满后执行擦除 本工程默认配置如下: l #define SEC_CNT_SECTOR_ADDR ((uint32_t)0x0800F800) l #define SEC_CNT_SECTOR_SIZE ((uint32_t)0x000) l #define SEC_CNT_ENTRY_SIZE 8 l #define SEC_CNT_MAX_ENTRIES (SEC_CNT_SECTOR_SIZE / SEC_CNT_ENTRY_SIZE) 其中,每个 Entry 使用 8 Bytes 存储: typedef struct { uint32_t value; uint32_t inverse; } sec_cnt_entry_t; value 保存 SecurityCounter,inverse 保存其按位取反值,用于基本的数据完整性检查。 当 Firmware Image 中的 Security Counter 大于当前设备保存值时,Bootloader 将更新 Counter;如果新 Image 的 Counter 小于当前值,则按照 Anti-rollback 策略拒绝回滚。 当当前 Sector 的 Entry 全部使用后,Bootloader 会擦除该 Sector,并从第一个 Entry 重新记录新的 Security Counter。 修改方式:用户可根据实际 Flash Layout 调整SEC_CNT_SECTOR_ADDR,将 Security Counter 放置在独立的 Flash Sector 中,同时根据实际 Flash Sector 大小修改 SEC_CNT_SECTOR_SIZE。修改存储地址时,应确保该区域不会与 Bootloader、Primary Slot、Secondary Slot 等区域重叠。 3.4.2.5 Mbed TLS配置管理 mbedtls_config.h 用于配置 MCUboot 所需的 Mbed TLS 加密算法及相关模块,根据当前参考工程的安全功能进行裁剪,以减少代码和 RAM/Flash 占用。 本工程主要配置以下功能: l SHA-256 Firmware Image Hash 计算 l ECDSA-P256 Firmware Image 签名验证 l ECDH 加密镜像密钥交换 l AES-CTR 加密 Firmware Image 解密 l HKDF 加密密钥派生 l ASN.1 / OID 密钥及签名数据解析 l PK / MPI / ECP 公钥及椭圆曲线运算 同时通过以下配置对资源占用进行优化: #define MBEDTLS_ECP_WINDOW_SIZE 2 #define MBEDTLS_ECP_FIXED_POINT_OPTIM 0 #define MBEDTLS_MPI_MAX_SIZE 256 修改方式:用户可根据实际启用的 MCUboot 功能增减 Mbed TLS模块。例如关闭 Firmware Image 加密功能后,可移除 ECDH、AES、HKDF 等不再使用的模块,从而进一步减少 Bootloader 的代码空间和运行资源占用。 3.5 Application工程介绍Application 工程用于实现用户应用程序,并与 MCUboot 的 Firmware Image 格式及 Flash 存储布局相匹配。Application 工程本身不包含 MCUboot 核心代码,但需要根据 Bootloader 的 Flash Layout 对工程地址、链接脚本以及镜像生成相关配置进行适配。 在使用参考工程时,Application 主要需要关注以下内容: l Application Flash 地址及空间配置 l Linker Script 配置 l 启动文件及向量表配置 l MCUboot Image Header 适配 l Firmware Image 生成 l Application 工程编译及升级文件生成 3.5.1 Application工程配置Application 工程最重要的配置是 Flash 地址和代码空间。Application 必须放置在 MCUboot 为其预留的 Slot 区域内,不能与 Bootloader 或其他 Flash 区域重叠。 Application 工程的 Flash 配置应与 Bootloader 中 sysflash.h 定义的 Flash Layout 保持一致。 其中,Application 工程实际生成的程序需要放置在 Primary Slot 对应的 Application 区域。 需要特别注意,Application 的链接地址不能简单设置为整个 Primary Slot 的起始地址,而需要考虑 MCUboot Image Header 所占用的空间。 3.5.2 Application功能介绍mcuboot_app 为 MCUboot 配套的 Application 参考工程,主要用于演示 Application 启动、Image Confirm 以及 USART 固件升级功能。 Application 启动后主要执行以下初始化和处理: l 系统及外设初始化:配置系统时钟、Board、USART 和定时器。 l Vector Table 配置:将 SCB->VTOR 设置为 Application 的起始地址,使中断向量表指向 Application。 l Image Confirm:调用 boot_set_confirmed() 确认当前 FirmwareImage,防止 MCUboot 在下次启动时将未确认的 Image 回滚。 l USART IAP 初始化:配置 USART 升级接口。 l 固件升级处理:循环调用 iap_upgrade_handle(),接收并处理上位机发送的 Firmware Image。 注意:IAP升级协议参考AN0001_AT32_IAP_using_the_USART。 主要代码流程如下: - system_clock_config();
- at32_board_init();
- uart_print_init(115200);
- tmr_init();
- /* Reset the vector table offset to the application */
- SCB->VTOR = 0x08010200;
- /* Enable IRQ */
- __enable_irq();
- /* Confirm current image */
- boot_set_confirmed();
- /* Initialize USART IAP */
- iap_usart_init(115200);
- while (1)
- {
- iap_upgrade_handle();
- }
复制代码
其中,Application 的起始地址必须与 MCUboot Flash Layout 及 Linker Script 保持一致。用户修改 Flash Layout 后,需要同步调整 SCB->VTOR 以及 Application 工程的链接地址。 4 AT32 MCUboot使用流程本节介绍 AT32 MCU Secure Boot 和 Secure Firmware Upgrade 参考工程的实际使用流程,包括工程准备、密钥生成、Bootloader 配置与编译、Application编译、Firmware Image 生成、首次烧录以及 USART IAP 固件升级。 4.1 硬件环境本文档中的demo基于AT-START-F407开发板实现。
4.2 软件环境准备AT32 MCUboot 参考工程使用 KeilMDK 进行工程编译和下载,并使用 MCUboot 提供的 imgtool 工具生成 Firmware Image。 使用参考工程前,需要准备以下软件: l Keil MDK:用于编译 Bootloader 和 Application 工程。 l Python环境:用于运行 imgtool。 l imgtool:位于参考工程 tool/imgtool.py。 l ICP/IAP 工具:用于固件烧录和升级,可从官网下载。 Note: 本应用笔记的项目基于keil 5而建立,若用户需要在其他编译环境上使用,请参考AT32Fxx_Firmware_Library_V2.x.x\project\at_start_f4xx\templates中各种编译环境(例如IAR6/7,keil4/5)进行简单修改即可。 进入 tool 目录后,可使用以下命令确认 Python 和 imgtool 环境是否正常: python --version python imgtool.py --help 正常显示 Python 版本及 imgtool 帮助信息后,即可进行后续操作。 4.3 软件工程使用本参考工程主要包含 Bootloader 工程和 Application 工程: Bootloader 工程:utilities/mcuboot_bootloader sLib Bootloader工程:utilities/mcuboot_bootloader_slib Application 工程:utilities/mcuboot_app 首次使用参考工程时,建议按照以下顺序完成配置和操作: 1. 生成产品密钥; 2. 将所需密钥配置到 Bootloader 工程; 3. 配置 MCUboot; 4. 配置 Flash Map; 5. 确认 Security Counter 配置; 6. 编译 Bootloader; 7. 烧录 Bootloader; 8. 编译 Application; 9. 使用 imgtool 生成 Firmware Image; 10. 将 Firmware Image 烧录到 Slot 0。 完成上述步骤后,复位 MCU,MCUboot 将对 Slot 0 中的 Firmware Image 进行验证,验证通过后启动 Application。 注意:如果使用参考工程的默认配置,可直接按照上述流程进行编译和烧录;当产品需要修改 Flash 空间、密钥、升级策略或安全计数器等配置时,再根据实际需求修改对应参数 4.3.1 生成认证key认证 Key 用于验证 Firmware Image 的完整性和真实性。 以 ECDSA P-256 为例,在 tool 目录下执行: python imgtool.pykeygen -k signing-key.pem -t ecdsa-p256 执行完成后生成:signing-key.pem,此为Firmware 签名私钥 使用以下命令获取对应的公钥: python imgtool.pygetpub -k signing-key.pem 将生成的公钥更新到bootloader 工程中对应mcuboot_port/key.c 中ecdsa_pub_key[]数组; 注意: signing-key.pem 为签名私钥,仅用于 Firmware Image 签名,应妥善保管,不应存放在 Bootloader、Application 或设备 Flash 中。 4.3.2 生成固件升级加密key当参考工程启用 Firmware Image 加密功能时,需要生成 ECIES-P256 加密密钥对,默认有开启此功能。 在 tool 目录下执行: python imgtool.pykeygen -k encryption-key.pem -t ecdsa-p256 执行完成后生成:encryption-key.pem,此为ECIES-P256 私钥,这个私钥需要放到bootloader中。 执行下列命令导出私钥数组: python imgtool.pygetpriv -k encryption-key.pem 将生成的私钥更新到bootloader 工程中对应mcuboot_port/key.c 中enc_priv_key []数组; 注意:签名私钥和加密 Key 均属于敏感密钥,应妥善保管,避免提交到公开代码仓库。encryption-key.pem 的具体配置方式应与参考工程中的加密实现保持一致。 4.3.3 Bootloader编译与下载完成 Bootloader 配置后,打开 Keil utilities\mcuboot_bootloader\mdk_v5工程并进行编译。 如果使用sLib, 使用工程utilities\mcuboot_bootloader_slib\mdk_v5 编译成功后, 使用 ICP 或 Keil Debugger 将程序烧录至 MCU 的 Bootloader 区域。 使用mcuboot_bootloader_slib时需要使用ICP进行下载并启用sLib,
首次烧录时,设备中尚未存在有效的 Application。复位后,MCUboot 启动并检查 Slot 0,如果未检测到有效的 Firmware Image,则不会进入 Application。 此时可通过调试串口等方式确认 MCUboot 已正常运行。 如下是首次运行时的通过串口打印信息:
4.3.4 Application编译与下载Application 工程的编译下载步骤如下: 打开 Application 工程:utilities\mcuboot_app\mdk_v5 编译生成,utilities\mcuboot_app\mdk_v5\objects\mcuboot_app.bin 使用imgtool对 mcuboot_app.bin 进行签名,生成 MCUboot 可识别的 Firmware Image。 首次烧录到 Slot 0 时,Firmware Image 仅进行签名,不进行加密。 即本步骤不使用 imgtool 的加密参数,确保生成的镜像为签名但未加密的 Firmware Image。 使用如下命令生成签名固件: python imgtool.pysign --key signing-key.pem --header-size 0x200 --pad-header --align 8 --slot-size0x70000 --security-counter 1 --version 1.0.0 mcuboot_app.binmcuboot_app_img_v1.0.0.bin 生成 mcuboot_app_img_v1.0.0.bin 后,使用 ICP 工具将其烧录到 Slot 0 起始地址。 下载完成后复位 MCU,MCUboot 检测 Slot 0 中的 Firmware Image,验证 Image 的完整性和签名。验证通过后,跳转至 Application 执行。
注意:首次烧录主要用于验证 Bootloader 和 Application 的基本启动流程,因此 Slot 0 中的 Firmware Image 不进行加密。后续固件升级测试中,再使用签名 + 加密 + Security Counter 的方式生成升级 Firmware Image,并通过 IAP 完成升级。 4.3.5 Application 升级测试首次启动验证通过后,可以进一步验证 Secure Firmware Upgrade 功能。 本例通过修改 Application 的 LED 显示效果和 Firmware Version,模拟实际产品 Firmware 升级。 1. 修改mcuboot_app version 1.0.1 ,修改如下: #defineAPP_VERSION "1.0.1" 2. TMR3_GLOBAL_IRQHandler 中的LED2 闪烁改为LED4,修改如下 at32_led_toggle(LED4); 修改完成之后重新编译生成utilities\mcuboot_app\mdk_v5\objects\mcuboot_app.bin 此时再使用imgtool对新的mcuboot_app.bin 进行签名加密,使用如下命令: python imgtool.py sign --key signing-key.pem--encrypt encryption-key.pem --encrypt-keylen 128 --header-size 0x200 --pad-header --align 8 --slot-size 0x70000 --security-counter 2 --version 1.0.1mcuboot_app.bin mcuboot_app_img_v1.0.1.bin 生成 mcuboot_app_img_v1.0.1.bin 后,使用 IAP 工具将其烧录到 Slot 1 的image起始地址,注意Slot1的第一个sector地址时swap offset的地址,image地址是在swap offset之后的地址: 如下是IAP升级示例: 升级成功之后,复位,启动之后,MCUboot升级成功打印:
|