3. i.MX安全启动硬件基础
i.MX 系列处理器的安全启动并不是纯软件行为,它依赖一组片上硬件模块协同完成“信任根建立、密钥固化、镜像验签、状态防回滚、时间可信”这几件事。理解这些模块的职责边界与数据通路,是后续配置 HAB/ AHAB、签名镜像、做 OTA 回滚保护的前提。本节围绕 CAAM、SNVS、OCOTP/eFuse、SRTC 四个核心硬件对象,说明它们各自承担什么、彼此如何连接,以及密钥到底“存在哪里、怎么被使用”。
一、四个硬件模块的职责划分
CAAM(Cryptographic Accelerator and Assurance Module)是加解密与认证的运算引擎。它内部包含 Job Ring、DECO、RNG、密钥库(Key Blob/Keystore)等单元,负责 SHA-256/384、AES、RSA/ECC 验签、真随机数生成。安全启动时,Boot ROM 把镜像的签名和公钥交给 CAAM,由 CAAM 完成哈希与签名验证,而不是由 CPU 用软件慢慢算。
OCOTP(On-Chip One-Time Programmable)控制器是访问 eFuse 阵列的接口。eFuse 是物理上一次性可编程的存储单元,烧断后不可恢复。它保存的是“信任根”级别的信息:SRK 公钥哈希、SEC_CONFIG 安全配置、生命周期状态、MAC 地址、以及用于密钥派生的 OTP 密钥(OTPMK)。
SNVS(Secure Non-Volatile Storage)是低功耗安全域,包含非易失存储、单调计数器、防篡改检测和 SRTC。它管理安全状态机(Secure/Non-Secure/Trusted)、零主密钥(ZMK)以及回滚保护所需的单调计数器。
SRTC(Secure Real-Time Counter)是 SNVS 内的安全实时计数器,掉电后由备用电池或超级电容维持走时。它提供单调递增的时间戳,用于证书有效期判断、防回滚和 OTA 版本控制。
二、eFuse 与 OCOTP:信任根的物理落点
eFuse 阵列按 32 位字(word)编址,OCOTP 控制器提供影子寄存器(shadow register)供软件读取。烧写通过 fuse prog 命令或 U-Boot 的 mxc_ocotp 驱动完成。关键字段包括:
- SRK_HASH[0..7]:存放 SRK 公钥的 SHA-256 哈希,共 8 个 word。Boot ROM 用它与 CSF 中携带的公钥比对,确认公钥未被替换。
- SEC_CONFIG[1]:安全配置位。置位后进入安全启动模式,禁止从非签名镜像启动。
- OTPMK[0..7]:零主密钥,用于派生 AES 密钥加密 Key Blob。烧写后不可读,只能由 CAAM 内部使用。
- SRK_REVOKE:密钥吊销位,用于在密钥泄露时作废对应 SRK。
三、CAAM 的密钥使用方式
CAAM 不直接暴露密钥明文。它通过三种机制管理密钥:
- 密钥库(Keystore):CAAM 内部有受保护的密钥存储区,可保存 AES、HMAC 等对称密钥,软件只能通过句柄引用。
- Key Blob:用 OTPMK 派生的密钥加密后的密钥包,可存放在外部 Flash。解密时由 CAAM 用 OTPMK 还原,即使 Flash 被读取也无法解出明文。
- 公钥哈希验证:验签时 CAAM 只接收公钥和签名,内部计算哈希并与 eFuse 中的 SRK_HASH 比对,公钥本身不需要保密。
以 HAB 为例,CSF 中包含 SRK 公钥、签名和证书。Boot ROM 将 CSF 交给 CAAM,CAAM 先算公钥哈希,与 OCOTP 中 SRK_HASH 比对;一致后再用该公钥验证 CSF 签名;通过后才允许执行镜像。整个过程 CPU 只负责搬运数据,不参与密码运算。
四、SNVS 与 SRTC:状态与时间的可信来源
SNVS 的安全状态机决定芯片当前处于哪种安全级别。上电后 Boot ROM 读取 SNVS 状态,若处于 Open 状态则允许非安全启动;若已进入 Secure 状态,则强制验签。SNVS 还维护单调计数器,每次 OTA 升级成功后计数器加一,旧版本镜像因计数器不匹配而被拒绝,从而实现防回滚。
SRTC 是 SNVS 内的秒级计数器,由 SNVS_LPSRTCMR 和 SNVS_LPSRTCLR 两个寄存器组成 64 位值。它需要 VBAT 供电维持走时。在 OTA 场景中,SRTC 用于判断证书是否在有效期内,以及比较固件版本的时间戳。示例:若当前 SRTC 读数为 0x0000_1234_5678,而新固件证书的 notBefore 为 0x0000_1234_0000,则证书有效;若固件时间戳小于已记录的最小版本时间戳,则拒绝升级。
五、密钥存储机制的实际配置示例
以下为 U-Boot 环境下烧写 SRK 哈希与安全配置的典型命令序列(示例参数,实际值需根据 SRK 公钥计算):
# 计算 SRK 公钥哈希(在主机端)
$ srktool --hab_alg sha256 --srhash srk_hash.bin SRK_1_2_3_4.pem
# 在 U-Boot 中烧写 SRK_HASH 到 eFuse word 0~7
=> fuse prog 0 0 0x12345678
=> fuse prog 0 1 0x9abcdef0
...(共 8 个 word)
# 烧写 SEC_CONFIG[1] 进入安全启动
=> fuse prog 0 1 0x00000002
# 烧写 OTPMK(由 NXP 提供的密钥或自生成)
=> fuse prog 1 0 0xdeadbeef
...(共 8 个 word)
# 复位后检查安全状态
=> fuse read 0 1
烧写完成后,Boot ROM 在下次上电时会读取 SEC_CONFIG,若为安全模式则强制验签。此时若镜像未签名或签名不匹配,芯片将停在 ROM 阶段,串口输出 HAB: Image verification failed 或类似错误。
六、模块间的数据流与依赖关系
把上述模块串起来看:eFuse 提供不可篡改的信任根(SRK 哈希、OTPMK、SEC_CONFIG);OCOTP 是访问 eFuse 的窗口;CAAM 是执行验签和密钥派生的引擎;SNVS 管理安全状态和单调计数器;SRTC 提供可信时间。Boot ROM 是调度者,它按固定顺序读取这些硬件资源,完成从信任根到镜像的逐级验证。OTA 升级时,新镜像的签名、版本号和时间戳分别由 CAAM、SNVS 计数器和 SRTC 校验,三者全部通过才允许写入并切换启动分区。
fuse read 确认 SRK_HASH 和 SEC_CONFIG 是否烧写正确,再用 hab_status 查看 CAAM 返回的验签事件,最后检查 SRTC 是否正常走时。多数“验签失败”根因是 eFuse 内容与签名时使用的 SRK 不一致。