3 Signing Kernel Images and Kernel Modules for Use With Secure Boot

This chapter provides instructions on signing kernel modules for Secure Boot.

Attention:

Oracle doesn't support any modules that are built from source directly outside of Oracle's official release mechanisms. For help with these modules, contact the hardware vendor.

A system in Secure Boot mode only loads boot loaders and kernels that have been signed by Oracle. However, you might need to build and install a third-party module to enable specific hardware on a deployed system. If you still require UEFI Secure Boot, the module must be signed with a key that can be validated against a certificate within the UEFI Secure Boot key database or within the MOK database so that the module is recognized at boot.

Important:

Using the MOK utility on a server depends on server firmware implementation and configuration. Check that the server provides this capability before manually updating signature keys used for UEFI Secure Boot. If you're unsure, don't follow the instructions provided here.

Adding certificates to the MOK database by using the MOK utility requires that you have physical access to the system so that you can complete the enrollment request after the Shim is loaded by UEFI. Don't follow the instructions in this document if you have no physical access to the system.

Because of differences in kernel releases, instructions on how to sign modules differ depending on the kernel version on the system. In particular, the key signature type within the module signature has changed from X.509 to PKCS#7. Therefore, although the process to sign the module by using the kernel-provided sign-file utility is still used, you might be required to use a utility more appropriate to the specific kernel for which a module is being signed.

Requirements for Signing Kernel Images and Kernel Modules

Before you can sign a module, you must install several required packages, including the kernel source for the kernel where the module is loaded. You also require a signing certificate for a key pair that you have created for this purpose.

Signing kernel images and kernel modules have the following requirements:

Installing Required Packages

You need only a standard minimal installation of the latest Oracle Linux 10 release for this procedure. The steps assume that the system is using UEK as the operating environment.

  1. Install the required kernel packages.

    Obtain the package that contains the system's kernel source:

    sudo dnf install kernel-uek-devel

    Note:

    If you're using RHCK, the kernel source is in the kernel-devel package.

  2. Update the system.

    Update the system to ensure that you have the most recent kernel and related packages:

    sudo dnf update
  3. Reboot the system.

    This step is in case the kernel is included in the system update. By rebooting, you avoid confusion around the kernel version that you're working with and the kernel running on the system when you begin kernel-signing operations.

  4. Install the module signing utilities.

    Install the required utilities for performing module signing operations.

    sudo dnf install openssl keyutils mokutil pesign
  5. (Optional) install build tools.

    If you need to build modules from source, you might install the Development Tools group to ensure that build tools are available, for example:

    sudo dnf group install "Development Tools"

Generating a Signing Certificate

If you don't already have a signing certificate to be used for signing third-party modules or kernel images, you can generate one by using the OpenSSL utilities. For more information about OpenSSL and the public key infrastructure, see Oracle Linux: Managing Certificates and Public Key Infrastructure.
  1. Create a configuration file that OpenSSL can use to obtain default values when generating certificates.

    As best practice, create the file in /etc/ssl/x509.conf with the rest of the OpenSSL configuration. The following is an example of the configuration file:

    [ req ]
    default_bits = 4096
    distinguished_name = req_distinguished_name
    prompt = no
    string_mask = utf8only
    x509_extensions = extensions
    
    [ req_distinguished_name ]
    O = Module Signing Example
    CN = Module Signing Example Key
    emailAddress = first.last@example.com
    
    [ extensions ]
    basicConstraints=critical,CA:TRUE
    keyUsage=digitalSignature
    extendedKeyUsage = codeSigning
    subjectKeyIdentifier=hash
    authorityKeyIdentifier=keyid:always
  2. Generate a new key pair from the configuration file.

    For example, the following command creates a signing certificate that's valid for 10 years (3,650 days).

    sudo openssl req -x509 -new -nodes -utf8 -sha512 -days 3650 -batch -config /etc/ssl/x509.conf -outform DER -out /etc/ssl/certs/pubkey.der -keyout /etc/ssl/certs/priv.key

    Ensure that the keys are adequately protected.

  3. Export the certificate in PEM format.

    Enter the following command to export the certificate as a .pem file:

    sudo openssl x509 -inform DER -in /etc/ssl/certs/pubkey.der -out /etc/ssl/certs/pubkey.pem

Signing the Kernel for Secure Boot

UEFI Secure Boot requires that kernels are signed with a trusted certificate to prevent attackers from installing and running unauthorized OSs.

Oracle signs kernel releases that are provided through official software channels to verify their origin and integrity. For a custom kernel to perform the boot or kexec operations, you must sign the kernel image by using the signing certificate that you created and confirm that you trust kernel images that are signed with that certificate.

Signing the kernel for Secure Boot involves the following tasks:

  1. Configuring an NSS Database

  2. Signing the Kernel Image

  3. Updating the MOK Database

