Skip to content

safeboot - new tool for setting up UEFI secure boot ​

TIP

Use the repo from https://github.com/umbernhard/safeboot instead of the original author https://github.com/osresearch/safeboot because it solve the bug of Function library not installed to correct path after dpkg install the deb file.

Bug mentioned in: https://github.com/osresearch/safeboot/issues/153 and fixed in: https://github.com/osresearch/safeboot/pull/155

Install safeboot ​

git clone https://github.com/umbernhard/safeboot
cd safeboot/
make requirements
make -j8
make all -j8
make package
dpkg -i safeboot-unstable.deb

After install, it will copy all files to /etc/safeboot

Next, verify safeboot command work.

# safeboot
Usage: /usr/sbin/safeboot [commands|yubikey-init|yubikey-pubkey|uefi-sign-keys|uefi-set-keys|pcrs-sign|luks-seal|sign|unify-kernel|sign-kernel|install-kernel|linux-sign|recovery-sign|recovery-reboot|bootnext|remount|sip-init|unlock|mount-all] ....

Use safeboot to init system ​

Create self-signed cert ​

Create a self-signed cert. This will prompt for PEM passphrase. This will create several files in /etc/safeboot

  • public key cert (signed):cert.pem and cert.crt
  • private key: signing.key

command:

safeboot key-init "/CN=$HOSTNAME.dsync89.com/OU=dsync89/O=dsync89.com/"

output:

# safeboot key-init "/CN=$HOSTNAME.dsync89.com/OU=dsync89/O=dsync89.com/"
$KEY=pkcs11:; updating in local.conf
Generating a RSA private key
...................+++++
..............................+++++
writing new private key to '/etc/safeboot/signing.key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
/etc/safeboot/cert.crt: Creating from /etc/safeboot/cert.pem
/etc/safeboot/cert.pub: Creating from /etc/safeboot/cert.pem

cert generated

Create three signed certs for PK, KEK, and db ​

Create three signed certificates for the PK, KEK, and db using the attached Yubikey or x509 key stored in /etc/safeboot/signing.key and store them in the UEFI SecureBoot configuration. You should have run safeboot yubikey-init or safeboot key-init to have already generated the keys.

Due to an issue with the OpenSSL PKCS11 engine, you will have to authenticate to the Yubikey multiple times during this process.

Note: You must enter Secure Boot Setup Mode by disabling secure boot status in BIOS before running, otherwise it will complain update db failed.

Run the following to reboot into BIOS firmware setup mode

systemctl reboot --firmware-setup

On OVMF BIOS VM. Make sure to uncheck Attempt Secure Boot. Also Reset all secure boot keys since we will use our own unless you want to sign the kernel. The default shim is still signed by Microsoft CA which signs Canonical.

example

safeboot uefi-sign-keys

output

# safeboot uefi-sign-keys
Signing UEFI variable db
Timestamp is 2022-11-3 06:45:53
Authentication Payload size 1019
Enter PEM pass phrase:
Signature of size 1400
Signature at: 40
Signing UEFI variable KEK
Timestamp is 2022-11-3 06:45:55
Authentication Payload size 1021
Enter PEM pass phrase:
Signature of size 1400
Signature at: 40
Signing UEFI variable PK
Timestamp is 2022-11-3 06:45:56
Authentication Payload size 1019
Enter PEM pass phrase:
Signature of size 1400
Signature at: 40
Installing UEFI variable db
Installing UEFI variable KEK
Installing UEFI variable PK

Verify

root@prestaging-worker1:/boot/efi/EFI/linux-unified-v2# efi-readvar
Variable PK, length 979
PK: List 0, type X509
    Signature 0, size 951, owner b63cd8b7-6b67-462f-ba49-0ba1d8220943
        Subject:
            CN=prestaging-worker1.dsync89.com, OU=dsync89, O=dsync89.com
        Issuer:
            CN=prestaging-worker1.dsync89.com, OU=dsync89, O=dsync89.com
Variable KEK, length 979
KEK: List 0, type X509
    Signature 0, size 951, owner b63cd8b7-6b67-462f-ba49-0ba1d8220943
        Subject:
            CN=prestaging-worker1.dsync89.com, OU=dsync89, O=dsync89.com
        Issuer:
            CN=prestaging-worker1.dsync89.com, OU=dsync89, O=dsync89.com
