信任链验证流程 (The Chain of Trust)
整个过程就像一场严格的接力赛,每一棒都必须从可信的上一位手中接过接力棒(信任),验证无误后,再跑自己的那段路,并把信任传递给下一棒
现在,我们来详细解读图中的每一步:
第 1 棒:硬件信任根 → Bootloader
- 运动员(验证者): 芯片内置的只读存储器(ROM)代码。这是“发令员”,绝对可信
- 接力棒(被验证对象): 第一阶段 Bootloader(例如
XBL
或ABL
) - 验证规则:
① ROM 代码从硬件信任根(eFuse) 中读取预先烧录好的、OEM公钥的正确哈希值
② ROM 代码从 Bootloader 镜像中提取出“候选”的OEM公钥
③ ROM 代码计算这个“候选”公钥的哈希值,并与 eFuse 中的正确哈希值进行比对
④ 如果匹配,说明这个公钥是合法的。ROM 代码随后用这个合法的公钥去验证 Bootloader 镜像本身的数字签名
⑤ 签名验证通过,ROM 代码才将执行权交给 Bootloader。至此,Bootloader 成为了一个“可信实体”
第 2 棒:Bootloader → vbmeta.img
- 运动员(验证者): 刚刚被验证为可信的 Bootloader
- 接力棒(被验证对象):
vbmeta.img
镜像 - 验证规则:
① Bootloader 从闪存上的vbmeta
分区中加载vbmeta.img
到内存
② Bootloader 使用其内置的、刚刚被验证为合法的 OEM公钥,去解密vbmeta.img
末尾的加密签名,得到一个“声称的哈希值(A)”
③ Bootloader 再自己对vbmeta.img
的实际内容计算出一个“计算出的哈希值(B)”
④ 对比 A 和 B。如果 A == B,证明vbmeta.img
确实来自OEM且未被篡改。Bootloader 现在信任vbmeta.img
里的所有内容
第 3 棒:vbmeta.img → 其他分区(boot, system, vendor)
- 运动员(验证者): 内核(借助
vbmeta.img
提供的规则) - 接力棒(被验证对象):
boot.img
,system.img
,vendor.img
等 - 验证规则:
○ 对于 boot.img: Bootloader 直接读取vbmeta.img
中关于boot
分区的哈希描述符。它计算boot
分区的实际哈希值,与描述符中的值比对。匹配则加载内核
○ 对于 system.img/vendor.img:
① Bootloader 将控制权移交给已被验证的 Linux 内核
② 内核启动后,会读取vbmeta.img
中关于system
和vendor
分区的哈希树描述符,获取到受信任的根哈希
③ 内核利用dm-verity
驱动,使用这个根哈希来实时验证system
分区中的每一个数据块(4KB)。vendor
分区同理
④ 任何对数据的篡改都会导致读取失败,从而保护系统的完整性
为什么这种设计很优秀?
- 解耦 (Decoupling): Bootloader 不需要知道如何验证每一个具体分区,它只需要信任并验证
vbmeta.img
即可。分区验证策略(用哈希还是用哈希树)的变更不需要修改 Bootloader 代码 - 灵活性 (Flexibility): 通过
vbmeta.img
可以轻松支持新的分区(如product
,system_ext
),只需将其描述符加入即可 - 分权治理 (Delegation): 通过链式描述符,可以将不同分区的验证权委托给不同的实体(例如 Google 验证
system
,OEM 验证vendor
),实现了复杂的供应链安全模型