You are not logged in.
I've been reading on here about kernel module signing
I have UEFI secure boot setup with my own keys, however I'm not sure how I can get the kernel to use the public keys stored in my UEFI firmware
it does says on the link I provided earlier that
Further, the architecture code may take public keys from a hardware store and add those in also (e.g. from the UEFI key database).
and searching around I see some documentation/articles about how Red Hat Enterprise can do this
Do I have to do something specfic to the kernel or something to use the keys from UEFI firmware. I don't see any information on this
and pointers/advice?
thanks
Last edited by sinatosk (2019-08-31 10:54:42)
Offline
While I did not get any farther into this than signing modules/dkms modules (in Manjaro), these should help you.
https://wiki.archlinux.org/index.php/Secure_Boot
Eenie meenie, chili beanie, the spirits are about to speak -- Bullwinkle J. Moose
It's a big club...and you ain't in it -- George Carlin
Registered Linux user #149839
perl -e 'print$i=pack(c5,(41*2),sqrt(7056),(unpack(c,H)-2),oct(115),10); '
Offline
none of these helped this is not related to what I want
I want the kernel to read the public keys from UEFI firmware and use those
Offline
Is the key you added to the EFI not in the .system_keying?
Offline
no and when I run the command using sudo or loggin in as root via "su" command
# keyctl list %:.system_keyring
it says
Can't find 'keyring:.system_keyring'
ofcourse that keyring doesn't exist but I thought the kernel automatically created this or I'm missing something?
Last edited by sinatosk (2019-08-30 20:02:29)
Offline
# keyctl list %:.builtin_trusted_keys
If you are using the linux package from the repositories the randomly generated key embedded in the kernel should be listed.
Edit:
keyring names were changed in 4.7 https://github.com/torvalds/linux/commi … 3d161d01c9
and the in kernel documentation fixed in 4.17 https://github.com/torvalds/linux/commi … 3b55613dcb
Last edited by loqs (2019-08-30 20:13:50)
Offline
yeah, thats in there but thats the auto generated during kernel compile/build
I would like the kernel to read the public keys from UEFI firmware too and I'm under the impression that it can based on the documentation I read from kernel.org and red hat website
Offline
I agree with your understanding provided the system is booting in EFI mode with secure boot enabled then the EFI keys should be added to the keyring by the kernel.
Offline
# keyctl list %:.builtin_trusted_keys
If you are using the linux package from the repositories the randomly generated key embedded in the kernel should be listed.
Edit:
keyring names were changed in 4.7 https://github.com/torvalds/linux/commi … 3d161d01c9
and the in kernel documentation fixed in 4.17 https://github.com/torvalds/linux/commi … 3b55613dcb
if I understand this correctly
my system is in EFI mode and secure boot enabled and using my custom public/private key on the kernel
and doing a
zcat /proc/config.gz | grep CONFIG_SECONDARY_TRUSTED_KEYRING
which returns
CONFIG_SECONDARY_TRUSTED_KEYRING=y
that means my UEFI public keys should show in "builtin_trusted_keys", but... they ain't... hmmm
edit: thanks for digging this up by the way, great stuff
Last edited by sinatosk (2019-08-30 20:24:15)
Offline
looking in arch linux kernel config I'm seeing this
#
# Certificates for signature checking
#
CONFIG_MODULE_SIG_KEY="certs/signing_key.pem"
CONFIG_SYSTEM_TRUSTED_KEYRING=y
CONFIG_SYSTEM_TRUSTED_KEYS=""
# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set
CONFIG_SECONDARY_TRUSTED_KEYRING=y
CONFIG_SYSTEM_BLACKLIST_KEYRING=y
CONFIG_SYSTEM_BLACKLIST_HASH_LIST=""
# end of Certificates for signature checking
and this looks correct to me as I should be seeing my keys, but I ain't... and I don't know why
Offline
The kernel detects that secure boot is enabled?
dmesg | grep -i secure
Edit: I think the kernel has changed handling of platform keys again. Now you probably need CONFIG_INTEGRITY_PLATFORM_KEYRING, but that only works for kexec images. Modules can only be verified against the secondary keyring, not the platform keyring. Keys can only be added to the secondary keyring by root if those keys are signed by a key the kernel already trusts in the primary or secondary keyring. I don't know if a patch would be accepted to allow platform keys as module signatures.
https://github.com/torvalds/linux/blob/ … ning.c#L81
https://github.com/torvalds/linux/blob/ … ing.c#L204
https://github.com/torvalds/linux/blob/ … y/digsig.c
https://github.com/torvalds/linux/blob/ … efi.c#L118
https://github.com/torvalds/linux/blob/ … ity.h#L237
Last edited by progandy (2019-08-30 23:17:29)
| alias CUTF='LANG=en_XX.UTF-8@POSIX ' |
Offline
Offline
This will never be upstream, so there is currently no way to add signed modules without recompiling the kernel I think. Or is there a way to add a key to an already compiled kernel?
https://lore.kernel.org/lkml/1556221605 … rship.com/
Last edited by progandy (2019-08-31 07:17:34)
| alias CUTF='LANG=en_XX.UTF-8@POSIX ' |
Offline
Just woke up
I would prefer it to use just KEK, db and dbx keys
I'm also assuming that it will at the dbx keys to the blacklist and ofcourse linux will refuse those that are part of the blacklist
edit: just looking at the links provided by progandy
Last edited by sinatosk (2019-08-31 07:19:38)
Offline
Without recompiling the kernel with the patch mentioned by loqs you cannot do that.
You could ask for the arch kernel to reserve some space in the system keyring where you can insert your own key into the kernel binary itself without recompiling. It doesn't do that, yet.
https://github.com/torvalds/linux/commi … 6e5bbde772
Last edited by progandy (2019-08-31 07:25:21)
| alias CUTF='LANG=en_XX.UTF-8@POSIX ' |
Offline
I might be wrong but after looking at some of the links you've provided on post 11
I eventually found CONFIG_LOAD_UEFI_KEYS here which depends on a kernel module "integrity" which is not included in the arch linux kernel
I'll recompile the kernel ( I normally do anyway ) to include the module and see if that works
Offline
ok, while I havn't tried signing any modules yet the public keys are now showing from UEFI variable "db" and the contents from "dbx" are stored in linux kernel blacklist
this is what I set in my kernel config
CONFIG_INTEGRITY=y
CONFIG_INTEGRITY_SIGNATURE=y
CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
CONFIG_INTEGRITY_TRUSTED_KEYRING=y
CONFIG_INTEGRITY_PLATFORM_KEYRING=y
CONFIG_LOAD_UEFI_KEYS=y
CONFIG_INTEGRITY_AUDIT=y
# CONFIG_IMA is not set
# CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY is not set
# CONFIG_EVM is not set
CONFIG_SIGNATURE=y
to get them to show
thanks for your pointers progandy and loqs
Last edited by sinatosk (2019-08-31 10:54:14)
Offline
While not related to this post but was my next step after this post
progandy, I've been unable to get the kernel to use platforms key against the modules and everything you said in post 11 is true after looking through the code...
I've tried linking the keys using keyctl but failed due to permission problems ( denied )
I don't know why they changed it like this
the patch that loqs posted on post 12 ( I've not tried this yet ) seems like the only way I can get the modules verified by my platform keys
I wonder what red hat will do here in the future
Offline
If the kernel is compiled with SYSTEM_EXTRA_CERTIFICATE, then it is possible to embed one certificate into the builtin keyring of an already compiled kernel with the program linked in #15. Then you can use keyctl to add additional keys to the secondary keyring if they are signed with this "extra certificate". I believe you could add your uefi owner certificate here (not the private key!) with insert-sys-cert and then import the signed db keys with keyctl, but I don't know if those key and signature formats are easily compatible.
As for why they changed it, that is mentioned in the link in post #13.
Last edited by progandy (2019-08-31 21:17:57)
| alias CUTF='LANG=en_XX.UTF-8@POSIX ' |
Offline
Thanks to your replies I was able to successfully load signed modules using a certificate of my own, like the one containing my EFI public key. Since this could be useful to someone else, here are the steps I followed:
1. Build an ABS kernel with CONFIG_SYSTEM_TRUSTED_KEYS set to your X.509 PEM-encoded certificate:
$ sed -i '/^CONFIG_SYSTEM_TRUSTED_KEYS/{s#=.*#="/path/to/your/pub.crt"#}' config
$ updpkgsums
$ makepkg -s (this will take long!)
2. Install the newly created kernel package, along with the kernel headers package.
3. Configure DKMS so it can handle the signature process as part of the module installation. Here I use the following configuration (based on https://wiki.archlinux.org/index.php/Si … el_modules):
/etc/dkms/signature.conf
POST_BUILD=../../../../../../etc/dkms/module-sign.sh
/etc/dkms/module-sign.sh
#!/bin/bash
cd "../${kernelver}/${arch}/module/" || exit 1
SIGN="/usr/lib/modules/${kernelver}/build/scripts/sign-file"
if [ -f "${SIGN}" ]; then
[ ! -d ./tmp ] && mkdir ./tmp
shopt -s nullglob
for mod in ./*.ko ./*.ko.xz; do
mod_tmp="./tmp/${mod#./}"
cp -a "${mod}" "${mod_tmp}"
if [ "${mod##*.}" = "xz" ]; then
xz -f --decompress "${mod_tmp}"
isxz=1
mod_tmp="${mod_tmp%*.xz}"
fi
if grep -Eq "^signature:" < <(modinfo "${mod_tmp}"); then
echo "Removing old sig"
strip "${mod_tmp}"
fi
echo "DKMS: Signing kernel (${kernelver}) module: ${mod}"
$SIGN sha512 /path/to/your/private.key /path/to/your/pub.crt "${mod_tmp}"
if test -v isxz; then
xz -f ${mod_tmp}
mod_tmp="${mod_tmp}.xz"
fi
mv "${mod_tmp}" "${mod}"
done
fi
4. Use dkms along with the DKMS variant of the modules packages you need, so they can be recompiled and signed for your new kernel. To do so, for each module package, make a soft link to the configuration file:
# cd /etc/dkms
# ln -s signature.conf package_name.conf
then execute:
# dkms install -m module_name -v module_version -k kernel_version
5. Reboot to your new kernel.
The command keyctl show -x %:.builtin_trusted_keys should display the public key you added in the kernel trusted keyring.
Then you would be able to use modules.sig_enforce=1 in your kernel command line, kernel lockdown features as well
PS: sorry for my bad english
PS2: post edited as I realized that CONFIG_SYSTEM_EXTRA_CERTIFICATE would not be necessary in this situation.
Last edited by singeinfini (2020-04-26 21:51:05)
Offline
Thank you for your explanation.
So you mean that all kernel modules have to be unsigned first, then signed again with personal key, and put back in the kernel directories tree ?
I believe your whole procedure has to be applied even for a single out of tree module, isn't it ?
Thanks to your replies I was able to successfully load signed modules using a certificate of my own, like the one containing my EFI public key. Since this could be useful to someone else, here are the steps I followed:
1. Build an ABS kernel with CONFIG_SYSTEM_TRUSTED_KEYS set to your X.509 PEM-encoded certificate:
$ sed -i '/^CONFIG_SYSTEM_TRUSTED_KEYS/{s#=.*#="/path/to/your/pub.crt"#}' config $ updpkgsums $ makepkg -s (this will take long!)
2. Install the newly created kernel package, along with the kernel headers package.
3. Configure DKMS so it can handle the signature process as part of the module installation. Here I use the following configuration (based on https://wiki.archlinux.org/index.php/Si … el_modules):
/etc/dkms/signature.conf POST_BUILD=../../../../../../etc/dkms/module-sign.sh
/etc/dkms/module-sign.sh #!/bin/bash cd "../${kernelver}/${arch}/module/" || exit 1 SIGN="/usr/lib/modules/${kernelver}/build/scripts/sign-file" if [ -f "${SIGN}" ]; then [ ! -d ./tmp ] && mkdir ./tmp shopt -s nullglob for mod in ./*.ko ./*.ko.xz; do mod_tmp="./tmp/${mod#./}" cp -a "${mod}" "${mod_tmp}" if [ "${mod##*.}" = "xz" ]; then xz -f --decompress "${mod_tmp}" isxz=1 mod_tmp="${mod_tmp%*.xz}" fi if grep -Eq "^signature:" < <(modinfo "${mod_tmp}"); then echo "Removing old sig" strip "${mod_tmp}" fi echo "DKMS: Signing kernel (${kernelver}) module: ${mod}" $SIGN sha512 /path/to/your/private.key /path/to/your/pub.crt "${mod_tmp}" if test -v isxz; then xz -f ${mod_tmp} mod_tmp="${mod_tmp}.xz" fi mv "${mod_tmp}" "${mod}" done fi
4. Use dkms along with the DKMS variant of the modules packages you need, so they can be recompiled and signed for your new kernel. To do so, for each module package, make a soft link to the configuration file:
# cd /etc/dkms # ln -s signature.conf package_name.conf
then execute:
# dkms install -m module_name -v module_version -k kernel_version
5. Reboot to your new kernel.
The command keyctl show -x %:.builtin_trusted_keys should display the public key you added in the kernel trusted keyring.Then you would be able to use modules.sig_enforce=1 in your kernel command line, kernel lockdown features as well
PS: sorry for my bad english
PS2: post edited as I realized that CONFIG_SYSTEM_EXTRA_CERTIFICATE would not be necessary in this situation.
Offline