Configuring an NSS Database

The NSS database stores complete sets of keys that the tool for signing kernels accesses to obtain the kernel signing key.

  1. Configure an NSS database.

    Run the following command to create a certificate and key database in the current directory.

    sudo certutil -d . -N
  2. Create a password for the database as prompted.
  3. Export a PKCS#12 version of the kernel signing key.

    NSS utilities are only capable of working with PKCS#12 formatted key files, so you need to perform this step so that you can sign the kernel image.

    sudo openssl pkcs12 -export -inkey /etc/ssl/certs/priv.key -in /etc/ssl/certs/pubkey.pem -name cert -out /etc/ssl/certs/cert.p12
  4. Enter the export password as prompted.

    The password refers to the password for the PKCS#12 archive. For convenience, make this password match the password for the NSS database.

  5. Add or import the PKCS#12 version of the kernel signing key.

    Enter the following command to import the kernel signing key to the new database.

    sudo pk12util -d . -i cert.p12
  6. Enter the passwords as prompted.

    Two password prompts are displayed: first, for the NSS database, then for the PKCS#12 archive.

    Enter Password or Pin for "NSS Certificate DB":
    Enter password for PKCS12 file:
    pk12util: PKCS12 IMPORT SUCCESSFUL

Signing the Kernel Image

In this task, you use the pesign utility to sign the kernel with a new signature using the signing key in the NSS database.

  1. Remove the existing PE signature.

    Enter the following command:

    sudo pesign -u 0 -i /boot/vmlinuz-$(uname -r) --remove-signature -o vmlinuz.unsigned
  2. Assign a new signature.

    Assign a new signature based on the kernel signing key in the NSS database:

    sudo pesign -n . -c cert -i vmlinuz.unsigned -o vmlinuz.signed -s
  3. Enter the password as prompted.

    The password of the NSS certificate database is the one that you created in Configuring an NSS Database.

  4. Copy the signed kernel back to the /boot directory.

    The following command performs the copy operation. The -b option in the command creates a backup of the original kernel image.

    sudo cp -bf vmlinuz.signed /boot/vmlinuz-$(uname -r)

Updating the MOK Database

Because the key that you created isn't included in the UEFI Secure Boot Key Database, you must enroll it into the MOK database in the Shim.

  1. Import the key.

    Import the key with the following command:

    sudo mokutil --import /etc/ssl/certs/pubkey.der

    The command prompts you for a single-use password that you use when the MOK Management service enrolls the key after you reboot the system.

  2. Reboot the system.

    The UEFI Shim automatically starts the Shim UEFI key manager at boot. Ensure that you hit a key within 10 seconds to interrupt the boot process to enroll the MOK key you created.

  3. Press any key to perform MOK Management.
  4. Select Enroll MOK from the menu.
  5. Select View key 0 from the menu to display the key details.
  6. Check and confirm.

    Verify that the values presented match the key that you used to sign the module and that you inserted into the kernel image, then press any key to return to the Enroll MOK menu.

  7. Select Continue from the menu.

    The Enroll the key(s)? screen is displayed.

  8. Select Yes to enroll the key.
  9. Enter the password

    At the password prompt, enter the password that you used when you imported the key at the beginning of this procedure.

    The key is enrolled within the UEFI Secure Boot key database.
  10. Reboot the system.

    When the Perform MOK management screen is displayed, select Reboot from the menu.

Signing the Kernel Module for Secure Boot

UEFI Secure Boot requires that kernel modules are signed with a trusted certificate to prevent attackers from installing and running unauthorized OS and malicious drivers.

Oracle signs kernel releases that are provided through official software channels to verify their origin and integrity. However, to install other drivers, you must create signing certificates for them, sign the relevant kernel modules, and confirm that you trust the kernel modules that are signed with that certificate.

UEFI Secure Boot trusts modules that are signed using platform certificates that are available in the UEFI and MOK databases. The key for signing the module is enrolled into the database.

Signing the kernel module involves the following tasks:

  1. Signing the Kernel Module

  2. Updating the MOK Database with the Kernel Module Certificate

Signing the Kernel Module

