【技术】让人头疼的Linux3.7+内核签名机制

最近测试Linux操作系统的模块编程中发现一个问题,当我编写好一个内核模块时,通过insmod命令,命令行返回一个错误:

sudo sinsmod hello.ko
<< insmod: ERROR: could not insert module hello.ko: Required key not available

查阅资料后发现,Linux内核在3.7以后的版本增加了签名机制,并且UEFI启动的电脑需要校验UEFI Secure Key签名。

执行下面的命令:

grep "CONFIG_MODULE_SIG" /boot/config-`uname -r`

可以看到:

CONFIG_MODULE_SIG=y
# CONFIG_MODULE_SIG_FORCE is not set
CONFIG_MODULE_SIG_ALL=y
CONFIG_MODULE_SIG_UEFI=y
# CONFIG_MODULE_SIG_SHA1 is not set
# CONFIG_MODULE_SIG_SHA224 is not set
# CONFIG_MODULE_SIG_SHA256 is not set
# CONFIG_MODULE_SIG_SHA384 is not set
CONFIG_MODULE_SIG_SHA512=y
CONFIG_MODULE_SIG_HASH="sha512"
CONFIG_MODULE_SIG_KEY="certs/signing_key.pem"

当前内核启动了模块签名,所有模块以及UEFI模块都推荐签名,没有经过签名的模块不允许被载入到内核空间。

一、操作步骤

我们可以通过制作我们的签名来保证我们的模块载入能够正确进行。下面截图是通过命令查找到的系统载入的keyring。

sudo keyctl list %:.system_keyring

《【技术】让人头疼的Linux3.7+内核签名机制》

我们需要用到的工具如下

  • openssl,生成X509公私秘钥对。
  • sign-file,对内核模块使用X509公私秘钥对签名。
  • mokutil,手动注册公钥到系统。
  • keyctl,手动取消注册公钥到系统。

第一步:生成配置文件

cat << EOF > configuration_file.config
[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
prompt = no
string_mask = utf8only
x509_extensions = myexts

[ req_distinguished_name ]
O = Organization
CN = Organization signing key
emailAddress = E-mail address

[ myexts ]
basicConstraints=critical,CA:FALSE
keyUsage=digitalSignature
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid
EOF

第二步:生成公私钥

一般存储在相应内核的源码目录内,不过还是建议存储在~中。

openssl req -x509 -new -nodes -utf8 -sha256 -days 36500 \
-batch -config configuration_file.config -outform DER \
-out public_key.der -keyout private_key.priv

生成的一对秘钥的文件名为public_key.der和private_key.priv。

第三步:导入公钥到系统内核的MOK列表

sudo smokutil --import public_key.der

导入时需要输入密码,请记住这个密码,重启以后需要使用。

重启系统,shim.efi 会发现新添加的 KEY,并会启动 MokManager.efi 模块,此时需要选择 Eroll Key 选项,然后输入上面的密码。

二、其他操作

编译.ko模块之后为文件末尾打上签名戳

sudo cd su/usr/src/kernels/$(uname -r)/scripts/sign-file sha256 private_key.priv public_key.der hello.ko

这里使用了/usr/src/kernels/$(uname -r)/scripts/sign-file脚本,在Ubuntu系统中,地址为:/usr/src/linux-headers-$(uname -r)/scripts/sign-file,请注意不同linux发行版本内核源码地址。

打好签名戳后,可以通过下面的命令在模块的最后看到签名的痕迹:

hexdump -C hello.ko | tail -10

最后开心地加载模块吧~~!

 insmod hello.ko

三、感谢以下网站提供参考学习

https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/System_Administrators_Guide/sect-signing-kernel-modules-for-secure-boot.html

https://jin-yang.github.io/post/kernel-modules.html

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注