How to make secure boot with fully encrypted disk without bootloader on UEFI

Hello everyone! This is Alexey Gavrilov, DevOps engineer at Flant. This article is intended for fairly sophisticated Linux users. I will show you how to install Debian or its analogues using the standard installer in Secure boot. I tested this setup on AWS ARM64 and Selectel Cloud. The final scripts also work on a company Lenovo ThinkPad T14 and a personal L380 Yoga.

What we will ultimately achieve:

  1. Enabled Secure boot with personal keys for it. This way we will be able to boot only EFI files signed with our key. This will exclude the possibility of running third-party EFI files signed with other keys, for example, Microsoft or the hardware manufacturer.

  2. The kernel file and initramfs, which are signed with our key. This is possible by using UKI. This way we get an EFI file whose contents are signed. This allows us to exclude grub or systemd-boot from the boot sequence. Excluding bootloaders is necessary to reduce the possible vector of hacking the laptop.

  3. Encrypted partitions, except EFI boot. This will allow us to prevent data leakage in case of laptop theft, and also make life more difficult for a potential hacker by ensuring that he will only have signed EFI files at his disposal.

Manual installation option

Before we proceed with the installation, let's make sure that Secure Boot is enabled is in setup mode. In this case, the UEFI BIOS settings must be password protected so that Secure boot cannot be disabled.

Next we work according to the following algorithm:

1. You need to boot up from the installer and select the expert mode. This gives additional questions during installation, but also opportunities for more fine-tuning of the new system.

2. Using the installation program, we will partition the disk into:

  • EFI system partition (it must be at least 512 MB, otherwise all EFI files may not fit);

  • encrypted root partition. Here you can make the partition as complex as you want. The main thing is to remember that the partitions are in LUKS-section or its analogue.

[12:18:23][ssh][root@aws2] ~ $ cat /etc/crypttab 
nvme0n1p2_crypt UUID=2de785af-2b9e-432a-bb31-a8f1fe36fa31 none luks,discard
[12:18:29][ssh][root@aws2] ~ $ cat /etc/fstab 
/dev/mapper/aws-root /               ext4    errors=remount-ro 0       1
# /boot/efi was on /dev/nvme0n1p1 during installation
UUID=F751-88E0  /boot/efi       vfat    umask=0077      0       1
/swapfile swap swap defaults 0 0
[12:18:35][ssh][root@aws2] ~ $ lsblk 
NAME                MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINTS
zram0               253:0    0  466M  0 disk  [SWAP]
nvme0n1             259:0    0   25G  0 disk  
├─nvme0n1p1         259:1    0  487M  0 part  /boot/efi
└─nvme0n1p2         259:2    0 24.5G  0 part  
  └─nvme0n1p2_crypt 254:0    0 24.5G  0 crypt 
    └─aws-root      254:1    0 24.5G  0 lvm   /

3. At the system installation stage, select backports as a package for bookworm (stable), because in bookworm no systemd-ukify.

4. At the bootloader selection stage, we will select the option without a bootloader. In this case, we need to skip the point with installing grub.

5. Finish the installation. However, you need to stop before rebooting, as the system will not be able to start correctly at this point.

6. Let's switch in Shell mode to modify a new system that is mounted in /target during installation.

7. Let's change the priority bookworm-backports on priority as for bookworm. This is needed to install systemd-ukify.

TARGET=/target

# ukify install
cat > $TARGET/etc/apt/preferences.d/bookworm-backports <<EOF
Package: *
Pin: release bookworm-backports
Pin-Priority: 500
EOF

8. Update the packages in the new system to install the versions from bookworm-backports:

in-target sh -c "export DEBIAN_FRONTEND=noninteractive && apt update && apt full-upgrade -y"

9. Install the necessary packages:

apt-install systemd-boot-efi efibootmgr sbsigntool python3-pefile

