Hi all,
I've written some scripts to help with the signature verification aspect of this
change. I've attempted to have them seamlessly handle different environments, but
please let me know if you observe any misbehaviour. I'd particularly like to get input
on the second script. The first can setup a system for signature verification only if the
relevant modules are made available separately. Also, compare the steps the script takes
with the wiki page. The script assumes that the modules are loaded by default (they are
once they're included in the build) too. Check steps 2 and 3 in the "verify"
portion of the How To Test section for what is missing (So, this is definitely useful
after F31's release, but can be convenient now too).
Thanks.
grub2-switch-to-verify:
#!/bin/bash
## This, for now, is a holistic script. It assumes that we've either configured
signature verification, or not.
## This will need to be changed. Individual scripts should check for their files, and call
on a central script (or
## function therein) to configure things otherwise.
if [[ $(id -u) != 0 ]]; then
echo "You must run this script as root"
exit 1
fi
sata_or_nvme=$(if [[ $(mount | grep "/boot/efi" | cut -d " " -f 1) =~
(/dev/nvme*|/dev/mmcblk*) ]]; then echo 3; else echo 2; fi)
drive_num=$(lsblk | grep /boot/efi | cut -d " " -f 1 | cut -c 3- | rev | cut -c
$sata_or_nvme- | rev)
part_type=$(fdisk /dev/$drive_num -l | grep "Disklabel type" | cut -d "
" -f 3)
ESP_partnum=$(lsblk | grep /boot/efi | cut -c 6)
#export GPG_TTY=$(tty)
function firstrun {
touch /var/tmp/grub_verify-pgp_pass
chmod 600 /var/tmp/grub_verify-pgp_pass
gpg --gen-random --armor 0 24 > /var/tmp/grub_verify-pgp_pass
gpg --pinentry-mode loopback --batch --quick-generate-key --passphrase-file
/var/tmp/grub_verify-pgp_pass "Grub_verify testing key" rsa sign never
gpg --export "Grub_verify testing key" > /boot/efi/EFI/fedora/pubkey
echo "
trust (hd0,$part_type$ESP_partnum)/efi/fedora/pubkey --skip-sig
set check_signatures=enforce" >> /etc/grub.d/40_custom
grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg
resign
}
function resign {
for x in $(find /boot -name "*.cfg.sig" -or -name "*.lst.sig" -or
-name "*.mod.sig" -or -name "vmlinuz*.sig" -or -name
"initramfs*.sig" -or -name "grubenv.sig"); do rm -f "$x";
done
for x in $(find /boot -name "*.cfg" -or -name "*.lst" -or -name
"*.mod" -or -name "vmlinuz*" -or -name "initramfs*" -or
-name "grubenv"); do gpg --batch --detach-sign -u "Grub_verify testing
key" --pinentry-mode loopback --passphrase-fd 0 "$x" <
/var/tmp/grub_verify-pgp_pass; done
}
if [ ! -f /boot/efi/EFI/fedora/grub.cfg.sig ]; then
firstrun
exit 0
else
resign
exit 0
fi
grub_verify-kern-postinst:
#!/bin/bash
## This is only going to address the kernel and initramfs (we're tacking on grubenv,
as it is edited concurrently with
## kernel upgrades. However, "savedentry" might only change after a reboot. This
requires further testing). While these
## are the most frequently modified, those with certain configurations will need to keep
an eye on things.
##
## Thankfully, the new BootLoaderSpec format ensures that grub.cfg is rarely modified. The
large majority of users don't
## use custom.cfg and user.cfg is generally on written once. An initial round of signing
should cover all of this.
## grubenv will be resigned by this version of the script, but requires further testing.
## The default configuration doesn't allow for inserting modules, so we don't need
to resign any of them. While this can
## hopefully be changed with Grub's 2.04 release, by that time additional module
loading can be automated
## per-environment with patches to grub2-mkconfig.
##
## Once/if we turn on signature verification by default, all of the above will be handled
with patches to the relevant
## scripts.
## It's unlikely that we'll hit this, but we need to be sure in case we're run
directly.
if [[ $(id -u) != 0 ]]; then
echo "You must run this script as root"
exit 1
fi
old_sigs=$(for x in $(find /boot -name "vmlinuz*.sig" -or -name
"initramfs*.sig" | grep -v rescue | sed 's/.sig//'); do if [[
"$x" != "$(rpm -ql kernel-core | grep -e /boot/vmlinuz -e /boot/initramfs |
grep "$x")" ]]; then echo "$x"; fi; done)
new_uname_r=$(rpm -qa --last kernel | head -n 1 | cut -d " " -f 1 | sed
's/kernel-//')
for x in $old_sigs; do rm -f "$x.sig"; done
for x in $(find /boot -name "grubenv.sig"); do rm -f "$x"; done
for x in $(find /boot -name "vmlinuz-$new_uname_r" -or -name
"initramfs-$new_uname_r.img" -or -name "grubenv"); do gpg --batch
--detach-sign -u "Grub_verify testing key" --pinentry-mode loopback
--passphrase-fd 0 "$x" < /var/tmp/grub_verify-pgp_pass; done
exit 0