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之间的信任关系。我建议你仔细看看,理解了这个流程,安全启动的信任链就基本掌握了。
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里的条目一定要保持唯一性。