[Kernel] add genkey file for kernel key generation

Recent kernels signs their modules with an autogenerated key at compilation time, which is configured with a genkey file. If that file doesn’t exist, it will also be autogenerated.

dmesg | grep cert

shows basic certificate info, more details with sudo cat /proc/keys.

It just says “autogenerated kernel key” on Manjaro 4.19.

However, you can provide a genkey file with customised info.
The file should be put in $srcdir/certs/x509.genkey, it would look like this.

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

[ req_distinguished_name ]
O = <Organisation>
CN = <Comment>
emailAddress = <email@add.ress>

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

My suggestion is to change the info in req_distinguished_name to something like “Manjaro”.
Low priority obviously :wink:

EDIT:
add link to kernel documentation:
https://www.kernel.org/doc/html/v4.19/admin-guide/module-signing.html

It is strongly recommended that you provide your own x509.genkey file.

8 Likes

Since I’m currently working on this for my custom kernel… has this already been considered for Manjaro?

I believe this could even be used to sign extramodules as described in the kernel documentation. I’m not quite there yet though.

2 Likes

Yes, it can:

$ modinfo nvidia
filename:       /lib/modules/4.19.34-1-vd/extramodules/nvidia.ko.gz
alias:          char-major-195-*
version:        418.43
supported:      external
[...]
retpoline:      Y
name:           nvidia
vermagic:       4.19.34-1-vd SMP preempt mod_unload modversions 
sig_id:         PKCS#7
signer:         vd kernel key
sig_key:        64:[...]
sig_hashalgo:   sha512
signature:      54:[...]

Cool stuff :slight_smile:

In order to do that, you have to generate a key and use sign-file from the kernel source tree on the modules.

2 Likes

It seems that dkms now autocompresses the modules (for example in case of VBox), which means you would first have to uncompress them (unxz), then sign and recompress (with xz or gzip -9).
I'm sure there are more elegant ways...

1 Like

Are you keeping your source tree in /usr/src?

I've been toying with this idea as well, but I do my compiling in /tmp.

Do you put your 'master' cert file in your PKGBUILD source array, or just copy it from a secure location at the start of the

