2、安全启动核心组件解析:PK、KEK、db、dbx

安全启动的信任链,说白了就是一套「谁可以签名、谁可以运行」的规则。这套规则由四个核心数据库来承载:PK、KEK、db、dbx。我刚开始接触UEFI时,总觉得这四个东西长得差不多,容易搞混。后来在项目里被坑过几次,才真正理解了它们各自的分工。

嗯,咱们一个一个来看。

2.1 PK(平台密钥)—— 信任的根

PK是Platform Key的缩写,中文叫平台密钥。它是整个安全启动体系的「最高权限」。你想想看,一台电脑的信任链从哪里开始?就是从PK开始的。

PK的作用很简单:它用来验证KEK的签名。也就是说,只有用PK私钥签过名的KEK,才会被固件信任。PK的公钥存储在固件的NVRAM里,出厂时由OEM写入。

关键点:PK只有一对。一台机器上只能有一个有效的PK。如果你想换PK,必须用旧的PK私钥去签名新的PK证书,然后通过SetVariable更新。

我在项目中遇到过一台设备,PK被意外清空了。结果呢?安全启动直接进入「Setup Mode」,任何人都可以往db里加东西。嗯,这其实是个安全隐患。

2.2 KEK(密钥交换密钥)—— 授权的中间人

KEK全称Key Exchange Key,密钥交换密钥。它的角色是「授权者」。PK授权给KEK,KEK再去授权给db和dbx的更新。

说白了,KEK就是一道中间层。为什么要有这一层?我个人的理解是:为了权限分离。PK的私钥通常被OEM锁在保险柜里,平时根本不动。日常更新db和dbx,用的是KEK的私钥。这样即使KEK泄露,也不会动摇整个信任根。

组件 谁签它 它签谁 数量限制
PK 自签名或OEM KEK 只能1个
KEK PK db、dbx 可以多个
db KEK 引导程序、OS加载器 可以多个
dbx KEK (撤销列表) 可以多个

KEK可以有多把。比如OEM自己留一把,操作系统厂商也有一把。这样Windows更新db时,用微软自己的KEK签名就行,不需要找OEM要PK。

2.3 db(签名数据库)—— 白名单

db就是Signature Database,签名数据库。它是一份「白名单」。里面存的是:

  • 受信任的证书
  • 受信任的镜像哈希值
  • 受信任的文件签名

当固件要启动一个EFI程序或OS加载器时,会拿它的签名去跟db里的条目比对。匹配上了,就放行;匹配不上,就拒绝启动。

db的更新必须由KEK签名。我记得有一次帮客户排查问题,他们的Linux系统启动不了,原因是db里没有shim的证书。后来用KEK签了个更新,把shim证书加进db,问题就解决了。

小技巧:你可以用efi-readvar命令查看当前系统的db内容。在Linux下执行efi-readvar -v db,就能看到所有受信任的证书和哈希。

2.4 dbx(撤销签名数据库)—— 黑名单

dbx是db的「反面」。它是一份黑名单,用来撤销那些已经被发现不安全、或者不再受信任的签名。

举个例子:某个Bootkit病毒拿到了合法的签名,被加入了db。安全厂商发现后,会把这个签名的哈希或者证书指纹加入dbx。这样即使病毒还在db里,也会因为dbx的匹配而被拒绝启动。

dbx的优先级高于db。也就是说:先查dbx,再查db。如果某个镜像同时出现在db和dbx里,dbx胜出,启动被阻止。

警告:dbx更新要非常谨慎。我曾经见过一个案例,有人误把OEM自己的证书加进了dbx,结果所有该OEM签名的驱动都无法加载,机器直接变砖。恢复只能靠物理刷写SPI Flash。

2.5 四者关系全景图

下面这张图展示了PK、KEK、db、dbx之间的信任关系。我建议你仔细看看,理解了这个流程,安全启动的信任链就基本掌握了。

安全启动核心组件信任关系图 安全启动核心组件信任关系 PK(平台密钥) 信任的根,最高权限 KEK(密钥交换密钥) 授权中间人 db(签名数据库) 白名单:允许启动 dbx(撤销数据库) 黑名单:禁止启动 签名授权 签名更新 签名更新 说明: 1. PK 签名授权 KEK,KEK 签名更新 db 和 dbx。 2. 启动时先查 dbx(黑名单),再查 db(白名单)。dbx 优先级高于 db。

2.6 实际操作:查看当前系统的PK/KEK/db/dbx

在Linux系统下,你可以用efi-readvar工具来查看这些数据库的内容。我个人习惯先看PK,确认机器是否处于User Mode。

# 查看PK
efi-readvar -v PK

# 查看KEK
efi-readvar -v KEK

# 查看db
efi-readvar -v db

# 查看dbx
efi-readvar -v dbx

输出结果会显示证书的颁发者、主题、序列号等信息。如果某个数据库为空,说明对应的变量没有被设置。

提示:在Windows下,可以用powershell Get-SecureBootUEFI命令查看安全启动状态。不过Windows不直接暴露PK/KEK/db/dbx的原始内容,需要借助第三方工具如RU.EFI。

2.7 常见误区与避坑

  • 误区一:PK可以有多把。错!PK只能有一把。如果你试图设置第二个PK,固件会拒绝。
  • 误区二:dbx里的条目会永久生效。不一定。dbx可以更新,也可以删除(但需要KEK签名)。不过删除dbx条目风险很高,我一般不推荐。
  • 误区三:KEK和PK可以用同一把。技术上可以,但实践中千万别这么干。我曾经见过一个厂商这么搞,结果KEK泄露后整个信任链都废了。

避坑指南:我曾经在调试一台设备时,发现db里同时存在两个版本相同的证书,只是哈希不同。结果导致签名验证时出现歧义,启动时断时续。后来清理了重复条目才恢复正常。所以,db里的条目一定要保持唯一性。