Just want to share my configuration for getting Garuda dr460nized started with Secure Boot enabled. Before that, I set it up with full disk encryption using luks2 (over btrfs) and argon2 (GRUB - ArchWiki).
Set up Secure Boot on Garuda Linux (Arch)
With grub, shim and key signing, basically following the info in the Arch wiki first:
https://wiki.archlinux.org/title/Unified_Extensible_Firmware_Interface/Secure_Boot#shim
Install shim-signed package
cd /usr/src
git clone https://aur.archlinux.org/shim-signed.git
cd shim-signed
makepkg -si
And copy the signed loader to the EFI directory of the current loader (which can be checked by running efibootmgr
). For me, it’s the EFI/Garuda
directory.
sudo cp /usr/share/shim-signed/shimx64.efi /boot/efi/EFI/Garuda/
sudo cp /usr/share/shim-signed/mmx64.efi /boot/efi/EFI/Garuda/
Create an UEFI boot menu entry for shim (use a label of your choice):
sudo efibootmgr --unicode --disk /dev/nvme0n1 --part 1 --create --label "Garuda-Shim" --loader /EFI/Garuda/shimx64.efi
Shim loads then the grubx64.efi
created later from the same folder on the EFI partition.
Generate a new Machine Owner Key (MOK)
Store the new keys in roots home dir under /root/bootkeys/
.
cd /root/
mkdir bootkeys && cd bootkeys && chmod 700 .
openssl req -newkey rsa:2048 -nodes -keyout MOK.key -new -x509 -sha256 -days 3650 -subj "/CN=My Machine Owner Key/" -out MOK.crt
openssl x509 -outform DER -in MOK.crt -out MOK.cer
And sign the boot loader as described in the Arch Wiki and make sure to install the mkinitcpio post hook as described (/etc/initcpio/post/
might need to be created first). There is a script for that below.
As an example, the kernel and grub can be signed manually like this:
cd /root/bootkeys/
sbsign --key MOK.key --cert MOK.crt --output /boot/vmlinuz-linux-zen /boot/vmlinuz-linux-zen
sbsign --key MOK.key --cert MOK.crt --output /boot/efi/EFI/Garuda/grubx64.efi /boot/efi/EFI/Garuda/grubx64.efi
Check that Grub is signed:
sbverify --cert /root/bootkeys/MOK.crt /boot/efi/EFI/Garuda/grubx64.efi
Copy MOK.cer
to the EFI system partition to be enrolled either by MokManager or from within your BIOS manually:
cp MOK.cer /boot/efi/
This is required once, so that Secure Boot accepts the binaries signed with that custom key later on.
Get sbat.csv for grub
Grub needs to be installed with an SBAT and signed by the previously created machine owner key on each update, as described in the h**ps://wiki.archlinux.org/title/GRUB#Shim-lock.
Note: Turned out that the patched grub package for argon2 support does not include the sbat.csv file shipped with the original grub package in Arch. Get it and install along grubs files:
wget "https://gitlab.archlinux.org/archlinux/packaging/packages/grub/-/blob/main/sbat.csv"
set GRUBVER="$(pacman -Q | grep grub-improved | cut -d' ' -f2 | cut -d. -f1-2)"
sed -i "s#%PKGVER%#$GRUBVER#" sbat.csv
sudo mv sbat.csv /usr/share/grub/sbat.csv
Example: Install Grub with SBAT
grub-install --sbat /usr/share/grub/sbat.csv
Check that Grub has a SBAT section, run:
objdump -j .sbat -s /boot/efi/EFI/Garuda/grubx64.efi | head
Finally, a build script
To be used as grub-install
replacement. It installs the kernel signing hook and builds a grub image containing a memdisk for embedding the font and config files which can not be signed like the binaries above:
cat /root/bootkeys/install+sign.sh
:
#!/bin/sh
set -e
certpath="/root/bootkeys"
grub_efi="/boot/efi/EFI/Garuda/grubx64.efi"
# for secure boot, make sure an EFI boot entry for shim exists, do this manually once
#efibootmgr --unicode --disk /dev/nvme0n1 --part 1 --create --label "Shim" --loader /EFI/Garuda/shimx64.efi
# install kernel update signing hook
# from https://wiki.archlinux.org/title/Unified_Extensible_Firmware_Interface/Secure_Boot#shim_with_key
cat > /etc/initcpio/post/kernel-sbsign << EOF
#!/usr/bin/env bash
kernel="\$1"
[[ -n "\$kernel" ]] || exit 0
# use already installed kernel if it exists
[[ ! -f "\$KERNELDESTINATION" ]] || kernel="\$KERNELDESTINATION"
keypairs=("$certpath/MOK.key" "$certpath/MOK.crt")
for (( i=0; i<\${#keypairs[@]}; i+=2 )); do
key="\${keypairs[\$i]}" cert="\${keypairs[(( i + 1 ))]}"
if ! sbverify --cert "\$cert" "\$kernel" &>/dev/null; then
sbsign --key "\$key" --cert "\$cert" --output "\$kernel" "\$kernel"
fi
done
EOF
# Make sure grub config is recent
grub-mkconfig -o /boot/grub/grub.cfg
# update grub files in /boot/grub, copied to memdisk later
grub-install --no-nvram
cd "$certpath"
efi_vendor="$(basename "$(dirname "$grub_efi")")"
sh -x build-efi-images grub-mkimage /usr/lib/grub/x86_64-efi ./out "" x86_64-efi x64 /usr/share/grub/sbat.csv "$efi_vendor"
mv out/grubx64.efi "$grub_efi"
sbsign --key MOK.key --cert MOK.crt --output "$grub_efi" "$grub_efi"
rmdir out
Using a modified build-efi-images from Ubuntu
The original build-efi-images script is from h**ps://git.launchpad.net/ubuntu/+source/grub2-unsigned/plain/debian/build-efi-images, I modified it for Garuda/Arch and removed the parts not needed (such as CD and netboot images).
cat /root/bootkeys/build-efi-images
:
#! /bin/sh
set -e
# Copyright (C) 2010, 2011, 2012 Canonical Ltd.
# Author: Colin Watson <cjwatson@ubuntu.com>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
# Make EFI boot images for signing.
if [ $# -lt 7 ]; then
echo "usage: $0 GRUB-MKIMAGE GRUB-CORE OUTPUT-DIRECTORY DEB-ARCH PLATFORM EFI-NAME SBAT-CSV [EFI-VENDOR]"
exit 1
fi
grub_mkimage="$1"
grub_core="$2"
outdir="$3"
deb_arch="$4"
platform="$5"
efi_name="$6"
sbat_csv="$7"
efi_vendor="${8:-$(dpkg-vendor --query vendor | tr '[:upper:]' '[:lower:]')}"
# make sure downstreams didn't mess up sbat.csv
if ! grep -q ^grub.arch $sbat_csv; then
echo Missing sbat entry for "grub.arch" >&2
exit 1
fi
# mkfs.msdos may not be on the default PATH.
export PATH="$PATH:/sbin:/usr/sbin"
workdir=
cleanup () {
[ -z "$workdir" ] || rm -rf "$workdir"
}
# comment this to check the contents of the memdisk
trap cleanup EXIT HUP INT QUIT TERM
rm -rf "$outdir"
mkdir -p "$outdir"
workdir="$(mktemp -d wd-build-efi-images.XXXXXX)"
# use the regular grub preloaded config to unlock the crypto device
cat "/boot/grub/x86_64-efi/load.cfg" > "$workdir/grub-bootstrap.cfg"
# set the right prefix, according to the paths on the memdisk, created next
cat >> "$workdir/grub-bootstrap.cfg" << EOF
set prefix="(memdisk)"
EOF
memdiskpath="$workdir/memdisk/"
mkdir -p "$memdiskpath"
cp -R /boot/grub/fonts /boot/grub/grub* "$memdiskpath/"
mksquashfs "$workdir/memdisk" "$workdir/memdisk.squashfs" -comp xz
CD_MODULES="
all_video
boot
btrfs
cat
chain
configfile
echo
efifwsetup
efinet
ext2
fat
font
gettext
gfxmenu
gfxterm
gfxterm_background
gzio
halt
help
hfsplus
iso9660
jpeg
keystatus
loadenv
loopback
linux
ls
lsefi
lsefimmap
lsefisystab
lssal
memdisk
minicmd
normal
ntfs
part_apple
part_msdos
part_gpt
password_pbkdf2
png
probe
reboot
regexp
search
search_fs_uuid
search_fs_file
search_label
serial
sleep
smbios
squash4
test
tpm
true
video
"
# Platform-specific modules
case $platform in
x86_64-efi|i386-efi)
CD_MODULES="$CD_MODULES
cpuid
play
"
;;
arm64-efi)
CD_MODULES="$CD_MODULES
fdt
"
;;
esac
GRUB_MODULES="$CD_MODULES
cryptodisk
gcry_arcfour
gcry_blowfish
gcry_camellia
gcry_cast5
gcry_crc
gcry_des
gcry_dsa
gcry_idea
gcry_md4
gcry_md5
gcry_rfc2268
gcry_rijndael
gcry_rmd160
gcry_rsa
gcry_seed
gcry_serpent
gcry_sha1
gcry_sha256
gcry_sha512
gcry_tiger
gcry_twofish
gcry_whirlpool
luks2
argon2
pgp
bli
lvm
"
# Normal disk boot image
echo "Including modules $GRUB_MODULES in $outdir/grub$efi_name.efi"
"$grub_mkimage" \
-O "$platform" \
-o "$outdir/grub$efi_name.efi" \
-c "$workdir/grub-bootstrap.cfg" \
-d "$grub_core" \
-m "$workdir/memdisk.squashfs" \
--sbat "$sbat_csv" \
$GRUB_MODULES
exit 0
Lessons learned
Grub check_signatures
Attempting to solve the error ‘prohibited by Secure Boot policy’ by using signature checking with grub on files other than the peimages above. (tldr; It does not help with Secure Boot errors.)
Make sure to select an RSA key when generating one since the default ed25519 was silently ignored by grubs –pubkey argument (gpg 2.4.5, 2.12).
See also: h**ps://bbs.archlinux.org/viewtopic.php?pid=2080017#p2080017
cd /root/bootkeys/
gpg --homedir gpg --full-gen-key
gpg --homedir gpg --export > boot.key
Install grub signature helpers
Kindly provided by Bandie in h**ps://github.com/Bandie/grub2-signing-extension.
Install to /usr/src
and symlink into /usr/local/sbin
:
cd /usr/src
git clone https://github.com/Bandie/grub2-signing-extension.git
cd /usr/local/sbin
for fn in /usr/src/grub2-signing-extension/sbin/*; do ln -s "$fn" "${fn##*/}"; done
Sign all grub files with the newly created certificate:
export GNUPGHOME=/root/bootkeys/gpg
grub-sign
Finding the modules embedded in a grubx64.efi
By employing rabin2 from the radare2 package and following the idea from here h**ps://askubuntu.com/a/1466507 and with ensuring that the module exists on disk actually:
for mod in $(rabin2 -qq -zz /boot/efi/EFI/Garuda/grubx64.efi | grep -A10 --no-group-separator LICENSE= |grep -v LICENSE=|grep -v '^grub_' |grep -v '^_'|grep -v '^\.'|grep -v '[A-Z ]' | sort -u ); do [ -f /usr/lib/grub/x86_64-efi/$mod.mod ] || continue; echo "$mod"; done | tr '\n' ' '
Hope this helps anyone trying to do this as well!
Best wishes!