4. 安全启动数据库:PK、KEK、db、dbx

好,咱们进入安全启动最核心的部分——四个数据库。说白了,UEFI 安全启动的整个信任链,就是靠这四个数据库撑起来的。我刚开始接触时也觉得绕,但只要你理解了它们各自管什么、谁签谁,其实没那么复杂。

4.1 四个数据库的定位

先给个总览。安全启动有四个关键数据库:

  • PK(Platform Key,平台密钥)——最高权限,所有者凭证
  • KEK(Key Exchange Key,密钥交换密钥)——中间人,负责更新 db/dbx
  • db(Allowed Database,允许数据库)——白名单,存受信任的证书或哈希
  • dbx(Forbidden Database,禁止数据库)——黑名单,存被吊销的证书或哈希

它们的层级关系,我画了张图,你看一眼就明白了。

安全启动数据库层级结构 PK(平台密钥) 最高权限,所有者凭证 KEK(密钥交换密钥) 中间人,授权更新 db(允许数据库) 白名单:受信任证书/哈希 dbx(禁止数据库) 黑名单:吊销证书/哈希 签名授权 签名更新 签名更新 关键规则: • PK 签名 KEK,KEK 签名 db/dbx 的更新 • 启动时:镜像签名必须匹配 db 且不在 dbx 中 • 只有 PK 的所有者才能更换 PK 本身

4.2 PK(平台密钥)—— 最高统治者

PK 是整个安全启动的根信任。谁持有 PK 的私钥,谁就是这台机器的真正主人。我见过不少厂商把 PK 私钥锁在硬件安全模块里,每次签名都要走审批流程,就是这个原因。

PK 的核心职责:

  • 签名新的 KEK
  • 更换 PK 自身(必须用旧 PK 签名新 PK)
  • 关闭安全启动(用 PK 签名一个空更新)
⚠ 我曾经踩过的坑: 有次测试时,我把 PK 私钥放在一个共享文件夹里,结果被同事误删了。之后想更新 KEK 发现签不了名,整台机器变砖。所以——PK 私钥必须离线保管,最好用硬件令牌。

4.3 KEK(密钥交换密钥)—— 授权代理人

KEK 的作用,说白了就是「PK 太金贵了,日常更新 db 这种小事别烦它」。PK 把更新 db/dbx 的权力委托给 KEK,KEK 就可以签名这些更新请求。

一台机器可以有多个 KEK。比如:

  • 微软的 KEK(Windows 更新 db 用)
  • OEM 自己的 KEK(厂商更新硬件驱动签名用)
  • 企业 IT 部门的 KEK(管控公司设备用)

我个人习惯是,在量产阶段只保留必要的 KEK,多余的都删掉。你想想看,多一个 KEK 就多一个攻击面,没必要。

4.4 db(允许数据库)—— 白名单

db 里存的是「可以运行」的东西。可以是:

  • X.509 证书(信任该证书签名的所有镜像)
  • 镜像的 SHA-256 哈希(只信任这一个具体文件)
  • EFI 镜像的签名数据库条目

启动时,UEFI 固件会做这么几步:

  1. 提取镜像的签名
  2. 检查签名是否在 db 中有匹配的证书
  3. 检查该签名是否在 dbx 中被吊销
  4. 如果 db 匹配且 dbx 未命中,放行
💡 小技巧: 如果你只想让某个特定版本的引导加载器运行,用哈希条目比用证书更安全。因为证书一旦泄露,攻击者可以用它签名恶意代码。哈希只认这一个文件,更精准。

4.5 dbx(禁止数据库)—— 黑名单

dbx 就是吊销列表。当发现某个证书或哈希有问题时,把它加进 dbx,固件就会拒绝加载对应的镜像。

实际场景:

  • 某个 bootkit 利用了旧版 GRUB 的漏洞,微软发布 dbx 更新吊销那个 GRUB 的签名
  • 厂商的签名证书被泄露,紧急吊销该证书
  • 某个测试用的调试证书被误用,加入 dbx 封禁

我记得有一次,客户发现某款网卡的 Option ROM 签名证书过期了,但固件没吊销。结果那批机器在启动时总是卡在 PXE 阶段。最后我们通过 dbx 更新把那个过期证书封掉,问题才解决。

4.6 四个数据库的关系总结

用一张表来对比,更清楚:

数据库 谁签名更新 存储内容 能否被替换 典型数量
PK 自身(旧 PK 签新 PK) 1 个 X.509 证书 只能由自身替换 1 个
KEK PK 多个 X.509 证书 由 PK 签名更新 1~3 个
db KEK 证书 / 哈希 / 签名条目 由 KEK 签名更新 几十到几百个
dbx KEK 证书 / 哈希 / 签名条目 由 KEK 签名更新 几十到几百个

嗯,这里要注意一点:db 和 dbx 的条目可以很多,但 PK 和 KEK 一般就几个。因为 PK 和 KEK 是「授权者」,db/dbx 是「被授权的内容」。授权链条越短越安全。

4.7 实际部署时的建议

基于我这些年做安全启动集成的经验,给你几个实操建议:

  • PK 私钥永远不要出现在生产环境。只在离线机器上签名,签完就锁起来。
  • KEK 可以多备几个。万一主 KEK 出问题,还有备用的能更新 db。
  • db 里不要放通配证书。比如有些厂商图省事,放一个「信任所有微软签名」的证书,结果第三方恶意驱动也能过。尽量精确到具体证书。
  • dbx 要定期更新。安全漏洞是不断发现的,固件厂商会发布 dbx 更新,别忽略。

一句话总结: PK 是根,KEK 是枝,db 是叶,dbx 是毒叶。根不动,枝授权,叶生长,毒叶摘掉。整个安全启动的信任链就是这么简单。