Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save devovh/2b8f549863f5ad03a8f942838e64ae99 to your computer and use it in GitHub Desktop.
Save devovh/2b8f549863f5ad03a8f942838e64ae99 to your computer and use it in GitHub Desktop.
Enable Linux Secure Boot with TPM 2.0 (Archlinux) - rEFInd
--- /usr/share/libalpm/hooks/90-mkinitcpio-install.hook 2020-03-05 12:45:41.000000000 +0800
+++ /etc/pacman.d/hooks/90-mkinitcpio-install.hook 2020-06-13 23:08:32.861202141 +0800
@@ -8,5 +8,7 @@
[Action]
Description = Updating linux initcpios...
When = PostTransaction
-Exec = /usr/share/libalpm/scripts/mkinitcpio-install
+Exec = /usr/local/share/libalpm/scripts/mkinitcpio-install
+Depends = sbsigntools
+Depends = x11-ssh-askpass
NeedsTargets

Required

Manjaro Xface version.

Hardware

  • TPM module installed in the motherboard (that is set to TPM 2.0 mode from the BIOS).

Packages

  • refind
  • sbsigntools
  • shim or shim-signed
  • tpm2-tss-engine
  • tpm2-tools (optional)
  • patch

Usage

sudo -i
sudo pacman -S refind sbsigntools tpm2-tss-engine tpm2-tools patch
sudo pamac install shim
or
sudo pamac install shim-signed

# Patch refind-install script
curl -o- https://gist.githubusercontent.com/heri16/6df9ae37ae51496fe376debaca45540b/raw/refind-install.patch | patch /usr/bin/refind-install

# Install reFind EFI Bootloader to ESP partition (encrypted keys without TPM)
# refind-install --shim /usr/share/shim/shimx64.efi --localkeys --encryptkeys --yes

# Install reFind EFI Bootloader to ESP partition (encrypted keys on TPM)
refind-install --shim /usr/share/shim/shimx64.efi --localkeys --encryptkeys --engine tpm2tss --yes
efibootmgr

# Sign Linux kernel
sbsign --engine tpm2tss --key /etc/refind.d/keys/refind_local.key --cert /etc/refind.d/keys/refind_local.crt --output "/boot/vmlinuz-linux" "/boot/vmlinuz-linux"
sbverify --list "/boot/vmlinuz-linux"

sbsign --engine tpm2tss --key /etc/refind.d/keys/refind_local.key --cert /etc/refind.d/keys/refind_local.crt --output "/boot/vmlinuz-linux-lts" "/boot/vmlinuz-linux-lts"
sbverify --list "/boot/vmlinuz-linux-lts"

# Sign Manjaro's Grub2 EFI Bootloader (optional)
sbsign --engine tpm2tss --key /etc/refind.d/keys/refind_local.key --cert /etc/refind.d/keys/refind_local.crt --output "/boot/efi/EFI/Arch/grubx64.efi" "/boot/efi/EFI/Arch/grubx64.efi"
sbverify --list "/boot/efi/EFI/Arch/grubx64.efi"

sudo cp /usr/share/shim/shimx64.efi /boot/efi/EFI/Arch/shimx64.efi
sudo cp /usr/share/shim/mmx64.efi /boot/efi/EFI/Arch/mmx64.efi
sudo cp /usr/share/shim/fbx64.efi /boot/efi/EFI/Arch/fbx64.efi

sudo efibootmgr -c -d /dev/nvme0n1 -p 1 -L "manjaro-secureboot" -l "\boot\efi\EFI\Arch\shimx64.efi"

# Reboot into BIOS

Then, reboot into BIOS to enable SecureBoot.

Once in MokManager add refind_local.cer to MoKList. refind_local.cer can be found inside a directory called keys in the rEFInd's installation directory, e.g. esp/EFI/refind/keys/refind_local.cer.

