How to sign a kernel module for Secure Boot on Debian in 2023
This is a quick guide on how to write a Hello, world kernel module and sign it so that it’s loadable with Secure Boot enabled on Debian.
First, create a working directory, write a simple kernel module named hwkm
(hello world kernel module) and compile it:
$ mkdir ~/src/hwkm && cd ~/src/hwkm
$ echo '#include <linux/module.h>
#include <linux/printk.h>
#include <linux/init.h>
static int __init minit(void) { printk(KERN_INFO "hwkm loaded.\n"); return 0; }
static void __exit mexit(void) { printk(KERN_INFO "hwkm unloaded.\n"); }
module_init(minit);
module_exit(mexit);
MODULE_LICENSE("GPL");' > hwkm.c
$ echo 'obj-m += hwkm.o
PWD := $(CURDIR)
all:
\tmake -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
\tmake -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean' > Makefile
$ sudo apt install linux-headers-$(uname -r)
$ sudo apt install clang
$ make
//...output omitted
make[1]: Leaving directory '/usr/src/linux-headers-6.1.0-6-amd64'
This will give you a binary for the kernel module - hwkm.ko
. If you try to
load it you will see that the kernel rejects it:
$ sudo insmod hwkm.ko
insmod: ERROR: could not insert module hwkm.o: Key was rejected by service
$ sudo dmesg
//...output omitted
[ 4082.598922] Loading of unsigned module is rejected
Why is that? Because major distributions nowadays have Secure Boot enabled by
default and Secure Boot requires kernel modules to be signed in order to be
loaded. The main program in charge of Secure Boot on Debian is shim
, a
first-stage bootloader which ships by default in Debian 11 and is signed by the
Microsoft UEFI CA. shim
checks that the kernel is signed, but also that kernel
modules are signed. In order to sign a kernel module, it is necessary to enroll
a Machine Owner Key. It is possible that shim
already ships with a Machine Owner Key
(check /var/lib/shim-signed/mok/
), but in case not generate one:
$ mkdir ~/mok && cd ~/mok
$ echo 'HOME = .
RANDFILE = $ENV::HOME/.rnd
[ req ]
distinguished_name = req_distinguished_name
x509_extensions = v3
string_mask = utf8only
prompt = no
[ req_distinguished_name ]
countryName = DE
stateOrProvinceName = Berlin
localityName = Berlin
0.organizationName = claudiuvursache
commonName = Custom Machine Owner Key
emailAddress = claudiu@ursache.io
[ v3 ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical,CA:FALSE
extendedKeyUsage = codeSigning
nsComment = "OpenSSL Generated Certificate"' > openssl.cnf
$ openssl req -config ./openssl.cnf \
-new -x509 -newkey rsa:2048 \
-nodes -days 36500 -outform DER \
-keyout "MOK.priv" \
-out "MOK.der"
As soon as you have a key to import, issue an import request for the Machine Owner Key
using mokutil
:
$ man mokutil 2&>1 | grep -A1 NAME | grep -v ^N
mokutil - utility to manipulate machine owner keys
$ sudo mokutil --import MOK.der
input password:
input password again:
Write down the password somewhere. The next step is finalizing the key
enrollment using the UEFI program MokManager, which is part of shim
. A
reboot is required:
$ sudo reboot
After the reboot you will be prompted by MokManager
:
Select Enroll MOK:
Then select Continue:
When asked to enroll the key, select yes:
Enter the password you provided to mokutil
in the previous step:
Finally, reboot:
Now if you check mokutil
, you will see the enrolled key:
$ sudo mokutil -l | grep 'Custom Machine' | grep Subject
Subject: C=DE, ST=Berlin, L=Berlin, O=claudiuvursache, CN=Custom Machine Owner Key/emailAddress=claudiu@ursache.io
And you can use the key to sign the kernel module:
$ /usr/lib/linux-kbuild-$(uname -r | awk -F'.' '{print $1"."$2}')/scripts/sign-file sha256 ~/mok/MOK.priv ~/mok/MOK.der ./hwkm.ko
To confirm that everything worked, load the kernel module, unload it, and then
grep dmesg
for the appropriate log line:
$ sudo insmod hwkm.ko
$ sudo rmmod hwkm.ko
$ sudo dmesg | grep hwkm
[ 408.293551] hwkm: loading out-of-tree module taints kernel.
[ 408.294224] hwkm loaded.
[ 422.427946] hwkm unloaded.
With that, you’ve successfully signed a kernel module on Debian in 2023.
References
https://wiki.debian.org/SecureBoot
https://www.kernel.org/doc/html/v4.15/admin-guide/module-signing.html
https://blog.hansenpartnership.com/adventures-in-microsoft-uefi-signing/
https://docs.oracle.com/cd/F22978_01/tutorial-uefi-secureboot-module/
https://www.rodsbooks.com/efi-bootloaders/secureboot.html#initial_shim
https://www.funtoo.org/UEFI_Secure_Boot_and_SHIM
https://edk2-docs.gitbook.io/understanding-the-uefi-secure-boot-chain/