10. Let's set it up dropbear to be able to remotely enter the password for the encrypted disk via SSH. In this case, we reconfigure dropbear on port 1022 at startup and do hard link on /root/.ssh/authorized_keys. This will allow you to log in with the same key when starting the server, and also when changing the contents to get a new list of keys after application update-initramfs:

apt-install dropbear-initramfs
echo 'DROPBEAR_OPTIONS="-I 600 -j -k -p 1022 -s -c cryptroot-unlock"' >> $TARGET/etc/dropbear/initramfs/dropbear.conf
ln $TARGET/root/.ssh/authorized_keys $TARGET/etc/dropbear/initramfs/authorized_keys

11. Let's remember the kernel startup parameters:

root_fs=$(cat $TARGET/etc/fstab | grep errors=remount-ro | grep " / " | awk '{print "root=" $1}')
echo "$root_fs ro" > $TARGET/etc/kernel/cmdline

12. Let's make an additional setting for kernel-install from systemd. These scripts add the compiled EFI kernel files to the boot menu. Also, a setting is added for compiling kernels into EFI files:

cat > $TARGET/etc/kernel/install.d/99-efiboot.install <<EOF
#!/bin/sh
set -e
[ "\$KERNEL_INSTALL_LAYOUT" = "uki" ] || exit 0
COMMAND="\${1:?}"
KERNEL_VERSION="\${2:?}"
boot=\$(mount | grep "\$KERNEL_INSTALL_BOOT_ROOT" | awk '{print \$1}')

case "\$COMMAND" in
  remove)
    if [ "\$(efibootmgr | grep \$KERNEL_VERSION | wc -l)" -eq "1" ] ; then
      efibootmgr -B -b "\$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8)"
    fi
    ;;
  add)
    if [ "\$(efibootmgr | grep \$KERNEL_VERSION | wc -l)" -eq "0" ] ; then
      prefix='\EFI\Linux\'
      efibootmgr -d \$boot -C -L "\${KERNEL_VERSION}" -l "\$prefix\${KERNEL_INSTALL_ENTRY_TOKEN}-\${KERNEL_VERSION}.efi"
    fi
    if [ -f "/boot/initrd.img" ] ; then
      if [ "\$(ls -la /boot/initrd.img | grep \$KERNEL_VERSION | wc -l)" -eq "1" ] ; then
        efibootmgr -o "\$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8)"
      fi
    else
      if [ "\$(efibootmgr | grep BootOrder: | grep \$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8) | wc -l)" -eq "0" ] ; then
        list=""
        if [ "\$(efibootmgr | grep BootOrder: | awk '{print \$2}' | wc -l)" -eq "1" ] ; then
          list=",\$(efibootmgr | grep BootOrder: | awk '{print \$2}')"
        fi
        efibootmgr -o "\$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8)\$list"
      fi
    fi
    ;;
  *)
    exit 0
    ;;
esac
EOF
chmod +x $TARGET/etc/kernel/install.d/99-efiboot.install

cat > $TARGET/etc/kernel/install.conf <<EOF
layout=uki
uki_generator=ukify
EOF

cat > $TARGET/etc/kernel/postrm.d/zz-kernel-install <<EOF
#!/bin/bash
if [[ -z \${1:-} ]]; then
  echo "E: initramfs-tools: \${DPKG_MAINTSCRIPT_PACKAGE:-kernel package} did not pass a version number" >&2
  exit 1
else
  version="\$1"
fi
kernel-install remove "\${version}" "/boot/vmlinuz-\${version}" "/boot/initrd.img-\${version}"
EOF
chmod +x $TARGET/etc/kernel/postrm.d/zz-kernel-install

cat > $TARGET/etc/kernel/postinst.d/zz-kernel-install <<EOF
#!/bin/bash
if [[ -z \${1:-} ]]; then
  echo "E: initramfs-tools: \${DPKG_MAINTSCRIPT_PACKAGE:-kernel package} did not pass a version number" >&2
  exit 1
else
  version="\$1"