sudo openssl req -new -x509 -newkey rsa:2048 -keyout /boot/efi/EFI/refind/keys/refind_local.key -out /boot/efi/EFI/refind/keys/refind_local.crt -nodes -days 3650 -subj "/CN=Manjaro kernel signing key/"

sudo openssl x509 -in /boot/efi/EFI/refind/keys/refind_local.crt -out /boot/efi/EFI/refind/keys/refind_local.cer -outform DER

sudo sbsign --key /boot/efi/EFI/refind/keys/refind_local.key --cert /boot/efi/EFI/refind/keys/refind_local.crt --output /boot/efi/EFI/Arch/grubx64.efi /boot/efi/EFI/Arch/grubx64.efi

sudo sbsign --key /boot/efi/EFI/refind/keys/refind_local.key --cert /boot/efi/EFI/refind/keys/refind_local.crt --output /boot/vmlinuz-linux /boot/vmlinuz-linux

sudo sbsign --key /boot/efi/EFI/refind/keys/refind_local.key --cert /boot/efi/EFI/refind/keys/refind_local.crt --output /boot/vmlinuz-linux-lts /boot/vmlinuz-linux-lts

Misc

Enable pacman hook

Make pacman sign the kernel automatically on kernel updates.

sudo -i
sudo pamac install x11-ssh-askpass
sudo mkdir /usr/share/libalpm/
sudo mkdir /usr/share/libalpm/scripts/
sudo mkdir /usr/local/share/libalpm/
sudo mkdir /usr/local/share/libalpm/scripts/
sudo mkdir /etc/pacman.d/
sudo mkdir /etc/pacman.d/hooks/
curl -o- https://gist.githubusercontent.com/heri16/6df9ae37ae51496fe376debaca45540b/raw/90-mkinitcpio-install.hook.patch | patch -o "/etc/pacman.d/hooks/90-mkinitcpio-install.hook" /usr/share/libalpm/hooks/90-mkinitcpio-install.hook
curl -o- https://gist.githubusercontent.com/heri16/6df9ae37ae51496fe376debaca45540b/raw/mkinitcpio-install.patch | patch -o "/usr/local/share/libalpm/scripts/mkinitcpio-install" /usr/share/libalpm/scripts/mkinitcpio-install

RESTORE GRUB