build() {

function?

No, I'm compiling in /tmp as well.

I keep the cert file in a secure location - it includes both private and public keys, but you can split them. I'm not even sure if I do this correctly, but at least the signing thing works.
It should be enough to just follow the instructions from the kernel documentation.

All this would make more sense in case of 'secure boot', where you could probably sign with the key stored in the TPM chip?

Since this was originally a feature request, I wonder what Manjaro thinks of this. Not necessarily signing the extramodules, but a x509.genkey file would be welcome. Adds a little "professionalism" me thinks.

1 Like

That's the direction I'm going ATM. Created a custom X509.genkey file, added it to the source array in my PKGBUILD, copy it over to the extracted source, and...it works.

[merell@Jammin1 ~]$ modinfo drm |grep signer
signer:         Jammin1_kernel_key
[merell@Jammin1 ~]$

Yup. But, I am about as keen about mucking around in my BIOS as I am about overclocking...just too darn scared. :fearful:

Did you do this manually (unxz/gunzip...sign-file (in the sources)...xz/gzip...?

I'm not privy...how do you make your source tree persistent across a reboot?

I just added a few lines to the PKGBUILD of the extramodule (here nvidia):

echo -e "Signing modules with kernel key...\n"
for i in nvidia.ko nvidia-{modeset,drm,uvm}.ko; do
	sign-file.sh "${pkgdir}/usr/lib/modules/${_extramodules}/$i"
done
gzip -9 "${pkgdir}/usr/lib/modules/${_extramodules}/"*.ko // this line is already present

sign-file.sh is just a wrapper script to the real sign-file binary.

1 Like

Thanks for the starting point!

[merell@Jammin1 ~]$ modinfo vboxdrv|grep -e signer -e filename
filename:       /lib/modules/5.2.0-4-Jammin1/extramodules/vboxdrv.ko.gz
signer:         Jammin1_kernel_key
[merell@Jammin1 ~]$ 

vbox* are the only extramodules I use.

1 Like

I've become fascinated with this.

So, I compiled a test module, and got it installed:

[merell@Jammin1 ~]$ lsmod|grep hello
hello                  16384  0
[merell@Jammin1 ~]$

I also set CONFIG_SYSTEM_TRUSTED_KEYS in the config, and generated a new key just for that.

It works!

In tree:

[merell@Jammin1 ~]$ modinfo drm |grep signer
signer:         Jammin1_kernel_key
[merell@Jammin1 ~]$

New module:

[merell@Jammin1 /tmp/thisisatest/module]$ modinfo hello.ko|grep signer
signer:         Jammin1_module_key
[merell@Jammin1 /tmp/thisisatest/module]$

Pretty cool.

ETA:

[merell@Jammin1 ~]$ modinfo vboxdrv|grep signer
signer:         Jammin1_module_key
[merell@Jammin1 ~]$
1 Like

Interesting stuff guys. We might explore this in a later stage. However keep me posted.

Yeah that's indeed very interesting... :slight_smile:

You should now also be able to use the module.sig_enforce boot parameter, which prevents loading of unsigned (or not validly signed) modules, potentially increasing security as it would keep malicious modules out.
I haven't tested this though.

Not quite there yet; you need the vbox DKMS modules to build the vbox 'extramodules', and the DKMS modules are not signed.

1 Like

The last few days, I tried to automatically sign DKMS modules for my own Kernel builds. I add -up as my localversion. The pacman hook and the signing script rely on that, but it can be changed easily.

I add my own version of x509.genkey to the certs folder and let the Kernel-build generate a fresh key that is only used to sign the in-tree modules. I don't store it after the build.

I also add a cert file dkms-kernel-cert.pem to the certs folder. This file only contains the certificate ( public key ) and is added to the default keyring via

CONFIG_SYSTEM_TRUSTED_KEYS="certs/dkms-kernel-cert.pem"

The private key with the cert was generated manually and is stored. I use this key to sign the dkms modules. I like this way because with it I don't need to store the private key in to many locations.
It is also possible to save multiple certs in one file and add them to the Kernel keyring.
The dmesg will print a line for all loaded keys that are added to the keyring.

The pacman hooks is basically the dkms-install hook. Since it will have the same target, but I narrowed the target down to my own Kernel build. This hook will start the DKMS-signing.sh script. I named the hook 72-dkms-signing.hook , because it needs to run after the dkms-install hook.

The DKMS-signing.sh script is a little bit ugly, but it works for me. Things like, grepping thru a binary file, a for loop in a for loop or semi-optimal working regex's aren't nice, so it needs some extra work.

The hook and the signing script: https://gist.github.com/xabbu/cada05287d55f1903094775b8ae5bc02

I noticed dkms isn't happy if the module in /usr/lib/modules/... is different to the one stored by it in /var/lib/dkms/... . So the script copies the signed module back to /var/lib/dkms/...

I tried the script only with modules I use myself. It might break horrible with other modules. I use 8192eu, acpi_call, broadcom-wl, vboxhost and wireguard.

I found that it is possible to add multiple signatures to a module. Multiple signatures will not break the module, but only the last one is checked by the Kernel.

I also added CONFIG_MODULE_SIG_FORCE=y to my config. This prevents loading of unsigned and invalid signed modules. But it was more a test, since it can't be turned off.

2 Likes

I'll work on the naming (-up) changes, and install/run this on my next kernel build.

As an aside, do you only use the DKMS version of vboxhost?

ETA: Worked like a charm! Thanks, @xabbu!!!

ETA #2: rebuilt with CONFIG_MODULE_SIG_FORCE=y. Still working!

1 Like

Nice to hear.

Yes. I use for all my out-of-tree modules DKMS. I do this for my own Kernel build and all repo Kernel's I have installed. vboxhost is also the reason I added a seconded for loop. This is the only dkms package I use which builds more than one module.

1 Like

Thank you for the feedback, xabbu! That DKMS stuff sounds interesting. I only use it for VBox currently, but might look into it.
My approach is different and more hacked together; the kernel's PKGBUILD asks the user for the full path to the cert, and if not available, simply reverts to x509.genkey autogenerated key.

2 Likes