4、安全密钥存储:SHE内部NVM的密钥存储机制与保护策略

好,咱们接着聊SHE规范里最核心的一个话题——密钥到底怎么存?

你想想看,密钥要是被偷了,那整个安全体系就形同虚设。我见过不少项目,算法选得挺强,防侧信道也做得不错,结果密钥存储环节出了纰漏,功亏一篑。所以这一章,咱们把SHE内部NVM的密钥存储机制掰开揉碎了讲清楚。

4.1 SHE的NVM架构:密钥到底放在哪?

SHE规范里定义的NVM,说白了就是芯片内部的一块非易失性存储器。它跟普通的Flash或者EEPROM不一样——SHE的NVM是专用于密钥存储的,普通用户代码根本访问不到。

我个人习惯把SHE的NVM想象成一个“保险柜”。这个保险柜有多个小格子,每个格子对应一个密钥槽(Key Slot)。SHE规范定义了最多16个密钥槽,编号从0到15。

密钥槽编号 用途 是否可被用户读取
0 调试密钥(Debug Key)
1-11 通用密钥(Generic Key)
12-13 RAM密钥(仅运行时存在)
14 安全启动密钥
15 主密钥(用于派生其他密钥)

嗯,这里要注意:所有密钥槽对用户都是不可读的。你只能通过SHE提供的API去使用密钥,比如加密、解密、MAC计算,但你不能直接问“给我把密钥0x05读出来”。这是SHE安全设计的底线。

核心原则:SHE的NVM密钥存储遵循“可用不可见”原则。密钥在NVM里是密文存储的,即使攻击者物理剖片,拿到的也是一堆乱码。

4.2 密钥存储格式:不仅仅是128位数据

你以为密钥就是往NVM里写128位二进制数?太天真了。

SHE规范对密钥存储格式有严格定义。每个密钥槽在NVM中实际占用144位(18字节)的空间。为什么多出16位?

  • 128位:密钥本体
  • 4位:密钥版本号(用于密钥更新和回滚保护)
  • 4位:密钥标志位(指示密钥类型、是否可导出等属性)
  • 8位:CRC校验(用于检测NVM数据完整性)

我在项目中遇到过一个问题:某次OTA升级后,密钥莫名其妙失效了。排查了半天,发现是NVM写入时CRC计算出了偏差。从那以后,我每次做密钥写入都会额外做一次读回校验。

实战技巧:密钥写入后,建议立即执行一次SECURE_BOOT或者LOAD_KEY命令验证密钥是否可用。不要等到系统运行时才发现密钥坏了。

4.3 密钥保护策略:NVM里的密钥是怎么加密的?

直接往NVM里写明文密钥?那是给自己挖坑。

SHE规范要求,NVM中存储的密钥必须经过密钥加密密钥(KEK)加密。这个KEK是怎么来的?

  1. 芯片唯一密钥(UID Key):基于芯片唯一ID派生,每颗芯片都不一样。
  2. 用户自定义密钥(User Key):由OEM在产线注入,同一批次可能共享。
  3. 两者结合:通过KDF(密钥派生函数)生成最终的KEK。

说白了,你写入NVM的密钥,在物理存储层面是经过加密的。攻击者就算把芯片磨到只剩NVM层,用电子显微镜看,看到的也是加密后的密文。没有KEK,他拿这堆数据一点办法都没有。

警告:千万不要尝试绕过SHE的API直接操作NVM地址。我曾经见过一个团队,为了“提高效率”自己写驱动操作NVM,结果把密钥存储区的校验信息搞乱了,整批芯片报废。SHE的NVM操作必须通过SHE模块提供的接口。

4.4 密钥生命周期管理:从生到死

密钥不是写进去就完事了。SHE规范定义了完整的密钥生命周期:

阶段 操作 说明
1. 初始化 NVM全擦除 出厂时所有密钥槽为全0或全1状态
2. 写入 LOAD_KEY 通过安全通道写入加密后的密钥
3. 使用 加密/解密/MAC 密钥仅在SHE内部使用,不暴露
4. 更新 LOAD_KEY(新版本) 版本号递增,防止回滚攻击
5. 删除 NVM擦除 物理擦除,不可恢复

这里有个关键点——密钥版本号。SHE规范要求,每次更新密钥时,版本号必须递增。如果攻击者试图把旧版本的密钥写回去(回滚攻击),SHE会检测到版本号降低,直接拒绝操作。

我曾经在给一家Tier1做安全审计时发现,他们的密钥更新逻辑里没有检查版本号。结果测试人员用旧固件刷回去,系统居然还能正常工作。这要是被攻击者利用,后果不堪设想。

4.5 密钥导出策略:什么时候可以“拿出来”?

SHE规范里有个很有意思的设计——密钥导出(Key Export)。某些场景下,你需要把密钥从一个SHE模块转移到另一个SHE模块。比如,ECU更换时,需要把旧ECU的密钥迁移到新ECU。

但密钥不能直接明文导出。SHE规范定义了安全导出协议

  • 导出时,密钥会使用目标SHE的公钥进行加密
  • 只有目标SHE才能用自己的私钥解密
  • 传输过程中,密钥始终处于加密状态

嗯,这里要注意:不是所有密钥都允许导出。密钥槽的标志位里有一个“可导出”位。如果这个位被置0,那这个密钥就永远锁死在当前芯片里了。我个人建议,对于安全启动密钥、主密钥这类关键密钥,一律设置为不可导出。

最佳实践:只有那些需要在产线或者售后环节进行密钥分发的密钥,才设置为可导出。其他密钥,尤其是用于安全启动和固件加密的密钥,务必设置为不可导出。

4.6 实战中的坑与避坑指南

讲了这么多理论,最后分享几个我在实际项目中踩过的坑:

  • 坑一:NVM写入时序——SHE的NVM写入需要一定时间(通常是几毫秒到几十毫秒)。如果在写入过程中掉电,密钥可能只写了一半。我现在的做法是:写入前先备份,写入后做CRC校验,校验失败就回滚。
  • 坑二:密钥槽冲突——多个安全服务可能使用同一个密钥槽。比如,CAN加密和UDS安全访问都用密钥槽1,结果一改全改。建议每个安全服务使用独立的密钥槽,做好文档记录。
  • 坑三:产线密钥注入——产线上批量烧录密钥时,一定要做唯一性校验。我曾经遇到过产线脚本写错了,1000颗芯片烧了同一个密钥。那批产品后来全部召回重做。

好了,关于SHE内部NVM的密钥存储机制,咱们就聊到这里。下一章我会讲密钥派生和会话密钥的生成,那部分更有意思——你想想看,怎么用一颗主密钥派生出成千上万颗会话密钥,还不降低安全性?到时候见。