How to Sign the Shim Bootloader with Your Own Secure Boot Keys

If you’ve ever attempted to build a Linux system that complies with Secure Boot requirements, you’ve likely encountered the Shim bootloader—a vital component that bridges UEFI Secure Boot and your custom bootloader or kernel. Producing your own signed bootloader is essential for organizations that want a custom security chain, or for enthusiasts who prefer not to rely on third-party Microsoft certificates.

TL;DR: Signing the Shim bootloader involves generating your own secure boot keys, building or obtaining a copy of Shim, and then signing it using your own keys. You will then need to enroll these keys in the machine’s firmware using a tool like KeyTool or via the UEFI setup. This allows you to create a Secure Boot environment fully under your control, without depending on Microsoft’s bootloader signing process.

Why Sign Shim Yourself?

By default, most distributions ship a Shim binary pre-signed by Microsoft, allowing them to be used on most UEFI-based systems without disabling Secure Boot. However, there are several good reasons to take the DIY route:

  • Increased security: You’re not relying on third-party certificates.
  • Custom trust chains: You can enforce your own chain of trust, including custom kernels and EFI binaries.
  • Offline or embedded systems: Useful in restricted environments or NPC (No Public Cloud) deployments.

Before diving in, be aware that this guide assumes some familiarity with Linux, UEFI, and shell commands.

Step 1: Generate Your Secure Boot Keys

Secure Boot requires three keys:

  • Platform Key (PK): Authorizes updates to KEK.
  • Key Exchange Key (KEK): Allows updates to the DB and DBX (bootloader whitelist and blacklist).
  • Database Key (DB): Used to authorize EFI binaries like Shim.

You can use openssl to generate these keys:

openssl req -new -x509 -newkey rsa:2048 -subj "/CN=My Secure Boot PK/" \
  -keyout PK.key -out PK.crt -days 3650 -nodes

openssl req -new -x509 -newkey rsa:2048 -subj "/CN=My KEK/" \
  -keyout KEK.key -out KEK.crt -days 3650 -nodes

openssl req -new -x509 -newkey rsa:2048 -subj "/CN=My DB/" \
  -keyout DB.key -out DB.crt -days 3650 -nodes

Convert them to EFI Signature Lists (ESLs) and AUTH format using cert-to-efi-sig-list and sign-efi-sig-list from the efitools package.

Step 2: Build or Download Shim

You can either download a pre-compiled Shim source package or build it from source. If security is a concern, building from source allows you to verify and customize the build.

git clone https://github.com/rhboot/shim.git
cd shim
make

This will generate shimx64.efi and fbx64.efi (fallback loader). These binaries must be signed with your custom key that is enrolled in the DB database.

Step 3: Sign Shim with Your DB Key

Use sbsign (from sbsigntools) to sign Shim:

sbsign --key DB.key --cert DB.crt --output shimx64.signed.efi shimx64.efi

Repeat for the fallback binary:

sbsign --key DB.key --cert DB.crt --output fbx64.signed.efi fbx64.efi

These signed binaries are now ready to replace the default ones in your EFI system partition (ESP).

Step 4: Enroll Your Keys into UEFI

Once generated, your PK, KEK, and DB must be enrolled into the motherboard’s firmware. Secure Boot must be in Setup Mode to enroll custom keys. Many UEFI setups allow entering Setup Mode via settings or by clearing PK values.

Use KeyTool.efi (available in the efitools git repo) to enroll your keys via a USB stick:

  1. Copy KeyTool.efi and your .auth/.esl files to a FAT32 USB stick.
  2. Boot into KeyTool through your UEFI boot menu.
  3. Enroll each key in the correct order: PK → KEK → DB.

Step 5: Test Your Shim Environment

After key enrollment and replacing your default bootloader with the signed Shim version, reboot your machine. If all goes well, Secure Boot will authenticate your Shim binary using your DB key, and proceed to load your main bootloader (e.g., GRUB).

To verify the signature, you can use:

sbverify --list shimx64.signed.efi

This will display the certificate used and confirm that the binary is signed correctly.

Optional: Build an Entire Custom Boot Chain

For more control, consider signing your grubx64.efi and even the Linux kernel with the same DB key:

sbsign --key DB.key --cert DB.crt --output grubx64.signed.efi grubx64.efi

And for kernel:

sbsign --key DB.key --cert DB.crt --output vmlinuz.signed vmlinuz

This creates a complete trusted stack starting from UEFI to Shim, GRUB, and even the kernel.

Tips and Troubleshooting

  • Always keep a backup: Mistakes in signing or enrollment can create an unbootable system.
  • Keep unsigned binaries handy: For USB rescue boots or recovery scenarios.
  • Use a test VM: QEMU supports OVMF (UEFI firmware), which makes it ideal for experimenting.

Conclusion

Signing the Shim bootloader with your own keys gives you complete control of your Secure Boot environment. It’s an essential step for those wanting custom Linux distributions, fully trusted systems, or tighter control over their boot sequence. While initially complex, the process becomes manageable with clear structure and the right tools. By taking the extra effort to build and sign your bootloader chain, you significantly improve the integrity and security of your Linux deployments.

With the growing popularity of Secure Boot, understanding and customizing your own bootloaders is no longer just a developer’s hobby, but a professional requirement in many environments. Happy signing!