Skip to content

Instantly share code, notes, and snippets.

@dojoe
Last active October 21, 2024 07:28
Show Gist options
  • Save dojoe/2a9e2dddca982c4f679552fc1ebb18df to your computer and use it in GitHub Desktop.
Save dojoe/2a9e2dddca982c4f679552fc1ebb18df to your computer and use it in GitHub Desktop.
Make DKMS sign kernel modules on installation, with full script support and somewhat distro independent

On systems with UEFI Secure Boot enabled, recent Linux kernels will only load signed modules, so it's about time DKMS grew the capability to sign modules it's building.

These scripts are extended and scriptified variants of https://computerlinguist.org/make-dkms-sign-kernel-modules-for-secure-boot-on-ubuntu-1604.html and https://askubuntu.com/questions/760671/could-not-load-vboxdrv-after-upgrade-to-ubuntu-16-04-and-i-want-to-keep-secur/768310#768310 and add some error checking, a passphrase around your signing key, and support for compressed modules.

dkms-sign-module is a wrapper for the more generic sign-modules which can also be used outside of DKMS.

Installation

  1. Create a directory under /root, say /root/module-signing, put the three scripts below in there and make them executable: chmod u+x one-time-setup sign-modules dkms-sign-module
  2. Run one-time-setup
  3. Reboot your computer to deploy the MOK
  4. For each module you will want to sign via DKMS, create a file /etc/dkms/<module_name>.conf with the following content:
    POST_BUILD=../../../../../../root/module-signing/dkms-sign-module
    
    The awkward relative pathname is important since DKMS prepends its own path to it, so an absolute path will not work.
#!/bin/bash
export PROMPT="Enter Machine Owner Key (MOK) passphrase to sign $module $module_version: "
export KERNELVER=$kernelver
$(dirname $0)/sign-modules ../$kernelver/$arch/module/*.ko*
#!/bin/bash
mydir=$(dirname $0)
echo "I am about to generate the Machine Owner Key (MOK)."
echo "The passphrase you enter for this key will be required every time you want to sign a module."
read -p "Please press Return to go on..."
openssl req -new -x509 -newkey rsa:2048 -keyout $mydir/MOK.priv -outform DER -out $mydir/MOK.der -days 36500 -subj "/CN=$(hostname) module signing key/" || exit 1
echo
echo "Now I will import the generated key into the secure keystore."
echo "The passphrase you will enter is only required once, during the following reboot."
read -p "Please press Return to go on..."
mokutil --import $mydir/MOK.der || exit 1
echo
echo "Please reboot your computer now to complete the enrollment of your new MOK."
echo "This is going to look somewhat similar to https://sourceware.org/systemtap/wiki/SecureBoot"
#!/bin/bash
if [[ -z "$1" ]]; then
echo "Usage: $0 module [module...]"
exit 1
fi
mydir=$(dirname $0)
PROMPT="${PROMPT:-Enter Machine Owner Key (MOK) passphrase: }"
KERNELVER=${KERNELVER:-$(uname -r)}
read_passphrase() {
# We write to /dev/tty to get around DKMS' redirection to /dev/null if it's being run with -q (e.g. during rpm installs)
echo -n "$PROMPT" > /dev/tty
read -s KBUILD_SIGN_PIN < /dev/tty
export KBUILD_SIGN_PIN
echo > /dev/tty
openssl rsa -check -noout -passin env:KBUILD_SIGN_PIN -in $mydir/MOK.priv > /dev/null 2>&1
}
do_sign() {
/lib/modules/$KERNELVER/build/scripts/sign-file sha256 $mydir/MOK.priv $mydir/MOK.der "$1"
}
while ! read_passphrase; do echo "Wrong passphrase, please try again."; done
for module in $@; do
echo "Signing module: $module"
module_basename=${module:0:-3}
module_suffix=${module: -3}
if [[ "$module_suffix" == ".xz" ]]; then
unxz $module
do_sign $module_basename
xz -f $module_basename
elif [[ "$module_suffix" == ".gz" ]]; then
gunzip $module
do_sign $module_basename
gzip -9f $module_basename
else
do_sign $module
fi
done
@xuzhen
Copy link

xuzhen commented Jul 11, 2020

@ajaygaur1984 Run the one-time-setup script to create it.

@ajaygaur1984
Copy link

i have run the one-time-setup script, its created MOK.priv but need to enter the PEM pass phrase, how could i find it, if could help
total 12
-rwxr--r-- 1 root root 191 Jul 11 09:47 dkms-sign-module
-rwxr--r-- 1 root root 833 Jul 11 09:48 one-time-setup
-rwxr--r-- 1 root root 1152 Jul 11 09:48 sign-modules
-rw------- 1 root root 0 Jul 11 10:21 MOK.priv

Generating a RSA private key
.....................................+++++
...................................................+++++
writing new private key to './MOK.priv'
Enter PEM pass phrase:

@xuzhen
Copy link

xuzhen commented Jul 11, 2020

@ajaygaur1984 That's the password to protect your private key. Enter any text you like.

@ajaygaur1984
Copy link

Thanks Xu Zhen but above solution won't work as UEFI Secure Boot is disabled. Could anyone please assist me as not able to install VirtualBox 6.1 on Ubuntu 20.04 (Windows host)as getting error [ (i have changed the kernel version from default to 5.7.0-microsoft-standard but still no luck): Tried so many things but nothing works]:

Loading new virtualbox-6.1.6 DKMS files...
It is likely that 5.7.0-microsoft-standard belongs to a chroot's host
Building for 4.19.0-041900-generic, 5.4.0-39-generic, 5.4.0-40-generic and 5.6.0-1017-oem
Building initial module for 4.19.0-041900-generic
ERROR (dkms apport): kernel package linux-headers-4.19.0-041900-generic is not supported
Error! Bad return status for module build on kernel: 4.19.0-041900-generic (x86_64)
Consult /var/lib/dkms/virtualbox/6.1.6/build/make.log for more information.
dpkg: error processing package virtualbox-dkms (--configure):
installed virtualbox-dkms package post-installation script subprocess returned error exit status 10

virtualbox
WARNING: The vboxdrv kernel module is not loaded. Either there is no module
available for the current kernel (5.7.0-microsoft-standard) or it failed to
load. Please recompile the kernel module and install it by

       sudo /sbin/vboxconfig

     You will not be able to start VMs until this problem is fixed.

Qt WARNING: could not connect to display
Qt FATAL: This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, xcb.
Aborted

@nberth
Copy link

nberth commented Oct 21, 2024

Note for those still using these scripts: in sign-modules, xz needs to be passed -C crc32 (see lwfinger/rtw88#189 for details; tldr: xz now uses CRC64, which the kernel is not able to deal with, leading to module decompression errors).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment