Tinfoil session 1: Enabling secure boot vector on linux
While being a strong proponent of security and privacy I for long neglected one particular security vector on my laptops - secureboot, relying on compensating controls I put in place. SecureBoot was pushed on me by Microsoft so I naturally reflexly rejected it. Now however is a time to reconsider the stance, especially in view of much higher pressure on privacy and as result much deeper penetration of foreing networked compute elements around us (this is the place we put our tinfoil hat on).
So the goal I have in mind in general is somewhat inspired by Librem laptops with libremkey and heads providing secure and tamper-proof boot vector. For this session the bar is set to merely make sure we can boot securily. Simple enough. Since I'm using Arch Linux the obvious starting point is Arch Wiki's article on SecureBoot. I'll need to create my own keys (stored securily), load them to EFI BIOS, sign the EFI image, enable secure boot and boot into linux. Easy peasy.
First we create crypto-vault to store our keys. They should not be stored on the same laptop of course, you should make a crypto vault from cheap usb thumbdrive. Cheap due to low volume, not poor quality. But for simplicity (and due to the fact the first laptop is mostly sitting on the table (I carry another one) - we'll do it on the local drive. Also I have a Nitrokey so the keyfile will be encryped by its pgp card.
First generate random 512bit key and put it on the ramdrive (so that we don't need to securely remove it later). Then use it as a keyfile to create luks partition:dd if=/dev/random of=/tmp/luks bs=64 count=1 sudo cryptsetup luksFormat /dev/sda8 /tmp/luks
Now encrypt the key, store it lokally and recycle the raw key:
gpg -e -r me@ruff.mobi < /tmp/luks >./key dd if=/dev/random of=/tmp/luks bs=64 count=1 rm /tmp/luks gpg -d -u me@ruff.mobi < ./key | sudo cryptsetup open /dev/sda8 Vault -d-
Format luks partition with fav fs (simple ext4 should be ok) and since we need root (sudo) to operate the vault we can move the key to root's home to avoid exposing it in open.
sudo mkfs.ext4 /dev/mapper/Vault sudo mkdir /mnt/sec sudo mv key /root/.key sudo cryptsetup close Vault
Now let's create simple script to open the vault and run the created script to actually open it. If you plan using the script for a longer term it would be better using part UUID instead part number. Numbers are volatile.
vim sezamy #!/bin/bash LUKS=/dev/sda8 sudo cat /root/.key | gpg -d -u me@ruff.mobi | sudo cryptsetup open $LUKS Vault -d- sudo mount /dev/mapper/Vault /mnt/sec $ bash -x sezamy + sudo cat /root/.key + gpg -d -u me@ruff.mobi + sudo cryptsetup open /dev/sda8 Vault -d- gpg: verschlüsselt mit 512-Bit ECDH Schlüssel, ID 7DAE27C8C4A956A3, erzeugt 2021-10-23 "Ruslan Marchenko (ruff) <me@ruff.mobi>" + sudo mount /dev/mapper/Vault /mnt/sec sudo mkdir /mnt/sec/ruff sudo chown ruff:ruff /mnt/sec/ruff/ chmod 700 /mnt/sec/ruff/
Now let's create a home for EFI keys and generate the keys using ArchLinux wiki as a tutorial:
cd /mnt/sec/ruff/ && mkdir UEFI && cd UEFI && mkdir {db,dbx,KEK,PK} openssl req -new -x509 -newkey rsa:4096 -nodes -sha256 -days 3650 \ -keyout PK.key -subj '/CN=MyPK/' -out PK.crt openssl req -new -x509 -newkey rsa:4096 -nodes -sha256 -days 3650 \ -keyout KEK.key -subj '/CN=MyKEK/' -out KEK.crt openssl req -new -x509 -newkey rsa:4096 -nodes -sha256 -days 3650 \ -keyout SDB.key -subj '/CN=MySDB/' -out SDB.crt sudo pacman -Syu sbsigntools efitools uuidgen --random > UEFI.guid cert-to-efi-sig-list -g `< UEFI.guid` PK.crt PK.esl sign-efi-sig-list -g `< UEFI.guid` -k PK.key -c PK.crt PK PK.esl PK/PK.auth cert-to-efi-sig-list -g `< UEFI.guid` KEK.crt KEK.esl sign-efi-sig-list -g `< UEFI.guid` -k PK.key -c PK.crt KEK KEK.esl KEK/KEK.auth cert-to-efi-sig-list -g `< UEFI.guid` SDB.crt SDB.esl sign-efi-sig-list -g `< UEFI.guid` -k KEK.key -c KEK.crt db SDB.esl db/SDB.auth sbkeysync --keystore . --verbose --dry-run --pk
At this point you should see your 3 new keys being detected by sbkeysync. If you're still using dual-boot you'd need to add Microsoft keys:
curl -L 'https://go.microsoft.com/fwlink/?LinkId=321192' > MSProdCA2011.cer curl -L 'https://go.microsoft.com/fwlink/?linkid=321194' > MSUEFICA2011.cer openssl x509 -in MSProdCA2011.cer -out MSProdCA2011.crt -inform DER openssl x509 -in MSUEFICA2011.cer -out MSUEFICA2011.crt -inform DER
Technically we can pipe it right from curl but we may need DER if we want to load them manually.
cert-to-efi-sig-list -g 77fa9abd-0359-4d32-bd60-28f4e78f784b MSProdCA2011.crt \ MSProdCA2011.esl cert-to-efi-sig-list -g 77fa9abd-0359-4d32-bd60-28f4e78f784b MSUEFICA2011.crt \ MSUEFICA2011.esl cat MSProdCA2011.esl MSUEFICA2011.esl > MS.esl sign-efi-sig-list -a -g 77fa9abd-0359-4d32-bd60-28f4e78f784b -k KEK.key \ -c KEK.crt db MS.esl db/MS.auth
The wiki is saying the efivars are locked by immutable flag, let's confirm this:
lsattr /sys/firmware/efi/efivars/{PK,KEK,db,dbx}*
They are indeed, so let's create a simple script which unsets immutable attr and syncs the keys:
echo 'sbkeysync --keystore . --verbose --pk' >> sync.sh vim sync.sh
and add chattr -i /sys/firmware/efi/efivars/{PK,KEK,db,dbx}* before and +i after
sudo bash -x sync.sh ... Error writing key update: Permission denied Error syncing keystore file ./db/SDB.auth
This operation is kind of finicky. On my two laptops, one refused entirely to load keys until I wiped all keys (which switched it into Setup Mode, hence is expected). Then it imported the keys with above command but I needed to re-run it multiple times, it seems sbkeysync is pushing keys in some arbitrary order, but EFI BIOS allows them to be loaded only in specific order (PK, KEK, db). My other laptop pushed db key (without PK/KEK) and then refused to accept either PK or KEK.
Ok, let's add via UEFI BIOS then. Copy auth files to ESP to be accessible from UEFI.
sudo cp {PK,KEK,db}/*.auth /esp/EFI/Linux/
Also sign the unified kernel image:
sudo mv /esp/EFI/Linux/arch.efi /esp/EFI/Linux/arch.uefi sudo sbsign --key UEFI/SDB.key --cert UEFI/SDB.crt \ --output /esp/EFI/Linux/arch.efi /esp/EFI/Linux/arch.uefi warning: data remaining[17838080 vs 17848308]: gaps between PE/COFF sections? warning: data remaining[17838080 vs 17848312]: gaps between PE/COFF sections? Signing Unsigned original image $ sbverify /esp/EFI/Linux/arch.efi warning: data remaining[17840376 vs 17850608]: gaps between PE/COFF sections? Signature verification failed $ sbverify /esp/EFI/Boot/bootx64.efi Signature verification OK $ sbverify /esp/EFI/Boot/bootx64.efi --list signature 1 image signature issuers: - /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Windows Production PCA 2011 image signature certificates: - subject: /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Windows issuer: /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Windows Production PCA 2011 - subject: /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Windows Production PCA 2011 issuer: /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Root Certificate Authority 2010 $ sbverify /esp/EFI/Linux/arch.efi --cert UEFI/SDB.crt warning: data remaining[17840376 vs 17850608]: gaps between PE/COFF sections? Signature verification OK systemctl reboot --firmware-setup
Setup PK/KEK from auth file, enable secure boot, ensure boot entry points to signed efi file, ensure you have set admin password (otherwise what's a point). Save and reboot. Now - here we have different results on two different laptops. First my attemp to deal with old Asus trio (tx201la).
It failed. Even though db looks ok:
$ efi-readvar Variable PK, length 1324 PK: List 0, type X509 Signature 0, size 1296, owner 54652821-eb08-4bd2-8108-9cbcebc308f4 Subject: CN=MyPK Issuer: CN=MyPK Variable KEK, length 1326 KEK: List 0, type X509 Signature 0, size 1298, owner 54652821-eb08-4bd2-8108-9cbcebc308f4 Subject: CN=MyKEK Issuer: CN=MyKEK Variable db, length 4469 db: List 0, type X509 Signature 0, size 1298, owner 54652821-eb08-4bd2-8108-9cbcebc308f4 Subject: CN=MySDB Issuer: CN=MySDB db: List 1, type X509 Signature 0, size 1572, owner 26dc4851-195f-4ae1-9a19-fbf883bbb35e Subject: C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, \ CN=Microsoft Corporation UEFI CA 2011 Issuer: C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, \ CN=Microsoft Corporation Third Party Marketplace Root db: List 2, type X509 Signature 0, size 1515, owner 26dc4851-195f-4ae1-9a19-fbf883bbb35e Subject: C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, \ CN=Microsoft Windows Production PCA 2011 Issuer: C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, \ CN=Microsoft Root Certificate Authority 2010 Variable dbx has no entries Variable MokList has no entries
It did boot into Windows though, hence MS keys are accepted in our new PK/KEK/DB chain. Let's check signature:
$ sbverify /esp/EFI/Linux/arch.efi warning: data remaining[17840376 vs 17850608]: gaps between PE/COFF sections? Signature verification failed
Hm, ok, so despite having new platform keys UEFI is refusing to accept our signature. Let's compare with built-in shim:
$ sbverify /esp/EFI/Linux/arch.efi -v warning: data remaining[17840376 vs 17850608]: gaps between PE/COFF sections? signature 1 image signature issuers: - /CN=MySDB image signature certificates: - subject: /CN=MySDB issuer: /CN=MySDB PKCS7 verification failed 139878892764160:error:21075075:PKCS7 routines:PKCS7_verify:certificate verify error:crypto/pkcs7/pk7_smime.c:284:Verify error:self signed certificate Signature verification failed [ruff@trx ruff]$ sbverify /esp/EFI/Boot/bootx64.efi -v signature 1 image signature issuers: - /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Windows Production PCA 2011 image signature certificates: - subject: /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Windows issuer: /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Windows Production PCA 2011 - subject: /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Windows Production PCA 2011 issuer: /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Root Certificate Authority 2010 PKCS7 verification passed Signature verification OK
Ok, so at least verification utility refuses to accept self-signed SDB while being ok with chained MS Windows signature. Let's create our own cert-chain then and try to cargo-cult the existing shim:
openssl req -new -newkey rsa:4096 -nodes -keyout Arch.key -sha256 \ -subj '/CN=My Arch/' -out Arch.csr openssl x509 -req -in Arch.csr -out Arch.crt -CA UEFI/SDB.crt \ -CAkey UEFI/SDB.key -CAcreateserial -days 3650 sudo sbsign --key Arch.key --cert Arch.crt --addcert SDB.crt --output \ /esp/EFI/Linux/arch.efi /esp/EFI/Linux/arch.uefi systemctl reboot --firmware-setup
And nothing. Going forward - it is a red herring, sbverify utility still fails to verify because it verifies against system trust anchor (root CAs). Either way the Asus EFI BIOS refuses to accept image signed by custom key.
To prove that I've repeated the whole process on second laptop - Dell Inspirion. And there it worked flawlessly at the first attempt. Eg. as mentioned earlier the EFI BIOS refued to accept PK/KEK keys from sbkeysync command. However after copying them to ESP, rebooting into BIOS, setting them manually from files, enabling secure boot and rebooting - my signed EFI image got loaded without any hiccup. I just rebooted again to set admin password and hence seal the secureboot.
$ bootctl --esp-path /esp --no-variables systemd-boot not installed in ESP. System: Firmware: UEFI 2.40 (American Megatrends 5.11) Secure Boot: enabled Setup Mode: user TPM2 Support: yes Boot into FW: supported
That's a result I expected, and a proof I did everything right the first time. However there are some gaps.
If you followed my thought train via prism of Arch Wiki, you might have not noticed the first gap - namely Unified Kernel Image (arch.uefi). That is - I didn't explain where did I get one, the process how to make one is explained in the referenced archwiki article.
The second gap is Microsoft key. Depending on how thick is a tinfoil on your hat you may want to skip this as it enables booting any image signed by Microsoft keys. While I do not trust microsoft products in terms of privacy, I still consider them having fair security in mind, merely due to the fact tons of huge businesses are relying on their security, and if that becomes (knowingly) compromised the backlash would destroy the company. But this is just for my peace of mind, I'm not at all trying to convince anyone. The choice is yours. And once I receive my gaming console I'll probably ditch it.
And as a spoiler for next part - do make sure you have your original boot method preserved (eg. unsecured efi grub). SecureBoot we just made is not yet ready for deployment, mere MVP.
Link... Mon Nov 29 23:17:42 2021