This post explains how to build a kernel and corresponding modules with the following criteria:
CONFIG_MODULE_SIG_KEY
is set to default and we destroy the private part of the signing key after the initial buildCONFIG_SYSTEM_TRUSTED_KEYS
contains an additional certificate we can use to sign modules built afterwards or out of treeModule signing enforcement is turned on
By having a separate key for signing modules, one could potentially revoke the ‘out of tree’ module signing key; but keep the built-in key for modules built during the initial build time.
The kernel documentation provides a more complete reference.
Generate your keys
First make an x509 key configuration file:
[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
prompt = no
string_mask = utf8only
x509_extensions = myexts
[ req_distinguished_name ]
CN = Out of tree build key
[ myexts ]
basicConstraints=critical,CA:FALSE
keyUsage=digitalSignature
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid
Save this as x509.genkey
.
Now generate the private/public key x509 keypairs:
openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -x509 \
-config x509.genkey -outform PEM -out kernel_key.pem \
-keyout kernel_key.pem
Build and Install your Kernel
Assuming you have kernel sources and know how to build it, ensure your configuration has the following:
CONFIG_MODULE_SIG_KEY="certs/signing_key.pem"
CONFIG_SYSTEM_TRUSTED_KEYS="/path/to/kernel_key.pem"
CONFIG_MODULE_SIG_ALL=y
CONFIG_MODULE_SIG_FORCE=y
CONFIG_MODULE_SIG_SHA512=y
CONFIG_MODULE_SIG_HASH="sha512"
Do the actual build:
make -j56 deb-pkg
Next install it and any headers onto your target machine.
Check the Keyring
After boot check your keyring:
$ sudo cat /proc/keys
0206fe7e I--Q--- 1 perm 1f3f0000 1000 65534 keyring _uid.1000: empty
14fa22e7 I------ 1 perm 1f0b0000 0 0 keyring .system_keyring: 2
1d3e0f7d I--Q--- 35 perm 3f030000 1000 1000 keyring _ses: 1
20a381a5 I------ 1 perm 1f030000 0 0 asymmetri Out of tree build key: be477ba1a33ecc6676673ad18c237554ad95c7ec: X509.rsa ad95c7ec []
216ffa7a I------ 1 perm 1f030000 0 0 asymmetri Build time autogenerated kernel key: 54c5a144b369821a007b666ac1c57b8c73df6e37: X509.rsa 73df6e37 []
2520d96e I------ 1 perm 1f0f0000 0 0 keyring .evm: empty
268f53e6 I------ 1 perm 1f030000 0 0 keyring .dns_resolver: empty
2ee865ad I------ 1 perm 1f0f0000 0 0 keyring .ima: empty
36604247 I--Q--- 2 perm 1f3f0000 0 65534 keyring _uid.0: empty
36d30925 I--Q--- 1 perm 1f3f0000 0 65534 keyring _uid_ses.0: 1
Build an Out of Tree Module
Using some simple hello world module try to build and insert it. Without signing it and with module signing enforcement you’ll get:
$ sudo insmod example.ko
insmod: ERROR: could not insert module example.ko: Required key not available
Sign the Module
First split the .pem file into its constitutent parts:
chmod 0600 kernel_key.pem
openssl pkey -in kernel_key.pem -out kernel_key.key
openssl x509 -outform der -in kernel_key.pem -out kernel_key.crt
Now we need to sign the module. First co-locate the kernel module and key onto the same machine. I’m going to scp the module out of the target machine and into my build machine.
./scripts/sign-file sha512 ./kernel_key.key ./kernel_key.crt example.ko
Move this to the target machine and try to insert the module.
$ sudo insmod example.ko
$ lsmod | grep example
example 16384 0
It worked.