Variable db, length 979
db: List 0, type X509
    Signature 0, size 951, owner b63cd8b7-6b67-462f-ba49-0ba1d8220943
        Subject:
            CN=prestaging-worker1.dsync89.com, OU=dsync89, O=dsync89.com
        Issuer:
            CN=prestaging-worker1.dsync89.com, OU=dsync89, O=dsync89.com
Variable dbx, length -4
Variable MokList has no entries

Create Unified Kernel and Insert to Boot Entry ​

TIP

When using the install-kernel subcommand to build a unified EFI, safeboot will use the HARDCODED path for kernel=/boot/vmlinuz which is a softlink to /boot/vmlinuz -> vmlinuz-5.4.0-131-generic and initrd=/initrd.img -> initrd.img-5.4.0-131-generic.

So there is no effect if you still specify kernel=/boot/vmlinuz-$(uname -r) andinitrd=/boot/initrd.img-$(uname -r) in the parameters.

But you still have to specify the root= parameter.

safeboot install-kernel unified-linux \
root=/dev/mapper/ubuntu--vg-ubuntu--lv ro \
evm=fix ima_tcb lsm=integrity ima_appraise=fix ima_policy=tcb ima_hash=sha256

We will use the initrd image created by clevis.

command

safeboot install-kernel linux-unified /boot/efi/EFI/linux/linux.efi kernel=vmlinuz-$(uname -r) initrd=initrd.img-$(uname -r) cmdline=BOOT_IMAGE=/vmlinuz-$(uname -r) root=/dev/mapper/ubuntu--vg-ubuntu--lv ro

output

# safeboot install-kernel linux-unified /boot/efi/EFI/linux/linux.efi kernel=/boot/vmlinuz-$(uname -r) initrd=/boot/initrd.img-$(uname -r) cmdline=BOOT_IMAGE=/vmlinuz-$(uname -r) root=/dev/mapper/ubuntu--vg-ubuntu--lv ro
/boot/efi/EFI/linux-unified: Creating directory on EFI System Partition
/boot/efi/EFI/linux-unified: Creating boot menu item on /dev/sda1, partition 1
Kernel commandline: '/boot/efi/EFI/linux/linux.efi kernel=vmlinuz-5.4.0-131-generic initrd=initrd.img-5.4.0-131-generic cmdline=BOOT_IMAGE=/vmlinuz-5.4.0-131-generic root=/dev/mapper/ubuntu--vg-ubuntu--lv ro'
/tmp/tmp.8vKxvcBiXC/linux.efi: Creating merged Linux/initrd image
.osrel=/etc/os-release: 382 @ 131072
.cmdline=/tmp/tmp.8vKxvcBiXC/cmdline.txt: 186 @ 196608
.linux=/boot/vmlinuz: 13664512 @ 262144
.initrd=/boot/initrd.img: 98509281 @ 13959168
/boot/efi/EFI/linux-unified/linux.efi.new: Signing (ignore warnings about gaps)
warning: data remaining[112221184 vs 112230796]: gaps between PE/COFF sections?
warning: data remaining[112221184 vs 112230800]: gaps between PE/COFF sections?
Enter PEM pass phrase:
Signing Unsigned original image
warning: data remaining[112222952 vs 112232568]: gaps between PE/COFF sections?
e0222a567c6eef77e88620d4ad165b63ae5e35730e27129a0bb1d02a5ffac782
059adb2cbc12d50593459a365f0f6aecf032cbf38f1171471007fa12af83bb1a  /boot/efi/EFI/linux-unified/linux.efi

Check that it is added and pointed to the right folder

# bootctl
...
Boot Loaders Listed in EFI Variables:
        Title: linux-unified-v2
           ID: 0x000A
       Status: active, boot-order
    Partition: /dev/disk/by-partuuid/4e09cb24-4fdf-4fa3-8aee-fdc8815011e9
         File: └─/EFI/linux-unified-v2/linux.efi
...

Check the signed unified EFI

# sbverify -l linux.efi
warning: data remaining[112222952 vs 112232568]: gaps between PE/COFF sections?
signature 1
image signature issuers:
 - /CN=prestaging-worker1.dsync89.com/OU=dsync89/O=dsync89.com
image signature certificates:
 - subject: /CN=prestaging-worker1.dsync89.com/OU=dsync89/O=dsync89.com
   issuer:  /CN=prestaging-worker1.dsync89.com/OU=dsync89/O=dsync89.com

Check that linux-unified-v2 boot order comes first