fi
kernel-install add "\${version}" "/boot/vmlinuz-\${version}" "/boot/initrd.img-\${version}"
EOF
mkdir -p $TARGET/etc/initramfs/post-update.d/
ln $TARGET/etc/kernel/postinst.d/zz-kernel-install $TARGET/etc/initramfs/post-update.d/zz-kernel-install
chmod +x $TARGET/etc/kernel/postinst.d/zz-kernel-install

13. Use sbctlto simplify the creation of certificates for Secure boot and their application to UEFI.

sbctl currently not in Debian, so you have to install it from GitHub. Key --yes-this-might-brick-my-machine is only needed for AWS, as the VM uses a fairly old version of the EFI BIOS. After executing this part, Secure boot will switch to user mode, as sbctl load the generated keys into it:

ARCH=$(chroot /target/ dpkg --print-architecture)
wget --quiet https://github.com/Foxboron/sbctl/releases/download/0.14/sbctl-0.14-linux-$ARCH.tar.gz -O - | tar -xz sbctl/sbctl -O > $TARGET/usr/local/bin/sbctl
chmod +x $TARGET/usr/local/bin/sbctl
  1. We will also configure /etc/kernel/uki.confso that when created, EFI files are signed with the specified keys:

cat > $TARGET/etc/kernel/uki.conf <<EOF
[UKI]
SecureBootSigningTool=sbsign
SecureBootPrivateKey=/usr/share/secureboot/keys/db/db.key
SecureBootCertificate=/usr/share/secureboot/keys/db/db.pem
EOF

15. Let's create keys for EFI, load them into UEFI and update initramfs and EFI files:

in-target sh -c "mount -o rw -t efivarfs efivarfs /sys/firmware/efi/efivars; \
    sbctl create-keys; \
    sbctl enroll-keys --yes-this-might-brick-my-machine; \
    update-initramfs -u -k all; \
    umount /sys/firmware/efi/efivars;"

Automated installation option

This is a virtually automated version of the installation. At the time of writing, disk partitioning is required. This option requires a working nginx with files accessible from the server during the installation process. The links in the files need to be replaced with your own.

1. Let's build an EFI installer file with parameters for loading the answer file for unattended installation auto=true url=https://le9i0nx.gitlab.io/autoinstall/aws-crypt.cfg interface=auto netcfg/dhcp_timeout=60 keyboard-configuration/xkb-keymap=en priority=criticalas well as settings for interaction via ttyS0 (this is necessary for working in AWS) console=tty0 console=ttyS0. After execution we get /boot/efi/EFI/BOOT/BOOTAA64.EFIfrom which we will launch the installer:

#!/bin/sh
set -x
wget "https://ftp.debian.org/debian/dists/stable/main/installer-amd64/current/images/netboot/debian-installer/amd64/initrd.gz"
wget "https://ftp.debian.org/debian/dists/stable/main/installer-amd64/current/images/netboot/debian-installer/amd64/linux"
apt update
apt install systemd-boot-efi binutils python3-pefile -y
wget https://raw.githubusercontent.com/systemd/systemd/v255/src/ukify/ukify.py -v -O /usr/local/bin/ukify
chmod +x /usr/local/bin/ukify

mkdir -p /boot/efi/EFI/BOOT/
ukify build \
	--linux=./linux \
	--initrd=./initrd.gz \
	--cmdline="auto=true url=https://le9i0nx.gitlab.io/autoinstall/aws-crypt.cfg interface=auto netcfg/dhcp_timeout=60 keyboard-configuration/xkb-keymap=en priority=critical theme=dark gfxpayload=800x600x16,800x600 console=tty0 console=ttyS0" \
	--uname="Debian install" \
	--output "/boot/efi/EFI/BOOT/BOOTAA64.EFI"

Debian Installation Script

2. Answer file for almost automatic installation. Here the important part is in the command d-i preseed/late_command string. It executes arbitrary commands after installing Debian. In our case, adding SSH keys to the root user and setting up Secure boot:

d-i preseed/late_command string \
  wget --quiet -O - https://le9i0nx.gitlab.io/autoinstall/ssh.sh > /ssh.sh; \
  sh /ssh.sh /target; \
  wget --quiet -O - https://le9i0nx.gitlab.io/autoinstall/secure-boot/kernel-install.sh > /install.sh; \
  sh /install.sh /target

Since the installation is supposed to be over the network, d is used-i network-console/authorized_keys_url string. It points to a file with keys that can be used to continue the installation:

d-i keyboard-configuration/xkb-keymap select us
d-i netcfg/get_hostname string unassigned-hostname
d-i netcfg/get_domain string unassigned-domain
d-i hw-detect/load_firmware boolean true
d-i anna/choose_modules string network-console
d-i preseed/early_command string anna-install network-console
d-i network-console/password password root42
d-i network-console/password-again password root42
d-i network-console/authorized_keys_url string https://le9i0nx.gitlab.io/autoinstall/authorized_keys

d-i debian-installer/language string en
d-i debian-installer/country string US
d-i debian-installer/locale string en_US.UTF-8
d-i localechooser/supported-locales multiselect en_US.UTF8, ru_RU.UTF8
d-i console-keymaps-at/keymap select us
d-i keyboard-configuration/variant select American English
d-i netcfg/choose_interface select auto
d-i mirror/http/proxy string
tzsetup-udeb time/zone select UTC
d-i clock-setup/utc boolean true
d-i clock-setup/ntp boolean true
clock-setup clock-setup/ntp-server string pool.ntp.org
d-i apt-setup/contrib boolean true
d-i apt-setup/non-free boolean true
d-i apt-setup/non-free-firmware boolean true
apt-setup-udeb apt-setup/enable-source-repositories boolean false
popularity-contest popularity-contest/participate boolean true
tasksel tasksel/first multiselect ssh-server, standard
d-i pkgsel/include string openssh-server wget ca-certificates vim
pkgsel pkgsel/update-policy select unattended-upgrades
pkgsel pkgsel/upgrade select full-upgrade
openssh-server openssh-server/password-authentication boolean false
d-i base-installer/install-recommends boolean false
bootstrap-base base-installer/initramfs-tools/driver-policy select most

d-i passwd/root-login boolean true
d-i passwd/root-password-crypted password $6$0YbiHUntJTa$k7geJE7k0.GJqG8XZKpIHrM0frlVX5ZsxFFsZ6D7SGb2IZ08La6bV8KPYkkPNEK6NJzmOggU/T3JRE0lRwE6w1
d-i passwd/make-user boolean false
d-i preseed/late_command string \
  wget --quiet -O - https://le9i0nx.gitlab.io/autoinstall/ssh.sh > /ssh.sh; \
  sh /ssh.sh /target; \
  wget --quiet -O - https://le9i0nx.gitlab.io/autoinstall/secure-boot/kernel-install.sh > /install.sh; \
  sh /install.sh /target
d-i apt-setup/services-select multiselect security, updates, backports
#bootstrap-base base-installer/kernel/image select linux-image-cloud-arm64
#d-i debian-installer/add-kernel-opts string console=tty0 console=ttyS0

The answer file itself.

3. Load the list of keys for SSH access:

#!/bin/sh
TARGET=$1
mkdir -p $TARGET/root/.ssh
chmod 0700 $TARGET/root/.ssh
wget --quiet -O - https://le9i0nx.gitlab.io/autoinstall/authorized_keys >> $TARGET/root/.ssh/authorized_keys
chmod 0600 $TARGET/root/.ssh/authorized_keys

Script.

4. Modifying the system to boot into Secure boot:

#!/bin/sh
set -x

TARGET=$1

# ukify install
cat > $TARGET/etc/apt/preferences.d/bookworm-backports <<EOF
Package: *
Pin: release bookworm-backports
Pin-Priority: 500
EOF

