TECHNICAL GUIDE
固件加密与安全启动设计_ 从Flash加密到安全烧写系统的完整实现路径 | 上海耀罡电子
固件是设备的大脑,一旦被读出来,整机方案就等于公开了。本文讲清三层保护的边界在哪,以及为什么「加密了固件」还远远不够。
固件的三层保护模型
先说清楚要防什么
「固件加密」这个说法容易让人误以为加密完就安全了。实际上要防的是三类不同的攻击者,需要三层不同的机制:
| 攻击者类型 | 目标 | 对应防线 |
|---|---|---|
| 好奇的拆机者 | 想读出固件源码 | 镜像加密 |
| 逆向分析者 | 想分析算法、改固件做盗版 | 安全启动 + 完整性校验 |
| 有物理接触的攻击者 | 想读出密钥、绕过校验 | 硬件根信任 + 密钥保护 |
三层的依赖关系
这三层是层层递进的,缺任何一层,前面那层的价值都会被削弱:
第三层:密钥保护(硬件根信任)
↓ 决定
第二层:安全启动(信任链传递)
↓ 依赖
第一层:镜像加密(内容保密)
只有加密、没有安全启动是最常见的错误组合:固件内容是密文没错,但攻击者可以用自己写的 bootloader 跳过解密校验,直接把密文当别的数据处理,或者用调试口单步执行把明文从内存里dump出来。
只有安全启动、没有镜像加密同样不够:固件在 Flash 里是明文,攻击者即使无法引导启动,也能用编程器把 Flash 读出来——只需要几十块钱的设备。
两者都有但密钥存在 Flash 里是最隐蔽的失败:加密密钥和解密逻辑放在同一块 Flash 上,读 Flash 的人两个都拿到了。
第一层:固件镜像加密
加密什么
固件加密的对象是待写入 Flash 的镜像文件本身。流程是:
编译产物 → 打包 → 加密 → 生成加密镜像 → 写入产线烧录
常见做法是使用 AES-256 对镜像做对称加密,密钥与芯片绑定。
对称而非非对称的原因:固件有几百 KB 到几 MB,非对称运算的吞吐量不足以支撑产线烧录速度;而对称加密完全够用,非对称的必要性由安全启动层来承担。
不能只加密代码段
一个常见的疏漏是只加密代码区、保留数据区明文。但很多关键信息恰恰在数据区:证书、密钥、配置参数、授权码。
如果证书是明文存放的,攻击者读出来就能在另一台设备上冒充同一台,第一层的加密等于白做。
正确做法是整个镜像一起加密,包括头部信息(版本号、长度、校验值)——头部信息如果不加密,攻击者就能通过修改长度或版本号来破坏解密流程。
加解密放在哪里做
加解密必须在芯片内部完成。
如果解密在主控上做(比如 bootloader 里实现 AES),那么 bootloader 本身就是明文写在 Flash 里的,攻击者读出来就知道算法和密钥存放位置。
正确架构是:
Boot ROM(芯片内,不可改写)
↓ 校验签名,通过则解密
↓ 交给硬件密钥解出的明文
Bootloader(可明文,但必须验签后续镜像)
↓
应用程序
DX88F01 这类 USB 安全认证 MCU 正是为这种架构设计的——它本身就是一颗带硬件算法协处理器的安全 MCU,可以把安全启动的信任根直接做进整条链路的起点。
第二层:安全启动与信任链
信任传递的基本逻辑
安全启动的核心是信任的单向传递:每一级只信任直接上一级,每一级都验证下一级的签名。
Root of Trust(芯片内,ROM 或 OTP 区,不可改写)
↓ 信任
Stage 1 Bootloader(验证 Stage 2 的签名)
↓ 信任
Stage 2 / 应用程序(验证后续模块)
关键在于 Root of Trust 必须是不可改写的。如果它存在可写的 Flash 里,攻击者可以先改掉 Root of Trust,再让它去签一个恶意镜像,整条信任链就崩了。
DX 系列芯片内部的 OTP(一次性可编程)区域正是为此设计的——烧写一次就永久锁定,之后无法被清除或改写。
签名验证用什么算法
固件签名推荐 ECDSA(P-256) 或 Ed25519:
| 算法 | 优势 | 适用 |
|---|---|---|
| ECDSA P-256 | 硬件加速普及广泛,兼容性好 | 主流 MCU 首选 |
| RSA-2048 | 兼容老旧方案 | 算力开销大 |
| Ed25519 | 签名小、验证快 | 算力充足的新平台 |
| HMAC 对称签名 | 快,但密钥必须存在设备里 | 仅适用于封闭环境 |
为什么首选非对称
对称签名(HMAC)的密钥必须存在设备内部才能验签,这又回到了「密钥怎么保护」的老问题。
非对称方案把公钥(可公开、只读)烧进设备,私钥只留在签发端:设备只需要能验证,不需要能签发——攻击者即使拿到全部设备,也无法伪造出通过验证的固件。
这与「设备证书」的信任链思路是同一套体系。
防回滚(Anti-Rollback)
只有签名验证是不够的。攻击者可以把旧版本的合法固件重新刷回去,利用历史版本里存在的漏洞。
解决办法是单调递增的版本计数器:设备 OTP 或 EEPROM 里存一个当前允许的最低版本号,启动时验证固件版本不低于该值,且验证通过后把计数器更新为当前版本。
注意这个计数器本身也必须防篡改——否则攻击者可以把计数器改小,允许旧固件启动。
第三层:密钥如何保护自己
密钥分级的必要性
固件加密密钥必须以某种形式存在设备里(否则设备无法解密)。问题是怎么让它不可读。
有效的做法是分层:
| 密钥 | 存放位置 | 可读性 |
|---|---|---|
| 固件加密密钥 | 安全芯片的加密存储区 | 外部无法读取,只能在芯片内使用 |
| 烧录授权密钥 | OTP 区,芯片内 | 出厂一次性写入,用于授权后续烧录 |
| 设备证书私钥 | 安全芯片内 | 外部无法导出 |
密钥永不离开芯片
这是整个方案的地基:所有敏感密钥的运算都在安全芯片内部完成,主控只能通过标准命令请求运算结果。
DX 系列的结构正是如此:芯片内部有 ECC / SHA1 / 3DES / TRNG 硬件算法协处理器,主控无法直接读取密钥内容,只能发起「用密钥 K 计算 H」这类受限操作。
攻击者拿到主板也无法导出密钥,这就把物理攻击的收益降到了最低。
调试接口必须被锁死
这是一个再强调都不过时的点:量产版必须关闭 JTAG/SWD 调试口。
很多产品在开发阶段开着调试口方便调试,量产时忘了关——这等于把所有安全机制全部作废:攻击者可以直接单步执行、读内存、绕过验签。
推荐做法是:通过 OTP 位一次性关闭调试口,这个动作不可逆。同时在软件层面关闭「读保护」绕过路径。
值得强调:这不是可有可无的加固项,而是必须做。在安全启动方案里,调试口未关的设备,等同于没有任何安全防护。
安全烧写系统:生产阶段怎么解决
生产阶段的三个难题
加密的固件要写进设备,但加密密钥必须每台不同(否则一台上破解全网失守),这带来三个生产难题:
| 难题 | 描述 |
|---|---|
| 密钥注入 | 每台设备要写入不同的密钥,且要防止被读出 |
| 防克隆 | 产线要防止有人把一台的密钥复制到另一台 |
| 追溯 | 要能查到某台设备注入了什么密钥、什么时间、谁操作的 |
安全烧写系统的解法
专业的安全烧写系统通过以下机制解决:
① 注入设备 通过专用烧录器把设备密钥写入芯片 OTP/安全区
写入后立即锁定,读写接口永久关闭
↓
② 绑定烧录 烧录器读取芯片唯一 SN,上传产线系统
产线系统用 SN 索引对应的加密镜像与证书
↓
③ 记录追溯 SN / 密钥指纹 / 烧录时间 / 工位号 / 操作员 全部落库
这个流程的三个安全属性:密钥在芯片内被锁定,无法导出(物理接触也拿不到);加密镜像按 SN 精确匹配(复制到另一台上无法解密启动);全流程可追溯(出问题能定位到具体批次与工位)。
为什么不能把密钥存在工控机或云端
常见的省事做法是:烧录时用一把主密钥加密所有固件,所有设备共用。
这样做的结果是:产线工控机一旦被入侵,所有在制品的密钥同时暴露;而且同一型号所有设备共用一把密钥,一台被破解就等于全系列失守。
正确做法是逐台生成设备密钥,加密镜像按 SN 一对一匹配。这会让产线流程复杂一些,但这是唯一能真正兑现「一机一密」的做法。
常见绕过路径与加固要点
真实攻击路径梳理
下面这些是实际中出现频率最高的绕过路径,每一条都有对应的加固手段:
| 绕过路径 | 原理 | 加固手段 |
|---|---|---|
| 调试口直连 | JTAG/SWD 未关闭,直接读内存 | OTP 位永久关闭调试口 |
| Flash 离线读取 | 编程器读出 Flash 明文 | 镜像加密 + 读保护 |
| 启动流程绕过 | 替换 bootloader,跳过验签 | Root of Trust 不可改写 + 签名校验 |
| 降级攻击 | 刷回有漏洞的旧版本 | 单调版本计数器(防回滚) |
| 侧信道 | 通过功耗/电磁/时序推断密钥 | 恒定时间运算 + 随机数扰动 |
| 物理重编程 | 拆芯片重烧 | 安全熔丝 / 一次性锁定 |
| 供应链替换 | 流通过程被动手脚 | 安全烧写 + 产线追溯 + 出厂抽检 |
优先级排序
资源永远有限,加固要按投入产出排:
| 优先级 | 动作 | 理由 |
|---|---|---|
| P0 | 关闭调试口(OTP 一次性) | 成本最低,收益最大,不做等于全废 |
| P0 | 固件镜像加密 | 防止编程器直接读取 |
| P1 | 安全启动签名校验 | 防止替换 bootloader 与固件 |
| P1 | 密钥存于安全芯片不可导出 | 保证物理接触也拿不到 |
| P2 | 防回滚版本计数 | 防降级攻击 |
| P2 | 安全烧写与产线追溯 | 防供应链与克隆 |
自检清单
上线前对照这份清单逐项确认:
□ 量产固件已关闭 JTAG/SWD 调试口,且不可恢复
□ Flash 中的固件镜像是密文(用编程器读出来不可直接反汇编)
□ 启动链第一级不可改写,且逐级验签
□ 固件版本计数器单调递增,不允许降级
□ 所有密钥均不可从外部读出,运算在芯片内完成
□ 每台设备密钥唯一,加密镜像按 SN 匹配
□ 产线有完整追溯记录
□ 调试固件与量产固件分离,量产版本无调试入口
常见问题
固件加密和安全启动,哪个更重要?
两者都必需,缺一不可。只有加密没有安全启动,攻击者可以替换 bootloader 绕过解密;只有安全启动没有加密,攻击者能用编程器直接读出 Flash 里的明文固件。更关键的是第三层——密钥必须存在不可读的硬件里,否则前两层都会被绕过。
为什么必须关闭调试接口?
因为开着调试口的设备,攻击者可以直接单步执行、读内存、跳过验签逻辑,所有加密与签名保护全部作废。这是成本最低、收益最大的一步加固——量产版应该通过 OTP 位一次性永久关闭调试口。
非对称签名和非对称加密可以用同一把密钥吗?
不可以,这是常见的概念混淆。非对称体系里有两组独立的密钥对:签名用私钥签名、公钥验签(设备只存公钥);加密用公钥加密、私钥解密(设备只存私钥)。固件签名用前者,会话密钥协商用后者,两者密钥必须完全分开生成与存储。
安全烧写系统是自己开发还是采购?
两种都可以,取决于产线规模与安全要求。产线规模不大时,用安全的烧录器配合自研的产线系统即可;对防克隆与追溯要求高时,通常采购专业的安全烧写方案。无论哪种,核心要求是一样的:逐台密钥注入、写入即锁定、按 SN 一对一匹配加密镜像、全流程留痕。
固件防回滚一定要做吗?
强烈建议做。攻击者刷回旧版本是成本极低的攻击方式,而旧版本里往往存在已知漏洞——2026 年多个嵌入式设备漏洞被公开时,大量设备的漏洞正是存在于已停止维护的旧固件中。实现成本只是加一个单调递增的版本计数器,却能挡掉一整类攻击。