4. 密码学基础
安全启动,说白了就是让芯片只运行你授权的代码。我见过不少产品,功能做得花里胡哨,结果启动链上有个漏洞,整个系统就跟没锁门一样。今天咱们就聊聊英飞凌HSM里这套启动流程到底怎么设计的。
4.1 BootROM:信任的起点
BootROM是芯片上电后执行的第一段代码。它固化在ROM里,出厂后改不了。为什么放在ROM里?因为ROM没法被篡改,这就是信任链的根。
我个人习惯把BootROM比作“看门老头”——他手里有一把钥匙,只认特定的签名。谁来敲门都得亮出身份,否则门不开。
BootROM的核心职责:
- 初始化硬件(时钟、内存、HSM外设)
- 验证下一级Bootloader的签名
- 建立信任链的根
- 提供回滚保护检查
BootROM里通常包含以下几部分:
| 模块 | 功能 | 存储位置 |
|---|---|---|
| 硬件初始化 | 配置PLL、SRAM、HSM引擎 | ROM |
| 公钥哈希 | 存储根公钥的哈希值(用于校验公钥完整性) | eFuse/OTP |
| 签名验证引擎 | 调用HSM硬件加速进行ECDSA/RSA验签 | ROM |
| 回滚计数器 | 读取并比较版本号 | eFuse/Flash |
嗯,这里要注意:公钥本身不放在ROM里,ROM里只存公钥的哈希。公钥放在Flash里,BootROM先算公钥的哈希,跟eFuse里的值比对,一致了才用这个公钥去验签。为什么要绕这么一圈?因为公钥可能更新,但ROM改不了。哈希放eFuse里,更新公钥时只需要烧新的eFuse就行。
4.2 启动链验证:多级签名校验
启动不是一步到位的。你想想看,BootROM才几十KB,它不可能把整个操作系统都验一遍。所以设计上采用链式验证:每一级只验下一级,层层递进。
典型的英飞凌HSM启动链长这样:
BootROM → Bootloader (BL1) → 应用Bootloader (BL2) → OS/App
每一级都做三件事:
- 读取下一级镜像:从Flash指定地址加载
- 验证签名:用当前级的公钥验下一级的签名
- 检查版本号:确保不低于当前运行版本
- 跳转执行:通过后把控制权交给下一级
我在项目中遇到过一个问题:客户把三级启动链改成了五级,结果启动时间从200ms飙到了800ms。为什么?每一级验签都要做一次ECDSA P-256运算,大概耗时40-60ms。五级就是200-300ms,再加上镜像加载和哈希计算,时间就上去了。所以我的建议是:启动链别超过三级,除非你有硬实时要求。
经验之谈:
我曾经帮一个客户优化启动时间,把三级验签改成两级——BootROM直接验应用Bootloader,省掉中间那一级。前提是应用Bootloader足够小,能放在BootROM能访问的固定地址。这样启动时间直接砍掉40%。
4.3 签名验证流程详解
签名验证不是简单地把签名解出来比对。完整的流程是这样的:
1. 从Flash读取镜像 + 签名 + 证书链
2. 用根公钥哈希验证证书链中的公钥
3. 用验证通过的公钥验签
4. 计算镜像哈希,与签名中的哈希比对
5. 检查镜像版本号 ≥ 回滚计数器值
6. 全部通过 → 跳转执行
这里有个细节:签名里包含的是镜像哈希的签名,不是镜像本身的签名。为什么?因为非对称签名慢,哈希计算快。先算哈希,再对哈希签名,效率高得多。
我个人习惯在镜像头部放一个结构体,包含版本号、镜像大小、哈希算法ID、签名算法ID、签名值。这样BootROM解析起来方便,不用猜。
避坑指南:
我曾经见过一个案例,开发者在镜像头部放了签名,但没放哈希算法ID。结果BootROM默认用SHA-256,实际镜像用的是SHA-384,验签一直失败。排查了两天才找到原因。所以镜像头部一定要显式声明算法ID,别用默认值。
4.4 回滚保护机制
回滚攻击是什么?黑客拿到一个旧版本固件,里面有已知漏洞,然后强制设备降级到这个版本。如果不做保护,你的安全更新就白费了。
英飞凌HSM支持两种回滚保护方式:
| 方式 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| eFuse计数器 | 每次升级烧断一根eFuse,BootROM检查版本号≥已烧断数 | 不可逆,安全性高 | eFuse数量有限(通常16-32根) |
| Flash版本号 | 在Flash中存储版本号,BootROM比较 | 可多次升级 | Flash可被擦写,安全性较低 |
我建议的做法是:关键安全更新用eFuse计数器,普通功能更新用Flash版本号。比如修复了远程代码执行漏洞的版本,必须烧eFuse,防止黑客降级回去。
回滚保护的检查时机:
- 每次启动时,BootROM读取镜像版本号
- 与eFuse/Flash中的回滚计数器比对
- 如果镜像版本号 < 回滚计数器值,拒绝启动
- 如果镜像版本号 ≥ 回滚计数器值,允许启动
关键设计原则:
回滚计数器只能增加,不能减少。eFuse烧断了就接不回去,Flash里的计数器也要用特殊保护(比如写保护位)。我曾经见过一个产品,回滚计数器放在普通Flash区域,黑客直接擦掉整个Flash,计数器归零,然后刷回旧版本。这就是设计缺陷。
4.5 安全启动流程图
下面这张图展示了完整的启动流程。我把它画成了SVG,方便你理解各环节的关系。
4.6 实际部署中的注意事项
部署安全启动时,有几个坑我踩过,分享给你:
- 公钥哈希的保护:eFuse烧录后要锁定,防止被篡改。我见过有人忘了锁,结果攻击者直接改哈希,用自己的公钥替换了。
- 签名算法的选择:英飞凌HSM支持ECDSA和RSA。我个人偏好ECDSA P-256,密钥短、速度快、安全性够。RSA-2048也行,但验签慢一些。
- 版本号管理:版本号要单调递增,不能回退。建议用时间戳或递增计数器,别用语义化版本号(比如v2.1.3),因为比较起来麻烦。
- 恢复机制:万一签名验证失败,设备不能变砖。要留一个恢复模式,比如通过串口或USB刷入新固件。但这个恢复模式本身也要有签名保护,否则就是后门。
重要提醒:
我曾经帮一个客户做安全审计,发现他们的恢复模式没有签名验证,任何人都能通过串口刷任意固件。这等于安全启动白做了。恢复模式必须跟正常启动一样严格,甚至更严格——因为攻击者可能物理接触设备。
4.7 性能与安全的权衡
安全启动不是免费的。每次验签都要消耗时间和算力。我整理了一个参考数据:
| 操作 | 耗时(典型值) | 说明 |
|---|---|---|
| SHA-256(256KB镜像) | ~5ms | HSM硬件加速 |
| ECDSA P-256验签 | ~40ms | HSM硬件加速 |
| RSA-2048验签 | ~60ms | HSM硬件加速 |
| eFuse读取 | ~1ms | 直接内存映射 |
| Flash读取(256KB) | ~10ms | Quad SPI模式 |
所以一个三级启动链,总耗时大概在150-200ms。如果你的产品要求1秒内启动,这个时间是可以接受的。但如果要求100ms以内,就得考虑优化了——比如减少启动级数,或者用更大的镜像块减少读取次数。
嗯,安全启动这块内容比较多,但核心就三点:BootROM是信任根、链式验证层层把关、回滚保护防止降级攻击。把这三点吃透了,英飞凌HSM的安全启动方案你就能拿捏住。