Skip to content

Instantly share code, notes, and snippets.

@sbueringer
Forked from dojoe/dkms-module-signing.md
Created October 16, 2019 04:22
Show Gist options
  • Select an option

  • Save sbueringer/bd8cec239c44d66967cf307d808f10c4 to your computer and use it in GitHub Desktop.

Select an option

Save sbueringer/bd8cec239c44d66967cf307d808f10c4 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
@ValuedEmployee

Copy link
Copy Markdown

@dominikegert Your .zst script seems to fail for me on my Artix system, I don't know if you would be able to give me some insight into what might be going wrong after these couple years:

(1/7) Updating module dependencies...
(2/7) Install DKMS modules
==> dkms install --no-depmod nvidia/610.43.03 -k 6.18.41-1-lts
==> WARNING: `dkms install --no-depmod nvidia/610.43.03 -k 6.18.41-1-lts' exited 1
==> dkms install --no-depmod nvidia/610.43.03 -k 7.1.5-artix1-2
==> WARNING: `dkms install --no-depmod nvidia/610.43.03 -k 7.1.5-artix1-2' exited 1
==> dkms install --no-depmod nvidia/610.43.03 -k 7.1.5-hardened1-3-hardened
==> WARNING: `dkms install --no-depmod nvidia/610.43.03 -k 7.1.5-hardened1-3-hardened' exited 1

@dominikegert

Copy link
Copy Markdown

I am sorry, but your "warnings" are related to a dkms install call, this is not performed by the script. - The script is only an addition to support .zst compressed modules for signing, not for installation via dkms.

@ValuedEmployee

ValuedEmployee commented Aug 4, 2026 •

Copy link
Copy Markdown

Strange, I guess I'll I have to do some digging and figure out what's wrong. I appreciate it!

@ValuedEmployee

Copy link
Copy Markdown

Here's what I got for Arch based distributions with .zst compressed modules. It will decompress the module, remove the old .zst, sign it, compress the signed .ko and then remove the .ko using all of your CPU cores. Confirmed it working with my kernel locked down in confidentiality mode!

#!/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}
    module_basename2=${module:0:-4}
    module_suffix2=${module: -4}

    if [[ "$module_suffix2" == ".zst" ]]; then
        zstd -q -T0 --auto-threads=logical -f -d --rm $module
        do_sign $module_basename2
        zstd -q -T0 --auto-threads=logical -19 -f --rm $module_basename2
    elif [[ "$module_suffix" == ".xz" ]]; then
        unxz $module
        do_sign $module_basename
        xz -C crc32 -f $module_basename
    elif [[ "$module_suffix" == ".gz" ]]; then
        gunzip $module
        do_sign $module_basename
        gzip -9f $module_basename
    else
        do_sign $module
    fi
done

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