# efibootmgr
BootCurrent: 0007
Timeout: 3 seconds
BootOrder: 000A,0009,0008,0007,0006,0003,0001,0004,0005,0000,0002
Boot0000* UiApp
Boot0001* UEFI QEMU DVD-ROM QM00003
Boot0002* EFI Internal Shell
Boot0003* UEFI QEMU QEMU HARDDISK
Boot0004* UEFI PXEv4 (MAC:2E5A3B52DAC5)
Boot0005* UEFI HTTPv4 (MAC:2E5A3B52DAC5)
Boot0006* ubuntu
Boot0007* linux
Boot0008* /boot/efi/EFI/linux/linux.efi
Boot0009* linux-unified
Boot000A* linux-unified-v2

Reboot and profit!

systemctl reboot --firmware-setup

Optional: If prior to running this, you already setup LUKS using clevis-tpm2 PIN and measure it to PCR bank 0-2 ​

If you setup LUKS using clevis-tpm2 PIN and measure it to PCR bank 0-2, the measurement will failed since the pcr bank changed. In other words, the disk won't be auto unlocked by clevis when you reboot in initrd image.

First, unbind the previously generated luks key

clevis luks unbind -d /dev/sda3 -s 1

Then, rebind

clevis luks bind -d /dev/sda3 tpm2 '{"pcr_bank":"sha256","pcr_ids":"0,1"}'

Profit!


Appendix ​

Create Unify Kernel ​

We will use the initrd.img created during clevis-tpm2 setup.

command

safeboot unify-kernel /boot/efi/EFI/linux/linux.efi kernel=/boot/vmlinuz-$(uname -r) initrd=/boot/initrd.img-$(uname -r)

output

# safeboot unify-kernel /boot/efi/EFI/linux/linux.efi kernel=vmlinuz-$(uname -r) initrd=initrd.img-$(uname -
r)
/boot/efi/EFI/linux/linux.efi: Creating merged Linux/initrd image
vmlinuz-5.4.0-131-generic: unable to read
# safeboot unify-kernel /boot/efi/EFI/linux/linux.efi kernel=/boot/vmlinuz-$(uname -r) initrd=/boot/initrd.i
mg-$(uname -r)
/boot/efi/EFI/linux/linux.efi: Creating merged Linux/initrd image
.kernel=/boot/vmlinuz-5.4.0-131-generic: 13664512 @ 131072
.initrd=/boot/initrd.img-5.4.0-131-generic: 98509281 @ 13828096

Sign the Unified Kernel ​

command

safeboot linux-sign /boot/efi/EFI/linux/linux.efi

output

# safeboot linux-sign /boot/efi/EFI/linux/linux.efi
SIP mode is not enabled
/boot/efi/EFI//boot/efi/EFI/linux/linux.efi: Creating directory on EFI System Partition
/boot/efi/EFI//boot/efi/EFI/linux/linux.efi: Creating boot menu item on /dev/sda1, partition 1
Kernel commandline: 'ro quiet splash vt.handoff=7 intel_iommu=on efi=disable_early_pci_dma lockdown=confidentiality                     root=/dev/mapper/ubuntu--vg-ubuntu--lv
                 safeboot.mode=/boot/efi/EFI/linux/linux.efi'
/tmp/tmp.mmzfWAoKdD/linux.efi: Creating merged Linux/initrd image
.osrel=/etc/os-release: 382 @ 131072
.cmdline=/tmp/tmp.mmzfWAoKdD/cmdline.txt: 183 @ 196608
.linux=/boot/vmlinuz: 13664512 @ 262144
.initrd=/boot/initrd.img: 98509281 @ 13959168
/boot/efi/EFI//boot/efi/EFI/linux/linux.efi/linux.efi.new: Signing (ignore warnings about gaps)
warning: data remaining[112221184 vs 112230796]: gaps between PE/COFF sections?
warning: data remaining[112221184 vs 112230800]: gaps between PE/COFF sections?
Enter PEM pass phrase:
Signing Unsigned original image
warning: data remaining[112222952 vs 112232568]: gaps between PE/COFF sections?
6a1caa1279ea471e4d9ba5d4df62800764f0b21a9c25c1c782a01a963418b885
6df829262a464f6b2b3eaeacba9281791a750e774ba1e71ed2b76bd4d936b790  /boot/efi/EFI//boot/efi/EFI/linux/linux.efi/linux.efi