Manually Self-Signing a Kernel Module on RHEL with Secure Boot Enabled
This document describes how to self-sign a third-party kernel module on RHEL 9 so it can be loaded when Secure Boot is enabled.
Scope:
Applies to any out-of-tree / third-party kernel module (
.ko).Does not cover how to build or install the module itself — only how to sign and load it with Secure Boot enabled.
0. Preconditions
RHEL 9.x with Secure Boot enabled
The kernel module is already built for the running kernel and installed somewhere under:
/lib/modules/$(uname -r)/...
or you know the full path to the.kofile.
Root access and ability to:
Reboot the system
Interact with the MOK Manager screen at boot
Install required packages:
sudo dnf install -y \
mokutil \
openssl \
"kernel-devel-$(uname -r)" \
"kernel-headers-$(uname -r)"1. Confirm the kernel module exists
Replace <module_name> with the module you want to sign (for example, mydriver):
sudo -i
modinfo <module_name> || echo "module not found"
If
modinfoprints metadata, the module is present and associated with the running kernel.If you see "module not found", make sure:
The module has been built for
$(uname -r)It is installed under
/lib/modules/$(uname -r)/...
You can also locate the .ko path directly:
modinfo -n <module_name>
This will print something like:
/lib/modules/$(uname -r)/extra/<module_name>.ko2. Generate a local MOK key pair
Create a directory for your local signing key (example path):
mkdir -p /root/module-mok
cd /root/module-mok
Generate a self-signed certificate and private key:
openssl req -new -x509 -newkey rsa:2048 \
-keyout MOK.priv -out MOK.pem \
-nodes -days 3650 \
-subj "/CN=Local Secure Boot Module Key/"
Secure the private key:
chmod 600 /root/module-mok/MOK.priv
What this does
Creates:
MOK.priv→ private key (used to sign modules)MOK.pem→ public certificate (to be enrolled via MOK)
This key pair is local to this system (or systems where you choose to copy it) and can be reused to sign multiple modules.
3. Convert PEM to DER and import via MOK
mokutil expects a certificate in DER format.
cd /root/module-mok
openssl x509 -in MOK.pem -inform PEM -outform DER -out MOK.der
mokutil --import /root/module-mok/MOK.der
You will be prompted to:
Set a password (twice).
This is not your root password.
It’s a one-time password you will type in the MOK Manager screen during the next boot to confirm the key enrollment.
Confirm the key is queued for enrollment:
mokutil --list-new
You should see an entry with:
Subject: CN=Local Secure Boot Module Key
4. Enroll the key in MOK Manager (boot-time)
Reboot:
reboot
During the next boot, you will see the blue MOK Manager screen.
Follow these steps:
Select Enroll MOK
(Optional) View key 0 to confirm the CN (you should see something like
Local Secure Boot Module Key)Select Continue
Select Yes to enroll the key
Enter the password you set when you ran
mokutil --importConfirm and let the system reboot again
After the system boots back into RHEL, verify the key is enrolled:
mokutil --list-enrolled | grep "Local Secure Boot Module Key"
You should see:
Issuer: CN=Local Secure Boot Module KeySubject: CN=Local Secure Boot Module Key
5. Sign the kernel module
Get the full path to the module:
sudo -i MOD=$(modinfo -n <module_name>) echo "$MOD"This should be something like:
/lib/modules/5.14.0-.../extra/<module_name>.koSet helper variables:
KDIR=/usr/src/kernels/$(uname -r) KEYDIR=/root/module-mokSign the module using the kernel’s
sign-filescript:"$KDIR"/scripts/sign-file sha256 \ "$KEYDIR"/MOK.priv \ "$KEYDIR"/MOK.pem \ "$MOD"Verify that the signature was applied:
modinfo "$MOD" | egrep 'signer|sig_key|sig_hashalgo'You should see output similar to:
signer: Local Secure Boot Module Key sig_key: <some fingerprint> sig_hashalgo: sha256
6. Load the module and verify Secure Boot acceptance
Reload module dependencies and load the module:
depmod -a
modprobe <module_name>
If Secure Boot accepts the signature,
modprobeshould return with no error.You should not see:
Key was rejected by service
Confirm the module is loaded:
lsmod | grep <module_name>
You should see a line containing <module_name> if it’s loaded.
If there is an issue, check the kernel log:
dmesg | tail -n 50
Look for messages related to module signing or Secure Boot.
Notes about kernel updates
When the kernel is updated:
Out-of-tree modules may need to be:
Rebuilt for the new kernel version
Re-signed using the same
MOK.priv/MOK.pemkey pair
General pattern after a kernel update:
# After installing and booting into the new kernel:
uname -r # confirm new kernel
modinfo <module_name> # ensure it's built for this kernel
MOD=$(modinfo -n <module_name>) # get new .ko path
KDIR=/usr/src/kernels/$(uname -r)
KEYDIR=/root/module-mok
"$KDIR"/scripts/sign-file sha256 \
"$KEYDIR"/MOK.priv \
"$KEYDIR"/MOK.pem \
"$MOD"
depmod -a
modprobe <module_name>
The MOK enrollment is persistent. You normally only generate/import/enroll the key once; future kernels just require rebuilding and re-signing modules with the same key.
Comments
Post a Comment