# ukify install python3-pefile -> systemd-ukify
PACKAGE="systemd-boot-efi efibootmgr sbsigntool python3-pefile dropbear-initramfs"
if [ "$TARGET" = "" ]; then
  apt update
  apt full-upgrade -y
  apt install -y $PACKAGE
else
  in-target sh -c "export DEBIAN_FRONTEND=noninteractive && apt update && apt full-upgrade -y"
  apt-install $PACKAGE
fi

# dropbear
echo 'DROPBEAR_OPTIONS="-I 600 -j -k -p 1022 -s -c cryptroot-unlock"' >> $TARGET/etc/dropbear/initramfs/dropbear.conf
ln $TARGET/root/.ssh/authorized_keys $TARGET/etc/dropbear/initramfs/authorized_keys

#kernel-install fixed
root_fs=$(cat $TARGET/etc/fstab | grep errors=remount-ro | grep " / " | awk '{print "root=" $1}')
#echo "$root_fs ro console=tty0 console=ttyS0" > $TARGET/etc/kernel/cmdline
echo "$root_fs ro" > $TARGET/etc/kernel/cmdline

cat > $TARGET/etc/kernel/install.d/99-efiboot.install <<EOF
#!/bin/sh
set -e
[ "\$KERNEL_INSTALL_LAYOUT" = "uki" ] || exit 0
COMMAND="\${1:?}"
KERNEL_VERSION="\${2:?}"
boot=\$(mount | grep "\$KERNEL_INSTALL_BOOT_ROOT" | awk '{print \$1}')

case "\$COMMAND" in
  remove)
    if [ "\$(efibootmgr | grep \$KERNEL_VERSION | wc -l)" -eq "1" ] ; then
      efibootmgr -B -b "\$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8)"
    fi
    ;;
  add)
    if [ "\$(efibootmgr | grep \$KERNEL_VERSION | wc -l)" -eq "0" ] ; then
      prefix='\EFI\Linux\'
      efibootmgr -d \$boot -C -L "\${KERNEL_VERSION}" -l "\$prefix\${KERNEL_INSTALL_ENTRY_TOKEN}-\${KERNEL_VERSION}.efi"
    fi
    if [ -f "/boot/initrd.img" ] ; then
      if [ "\$(ls -la /boot/initrd.img | grep \$KERNEL_VERSION | wc -l)" -eq "1" ] ; then
        efibootmgr -o "\$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8)"
      fi
    else
      if [ "\$(efibootmgr | grep BootOrder: | grep \$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8) | wc -l)" -eq "0" ] ; then
        list=""
        if [ "\$(efibootmgr | grep BootOrder: | awk '{print \$2}' | wc -l)" -eq "1" ] ; then
          list=",\$(efibootmgr | grep BootOrder: | awk '{print \$2}')"
        fi
        efibootmgr -o "\$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8)\$list"
      fi
    fi
    ;;
  *)
    exit 0
    ;;
esac
EOF
chmod +x $TARGET/etc/kernel/install.d/99-efiboot.install

cat > $TARGET/etc/kernel/install.conf <<EOF
layout=uki
uki_generator=ukify
EOF

cat > $TARGET/etc/kernel/postrm.d/zz-kernel-install <<EOF
#!/bin/bash
if [[ -z \${1:-} ]]; then
  echo "E: initramfs-tools: \${DPKG_MAINTSCRIPT_PACKAGE:-kernel package} did not pass a version number" >&2
  exit 1
else
  version="\$1"
fi
kernel-install remove "\${version}" "/boot/vmlinuz-\${version}" "/boot/initrd.img-\${version}"
EOF
chmod +x $TARGET/etc/kernel/postrm.d/zz-kernel-install

