内核模块验证#

在完成本文档中的步骤之前,请完成为 UEFI 启用安全启动中的步骤。

要启用 Linux 内核模块签名和验证,请使用以下文档

启用内核模块验证#

请确保在内核配置中强制执行内核模块签名检查。

内核配置

描述

为何启用?

CONFIG_MODULE_SIG=y
CONFIG_MODULE_SIG_ALL=y
CONFIG_MODULE_SIG_SHA512=y
CONFIG_MODULE_SIG_HASH=”sha512”
CONFIG_MODULE_SIG_KEY=”certs/signing_key.pem”
启用内核模块签名。每个内核模块都经过数字签名。内核在加载内核模块时检查内核模块签名。
内核模块签名确保在加载内核模块时其完整性和真实性。
强制执行后,内核仅从已知来源加载内核模块,并且仅当其完整性未被破坏时才加载。
CONFIG_MODULE_SIG_FORCE=y
选择内核模块签名验证模式
- off: permissive 模式。
如果模块已签名,则必须具有受信任的签名。如果模块未签名,则可以加载,并且内核被标记为已污染。

- on: restrictive 模式。
只有使用受信任签名签名的模块才能加载。其他模块将生成错误。
有关签名内核模块和保护签名密钥的更多信息,请参阅内核文档
CONFIG_SECURITY_LOCKDOWN_LSM=y
CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y
CONFIG_LOCK_DOWN_IN_SECURE_BOOT=y
强制执行内核锁定。
防止未经授权修改内核镜像,并防止访问位于内核内存中的安全和加密数据。

在主机上安装实用程序#

在开始之前,请确保您的 Ubuntu 主机上安装了以下实用程序

  • openssl

  • device-tree-compiler

  • efitools

  • uuid-runtime

签名和验证内核模块#

为 UEFI 启用安全启动部分中为 UEFI 启用安全启动时,请确保已注册供应商 db 密钥。现在,使用已注册的供应商 db 密钥签名内核模块,并验证安装已签名的内核模块。

  1. 以内核模块 pwm-fan.ko 为例

    1cd /opt
    2sudo cp /usr/lib/modules/5.15.0-1019-nvidia-tegra-igx/kernel/drivers/hwmon/pwm-fan.ko .
    3sudo cp pwm-fan.ko pwm-fan.ko.signed
    
  2. 从 Linux 中移除 pwm-fan.ko

    1lsmod | grep pwm
    2sudo modprobe -r pwm_fan
    3lsmod | grep pwm
    

    确保 pwm_fan 不在输出列表中。

安装未签名的内核模块#

  1. 检查内核模块的签名

    1cd /opt
    2modinfo pwm-fan.ko
    

    内核模块可能由自动生成的内核密钥签名,输出如下

    …
    sig_id:         PKCS#7
    signer:         Build time autogenerated kernel key
    …
    signature: …
    …
    
  2. 移除内核模块的签名

    1sudo strip -g pwm-fan.ko
    2modinfo pwm-fan.ko
    3sudo cp pwm-fan.ko pwm-fan.ko.unsigned
    

    确保输出不包含 <sig_id>、<signer> 和 <signature> 等。

  3. 将未签名的内核模块安装到 Linux

    1sudo insmod pwm-fan.ko
    

    该命令应失败,并显示以下错误日志

    nvidia@localhost:/opt$ sudo insmod pwm-fan.ko
    insmod: ERROR: could not insert module pwm-fan.ko: Operation not permitted
    [  476.015693] Lockdown: insmod: unsigned module loading is restricted; see man kernel_lockdown.7
    

    这意味着未签名的内核模块无法插入到启用安全启动的内核。

签名内核模块#

  1. 提取嵌入 RSA 公钥的供应商拥有的 db 证书到 DER 格式的文件中

    1cd <Your_DIR>/Linux_for_Tegra/uefi_keys
    2
    3# Convert x509 to PEM​
    4openssl x509 -in db_vendor.crt -outform PEM -out db_vendor.pem
    5
    6# Convert PEM to DER
    7openssl x509 -outform der -in db_vendor.pem​ -out db_vendor.der
    
  2. 将未签名的内核模块从 IGX 复制到主机

    1scp /opt/pwm-fan.ko.unsigned <host_name>@<host_ip>:<Your_DIR>/Linux_for_Tegra/uefi_keys
    
  3. 在主机上,使用 kmodsign 和注册的供应商拥有的 db 密钥对签名未签名的内核模块。

    1cd <Your_DIR>/Linux_for_Tegra/uefi_keys
    2
    3# The db_vendor.key is private key, and the db_vendor.crt is
    4# self-signed certificate that contains the RSA public key.
    5kmodsign sha512 db_vendor.key db_vendor.der pwm-fan.ko.unsigned pwm-fan.ko.sign.vendor
    

安装已签名的内核模块#

  1. 将供应商拥有的 db 密钥对签名的内核模块从主机复制到 IGX,并检查签名

    1cd /opt
    2sudo scp <host_name>@<host_ip>:Linux_for_Tegra/uefi_keys/pwm-fan.ko.sign.vendor .
    3sudo cp pwm-fan.ko.sign.vendor pwm-fan.ko
    4modinfo pwm-fan.ko
    

    内核模块由供应商拥有的签名数据库密钥签名,输出应如下所示

    …
    sig_id:         PKCS#7
    signer:         Vendor Owned Signature Database key
    …
    signature:   …
    …
    
  2. 安装由供应商拥有的 db 密钥对签名的内核模块

    1sudo insmod pwm-fan.ko
    2echo $?
    

    该命令应返回 0,这意味着内核模块已成功安装。

  3. 此外,检查内核模块是否在 lsmod 输出列表中

    1lsmod | grep pwm
    

    确保 pwm_fan 在输出列表中

    nvidia@localhost:/opt$ lsmod | grep pwm
    pwm_fan                20480  0
    pwm_tegra_tachometer    20480  0
    

    由供应商拥有的 db 密钥对签名的内核模块已成功插入到 Linux 内核中。