Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions misc/module-signing/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Module Sining

In order to make the dkms modules work with secure boot they need to be singed.
This directory contains scripts that help you with that task.

## Known Issues / Help Wanted

- doctor script does nothing
- only supports amd64
- only tested on Debian

## Run Doctor

The doctor script will check your environment and asks you to to install
additional packages if something is missing.

## Cert Import

If you alread have a certificate with a key under your control imported into
the bios you can scipt this section.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... can skip this ...


bla bla
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Elaborate... :-D


## Signing of VBOX modules

You need to either run the script in the directory that contains your
`MOK.der` and MOK.priv` or export the path in the `MOK_KEY_DIR` evironment
variable.

Execute the scipt `MOK_KEY_DIR=/path/to/your/key/dir ./sign-xbox-modules` as
root or via sudo to sign the modules.
10 changes: 10 additions & 0 deletions misc/module-signing/create-key
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
MOK_CN_NAME={MOK_CA_NAME:-"$USER@$HOST"}

if [[ -e MOK.priv ]]; then
echo key already exists
exit 2
fi

openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -outform DER -out MOK.der -days 36500 -subj "/CN=$MOK_CN_NAME (SecureBoot Mok)/" && \
chmod 600 MOK.priv
2 changes: 2 additions & 0 deletions misc/module-signing/import-to-bios
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env bash
mokutil --import MOK.der
63 changes: 63 additions & 0 deletions misc/module-signing/sign-xbox-modules
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env bash
# LICENSE GPL-2.0
# AUTHOR Jan Christoph Uhde - jan@uhde.io
set -uo pipefail

MOK_KEY_DIR="${MOK_KEY_DIR:-'.'}"

ferr() { echo "$*"; exit 1; }

hash_algo='sha256'
key="$MOK_KEY_DIR/MOK.priv"
x509="MOK_KEY_DIR/MOK.der"

# TODO - maybe this could be done better without exporting the key to the env
Copy link
Collaborator

@kakra kakra Mar 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could mktemp a file with restrictive permissions, grab a file descriptor, and remove the file from disk immediately. Then that FD would keep the file opened (and thus persisted on disk just without a filename, it will be lost as soon as the FD closes) and could be piped into other commands. If this is better, tho, I'm not sure because you could still read the files from /proc/PID/fd/ then. It's not very different from looking at /proc/PID/environ, so maybe not worth the effort. I'm not sure if bash scripts could easily access the keyring store.

# the key is only for a short time present in the process but it is still
# not optimal
test -v KBUILD_SIGN_PIN || read -p "passphrase for ${key}: " KBUILD_SIGN_PIN
export KBUILD_SIGN_PIN
echo

# The exact location of `sign-file` might vary depending on your platform.
# TODO - test with different distributions
for module_dir in /usr/lib/linux-kbuild*; do
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least Gentoo doesn't have this dir. But it has /usr/lib/modules/*/build/scripts/sign-file.c where .../build is a symlink to the installed kernel sources. This has some limitations:

  1. the build of the kernel may not have run at all
  2. sign-file is usually not compiled on Gentoo
  3. the kernel sources may no longer exist and only the built kernel modules still exist

echo
echo "working on $module_dir"
sign_file="$module_dir/scripts/sign-file"
test -x $sign_file || ferr "can not execute $sign_file"

version=${module_dir#/usr/lib/linux-kbuild-}
# TODO - other platforms?!
module_dir="/lib/modules/$version-amd64/updates/dkms"
Copy link
Collaborator

@kakra kakra Mar 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's nothing like /lib/modules/VERSION-amd64 on Gentoo. It looks more like this:

# ls -al /lib/modules/
insgesamt 0
drwxr-xr-x 1 root root   432  7. Mär 11:30 ./
drwxr-xr-x 1 root root 99808 12. Mär 23:30 ../
drwxr-xr-x 1 root root   492 14. Dez 01:12 6.18.0-gentoo/
drwxr-xr-x 1 root root   492 15. Feb 19:55 6.18.10-gentoo/
drwxr-xr-x 1 root root   492 19. Feb 21:37 6.18.12-gentoo/
drwxr-xr-x 1 root root   492 27. Feb 13:36 6.18.13-gentoo/
drwxr-xr-x 1 root root   492  4. Mär 00:18 6.18.14-gentoo/
drwxr-xr-x 1 root root   492 12. Mär 23:31 6.18.16-gentoo/
drwxr-xr-x 1 root root   492 18. Dez 00:34 6.18.1-gentoo/
drwxr-xr-x 1 root root   492 31. Dez 10:03 6.18.2-gentoo/
drwxr-xr-x 1 root root   492  2. Jan 22:08 6.18.2-gentoo-r1/
drwxr-xr-x 1 root root   492  4. Jan 15:18 6.18.3-gentoo/
drwxr-xr-x 1 root root   492 14. Jan 03:03 6.18.4-gentoo/
drwxr-xr-x 1 root root   492 18. Jan 16:38 6.18.5-gentoo/
drwxr-xr-x 1 root root   492 21. Jan 21:34 6.18.6-gentoo/
drwxr-xr-x 1 root root   492 30. Jan 01:45 6.18.7-gentoo/
drwxr-xr-x 1 root root   492 10. Feb 12:23 6.18.8-gentoo/
drwxr-xr-x 1 root root   492 10. Feb 23:45 6.18.9-gentoo/

So I'd assume that amd64 is actually the kernel version suffix provided by the distribution or kernel package, usually derived from the name of multiple kernel variants to choose from? TBH, I've never experienced an explicit architecture suffix, e.g. on Ubuntu the directory names look like 4.15.0-213-generic because that machine, I checked, has the generic kernel variant installed.

The suffix is part of uname -r. It belongs to the version, it's not some independent value.

echo "version: $version"
echo "module dir: $module_dir"

if ! [[ -d $module_dir ]] ; then
echo "no such directory: $module_dir"
continue
fi

echo
for module_path in "$module_dir"/hid-xpadneo* ; do
echo -n "module: $module_path ... "
if ! [[ -e "$module_path" ]] ; then
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would this happen? The only incident would be that the for-loop expansion literally resolved to .../hid-xpadneo* because no such dir or file existed. Shouldn't this rather be -f or -r instead?

echo "skipped"
continue
fi

case "$module_path" in
*xz)
Copy link
Collaborator

@kakra kakra Mar 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're matching *xz here but strip .xz below...

unxz --keep "$module_path" || ferr "failed to unpack"
$sign_file "${hash_algo}" "${key}" "${x509}" "${module_path%%.xz}" || ferr "failed to sign"
rm "$module_path"
xz --check=crc32 --lzma2=dict=512KiB "${module_path%%.xz}"
;;
*ko)
Copy link
Collaborator

@kakra kakra Mar 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about other compression methods? xz is common, but modules may be compressed as gz as well (which was common some years ago).

What about modules that have been previously signed? Is this idempotent?

Also I don't like that it seemingly goes through all modules and touches files that may be part of distribution packaging. This can result in broken checksums. It uses "$module_dir"/hid-xpadneo* but can we be sure this touches only the currently managed module?

Also, reviewing this, I found it confusing that the loop var is called module_path but is semantically different from module_dir above. I suggest renaming it to xpadneo_module_path or xpadneo_module.

$sign_file "${hash_algo}" "${key}" "${x509}" "${module_path}" || ferr "failed to sign"
;;
esac
echo "signed"
done
echo "$module_dir signed"
echo
done