These are the steps that worked for me, without having to install any new packages:
Check the disk designation in the program: sudo pacman -S gpart
Boot into Manjaro installer
Open terminal
sudo manjaro-chroot -a (and select system to mount)
grub-install /dev/nvme0n1 (it's sda for me; make sure you choose the right drive!)
grub-install --recheck /dev/nvme0n1 ## You name HDD
update-grub
exit
reboot

Useful Info

--- /usr/share/libalpm/scripts/mkinitcpio-install 2020-03-05 12:45:41.000000000 +0800
+++ /usr/local/share/libalpm/scripts/mkinitcpio-install 2020-06-20 06:09:53.900484682 +0800
@@ -39,8 +39,20 @@
fi
fi
- # always install the kernel
- install -Dm644 "${line}" "/boot/vmlinuz-${kernelbase}"
+ if [[ $DISPLAY ]]; then
+ # always sign & install the kernel for SecureBoot
+ KeyPassphrase=$(/usr/lib/ssh/ssh-askpass "Please enter your SecureBoot Key passphrase:")
+ SbSignCommand=$(printf "%q " /usr/bin/sbsign --engine tpm2tss --key /etc/refind.d/keys/refind_local.key --cert /etc/refind.d/keys/refind_local.crt --output "/boot/vmlinuz-${kernelbase}" "${line}")
+ echo "$KeyPassphrase" |
+ script -qefc "$SbSignCommand" --force /dev/null 2>&1 | ( \
+ head -n 2 >/dev/null # Skip the first two lines (incl. passphrase).
+ grep -v "data remaining.*gaps between PE/COFF sections"
+ )
+ /usr/bin/sbverify --list "/boot/vmlinuz-${kernelbase}"
+ else
+ # always install the kernel
+ install -Dm644 "${line}" "/boot/vmlinuz-${kernelbase}"
+ fi
# compound args for each kernel
args+=(-p "${pkgbase}")
#!/bin/sh
VERSION=5.7
cd /boot/efi/EFI/Linux
cat /boot/amd-ucode.img /boot/initramfs-${VERSION}-x86_64.img > initrd.img
objcopy \
--add-section .osrel="/usr/lib/os-release" --change-section-vma .osrel=0x20000 \
--add-section .cmdline="kernel-command-line.txt" --change-section-vma .cmdline=0x30000 \
--add-section .splash="/usr/share/systemd/bootctl/splash-manjaro.bmp" --change-section-vma .splash=0x40000 \
--add-section .linux="/boot/vmlinuz-${VERSION}-x86_64" --change-section-vma .linux=0x2000000 \
--add-section .initrd="initrd.img" --change-section-vma .initrd=0x3000000 \
"/usr/lib/systemd/boot/efi/linuxx64.efi.stub" "linux${VERSION//.}.efi"
sbsign --engine tpm2tss --key /etc/refind.d/keys/refind_local.key --cert /etc/refind.d/keys/refind_local.crt --output "linux${VERSION//.}.efi" "linux${VERSION//.}.efi"
sbverify --list "linux${VERSION//.}.efi"
rm initrd.img
--- /usr/bin/refind-install 2020-04-23 14:10:32.000000000 +0800
+++ ./refind-install 2020-06-12 13:48:27.371630998 +0800
@@ -23,6 +23,7 @@
# only under Linux.
# "--preloader" is synonymous with "--shim". Valid only under Linux.
# "--encryptkeys" password-protects the Secure Boot private key.
+# "--engine" engine that protects the Secure Boot private key.
# "--localkeys" to re-sign x86-64 binaries with a locally-generated key.
# Valid only under Linux.
# "--keepname" to keep refind_x64.efi name as such even when using shim.
@@ -156,6 +157,9 @@
;;
--encryptkeys) EncryptKeys=1
;;
+ --engine) Engine="$2"
+ shift
+ ;;
--shim | --preloader) ShimSource="$2"
ShimType=`basename $ShimSource`
shift
@@ -171,7 +175,7 @@
* ) echo "Usage: $0 [--notesp | --usedefault {device-file} | --root {dir} |"
echo " --ownhfs {device-file} ] [--keepname]"
echo " [--nodrivers | --alldrivers] [--shim {shimfile}]"
- echo " [--localkeys [--encryptkeys]] [--keepname] [--yes]"
+ echo " [--localkeys [--encryptkeys] [--engine {engine}]] [--keepname] [--yes]"
exit 1
esac
shift
@@ -216,6 +220,10 @@
echo "The --encryptkeys option requires the use of --localkeys! Aborting!"
exit 1
fi
+ if [[ $Engine && "$LocalKeys" == 0 ]] ; then
+ echo "The --engine option requires the use of --localkeys! Aborting!"
+ exit 1
+ fi
RLConfFile="$RootDir/boot/refind_linux.conf"
EtcKeysDir="$RootDir/etc/refind.d/keys"
} # GetParams()
@@ -1079,12 +1087,44 @@
cp -f "$DerKey" "$DerKey.backup" 2> /dev/null
fi
if [[ $EncryptKeys == 1 ]]; then
+ ReadKeyPassphrase
KeyEncryptionArgument=""
else
KeyEncryptionArgument="-nodes"
fi
- "$OpenSSL" req -new -x509 -newkey rsa:2048 -keyout "$PrivateKey" -out "$CertKey" \
+ if [[ ! $Engine ]]; then
+ if [[ $EncryptKeys == 1 ]]; then
+ echo "$KeyPassphrase" |
+ "$OpenSSL" req -new -x509 -newkey rsa:2048 -keyout "$PrivateKey" -out "$CertKey" \
+ $KeyEncryptionArgument -days 3650 -subj "/CN=Locally-generated rEFInd key/" -passout stdin
+ echo -e "$KeyPassphrase\n$KeyPassphrase" |
+ "$OpenSSL" pkcs8 -topk8 -iter 1000000 -in "$PrivateKey" -out "${PrivateKey}~" -passin stdin -passout stdin
+ mv "${PrivateKey}~" "$PrivateKey"
+ else
+ "$OpenSSL" req -new -x509 -newkey rsa:2048 -keyout "$PrivateKey" -out "$CertKey" \
$KeyEncryptionArgument -days 3650 -subj "/CN=Locally-generated rEFInd key/"
+ fi
+ else
+ EngineName=$("$OpenSSL" engine "$Engine" | cut -d ' ' -f 2)
+ if [[ "$Engine" == "tpm2tss" ]]; then
+ if [[ $EncryptKeys == 1 ]]; then
+ tpm2tss-genkey -a rsa -p "$KeyPassphrase" "$PrivateKey"
+ else
+ tpm2tss-genkey -a rsa "$PrivateKey"
+ fi
+ KeyReqArguments=(-engine "$Engine" -keyform engine -key "$PrivateKey")
+ else
+ KeyReqArguments=(-keygen_engine "$Engine" -newkey rsa:2048 -keyout "$PrivateKey")
+ fi
+ if [[ $EncryptKeys == 1 ]]; then
+ echo "$KeyPassphrase" |
+ "$OpenSSL" req -new -x509 ${KeyReqArguments[@]} -out "$CertKey" \
+ $KeyEncryptionArgument -days 3650 -subj "/CN=${EngineName}-generated rEFInd key/" -passin stdin
+ else
+ "$OpenSSL" req -new -x509 ${KeyReqArguments[@]} -out "$CertKey" \
+ $KeyEncryptionArgument -days 3650 -subj "/CN=${EngineName}-generated rEFInd key/"
+ fi
+ fi
"$OpenSSL" x509 -in "$CertKey" -out "$DerKey" -outform DER
chmod 0600 "$PrivateKey"
else
@@ -1100,16 +1140,25 @@
SignOneBinary() {
ReadKeyPassphrase --no-confirm
if [[ "$EncryptKeys" == 1 ]] ; then
- SbSignCommand=$(printf "%q " "$SBSign" --key "$PrivateKey" --cert "$CertKey" --output "$2" "$1")
+ if [[ ! $Engine ]]; then
+ SbSignCommand=$(printf "%q " "$SBSign" --key "$PrivateKey" --cert "$CertKey" --output "$2" "$1")
+ else
+ SbSignCommand=$(printf "%q " "$SBSign" --engine "$Engine" --key "$PrivateKey" --cert "$CertKey" --output "$2" "$1")
+ fi
echo "$KeyPassphrase" |
script -qefc "$SbSignCommand" --force /dev/null 2>&1 | ( \
head -n 2 >/dev/null # Skip the first two lines (incl. passphrase).
grep -v "data remaining.*gaps between PE/COFF sections"
)
- local status="${PIPESTATUS[1]}"
+ local status="${PIPESTATUS[1]}"
else
- "$SBSign" --key "$PrivateKey" --cert "$CertKey" --output "$2" "$1" 2>&1 >/dev/null | \
+ if [[ ! $Engine ]]; then
+ "$SBSign" --key "$PrivateKey" --cert "$CertKey" --output "$2" "$1" 2>&1 >/dev/null | \
+ grep -v "data remaining.*gaps between PE/COFF sections"
+ else
+ "$SBSign" --engine "$Engine" --key "$PrivateKey" --cert "$CertKey" --output "$2" "$1" 2>&1 >/dev/null | \
grep -v "data remaining.*gaps between PE/COFF sections"
+ fi
local status="${PIPESTATUS[0]}"
fi
if [[ "$status" != 0 ]] ; then
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment