注:
- 此教程需要访问 Oracle Cloud。要注册免费账户,请参阅开始使用 Oracle Cloud Infrastructure 免费层。
- 它使用 Oracle Cloud Infrastructure 身份证明、租户和区间示例值。完成实验室后,请使用特定于您的云环境的这些值替换这些值。
对内核模块进行签名以用于 UEFI 安全引导
本教程介绍了如何对自己的模块进行签名,以便在安装了 Unbreakable Enterprise Kernel 的 Oracle Linux 上使用 UEFI Secure Boot。本教程还说明了如何在 UEK R6U3 之前使用 UEK R6 内核的情况下将您自己的证书添加到内核的可信证书密钥环中;以及如何使用 mokutil 实用程序使用签名证书更新 UEFI 引导 shim。
警告
本教程面向正在执行软件测试的开发人员。请勿对 Oracle 支持的生产系统使用本教程中的过程。
先决条件
- Oracle Linux 系统(Oracle Linux 7 或 Oracle Linux 8)
- 系统正在运行最新的 UEKR6 内核
- 服务器的固件实现和配置支持 MOK 实用程序(有关更多信息,请参见 https://docs.oracle.com/en/learn/mokutil-uefi/)
目标
在本教程结束时,您应该能够完成以下工作:
- 用于 UEFI 安全引导的签名模块
- 将证书添加到内核的可信证书密钥环
- 使用
mokutil实用程序使用签名证书更新 UEFI 引导 shim
安装所需程序包
-
根据 Oracle Linux 系统运行以下命令。
-
Oracle Linux 8
sudo dnf update sudo dnf group install "Development Tools" sudo dnf install kernel-uek kernel-uek-devel keyutils mokutil pesign -
Oracle Linux 7
sudo yum-config-manager --enable ol7_optional_latest sudo yum update sudo yum group install "Development Tools" sudo yum-config-manager --enable ol7_UEKR6 && yum-config-manager --disable ol7_UEKR5
-
-
重新启动系统。
创建示例定制内核模块
为了本教程的目的,我们创建并构建示例定制内核模块。在大多数情况下,模块已由外部供应商提供,因此不需要执行此步骤。此处描述的过程是为了说明目的。
-
创建
~/hello目录。 -
使用以下条目创建文件
~/hello/hello.c:#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("A.Developer"); MODULE_DESCRIPTION("Hello World Linux Kernel Module"); static int __init hello_init(void) { printk(KERN_INFO "Hello world!\n"); return 0; } static void __exit hello_exit(void) { printk(KERN_INFO "Unloading Hello world.\n"); } module_init(hello_init); module_exit(hello_exit); -
使用以下条目创建文件
~/hello/Makefile:obj-m += hello.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean install: cp hello.ko /lib/modules/$(shell uname -r)/extra depmod -
构建然后安装模块。
cd ~/hello make && sudo make install -
测试模块。
sudo modprobe hello modprobe: ERROR: could not insert 'hello': Operation not permitted如果系统在安全引导模式下运行,则
modprobe将失败,因为模块尚未有效。
创建本地证书并对模块签名
-
创建 OpenSSL 配置文件以创建本地签名证书。
类型:
cat >>/tmp/x509.conf <<EOF [ req ] default_bits = 4096 distinguished_name = req_distinguished_name prompt = no string_mask = utf8only x509_extensions = extensions [ req_distinguished_name ] O = Module Signing Example CN = Module Signing Example Key emailAddress = first.last@example.com [ extensions ] basicConstraints=critical,CA:FALSE keyUsage=digitalSignature subjectKeyIdentifier=hash authorityKeyIdentifier=keyid EOF对于 O、CN 和 emailAddress 字段,输入更合适的值。
-
根据新配置生成新的专用 / 公共密钥对。
请注意,证书有效期为 10 年(3,650 天)。
mkdir ~/certs cd ~/certs openssl req -x509 -new -nodes -utf8 -sha512 -days 3650 -batch -config /tmp/x509.conf -outform DER -out pubkey.der -keyout priv.key Generating a RSA private key ........................................................ ............................++++ writing new private key to 'priv.key' ----- -
以 PEM 格式导出证书。
openssl x509 -inform DER -in pubkey.der -out pubkey.pem -
创建 PKCS#12 版本的证书。
在出现提示时指定导出密码。
openssl pkcs12 -export -inkey priv.key -in pubkey.pem -name cert -out cert.p12 Enter Export Password: Verifying - Enter Export Password: -
使用刚生成的密钥对模块签名。
cd ~/certs sudo /usr/src/kernels/$(uname -r)/scripts/sign-file sha512 priv.key pubkey.der /lib/modules/$(uname -r)/extra/hello.ko -
使用
modinfo命令,验证模块是否已使用您创建的密钥进行签名。modinfo hello filename: /lib/modules/5.4.17-2036.103.3.1.el8uek.x86_64/extra/hello.ko description: Hello World Linux Kernel Module author: A.Developer license: GPL srcversion: D51FB4CF0B86314953EE797 depends: retpoline: Y name: hello vermagic: 5.4.17-2036.103.3.1.el8uek.x86_64 SMP mod_unload modversions sig_id: PKCS#7 signer: Module Signing Example Key sig_key: AB:2C:E3:AB:87:D9:9C:6A:31:B8:80:20:D4:92:25:F3:9A:26:DC sig_hashalgo: sha512 signature: 9F:B0:25:CB:14:C1:C7:10:7F:60:1E:E6:66:82:64:58:91:1F:01:A5: D9:03:1B:9C:2D:42:00:45:78:2B:FA:70:F8:C7:3B:1A:A2:42:00:09: 33:E0:81:1D:C6:E6:46:A5:FE:8B:9F:8C:3D:4E:A1:3A:05:52:ED:F6: 25:F9:88:98:D3:70:78:1D:7E:63:F3:73:C8:C8:14:C2:3A:52:B4:8F: ...
将证书添加到内核可信密钥环(UEK R6U2 及更低版本)
注:
如果您运行的是 UEK R6U3 或更高版本,则不需要执行此步骤。UEK R6U3 中的安全引导实现已更新,以允许对使用 MOK 数据库中的密钥进行签名的模块进行模块装入。对于 UEK R6U3 之前的 UEK R6 发行版,仅当与它们签署的密钥位于内核的内置可信密钥环中时,模块才能够装入。
-
创建要与
pesign一起使用的 NSS 数据库。cd ~/certs certutil -d . -N Enter a password which will be used to encrypt your keys. The password should be at least 8 characters long, and should contain at least one non-alphabetic character. Enter new password: Re-enter password: -
将 PCKS#12 密钥添加到数据库。
cd ~/certs pk12util -d . -i cert.p12 Enter Password or Pin for "NSS Certificate DB": Enter password for PKCS12 file: pk12util: PKCS12 IMPORT SUCCESSFUL -
将密钥插入内核的
bzImage中。注:只能向内核添加一个额外的定制证书,因为内核的引导映像的压缩大小无法增加。
cd ~/certs sudo /usr/src/kernels/$(uname -r)/scripts/insert-sys-cert -s /boot/System.map-$(uname -r) -z /boot/vmlinuz-$(uname -r) -c pubkey.der INFO: Executing: gunzip <vmlinux-ceDv0X >vmlinux-rFFumH WARNING: Could not find the symbol table. INFO: sym: system_extra_cert INFO: addr: 0xffffffff828915d6 INFO: size: 8194 INFO: offset: 0x1c915d6 INFO: sym: system_extra_cert_used INFO: addr: 0xffffffff828935d8 INFO: size: 0 INFO: offset: 0x1c935d8 INFO: sym: system_certificate_list_size INFO: addr: 0xffffffff828935e0 INFO: size: 0 INFO: offset: 0x1c935e0 INFO: Inserted the contents of pubkey.der into ffffffff828915d6. INFO: Used 1481 bytes out of 8194 bytes reserved. INFO: Executing: gzip -n -f -9 <vmlinux-rFFumH >vmlinux-5wHA2r -
删除现有的 PE 签名并使用先前创建的 NSS 数据库密码重新签名内核。
cd ~/certs sudo pesign -u 0 -i /boot/vmlinuz-$(uname -r) --remove-signature -o vmlinuz.unsigned sudo pesign -n . -c cert -i vmlinuz.unsigned -o vmlinuz.signed -s Enter Password or PIN for 'NSS Certificate DB": -
将已签名内核复制回
/boot。cd ~/certs sudo cp -bf vmlinuz.signed /boot/vmlinuz-$(uname -r)
将证书注册到 UEFI 安全引导密钥数据库
对于 UEK R6U3 之前的 UEK R6 内核,必须注册用于将内核映像签名到 MOK 数据库的密钥。对于所有其他内核,用于签署模块本身的键将注册到数据库中。如果您使用相同的密钥对模块和内核进行签名,这些密钥可能相同。
注:有关使用
mokutil实用程序的更多信息,请参见 https://docs.oracle.com/learn/mokutil-uefi/。
-
将相应的密钥作为计算机所有者密钥 (Machine Owner Key, MOK) 添加到 UEFI 引导 shim。
mokutil import命令提示您输入需要在下一步中提供的密码。sudo mokutil --import pubkey.der input password: input password again: -
重新启动您的计算机。
重新引导时,UEFI SHIM 应自动启动 MokManager,该 MokManager 用于将 MOK 密钥添加到 UEFI 安全引导密钥数据库。
- 按键以执行 MOK 管理。
确保在 10 秒内按下某个键以中断引导过程以添加 MOK 密钥。 - 选择“注册 MOK”。
- 选择 "View key 0"。
- 验证密钥是否与所需的值匹配。
- 按任意键,然后选择“Continue(继续)”。
- 选择“是”以注册密钥。
- 提供使用 mokutil 导入密钥时使用的密码。
- 选择“reboot(重新引导)”。
- 按键以执行 MOK 管理。
-
验证证书是否已安装在可信密钥环中。
sudo keyctl show %:.builtin_trusted_keys Keyring 892034081 ---lswrv 0 0 keyring: .builtin_trusted_keys 367808024 ---lswrv 0 0 \_ asymmetric: Oracle CA Server: fbcd3d4d950c6b2b0e01f0a146c5a4e3855ae704 230958440 ---lswrv 0 0 \_ asymmetric: Module Signing Example Key: a43b4e638874b0656db2bc26216f56c0ac39f72b 408597579 ---lswrv 0 0 \_ asymmetric: Oracle America, Inc.: Ksplice Kernel Module Signing Key: 09010ebef5545fa7c54b626ef518e077b5b1ee4c 839574974 ---lswrv 0 0 \_ asymmetric: Oracle Linux Kernel Module Signing Key: 2bb352412969a3653f0eb6021763408ebb9bb5ab -
验证模块是否可以成功装入。
sudo modprobe hello lsmod | grep hello hello 16384 0 dmesg | tail -2 [ 108.848848] hello: loading out-of-tree module taints kernel. [ 108.849191] Hello world!
已知问题
Oracle Linux 7 上的以下内核版本在接受新证书时可能出现问题,同时对生成的 vmlinuz 文件保持相同的(或更小的)压缩大小。建议在开始此过程之前更新到最新的可用 UEKR6 发行版。
- 5.4.17-2022.el7uek.x86_64
- 5.4.17-2023.el7uek.x86_64
- 5.4.17-2025.el7uek.x86_64
- 5.4.17-2026.el7uek.x86_64
- 5.4.17-2028.1.el7uek.x86_64
- 5.4.17-2028.el7uek.x86_64
- 5.4.17-2011.3.2.el7uek.x86_64
- 5.4.17-2011.4.0.el7uek.x86_64
- 5.4.17-2013.el7uek.x86_64
- 5.4.17-2016.1.el7uek.x86_64
在 Oracle Linux 8 上,这些内核的等效版本中不会观察到压缩问题。
更多信息
- Oracle Linux:使用 UEFI 安全引导
- Oracle Linux UEFI 安全引导更新通知
- Oracle Linux:管理证书和公钥基础结构
- Oracle Linux 和 Unbrekable Enterprise Kernel (UEK) 发行版
- mokutil(1) 手册页
- pesign(1) 手册页
pesign --help命令
更多学习资源
在 docs.oracle.com/learn 上浏览其他实验室,或者在 Oracle Learning YouTube 渠道上访问更多免费学习内容。此外,访问 education.oracle.com/learning-explorer 以成为 Oracle Learning Explorer。
有关产品文档,请访问 Oracle 帮助中心。
Sign Kernel Modules for Use With UEFI Secure Boot
F55222-01
March 2022
Copyright © 2021, Oracle and/or its affiliates.