The sign-file utility ensures that the module is signed correctly for the kernel. This utility is provided within the kernel source.

  1. Ensure that module is already installed in /lib/modules/.
  2. Run the sign-file utility for the running kernel.

    Enter the following command to sign the module.

    sudo /usr/src/kernels/$(uname -r)/scripts/sign-file sha512 /etc/ssl/certs/priv.key /etc/ssl/certs/pubkey.der /lib/modules/$(uname -r)/path/to/module.ko
  3. (Optional) Check the signature information of the module.

    Use the modinfo command to check the signature information. The syntax is:

    modinfo module

    For example, a module named hello might display the following output:

    filename: /lib/modules/6.12.0-0.20.20.el10uek.x86_64/extra/hello.ko                      
    description:    Hello World Linux Kernel Module
    author:         A.Developer
    license:        GPL
    srcversion:     D51FB4CF0B86314953EE797
    depends:        
    retpoline:      Y
    name:           hello
    vermagic:       6.12.0-0.20.20.el10uek.x86_64 SMP mod_unload modversions 
    sig_id:         PKCS#7
    signer:         Module Signing Example Key
    sig_key:        AB:2C:E3:AB:87:D9:9C:6A:31:B8:80:20:D4:92:25:F3:9A:26:DC
    sig_hashalgo:   sha512
    signature:      9F:B0:25:CB:14:C1:C7:10:7F:60:1E:E6:66:82:64:58:91:1F:01:A5:
                    D9:03:1B:9C:2D:42:00:45:78:2B:FA:70:F8:C7:3B:1A:A2:42:00:09:
                    33:E0:81:1D:C6:E6:46:A5:FE:8B:9F:8C:3D:4E:A1:3A:05:52:ED:F6:
                    25:F9:88:98:D3:70:78:1D:7E:63:F3:73:C8:C8:14:C2:3A:52:B4:8F:
                    4C:8D:80:D9:0D:24:F8:C9:B1:28:82:B6:A9:27:56:C6:86:80:25:A5:
                    75:C8:78:A9:30:BD:01:4C:DD:43:7F:FD:41:98:2C:59:21:7D:39:17:
                    EC:2C:C1:65:1D:95:F0:09:C7:F6:45:10:83:15:78:A2:EE:D4:73:79:
                    B2:F0:57:C1:96:B3:4C:43:B8:D1:87:94:50:61:D6:EC:50:2B:6A:6C:
                    5C:C1:3E:8C:CB:6F:19:DC:EF:6C:12:07:03:99:B7:B3:22:0B:F6:AC:
                    CB:40:C6:34:15:EA:1F:88:D4:4E:1C:87:2D:5A:92:F7:12:A6:E7:91:
                    B3:80:AA:80:8F:49:B7:F0:F0:97:05:09:7A:65:30:4A:AE:10:BE:9F:
                    6A:E4:B2:24:BE:1A:21:D0:F6:15:05:DA:2C:64:EA:B2:8E:AC:6F:18:
                    40:65:21:F6:AA:17:31:AE:3F:3A:43:DB:A8:BC:71:79:EF:11:18:DE:
                    86:EE:74:2A:E0:44:FC:B3:FF:CB:CB:F0:CA:BD:7B:A1:57:84:D8:A6:
                    91:E5:B8:EF:1B:8A:63:16:43:03:AF:C4:C7:BF:52:9A:A9:23:75:C6:
                    42:54:69:4E:3D:51:56:5A:9D:9B:C7:11:5E:9A:30:87:5F:F3:5E:C3:
                    AE:2C:1D:6F:C9:4D:15:E5:CF:EC:46:0E:EF:D9:BB:2F:DF:DF:54:EA:
                    F3:B6:9C:A3:6F:80:19:B9:DF:FA:2A:30:4E:2E:70:74:11:F9:5C:F6:
                    EE:1A:DF:86:C4:2B:36:7E:B4:A4:D4:7E:30:19:1A:D1:92:D3:A7:FB:
                    53:BF:67:C3:65:9E:4B:92:F0:6C:D4:6C:05:9B:0F:BF:D1:5B:CB:86:
                    AE:68:00:AE:43:53:8B:7D:7E:18:20:CD:65:68:6C:4A:0D:93:A4:54:
                    09:39:9C:D3:BD:CD:17:B6:8A:D3:62:0C:CA:A8:FD:1A:52:CE:29:A0:
                    93:BF:AD:D2:58:3F:EA:4E:4B:50:31:6F:F6:B2:1E:87:C4:0A:9D:E4:
                    43:E9:C7:CA:E9:CB:EF:A6:61:5B:DA:01:33:37:66:DB:16:8D:7C:D7:
                    30:39:57:D4:0C:1A:54:AE:91:7B:FE:35:10:CC:34:03:99:EA:5A:57:
                    E0:95:61:02:42:95:A2:F5:2E:72:30:95

Updating the MOK Database with the Kernel Module Certificate

