17 UEFI(统一可扩展固件接口) #
UEFI(统一可扩展固件接口)是用于系统硬件自带的固件、系统所有的硬件组件以及操作系统之间的接口。
UEFI 在 PC 系统上的应用范围越来越广,因此正在逐渐替代传统的 PC-BIOS。例如,UEFI 能够很好地支持 64 位系统,提供安全的引导(“安全引导”,要求固件为 2.3.1c 或以上版本)。安全引导是其最为重要的特性之一。最后,借助 UEFI,标准固件将能够用于所有 x86 平台。
除此之外,UEFI 还具有以下优点:
从带有 GUID 分区表 (GPT) 的大磁盘(超过 2 TiB)引导。
独立于 CPU 的架构和驱动程序。
带有网络功能的灵活的预操作系统环境。
通过 PC-BIOS 式仿真支持引导老式操作系统的 CSM(兼容支持模块)。
有关详细信息,请参见https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface。以下小节并不是 UEFI 的整体概述,仅提供如何在 SUSE Linux Enterprise Desktop 实现特定功能的提示。
17.1 安全引导 #
在 UEFI 领域中,要想保障引导程序的安全,需要建立一个信任链。“平台”是此信任链的根;在 SUSE Linux Enterprise Desktop 环境中,可将主板和板载固件视为“平台”。换句话说,它就是硬件供应商,而信任链则从硬件供应商流向组件制造商、OS 供应商等。
系统通过公共密钥加密法表示信任。硬件供应商将所谓的“平台密钥 (PK)”放入固件中,代表可信根。操作系统供应商与其他方将其密钥与“平台密钥”签署在一起,以此记录他们之间的信任关系。
最后,通过要求固件不得执行任何代码(除非使用其中某个“可信”密钥签署了代码)来建立安全保障。这些代码可能是操作系统引导加载程序、位于特定 PCI Express 卡闪存中或磁盘上的驱动程序,也可能是固件本身的更新。
要使用安全引导,您需要用固件信任的密钥对您的 OS 加载程序签名,并且需要 OS 加载程序校验其加载的内核是否可信。
可以将密钥交换密钥 (KEK) 添加到 UEFI 密钥数据库中。这样,您便可以使用其他证书,只要这些证书是以 PK 的私用部分签署的即可。
17.1.1 在 SUSE Linux Enterprise Desktop 上实施 #
默认情况下安装微软的密钥交换密钥 (KEK)。
UEFI/x86_64 安装中默认会启用安全引导功能。您可在
对话框的 选项卡中找到 选项。该选项支持在固件中的安全引导已激活时引导,同时也支持在安全引导已停用时引导。“安全引导”特性要求 GUID 分区表 (GPT) 使用主引导记录 (MBR) 替代旧的分区。如果安装期间 YaST 检测到 EFI 模式,则会设法创建 GPT 分区。UEFI 预期会在 FAT 格式的 EFI 系统分区(ESP) 上查找到 EFI 程序。
要支持 UEFI 安全引导,需要有引导加载程序,且固件认可其数字签名是可信密钥。该密钥需要先天为固件所信任(无需任何手动干预)。
有两种办法可以实现。一种是与硬件供应商合作,让其签署 SUSE 密钥,然后 SUSE 会使用该 SUSE 密钥签署引导加载程序;另一种是通过微软的 Windows 徽标认证计划使引导加载程序获得认证,并使微软认可 SUSE 签名密钥(也就是让加载程序使用他们的 KEK 签名)。至此,SUSE 使引导加载程序获得了 UEFI 签名服务(在此情况下为 Microsoft)的签名。
SUSE 在实施层使用默认将会安装的 shim
加载程序。这是一种可以避免法律纠纷的智能解决方案,能够大幅简化认证和签名步骤。shim
加载程序的任务是加载 GRUB 2 等引导加载程序并对其进行校验,之后,此引导加载程序将仅加载 SUSE 密钥签名的内核。
可信用户分为以下两类:
首先是持有密钥的用户。平台密钥 (PK) 几乎允许所有操作。密钥交换密钥 (KEK) 的许可范围与 PK 一致,但不能更改 PK。
其次是能够以物理方式访问机器的任何用户。具有物理访问权限的用户可以重引导机器并对 UEFI 进行配置。
UEFI 提供下列两类变量以满足这些用户的需求:
第一类变量即所谓的“已验证的变量”,它们可从引导过程(所谓的“引导服务环境”)和正在运行的操作系统中更新。仅当对变量新值签名的密钥是用于对变量旧值签名的相同密钥时,才能进行更新。而且,您只能向这类变量追加或将其更改为序列号更高的数值。
第二类变量即所谓的“仅供引导服务使用的变量”。引导进程中运行的任何代码都可以获取这些变量。在引导过程结束后操作系统启动前,引导加载程序必须调用
ExitBootServices
呼叫。此后将无法获取这些变量,OS 也无法接触到这些变量。
UEFI 密钥列表属于第一类,因为该类变量除了允许联机更新外,还允许添加密钥、驱动程序、固件指纹以及将它们列入黑名单。第二类变量即“仅供引导服务使用的变量”。该类变量有助于以安全且支持开源的方式实施安全引导,因此符合 GPLv3 要求。
SUSE 首先启动 shim
,它是一个小而简单的 EFI 引导加载程序,由 SUSE 和 Microsoft 签名。
这样一来,shim
即可加载并执行。
shim
随后继续验证其想要加载的引导加载程序是否可信。默认情况下,shim
会使用其主体中所嵌入的独立的 SUSE 证书。此外,shim
还允许“登记”其他密钥,用于覆盖默认的 SUSE 密钥。下文将这些密钥称为“机器拥有者密钥”或缩写为 MOK。
接下来,引导加载程序会验证内核,然后加以引导。该内核将在模块上执行同样的操作。
17.1.2 MOK(机器拥有者密钥) #
要替换特定内核、驱动程序或引导过程中的其他组件,需要使用机器拥有者密钥 (MOK)。mokutil
工具可帮助您管理 MOK。
您可以使用 mokutil
创建 MOK 登记请求。该请求存储在名为 MokNew
的 UEFI 运行时 (RT) 变量中。在下次引导期间,shim
引导加载程序会检测 MokNew
并加载 MokManager
,这将为您提供几个选项。您可以使用 和 选项来将密钥添加到 MokList。使用 选项可从 MokNew
变量复制密钥。
通常,当 shim 无法加载 grub2
并改为加载 MokManager 时,会从磁盘登记密钥。由于 MokNew
尚不存在,您可以选择在 UEFI 分区上查找密钥。
17.1.3 引导自定义内核 #
以下内容基于 https://en.opensuse.org/openSUSE:UEFI#Booting_a_custom_kernel。
安全引导不会阻止您使用自行编译的内核。您必须使用自己的证书在该内核上签名,并让固件或 MOK 得以识别该证书。
创建一个自定义的 X.509 密钥以及用于签名的证书:
openssl req -new -x509 -newkey rsa:2048 -keyout key.asc \ -out cert.pem -nodes -days 666 -subj "/CN=$USER/"
有关创建证书的详细信息,请参见 https://en.opensuse.org/openSUSE:UEFI_Image_File_Sign_Tools#Create_Your_Own_Certificate。
将密钥和证书打包成 PKCS#12 结构:
>
openssl pkcs12 -export -inkey key.asc -in cert.pem \ -name kernel_cert -out cert.p12生成用于
pesign
的 NSS 数据库:>
certutil -d . -N将 PKCS#12 中包含的密钥和证书导入 NSS 数据库:
>
pk12util -d . -i cert.p12使用
pesign
将新签名“赋予”内核:>
pesign -n . -c kernel_cert -i arch/x86/boot/bzImage \ -o vmlinuz.signed -s列出内核映像上的签名:
>
pesign -n . -S -i vmlinuz.signed此时,您可以照常在
/boot
中安装内核。由于内核现有一个自定义的签名,因此需要将用于签名的证书导入 UEFI 固件或 MOK 中。将证书转为 DER 格式,以供导入固件或 MOK:
>
openssl x509 -in cert.pem -outform der -out cert.der将证书复制到 ESP 以简化访问:
>
sudo
cp cert.der /boot/efi/使用
mokutil
自动启动 MOK 列表。将证书导入到 MOK 中:
>
mokutil --root-pw --import cert.der--root-pw
选项可直接允许使用root
用户。检查准备注册的证书列表:
>
mokutil --list-new重引导系统;
shim
应该会启动 MokManager。您需要输入root
口令以确认将证书导入到 MOK 列表中。检查新导入的密钥以前是否注册过:
>
mokutil --list-enrolled
此外,也可以采用如下方式手动启动 MOK:
重引导
在 GRUB 2 菜单中,按
c
键。类型:
chainloader $efibootdir/MokManager.efi boot
选择
。导航至
cert.der
文件并按 Enter。按照说明登记密钥。正常情况下应按“0”,然后按“y”确认。
除此之外,固件菜单也可能提供了多种向“签名数据库”中添加新密钥的方式。
17.1.4 使用非内置驱动程序 #
在启用安全引导的情况下,不支持在安装过程中添加非内置驱动程序(即,不是 SUSE Linux Enterprise Desktop 自带的驱动程序)。用于 SolidDriver/PLDP 的签名密钥默认不受信任。
您可以通过两种不同的方式,在启用安全引导的情况下于安装期间安装第三方驱动程序。在这两种情况下,都要:
在安装前,通过固件或系统管理工具将所需密钥添加到固件数据库中。此选项取决于您当前使用的具体硬件。请咨询您的硬件供应商了解详细信息。
使用 https://drivers.suse.com/ 上或硬件供应商提供的可引导驱动程序 ISO,在首次引导时将所需密钥登记到 MOK 列表中。
要使用可引导驱动程序 ISO 将驱动程序密钥登记到 MOK 列表中,请执行以下步骤:
将上文所述 ISO 映像刻录到空 CD/DVD 媒体中。
使用新的 CD/DVD 媒体开始安装,并准备好标准的安装媒体或网络安装服务器的 URL。
如果您要进行网络安装,请在引导命令行上使用
install=
选项输入网络安装源的 URL。如果您是从光学媒体安装,安装程序会先从驱动程序包引导,然后要求插入产品的第一张安装光盘。
安装时将会使用包含经过更新的驱动程序的 initrd。
有关详细信息,请参见https://drivers.suse.com/doc/Usage/Secure_Boot_Certificate.html。
17.1.5 功能和限制 #
以安全引导模式引导时,可以使用以下功能:
安装到 UEFI 默认的引导加载程序位置,这是为了保留或恢复 EFI 引导项而采用的机制。
通过 UEFI 重引导。
如果没有其他可回退到的旧版 BIOS,Xen 超级管理程序将使用 UEFI 引导。
支持 UEFI IPv6 PXE 引导。
支持 UEFI 视频模式,内核可以从 UEFI 检索视频模式,以使用相同的参数配置 KMS 模式。
UEFI 支持从 USB 设备引导。
从 SUSE Linux Enterprise Server 15 SP3 开始,在安全引导模式下支持 Kexec 和 Kdump。
以安全引导模式引导时,存在以下限制:
为了确保无法轻易绕过安全引导,系统在安全引导模式下运行时会禁用特定内核功能。
引导加载程序、内核以及内核模块必须经过签名。
休眠(挂起到磁盘)处于禁用状态。
无法访问
/dev/kmem
和/dev/mem
,root 用户也不例外。无法访问 I/O 端口,连 root 用户也不例外。所有 X11 图形驱动程序必须使用内核驱动程序。
无法通过 sysfs 访问 PCI BAR。
无法使用 ACPI 中的
custom_method
。无法使用 asus-wmi 模块的 debugfs。
acpi_rsdp
参数对内核没有任何影响。
17.2 更多信息 #
https://uefi.org — UEFI 主页,其中列出了最新的 UEFI 规范。
由 Olaf Kirch 与 Vojtěch Pavlík 撰写的博文(上述章节内容主要取材于这些博文):
https://en.opensuse.org/openSUSE:UEFI — UEFI 与 openSUSE。