Security Boot
机制是UEFI
的一个特性,用于确保固件所加载的代码是可信的。它通过将可信根
存放在固件中,在加载阶段校验所加载的二进制可信。当前实现主要是基于X.509
证书的公私钥体系。固件使用可信的公钥来校验所加载的bootloader
, bootloader
再来校验内核或者第二阶段的bootloader
, 内核校验所加载的内核模块,这样一级级完成校验。
在开启了Security Boot
机制的CentOS8上,加载我们未签名的内核模块会失败:
1 | [root@localhost virtualdev]# insmod ./virtualdev.ko |
接下来我们来通过签名我们的内核模块完成加载。要签名和校验我们的内核模块,我们需要一对公钥私钥。私钥用于签名,公钥需要加载到系统固件的MOK: Machine Owner Key
列表中用于校验被签名的模块。
如果本身已经具备了公私密钥对,以下生成密钥对的步骤可以跳过。
首先,创建密钥对配置文件keypair.conf
,按需要填充相应信息:
1 | [ req ] |
调用openssl
生成密钥对:
1 | openssl req -x509 -new -nodes -utf8 -sha256 -days 36500 \ |
公钥为flygoast.der
文件, 私钥为flygoast.priv
文件。注意:私钥文件一定要注意安全保存。
接下来需要将公钥注册到目标系统的MOK
中。
首先,使用mokutil
创建一个MOK
导入请求, 这会要求输入和确认一个密码,后续步骤会需要这个密码:
1 | mokutil --import flygoast.der |
这时可以查看将要注册的密钥:
1 | [root@localhost sign]# mokutil --list-new |
注册请求创建完成需要重启目标系统。在重启时shim.efi
发现有注册请求,加载MokManager.efi
去通过UEFI
console
界面完成注册操作。
重启后系统会进入MokManager
的界面, 如图:
选择Enroll MOK
, 进入Enroll MOK
界面:
然后选择View Key 0
,确认该Key是你所指定的Key, 然后回到上一界面选择continue
:
接着选择Yes
确认注册该Key, 此时会要求输入之前创建注册请求时所登记的密码:
接着选择Reboot
:
重启后,我们登录目标系统。接下来完成签名。
内核自带了工具sign-file
用于签名内核模块:
1 | /usr/src/kernels/$(uname -r)/scripts/sign-file sha256 flygoast.priv flygoast.der virtualdev.ko |
签名完成后查看模块信息, 可以看到签名相关信息:
1 | [root@localhost sign]# modinfo ./virtualdev.ko |
这时我们再次加载内核模块, 可以加载成功:
1 | [root@localhost sign]# insmod ./virtualdev.ko |
参考链接:
- https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_monitoring_and_updating_the_kernel/signing-kernel-modules-for-secure-boot_managing-monitoring-and-updating-the-kernel
- https://gloveboxes.github.io/Ubuntu-for-Azure-Developers/docs/signing-kernel-for-secure-boot.html