These are the steps I followed enable VirtualBox on my laptop without disabling UEFI Secure Boot. They're nearly identical to the process described on Øyvind Stegard's blog, save for a few key details. The images here are borrowed from the Systemtap UEFI Secure Boot Wiki.
-
Install the VirtualBox package (this might be different for your platform).
src='https://download.virtualbox.org/virtualbox/rpm/fedora/virtualbox.repo' dst='/etc/yum.repos.d/virtualbox.repo' sudo curl ${src} > ${dst} dnf check-update sudo dnf install VirtualBox-6.0
-
Create an RSA key pair to sign kernel modules.
name="$(getent passwd $(whoami) | awk -F: '{print $5}')" out_dir='/root/module-signing' sudo mkdir ${out_dir} sudo openssl \ req \ -new \ -x509 \ -newkey \ rsa:2048 \ -keyout ${out_dir}/MOK.priv \ -outform DER \ -out ${out_dir}/MOK.der \ -days 36500 \ # This is probably waaay too long. -subj "/CN=${name}/" sudo chmod 600 ${out_dir}/MOK*
Note the absence of the
-nodes
option from Øyvind's post. With this optionopenssl
will create a private key with no passphrase. The omission of this option prompts for a passphrase, which seems like a good idea for something as important as a kernel module signing key. -
Import the MOK ("Machine Owner Key") so it can be trusted by the system.
sudo mokutil --import /root/module-signing/MOK.der
This will prompt for a password. The password is only temporary and will be used on the next boot. It does not have to be the same as the signing key passphrase.
-
Reboot your machine to enter the MOK manager EFI utility.
- Select Enroll MOK.
- Select Continue.
- Select Yes to enroll the keys.
- Enter the password from earlier.
- Select OK to reboot.
- Verify the key has been loaded by finding the it in the output of
dmesg | grep '[U]EFI.*cert'
-
Create a script for signing all the VirtualBox kernel modules.
#!/bin/sh readonly hash_algo='sha256' readonly key='/root/module-signing/MOK.priv' readonly x509='/root/module-signing/MOK.der' readonly name="$(basename $0)" readonly esc='\\e' readonly reset="${esc}[0m" green() { local string="${1}"; echo "${esc}[32m${string}${reset}"; } blue() { local string="${1}"; echo "${esc}[34m${string}${reset}"; } log() { local string="${1}"; echo "[$(blue $name)] ${string}"; } # The exact location of `sign-file` might vary depending on your platform. alias sign-file="/usr/src/kernels/$(uname -r)/scripts/sign-file" [ -z "${KBUILD_SIGN_PIN}" ] && read -p "Passphrase for ${key}: " KBUILD_SIGN_PIN export KBUILD_SIGN_PIN for module in $(dirname $(modinfo -n vboxdrv))/*.ko; do log "Signing $(green ${module})..." sign-file "${hash_algo}" "${key}" "${x509}" "${module}" done
This script differs from Øyvind's in two aspects. First, and most importantly, it has ✨ C O L O R S ✨. Second, it uses the magic
$KBUILD_SIGN_PIN
environment variable that doesn't appear anywhere in thesign-file
usage. I went spelunking in the Linux source for it, but in hindsight I could have just read the docs on manual module signing... I wrote this script to/root/bin/sign-vbox-modules
as that's usually onroot
's$PATH
. -
Execute the aforementioned script as
root
.sudo chmod 700 /root/bin/sign-vbox-modules sudo -i sign-vbox-modules
-
Load the
vboxdrv
module.sudo modprobe vboxdrv
I was able to fix this under Ubuntu 22.04 LTE, running the HWE (Hardware Enablement) stack with the latest kernel 5.19.0-50-generic, for Virtualbox 7.0.10r158379 with this command:
sudo mokutil --import /var/lib/shim-signed/mok/MOK.der
Check out this thread for Ubuntu: https://bugs.launchpad.net/ubuntu/+source/virtualbox/+bug/1992673
My understanding is that Secure Boot is a feature that allows manufacturers, OS creators, and users, to enroll signing keys MOK (Machine Owner Key), to enable various OSes to ensure they are running kernel and device driver code that has been signed by a trusted entity. Microsoft has a key it enrolls with popular manufacturers, but the various Linux distros do not. That "shim-signed" file is the private key for Ubuntu and Debian. That Linux MOK file needs to be manually trusted using mokutil.
I was able to get Virtualbox to temporarily run by following the instructions here, but after reboot, Virtualbox would still fail to load. What I found odd was that running
sudo modprobe vboxdrv
would give an error ofmodprobe: ERROR: could not insert 'vboxdrv'" Key was rejected by service.
and indmesg
ofLoading of module with unavailable key is rejected
, despite the Virtualbox kernel modules being signed by a trusted MOK. I then realized that there was probably another MOK being used and ranfind / -iname MOK.der
to find the file/var/lib/shim-signed/mok/MOK.der
, and read more about it.You'll need to rerun that command if you do a BIOS update.