Because the key that you created isn't included in the UEFI Secure Boot Key Database, you must enroll it into the MOK database in the Shim.

  1. Import the key.

    Use the mokutil utility to import the key:

    sudo mokutil --import /etc/ssl/certs/pubkey.der

    The command prompts you for a single use password that you use when the MOK Management service enrolls the key after you reboot the system.

  2. Reboot the system.

    The UEFI Shim automatically starts the Shim UEFI key manager at boot. Ensure that you hit a key within 10 seconds to interrupt the boot process to enroll the MOK key you created.

  3. Press any key to perform MOK Management.
  4. Select Enroll MOK from the menu.
  5. Select View key 0 from the menu to display the key details.
  6. Check and confirm the key values.

    Verify that the values presented match the key that you used to sign the module and that you inserted into the kernel image, then press any key to return to the Enroll MOK menu.

  7. Select Continue from the menu.

    The Enroll the key(s)? screen is displayed.

  8. Select Yes to enroll the key.
  9. Enter the password.

    At the password prompt, enter the password that you used when you imported the key at the beginning of this procedure.

    The key is enrolled within the UEFI Secure Boot key database.

  10. Reboot the system.

    When the Perform MOK management screen is displayed, select Reboot from the menu.

Validating That a Key Is Trusted

After the system is booted, you can validate whether a key is included in the appropriate kernel keyring. Validation depends on the kernel version that you're running. Also, the keyring name that you need to check varies, as the implementation has changed across kernel versions.

If the key that was generated for signing custom modules is listed within the correct keyring, you can load modules that are signed with this key while in Secure Boot mode.

UEK R8

The following describes how to validate a key in UEK R8.

The UEK R8 release provides the .machine keyring to enhance security. Keys in the .machine keyring are trusted by the Oracle Linux kernel. At system boot, all MOK keys are loaded into the .machine keyring.

The .machine keyring is linked to the .secondary_trusted_keys keyring. This linkage ensures that the .machine keyring is consulted whenever the kernel checks the .secondary_trusted_keys keyring to validate a signed kernel module.

In essence, when validating a signed kernel module, the kernel use the keys in the .secondary_trusted_keys keyring, which now also references the trusted keys in the .machine keyring, ensuring a comprehensive validation process. This is shown in the following example:

sudo 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

For more information, see the following article: The Machine Keyring.

RHCK

The following describes how to validate a key for Red Hat Compatible Kernels (RHCK).

Keys within both the builtin_trusted_keys keyring and the platform keyring are trusted for both module signing and for the kexec tools. You can follow the standard procedure to sign a module and add it to the MOK database for the key to appear in the platform keyring. The keyring is then automatically trusted.

Because a key can be loaded into the builtin_trusted_keys keyring, check both keyrings for the module signing key, for example:

sudo keyctl show %:.builtin_trusted_keys
Keyring
        441234704 ---lswrv      0     0  keyring: .builtin_trusted_keys
        798307349 ---lswrv      0     0   \_ asymmetric: Oracle CA Server: 32a7ceb6c56614c69b4729b455254bfaf09569a4
        277992501 ---lswrv      0     0   \_ asymmetric: Oracle Linux RHCK Module Signing Key: dd995b155c19b3a7c3ef7707b969e25f9639666e
        1000618915 ---lswrv     0     0   \_ asymmetric: Red Hat Enterprise Linux kpatch signing key: 4d38fd864ebe18c5f0b72e3852e2014c3a676fc8
        199403819 ---lswrv      0     0   \_ asymmetric: Red Hat Enterprise Linux Driver Update Program (key 3): bf57f3e87362bc7229d9f465321773dfd1f77a80
sudo keyctl show %:.platform
Keyring
        705628740 ---lswrv      0     0  keyring: .platform
        89698906 ---lswrv      0     0   \_ asymmetric: Microsoft Corporation UEFI CA 2011: 13adbf4309bd82709c8cd54f316ed522988a1bd4
        497244381 ---lswrv      0     0   \_ asymmetric: Oracle America, Inc.: d6ee3a06a222bf4244b8986a531046e59c14eeef
        710039804 ---lswrv      0     0   \_ asymmetric: Oracle America, Inc.: c65d1d746ae4cb127762e1dbd7ade48215703c5c
        730271863 ---lswrv      0     0   \_ asymmetric: Oracle America Inc.: 2e7c1720d1c5df5254cc93d6decaa75e49620cf8
        535985802 ---lswrv      0     0   \_ asymmetric: Oracle America, Inc.: 795c5945e7cb2b6773b7797571413e3695062514
        607819007 ---lswrv      0     0   \_ asymmetric: Oracle America, Inc.: f9aec43f7480c408d681db3d6f19f54d6e396ff4
        99739320 ---lswrv      0     0   \_ asymmetric: Oracle America, Inc.: 430c85cb8b531c3d7b8c44adfafc2e5d49bb89d4
        231916335 ---lswrv      0     0   \_ asymmetric: Microsoft Windows Production PCA 2011: a92902398e16c49778cd90f99e4f9ae17c55af53
        866576656 ---lswrv      0     0   \_ asymmetric: Oracle Linux Test Certificate: d30dffa37bec20ecfb1d3caee53cd746282e8cad
        230958440 ---lswrv      0     0   \_ asymmetric: Module Signing Example Key: a43b4e638874b0656db2bc26216f56c0ac39f72b