The Machine Keyring

June 6, 2023 | 11 minute read
Text Size 100%:

Introduction

UEFI Secure Boot provides a security feature that ensures only trusted digitially signed binaries are executed in the boot chain. Secure Boot validates each digital signature before allowing anything to load during boot. Linux kernel modules are one of the final components of the boot chain. To maintain the signing validation requirement, all kernel modules must be signed and validated. Linux distributions enforce integrity lockdown mode when booting with Secure Boot enabled. Within lockdown mode, kernel module signature validation is enforced. With the mainline kernel, users who wanted the extra flexibility to load their own kernel modules had to go through a complex process to enroll their own keys. This is a thing of the past, as there is now a much simpler process which this blog will explain.

History

Back in 2013, Linus requested a feature to allow end-users to have the ability “to add their own keys and sign modules they trust” [1]. Many attempts over the years were proposed to solve this problem; all were rejected. The most popular one that many distributions picked up (but was outright rejected upstream) was to load pre-boot firmware keys into the kernel, including the Secure Boot keys.

Keyrings

Linux keyrings are an in-kernel key management and retention facility. Prior to Linux mainline version 5.18, there were two restricted system kernel keyrings (builtin_trusted_keys and secondary_trusted_keys). Only these two keyrings could be used as a trust source for validating and loading sensitive code into the kernel. The keys contained in the builtin_trusted_keys keyring are compiled into the kernel (so vendor specific) and as such, it is not possible to add keys to this keyring during runtime. The secondary_trusted_keys keyring may have new keys loaded into it at anytime; however, the key being added to this keyring must be signed by a key already in the builtin_trusted_keys keyring. In effect, this meant that the key would need to be signed by the distro. There is no established mechanism for the users of a distro to get their keys signed to be included in this keyring.

What is New

On UEFI platforms, Linux is traditionally booted from shim, a light weight bootable signed executable. Shim owns many Boot Services (BS) UEFI variables. One such shim variable is Machine Owner Keys (MOK). These are keys the system owner has declared they trust. These keys can be used to validate things further down in the boot chain. For instance, a MOK key could be used to validate a custom kernel with Secure Boot enabled.

Linux 5.18 has introduced a new restricted system kernel keyring, “machine keyring”. The keys within the machine keyring are trusted for use within the Linux kernel. With the introduction of the machine keyring, MOK keys may now be used within Linux. For example: to validate a kernel module allowing the system owner to include their own keys as a trust source for use within the Linux kernel [2]. Just like the builtin_trusted_keys keyring is linked to the secondary_trusted_keys keyring, the new machine keyring is linked to it as well. With this new link in place, the machine keyring will be referenced when the kernel uses the secondary_trusted_keys keyring to vouch for something.

A new UEFI variable has been introduced to enable the machine keyring in Linux. This variable allows the system owner the ability to decide if they want to trust the MOK keys [3]. Within the Oracle Linux shim, this variable is on by default. The system owner may decide to turn this off with mokutil [4]. Again, just like enrolling MOK keys, changing this behavior happens after the reboot.

Oracle Linux Support

By default, the machine keyring will contain three MOK keys that are embedded into shim. These three keys are necessary for booting GRUB2 and Linux. As root on a machine, the keys can be displayed using the keyctl utility:

$ keyctl show %:.secondary_trusted_keys
Keyring
 772746105 ---lswrv      0     0  keyring: .secondary_trusted_keys
 252396885 ---lswrv      0     0   \_ keyring: .builtin_trusted_keys
 660166481 ---lswrv      0     0   |   \_ asymmetric: Oracle CA Server: 702a35b0d12005e5010c0614f7b8abf7c5bd5f73
  86702374 ---lswrv      0     0   |   \_ asymmetric: Oracle IMA signing CA: a2f28976a05984028f7d1a4904ae14e8e468e551
 247354640 ---lswrv      0     0   |   \_ asymmetric: Oracle America, Inc.: Ksplice Kernel Module Signing Key: 09010ebef5545fa7c54b626ef518e077b5b1ee4c
 264616160 ---lswrv      0     0   |   \_ asymmetric: Oracle Linux Kernel Module Signing Key: 2bb352412969a3653f0eb6021763408ebb9bb5ab
 772320403 ---lswrv      0     0   \_ keyring: .machine
 450491670 ---lswrv      0     0       \_ asymmetric: Oracle America, Inc.: 7c552922286d66bcb33c53d7ee0f1cd716ecdc63
 100307441 ---lswrv      0     0       \_ asymmetric: Oracle America, Inc.: 39bff3f0f578f26e527321cafda2a9cdbd71143c
 688922247 ---lswrv      0     0       \_ asymmetric: Oracle America, Inc.: 4ff35c3e09ce586fa776d56468d86b022af272f1

The examples presented in this section will illustrate two different approaches that can be used to enroll MOK keys to the machine keyring using Oracle Linux UEK7. There are various tools, methods and hardware for generating and storing private keys. The examples below use the most insecure method for demonstration purposes only. These examples also assume you have root access.

Using mokutil

  • Create a signing certificate to be enrolled in MOK
$ efikeygen -d /etc/pki/pesign --ca --self-sign --nickname="mokcert" --common-name='CN=FooBar' --serial=00  --kernel
  • Export the public certificate
$ certutil -L -d /etc/pki/pesign -n "mokcert" -o mokcert.der -r
  • Import the public certificate into the MOK

At the password prompt, create a temporary password and enter. This password will need to be entered again when shim loads MokManager to complete the MOK enrollment:

$ mokutil --import ./mokcert.der
input password:
input password again: 
  • Reboot the machine

Follow the onscreen prompts from MokManager for enrolling the new MOK key. MokManager will prompt you to enter the password created in the previous step. After the MOK key is enrolled, reboot the machine again. Afterwards, the new FooBar key will be included in the machine keyring.

$ keyctl show %:.secondary_trusted_keys
Keyring
 312971308 ---lswrv      0     0  keyring: .secondary_trusted_keys
1037502130 ---lswrv      0     0   \_ keyring: .builtin_trusted_keys
 330709123 ---lswrv      0     0   |   \_ asymmetric: Oracle CA Server: 702a35b0d12005e5010c0614f7b8abf7c5bd5f73
1015945864 ---lswrv      0     0   |   \_ asymmetric: Oracle IMA signing CA: a2f28976a05984028f7d1a4904ae14e8e468e551
 995965637 ---lswrv      0     0   |   \_ asymmetric: Oracle America, Inc.: Ksplice Kernel Module Signing Key: 09010ebef5545fa7c54b626ef518e077b5b1ee4c
 568726060 ---lswrv      0     0   |   \_ asymmetric: Oracle Linux Kernel Module Signing Key: 2bb352412969a3653f0eb6021763408ebb9bb5ab
 245236924 ---lswrv      0     0   \_ keyring: .machine
  75753354 ---lswrv      0     0       \_ asymmetric: Oracle America, Inc.: 7c552922286d66bcb33c53d7ee0f1cd716ecdc63
 423569441 ---lswrv      0     0       \_ asymmetric: FooBar: d542d5b607e29fbe3fc38373bfd8511078e0dbcb
 610218071 ---lswrv      0     0       \_ asymmetric: Oracle America, Inc.: 39bff3f0f578f26e527321cafda2a9cdbd71143c
 865719351 ---lswrv      0     0       \_ asymmetric: Oracle America, Inc.: 4ff35c3e09ce586fa776d56468d86b022af272f1

Using Certmule

If the system owner has a key in the UEFI Secure Boot DB, they can enroll keys into the MOK without showing physical presence [5]. This simplifies the MOK key enrollment process for large fleets where the key is deployed through the machine’s firmware. The binary, “certmule,” contains the key to be enrolled in the MOK and is signed by the DB key. As shim boots, upon seeing and validating a certmule, it will load the key into the MOK. Later, if the the key used to sign the certmule is revoked, the key will not be loaded into the MOK on subsequent boots.

  • Create a signing certificate to be embedded into a certmule binary
$ efikeygen -d /etc/pki/pesign --ca --self-sign --nickname='certmule' --common-name="CN=Test" --serial=00 --kernel
  • Clone the certmule repository and cd into it
$ git clone https://github.com/rhboot/certmule.git
$ cd certmule
  • Export the public certificate just created
$ certutil -L -d /etc/pki/pesign -n certmule -o certmule.der -r
  • Convert the x509 certificate format to an EFI Signature List format

With OL9 use efisecdb

$ efisecdb -a -g $(uuidgen) -c certmule.der -o db.esl

With OL8 use efisiglist

$ efisiglist -a -c certmule.der -o db.esl
  • Make the certmule
$ make update all

The certmule binary may be signed by any key contained within the UEFI Secure Boot DB. In this example, we are assuming the key embedded into the certmule is also already contained within the UEFI Secure Boot DB.

$ pesign -i certmule.efi -o /boot/efi/EFI/redhat/shim_certificate.efi -c certmule -s
  • Reboot the machine

After the reboot, the new Test certificate will be contained within the machine keyring.

$ keyctl show %:.secondary_trusted_keys
Keyring
 584848485 ---lswrv      0     0  keyring: .secondary_trusted_keys
 710271780 ---lswrv      0     0   \_ keyring: .builtin_trusted_keys
 694162499 ---lswrv      0     0   |   \_ asymmetric: Oracle CA Server: 702a35b0d12005e5010c0614f7b8abf7c5bd5f73
  23095449 ---lswrv      0     0   |   \_ asymmetric: Oracle IMA signing CA: a2f28976a05984028f7d1a4904ae14e8e468e551
 248749911 ---lswrv      0     0   |   \_ asymmetric: Oracle America, Inc.: Ksplice Kernel Module Signing Key: 09010ebef5545fa7c54b626ef518e077b5b1ee4c
 563122648 ---lswrv      0     0   |   \_ asymmetric: Oracle Linux Kernel Module Signing Key: 2bb352412969a3653f0eb6021763408ebb9bb5ab
 624487900 ---lswrv      0     0   \_ keyring: .machine
 848354545 ---lswrv      0     0       \_ asymmetric: Oracle America, Inc.: 7c552922286d66bcb33c53d7ee0f1cd716ecdc63
 959810021 ---lswrv      0     0       \_ asymmetric: Test: 8c7c76bb0d7cec080a9d3b5707d6ca9656676c96
1016027627 ---lswrv      0     0       \_ asymmetric: Oracle America, Inc.: 39bff3f0f578f26e527321cafda2a9cdbd71143c
 965116557 ---lswrv      0     0       \_ asymmetric: Oracle America, Inc.: 4ff35c3e09ce586fa776d56468d86b022af272f1

Untrust MOK keys within the kernel

By default, MOK keys are trusted and loaded into the machine keyring. If no additional MOK keys are loaded, the secondary_trusted_keys keyring will look similar to this:

$ keyctl show %:.secondary_trusted_keys
Keyring
 881532104 ---lswrv      0     0  keyring: .secondary_trusted_keys
 916562914 ---lswrv      0     0   \_ keyring: .builtin_trusted_keys
 957550911 ---lswrv      0     0   |   \_ asymmetric: Oracle CA Server: 702a35b0d12005e5010c0614f7b8abf7c5bd5f73
 201362191 ---lswrv      0     0   |   \_ asymmetric: Oracle IMA signing CA: a2f28976a05984028f7d1a4904ae14e8e468e551
 955284467 ---lswrv      0     0   |   \_ asymmetric: Oracle America, Inc.: Ksplice Kernel Module Signing Key: 09010ebef5545fa7c54b626ef518e077b5b1ee4c
 120852846 ---lswrv      0     0   |   \_ asymmetric: Oracle Linux Kernel Module Signing Key: 2bb352412969a3653f0eb6021763408ebb9bb5ab
  65129500 ---lswrv      0     0   \_ keyring: .machine
 796703122 ---lswrv      0     0       \_ asymmetric: Oracle America, Inc.: 7c552922286d66bcb33c53d7ee0f1cd716ecdc63
 536326034 ---lswrv      0     0       \_ asymmetric: Oracle America, Inc.: 39bff3f0f578f26e527321cafda2a9cdbd71143c
1019822789 ---lswrv      0     0       \_ asymmetric: Oracle America, Inc.: 4ff35c3e09ce586fa776d56468d86b022af272f1
  • Untrust the MOK keys from the machine keyring using mokutil

There will be a password prompt. This is a password you are creating. This password will need to be entered again when shim loads MokManager to untrust the MOK keys.

$ mokutil --untrust-mok
password length: 8~16
input password:
input password again: 
  • Reboot the machine

Follow the onscreen prompts from MokManager for untrusting the MOK keys. MokManager will prompt you to enter the password created in the previous step. Reboot the machine again. Afterwards, the machine keyring will not be used.

$ keyctl show %:.secondary_trusted_keys
Keyring
 914631770 ---lswrv      0     0  keyring: .secondary_trusted_keys
 181249890 ---lswrv      0     0   \_ keyring: .builtin_trusted_keys
 628701142 ---lswrv      0     0       \_ asymmetric: Oracle CA Server: 702a35b0d12005e5010c0614f7b8abf7c5bd5f73
 306795764 ---lswrv      0     0       \_ asymmetric: Oracle IMA signing CA: a2f28976a05984028f7d1a4904ae14e8e468e551
 300928728 ---lswrv      0     0       \_ asymmetric: Oracle America, Inc.: Ksplice Kernel Module Signing Key: 09010ebef5545fa7c54b626ef518e077b5b1ee4c
 805419922 ---lswrv      0     0       \_ asymmetric: Oracle Linux Kernel Module Signing Key: 2bb352412969a3653f0eb6021763408ebb9bb5ab

All MOK keys will show up in the platform keyring, along with the UEFI Secure Boot DB keys.

$ keyctl show %:.platform
Keyring
 797568476 ---lswrv      0     0  keyring: .platform
 718847600 ---lswrv      0     0   \_ asymmetric: Microsoft Windows Production PCA 2011: a92902398e16c49778cd90f99e4f9ae17c55af53
 540371605 ---lswrv      0     0   \_ asymmetric: Oracle America, Inc.: 39bff3f0f578f26e527321cafda2a9cdbd71143c
 936540732 ---lswrv      0     0   \_ asymmetric: Oracle America, Inc.: 4ff35c3e09ce586fa776d56468d86b022af272f1
 416352496 ---lswrv      0     0   \_ asymmetric: Oracle America, Inc.: 7c552922286d66bcb33c53d7ee0f1cd716ecdc63
 633944648 ---lswrv      0     0   \_ asymmetric: Microsoft Corporation UEFI CA 2011: 13adbf4309bd82709c8cd54f316ed522988a1bd4

References

  1. https://marc.info/?l=linux-kernel&m=136185386310140&w=2
  2. https://lkml.kernel.org/lkml/20220126025834.255493-1-eric.snowberg@oracle.com/
  3. https://github.com/rhboot/shim/commit/4e513405b4f1641710115780d19dcec130c5208f
  4. https://github.com/lcp/mokutil/commit/0276891eb83ed1fa5153c543297a296f143e0740
  5. https://github.com/rhboot/shim/commit/35d7378d29b9ad6f664df20efc4121e210859e65

Eric Snowberg


Previous Post

Understanding Ext4 Disk Layout, Part 1

Srivathsa Dara | 30 min read

Next Post


Measuring NVMe Latency

Rajan Shanmugavelu | 12 min read