1. 信任链的起源:从BIOS到UEFI的演进,为什么需要安全启动?

大家好,我是你们这堂课的主讲人。做了十几年嵌入式安全,我见过太多因为启动环节出问题而翻车的项目。今天咱们聊聊最基础、也最关键的问题:信任链到底从哪开始的?

说白了,一台设备开机,就像一个国家建立政权。第一个执行的代码,就是“开国元勋”。如果这个代码被篡改了,后面的一切都不可信。这就是安全启动要解决的核心问题。

1.1 从BIOS到UEFI:一段不得不说的历史

早年间,PC启动靠的是BIOS(Basic Input/Output System)。这东西诞生于1980年代,那时候互联网还没普及,更没人想到今天会有如此复杂的攻击手段。

BIOS的局限性,我总结了几点:

  • 16位实模式:只能访问1MB内存,启动过程像在螺蛳壳里做道场。
  • 固定入口:CPU复位后直接跳转到0xFFFF0,代码位置写死了。
  • 无签名校验:BIOS固件本身不验证自己的完整性,谁都能改。
  • 扩展困难:想加个新功能?得改主板,厂商不跟你玩。

我记得2010年左右,有个客户的产品在量产阶段发现BIOS被植入了后门。查到最后,是生产线上的一台烧录器被感染了。因为没有签名校验,恶意固件直接写进了Flash。那次教训,让整个团队意识到:启动代码必须被“锁死”。

后来UEFI(统一可扩展固件接口)出现了。它不只是BIOS的升级版,而是一次彻底的革命。

UEFI的核心改进:

  • 支持32位/64位运行模式,直接访问全部内存
  • 模块化设计,驱动可以动态加载
  • 支持网络启动、图形界面
  • 最关键:引入了Secure Boot(安全启动)机制

你想想看,UEFI把启动过程从“黑盒子”变成了“可验证的流水线”。每个模块在加载前都要检查签名,这就为信任链打下了基础。

1.2 为什么需要安全启动?三个真实场景告诉你

有人可能会问:“我用了UEFI,不就安全了吗?” 别急,UEFI只是提供了能力,但安全启动是必须主动开启的。我见过太多设备,UEFI装好了,Secure Boot却关着——等于给黑客留了后门。

场景一:Bootkit攻击

2011年的“Mebromi”病毒,是全球首个针对BIOS的Rootkit。它感染BIOS后,每次开机都先加载恶意代码,杀毒软件根本检测不到。为什么?因为杀毒软件启动时,病毒已经在内存里了。

场景二:供应链污染

我曾经帮一家工控厂商做安全审计。发现他们的设备在运输途中,被中间人替换了UEFI固件。设备到客户手里时,已经带了一个“后门账号”。如果没有安全启动,这种攻击几乎无法防御。

场景三:物理接触攻击

2015年,有研究者演示了通过SPI接口直接改写BIOS芯片的攻击。只要几分钟,就能植入持久化后门。安全启动通过签名验证,让这种物理篡改变得无效——因为改完的固件签名不对,系统拒绝启动。

注意:安全启动不是万能的。它只保证“启动代码是厂商签名的”,但不保证“签名厂商是可信的”。密钥管理是另一个大话题,我们后面会专门讲。

1.3 信任链的起点:硬件根信任

好了,现在我们知道安全启动很重要。但问题来了:第一个执行的代码,谁来验证它?

这就引出了“信任根”(Root of Trust)的概念。简单说,信任链必须有一个不可篡改的起点。这个起点通常是固化在芯片内部的ROM代码,或者是一次性可编程的fuse。

我习惯把信任链比作“接力赛”:

  • 第一棒:硬件信任根(ROM代码)——物理不可篡改
  • 第二棒:Bootloader(引导加载程序)——由ROM验证签名
  • 第三棒:操作系统内核——由Bootloader验证签名
  • 第四棒:系统服务和应用——由内核验证签名

每一棒都验证下一棒的签名,形成一条完整的信任链。只要起点是可信的,链条就不会断。

下面这张图展示了典型的信任链传递过程:

信任链传递流程图 信任链传递流程 硬件信任根 ROM / eFuse 验证签名 Bootloader 引导加载程序 验证签名 OS 内核 操作系统 验证签名 系统服务 应用 说明: 每一级都验证下一级的数字签名。只要信任根是安全的,整个链条就不可被篡改。 常见攻击点与防御 • 物理SPI改写 → 硬件信任根保护(ROM不可写) • Bootloader替换 → 签名验证(公钥固化在ROM) • 内核模块注入 → 内核签名策略(Kernel Lockdown) • 运行时Hook → 可信执行环境(TEE)隔离

1.4 UEFI Secure Boot 到底做了什么?

UEFI Secure Boot 是信任链在PC领域的标准实现。它的核心机制其实不复杂:

  1. 平台密钥(PK):由硬件厂商持有,用于签署KEK
  2. 密钥交换密钥(KEK):用于签署数据库更新
  3. 允许签名数据库(db):存放可信的签名证书
  4. 禁止签名数据库(dbx):存放已知恶意签名的黑名单

启动时,UEFI固件会检查每个可执行文件的签名是否在db中,且不在dbx中。匹配则允许执行,否则拒绝。

一个小技巧:我在调试Secure Boot问题时,经常先检查db和dbx的内容。很多“无法启动”的问题,其实是签名数据库被意外清空了。用 efibootmgr -v 可以查看当前数据库状态。

1.5 嵌入式世界的信任链:比PC更复杂

PC的UEFI Secure Boot已经很成熟了,但嵌入式设备的情况更复杂。我做过不少IoT设备的安全启动方案,发现几个关键差异:

对比项 PC(UEFI) 嵌入式(ARM/RISC-V)
信任根位置 UEFI固件(SPI Flash) 片上ROM(Boot ROM)
密钥存储 UEFI变量(可被OS修改) eFuse / OTP(一次性编程)
启动介质 硬盘/SSD NAND Flash / eMMC / SD卡
安全等级 可选(可关闭) 强制(通常不可关闭)
恢复机制 恢复模式/重置 有限(可能变砖)

举个例子,我在做一款智能门锁时,用的就是ARM Cortex-M系列芯片。它的Boot ROM是出厂固化的,不可更改。我们通过eFuse烧录了公钥哈希,Boot ROM在加载外部Flash中的Bootloader前,先验证签名。如果签名不对,直接死循环——连错误提示都不给。为什么?因为给攻击者任何反馈都是危险的。

避坑指南:我曾经在一个项目里,把公钥直接编译进了Bootloader。结果发现,攻击者可以通过替换Bootloader来绕过签名验证。正确的做法是:公钥必须存储在信任根内部(ROM或eFuse),而不是和待验证的代码放在一起。

1.6 小结:信任链的起点决定了终点

从BIOS到UEFI,从PC到嵌入式,安全启动的核心思想始终没变:建立一个不可篡改的起点,然后一级一级传递信任。

我个人认为,理解信任链的关键不在于记住那些协议细节,而在于建立一种“怀疑一切”的思维模式。每次启动,都要问自己:

  • 这段代码是谁写的?
  • 它被篡改过吗?
  • 谁有权限更新它?
  • 更新过程安全吗?