cat > $TARGET/etc/kernel/postinst.d/zz-kernel-install <<EOF
#!/bin/bash
if [[ -z \${1:-} ]]; then
  echo "E: initramfs-tools: \${DPKG_MAINTSCRIPT_PACKAGE:-kernel package} did not pass a version number" >&2
  exit 1
else
  version="\$1"
fi
kernel-install add "\${version}" "/boot/vmlinuz-\${version}" "/boot/initrd.img-\${version}"
EOF

mkdir -p $TARGET/etc/initramfs/post-update.d/
ln $TARGET/etc/kernel/postinst.d/zz-kernel-install $TARGET/etc/initramfs/post-update.d/zz-kernel-install
chmod +x $TARGET/etc/kernel/postinst.d/zz-kernel-install

# sbctl
if [ "$TARGET" = "" ]; then
  ARCH=$(dpkg --print-architecture)
else
  ARCH=$(chroot /target/ dpkg --print-architecture)
fi
wget --quiet https://github.com/Foxboron/sbctl/releases/download/0.14/sbctl-0.14-linux-$ARCH.tar.gz -O - | tar -xz sbctl/sbctl -O > $TARGET/usr/local/bin/sbctl
chmod +x $TARGET/usr/local/bin/sbctl

cat > $TARGET/etc/kernel/uki.conf <<EOF
[UKI]
SecureBootSigningTool=sbsign
SecureBootPrivateKey=/usr/share/secureboot/keys/db/db.key
SecureBootCertificate=/usr/share/secureboot/keys/db/db.pem
EOF

if [ "$TARGET" = "" ]; then
  sbctl create-keys
  sbctl enroll-keys --yes-this-might-brick-my-machine
  update-initramfs -u -k all
else
  in-target sh -c "mount -o rw -t efivarfs efivarfs /sys/firmware/efi/efivars; \
    sbctl create-keys; \
    sbctl enroll-keys --yes-this-might-brick-my-machine; \
    update-initramfs -u -k all; \
    umount /sys/firmware/efi/efivars;"
fi

Script.

How to switch to boot option with uki signed kernel on already working grub for UEFI

It is worth considering that during the transition, you can break the system boot, since you may not take into account the features of your installation. To avoid this, you need to do the following:

  1. Let's switch the PC boot to Secure boot setup mode. After that, it can be configured from the operating system.

  2. Let's change the priority bookworm-backports on priority as for bookworm. This is needed to install systemd-ukify:

cat >/etc/apt/preferences.d/bookworm-backports <<EOF
Package: *
Pin: release bookworm-backports
Pin-Priority: 500
EOF
  1. Let's update the packages in the new system to install the versions from bookworm-backports:

apt update && apt full-upgrade -y"
  1. Let's install the necessary packages:

apt-install systemd-boot-efi efibootmgr sbsigntool python3-pefile
  1. Let's remember the kernel startup parameters:

root_fs=$(cat/etc/fstab | grep errors=remount-ro | grep " / " | awk '{print "root=" $1}')
echo "$root_fs ro" > /etc/kernel/cmdline
  1. Let's make an additional setting for kernel-install from systemd. These scripts add the compiled EFI kernel files to the boot menu. Also, a setting is added for compiling kernels into EFI files:

cat > /etc/kernel/install.d/99-efiboot.install <<EOF
#!/bin/sh
set -e
[ "\$KERNEL_INSTALL_LAYOUT" = "uki" ] || exit 0
COMMAND="\${1:?}"
KERNEL_VERSION="\${2:?}"
boot=\$(mount | grep "\$KERNEL_INSTALL_BOOT_ROOT" | awk '{print \$1}')

