How to sign drivers/modules for the kernel with enabled secure boot?

I want to install This driver without disabling secure boot as I’m in a dual boot system with Windows and its required for some programs, but according to its instructions, I have to sign the driver in order to make it work, I’ve successfully installed NVIDIA’s proprietary drivers using this guide, but the more I look the more questions I have, which can be summed with the following bullet points:

  • Is installing any driver has the same procedure as this nvidia driver tutorial (be aware that this is for fedora 36 which has automated some stuff regarding the signing), or this is just a special case for nvidia?

  • Do I have to sign a new key every time I install a new driver/module? and Is it possible to screw other modules up while installing this driver ?

  • How to sign and install this driver ?

  • Why isn’t DKMS mentioned neither in fedora nor RPMfusion’s documentation ? does Fedora use another system for these stuff? I should also note that I barely understand those stuff.

  1. No, it is not necessary to go through that entire procedure for each module you want to install. Most of those steps are setup/preparation, not specific to the module being installed.

  2. No, you can use the same key for many modules.

  3. The build process for the module you want to use will need to make use of the akmod tool for the signing process. If it does not, you would have to do those steps manually.

  4. DKMS isn’t sufficient for signed modules.

3 Likes

So basically running this command from the readme will automatically make akmod sign the drivers with the same key generated for the previous drivers, right?

sudo dnf install -y "kernel-devel-uname-r == $(uname -r)"
make
sudo make install

if it was not the case, what the steps I should do ?

I don’t think that will happen automatically unless the Makefile for that module knows how to use akmod. The NVIDIA one certainly does.

2 Likes

If the package you are installing does not have the akmod part with it then it will not automatically build nor sign the module. VirtualBox and the nvidia driver, both from the rpmfusion repo, include an akmod package that handles automatically building the signed module.

What you downloaded from github likely does not have that feature so it will require you to do the manual steps, both to build and to sign the modules.

Also, since you are doing that manually, you will be required to repeat the build and sign steps for those modules with every kernel update. The module must be built to match the kernel.

Accordingly, it would make things simpler if you document the steps to follow so they are easy to repeat.

You can use the same key as was used for the nvidia drivers, but it is tedious to do the same thing over and over with every kernel update.

This is way to sign any driver (at least that is what I when I enabled secure boot in early times)

Create config ini file

touch x509-configuration.ini

File content (x509-configuration.ini)

[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
prompt = no
string_mask = utf8only
x509_extensions = myexts

[ req_distinguished_name ]
O = NAME
CN = COMPANY NAME
emailAddress = emailAddress

[ myexts ]
basicConstraints=critical,CA:FALSE
keyUsage=digitalSignature
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid

Create der and priv keys

openssl req -x509 -new -nodes -utf8 -sha256 -days 36500 -batch -config x509-configuration.ini -outform DER -out public_key.der -keyout private_key.priv

Enroll your secureboot key (as root)

mokutil --import mpublic_key.der

It will ask password and you need that once your pc rebooted for complete to enroll

Next If you wanna enroll your drivers (this is for any driver but I post what I sign as a example)

I created bash script for this and here is the file content

$ANY_PATH="define_path"
last_kernel=$(uname -r)  

# Or latest installed kernel version (example format 5.18.13-200.fc36.x86_64)

cd /usr/src/kernels/$last_kernel/scripts/
./sign-file sha256 $ANY_PATH/.securebootkeys/private_key.priv $ANY_PATH/.securebootkeys/public_key.der /usr/lib/modules/$last_kernel/extra/nvidia/nvidia-modeset.ko 
./sign-file sha256 $ANY_PATH/.securebootkeys/private_key.priv $ANY_PATH/.securebootkeys/public_key.der /usr/lib/modules/$last_kernel/extra/nvidia/nvidia-drm.ko 
./sign-file sha256 $ANY_PATH/.securebootkeys/private_key.priv $ANY_PATH/.securebootkeys/public_key.der /usr/lib/modules/$last_kernel/extra/nvidia/nvidia.ko 
./sign-file sha256 $ANY_PATH/.securebootkeys/private_key.priv $ANY_PATH/.securebootkeys/public_key.der /usr/lib/modules/$last_kernel/extra/nvidia/nvidia-uvm.ko 
#./sign-file sha256 $ANY_PATH/.securebootkeys/private_key.priv $ANY_PATH/.securebootkeys/public_key.der /usr/lib/modules/$last_kernel/extra/nvidia/nvidia-ib-peermem-stub.ko 
./sign-file sha256 $ANY_PATH/.securebootkeys/private_key.priv $ANY_PATH/.securebootkeys/public_key.der /usr/lib/modules/$last_kernel/extra/nvidia/nvidia-peermem.ko 

# v4l2loopback driver signature
./sign-file sha256 $ANY_PATH/.securebootkeys/private_key.priv $ANY_PATH/.securebootkeys/public_key.der /usr/lib/modules/$last_kernel/extra/v4l2loopback/v4l2loopback.ko

# VirtualBox driver signature
./sign-file sha256 $ANY_PATH/.securebootkeys/private_key.priv $ANY_PATH/.securebootkeys/public_key.der /usr/lib/modules/$last_kernel/extra/VirtualBox/vboxdrv.ko
./sign-file sha256 $ANY_PATH/.securebootkeys/private_key.priv $ANY_PATH/.securebootkeys/public_key.der /usr/lib/modules/$last_kernel/extra/VirtualBox/vboxnetadp.ko  
./sign-file sha256 $ANY_PATH/.securebootkeys/private_key.priv $ANY_PATH/.securebootkeys/public_key.der /usr/lib/modules/$last_kernel/extra/VirtualBox/vboxnetflt.ko
2 Likes

You can install dkms from the standard Fedora repository. WIth the package comes the file /usr/share/doc/dkms/README.md, and this file explains that generated modules will be signed, and also how to enroll the key in the Machine Owner Key storage (MOK).

Packages from Rpmfusion uses akmods instead. The akmods package also comes with README files explaining about signing.

You failed to provide the content of ./sign-file so we don’t know what that script actually does.
Also. it seems you put the keys into the kernel subdir that is specific to that kernel which requires the keys be either copied over each time a kernel is updated and a new module generated or a new signature needs to be generated each time the kernel is updated.

As you can tell from the first post in Installing nvidia drivers on a fedora 36 (in dual boot with windows 11) with secure boot enabled the kmodgenca command creates a public key file at /etc/pki/akmods/certs/public_key.der

(the post tells how to generate the key and to install it to bios)

If you were to generate your key in this way the same key could be used for both manually signing the module the way you do and for using it with akmod packages that build the module with akmods. It would only require modifying the path to the keys.

Generating one key is all that is required with the public key at /etc/pki/akmods/certs/public_key.der and the private key at /etc/pki/akmods/private/private_key.der

You failed to provide the content of ./sign-file

I don’t have to provide because It is comes with kernel If you check it. It is for sign I didn’t put there manually. (/usr/src/kernels/$(uname -r)/scripts/ it is in here)

Also I showed this because I used this way before f36 released without automatic and and It was works fine. I tested and used so many times when I had to run for each kernel update and sign the drivers.

I already know how to automatic but question was about how sign manually and I showed the way without akmod or dkms (plus dkms is old using akmod is better to control)

I did not say your method was incorrect.

I merely suggested a way that you could realistically use the same keys as are used by akmods when a new module is signed and avoid creating new keys or copying them from another location when doing updates.

I had not checked, but I see that sign-files is a binary so my question was invalid. My bad! :hot_face:

BTW, akmods has been available and in use for quite some time, not just with F36. It also does not rely on dkms.

This is very neat thank you, I will try this on a Fedora VM with secure boot on as soon as possible. I have a question as I have no experience with bash scripts yet:
What does this line do?

$ANY_PATH="define_path"

Another question, does this method work with any linux distribution with openssl and mokutil ?

Many distros do not have the akmods functionality that fedora does, so signing the packages automatically might be different (if at all possible).

Most distros do have mokutil so that part should work.

On distros that do not enable automatic compiling and signing the modules, the manual method above should work as well for almost all modules.

Your question cannot be answered definitively for all distros without testing on all distros, and then on all versions of each of those distros as well.

That variable for pointing just a path for example (/home/fedora/somefolder) you can use whatever you want. If you want you can even change it. I posted for “example” so you can understand easily. I didn’t use actual path of mine.

Simply go to Fedora User Docs/F36/System Administrator Guide/Kernel, module and driver configuration/Working with kernel modules => everything is clearly explained in detail being a feature to use EFI secure boot with Fedora and Microsoft signature among others things. There is a detail in real life about NVIDIA that baffles me …

The Ubunto repositories does provide Virtualbox, and the drivers are automatically compiled using the dkms facility. The resulting drivers are automatically signed.
The Arch distribution, according to its wiki pages, also uses dkms to install third party kernel modules.