4. HSM基础
密钥这东西,说白了就是汽车网络安全的命根子。你想想看,不管是安全启动、安全通信还是安全刷写,底层依赖的都是密钥。如果密钥本身的管理出了漏洞,那上层做得再花哨也没用。
我在英飞凌HSM上落地SHE规范时,最深的体会就是:密钥生命周期管理不是一把锁,而是一整套流程。从密钥怎么生出来,到怎么存、怎么用、怎么换、最后怎么销毁,每一步都有讲究。
4.1 SHE密钥槽(Key Slot)架构
SHE规范把密钥存储单元叫做密钥槽(Key Slot)。英飞凌HSM内部有一组专用的NVM区域,每个槽位固定存放一个密钥及其属性。
| 密钥槽属性 | 说明 | 我见过的坑 |
|---|---|---|
| Key ID | 槽位编号,SHE最多支持16个槽(0-15) | 有人把ID当优先级用,结果乱套了 |
| Key Value | 128位密钥本体 | 写入时校验位没对齐,直接锁死槽位 |
| Key Flags | 密钥属性标志位(只读、可导出、可更新等) | 标志位一旦固化,想改就得擦全片 |
| Write Counter | 写入次数计数器,防重放攻击 | 计数器溢出后槽位永久锁定 |
| Volatile Key Flag | 是否为易失性密钥(掉电即失) | 有人把易失密钥当持久密钥用,一断电就废了 |
核心原则:每个密钥槽在生命周期内只能被写入有限次数(SHE规范通常限制为5次或更少)。这不是硬件抠门,而是为了防攻击者反复尝试覆盖密钥。
4.2 密钥生成:从哪里来?
密钥生成分两种场景:内部生成和外部注入。
内部生成,就是让HSM自己用真随机数发生器(TRNG)产出一把密钥。我个人习惯在产线初始化阶段用这种方式生成根密钥。好处是密钥从不出HSM边界,安全性最高。
外部注入,则是通过安全通道把密钥写进HSM。比如OEM在产线上下发一把统一的传输密钥。这里要注意:外部注入必须走SHE的SECURE_BOOT或LOAD_KEY指令,不能直接写NVM。
我的经验:产线上用内部生成+锁定槽位的方式最省心。外部注入虽然灵活,但需要额外管理传输密钥的生命周期,复杂度翻倍。
4.3 密钥存储:放对地方才安全
英飞凌HSM的密钥存储分两类:
- 非易失性密钥(NVM Key):写入HSM专用Flash,掉电不丢失。适合根密钥、固件签名公钥等长期使用的密钥。
- 易失性密钥(Volatile Key):只存在于HSM RAM中,掉电即失。适合会话密钥、临时派生密钥。
我记得有个项目,客户把会话密钥存到了NVM槽位里,结果每次会话结束后密钥还留在芯片里。攻击者只要读一次NVM,所有历史通信都能解密。嗯,后来我强制要求:会话密钥必须用Volatile Key Flag标记。
4.4 密钥导入与导出:安全边界怎么守?
SHE规范对密钥导入导出有严格限制。说白了,密钥不能裸着进出HSM。
导入流程:
- 外部传入的密钥必须用已存在的密钥加密(Key Wrapping)。
- HSM内部解密后写入目标槽位。
- 写入完成后,临时解密缓冲区立即清零。
导出流程:
- 只有标记为"可导出"(Key Flags中DF=1)的密钥才能导出。
- 导出时用另一个密钥加密后再输出。
- 导出次数通常受Write Counter限制。
我曾经踩过的坑:有个项目为了调试方便,把固件签名私钥标记为可导出。结果产线被人物理攻击,私钥被加密导出后离线爆破。从那以后,我规定:生产环境下的私钥必须标记为不可导出。
4.5 密钥更新与轮换
密钥不能一把用到天荒地老。SHE规范支持密钥更新,但更新机制有讲究。
更新方式:
- 直接覆盖:用LOAD_KEY指令写入新密钥。前提是Write Counter未耗尽。
- 派生更新:基于当前密钥和新材料,通过KDF派生新密钥。适合OTA场景。
我建议在OTA升级方案中,采用双槽位轮换策略:
- 槽位A存当前密钥,槽位B存待激活密钥。
- 升级时先写入槽位B,验证通过后再激活。
- 万一升级失败,回滚到槽位A。
避坑指南:密钥更新后,旧密钥必须立即失效。我见过有人更新完密钥忘了更新Key Flags中的"激活"位,结果新旧两把密钥同时有效,攻击者随便挑一把用。
4.6 密钥销毁:死要见尸
密钥销毁比生成难得多。你想想看,Flash里存的数据,单纯擦除不一定能彻底清除。攻击者可以用电子显微镜读残留电荷。
SHE规范对销毁的要求:
- 逻辑销毁:将密钥值覆写为全0或全1,同时清除Key Flags。
- 物理销毁:触发HSM的安全擦除机制,对存储单元进行多次覆写。
- 槽位锁定:销毁后将Write Counter耗尽,防止密钥被重新写入。
我在实际项目中,对根密钥的销毁流程做了三遍确认:
- 先发CANCEL指令终止所有正在使用该密钥的操作。
- 再发LOAD_KEY写入全0值。
- 最后触发一次安全擦除中断。
注意:销毁操作不可逆。一旦执行,密钥永久丢失。所以销毁前一定要确认该密钥确实不再需要了。我见过测试人员在调试时误销毁了产线密钥,结果整批芯片报废。
4.7 SHE密钥槽管理策略总览
下面这张图是我自己总结的密钥槽管理流程,每次做新项目都会拿出来对照一遍。
4.8 实际项目中的密钥槽分配建议
以我最近做的一个T-Box项目为例,16个密钥槽的分配方案是这样的:
| 槽位 | 用途 | 类型 | 可导出 | 更新策略 |
|---|---|---|---|---|
| 0 | 根密钥(Root Key) | NVM | 否 | 产线写入后锁定 |
| 1 | 固件签名公钥 | NVM | 是(仅用于验证) | OTA更新 |
| 2 | 安全通信主密钥 | NVM | 否 | 双槽位轮换 |
| 3 | 安全通信备用密钥 | NVM | 否 | 与槽位2配对 |
| 4-7 | 会话密钥(动态分配) | Volatile | 否 | 每次会话重新生成 |
| 8-15 | 预留(OEM自定义) | 按需 | 按需 | 按需 |
我的建议:永远预留至少2个槽位给应急场景。有一次客户临时要求增加一把诊断密钥,幸好我预留了槽位,不然就得动固件架构。
密钥生命周期管理,说到底就是让密钥在正确的时间出现在正确的地方,用完就消失。SHE规范给了你一套完整的规则,但落地的时候,每个项目都有自己的脾气。多留个心眼,多设几道检查,总没错。