case "\$COMMAND" in
  remove)
    if [ "\$(efibootmgr | grep \$KERNEL_VERSION | wc -l)" -eq "1" ] ; then
      efibootmgr -B -b "\$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8)"
    fi
    ;;
  add)
    if [ "\$(efibootmgr | grep \$KERNEL_VERSION | wc -l)" -eq "0" ] ; then
      prefix='\EFI\Linux\'
      efibootmgr -d \$boot -C -L "\${KERNEL_VERSION}" -l "\$prefix\${KERNEL_INSTALL_ENTRY_TOKEN}-\${KERNEL_VERSION}.efi"
    fi
    if [ -f "/boot/initrd.img" ] ; then
      if [ "\$(ls -la /boot/initrd.img | grep \$KERNEL_VERSION | wc -l)" -eq "1" ] ; then
        efibootmgr -o "\$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8)"
      fi
    else
      if [ "\$(efibootmgr | grep BootOrder: | grep \$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8) | wc -l)" -eq "0" ] ; then
        list=""
        if [ "\$(efibootmgr | grep BootOrder: | awk '{print \$2}' | wc -l)" -eq "1" ] ; then
          list=",\$(efibootmgr | grep BootOrder: | awk '{print \$2}')"
        fi
        efibootmgr -o "\$(efibootmgr | grep \$KERNEL_VERSION | cut -c 5-8)\$list"
      fi
    fi
    ;;
  *)
    exit 0
    ;;
esac
EOF
chmod +x /etc/kernel/install.d/99-efiboot.install

cat > /etc/kernel/install.conf <<EOF
layout=uki
uki_generator=ukify
EOF

cat > /etc/kernel/postrm.d/zz-kernel-install <<EOF
#!/bin/bash
if [[ -z \${1:-} ]]; then
  echo "E: initramfs-tools: \${DPKG_MAINTSCRIPT_PACKAGE:-kernel package} did not pass a version number" >&2
  exit 1
else
  version="\$1"
fi
kernel-install remove "\${version}" "/boot/vmlinuz-\${version}" "/boot/initrd.img-\${version}"
EOF
chmod +x /etc/kernel/postrm.d/zz-kernel-install

cat > /etc/kernel/postinst.d/zz-kernel-install <<EOF
#!/bin/bash
if [[ -z \${1:-} ]]; then
  echo "E: initramfs-tools: \${DPKG_MAINTSCRIPT_PACKAGE:-kernel package} did not pass a version number" >&2
  exit 1
else
  version="\$1"
fi
kernel-install add "\${version}" "/boot/vmlinuz-\${version}" "/boot/initrd.img-\${version}"
EOF

mkdir -p /etc/initramfs/post-update.d/
ln /etc/kernel/postinst.d/zz-kernel-install /etc/initramfs/post-update.d/zz-kernel-install
chmod +x /etc/kernel/postinst.d/zz-kernel-install
  1. We use sbctlto simplify the creation of certificates for Secure boot and their application to UEFI.

    sbctl is currently not in Debian, so you have to install it from GitHub. After executing this part, Secure boot will switch to user mode, because sbctl load the generated keys into it:

ARCH=$(dpkg --print-architecture)
wget --quiet https://github.com/Foxboron/sbctl/releases/download/0.14/sbctl-0.14-linux-$ARCH.tar.gz -O - | tar -xz sbctl/sbctl -O > /usr/local/bin/sbctl
chmod +x /usr/local/bin/sbctl
  1. We will also configure /etc/kernel/uki.confso that when created, EFI files are signed with the specified keys:

cat > /etc/kernel/uki.conf <<EOF
[UKI]
SecureBootSigningTool=sbsign
SecureBootPrivateKey=/usr/share/secureboot/keys/db/db.key
SecureBootCertificate=/usr/share/secureboot/keys/db/db.pem
EOF
  1. Let's create keys for EFI, load them into UEFI and update initramfs and EFI files:

sbctl create-keys
sbctl enroll-keys
update-initramfs -u -k all
  1. After restarting, if the download was completed successfully, you should close access to changing BIOS settings using the new option.

Results

Once the installation is complete, we will have Debian installed on an encrypted disk with a limited list of what can be booted from the laptop. In such a system, we trust UEFI – that it will not allow unsigned EFI files to be booted.

Links used:

P.S.

Read also in our blog:

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *