Created
March 30, 2021 13:54
-
-
Save daxtens/cfc0a7e15614b0383e0c57f308cacdd1 to your computer and use it in GitHub Desktop.
Testing appended signature-based secure boot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
You can experiement with this using entirely free software. | |
You need the following trees: | |
https://github.com/daxtens/qemu branch pseries-secboot | |
https://github.com/daxtens/SLOF branch ibm,secure-boot | |
https://github.com/daxtens/grub branch appendedsig-2.06 | |
You also need: | |
- a key to sign grub, and accompanying DER certificate | |
- a key to sign linux, and accompanying DER certificate | |
Both should have keyUsage=digitalSignature and not be CAs. | |
Lastly you will need a working a ppc64(le) vm. | |
Then: | |
- build qemu. You need qemu-system-ppc64. | |
- use xxd to convert the certificate for verifying grub into a header | |
file, and copy it in to SLOF/lib/libcrypto/certificate.h. It must | |
create variables certificate_der and certificate_der_len. | |
- build SLOF for qemu (make qemu) | |
- verify that you can boot your VM with new SLOF and stock grub. | |
To boot with new SLOF, pass -bios ./SLOF/boot_rom.bin . It should | |
boot with new slof in non-secure (default) mode. | |
To enable secure boot, add ",secure-boot" to your machine | |
parameter, e.g. "-M pseries,secure-boot". This should now refuse to | |
boot with an error in SLOF. | |
(Note that the SLOF verfication is a bit lackadaisical, it doesn't | |
stop you dropping to the all-powerful OF prompt, and it only | |
requires signatures on 32-bit binaries. -kernel vmlinux should | |
still work even in SB mode, for example. I haven't tested | |
netbooting.) | |
- Build grub in your VM. | |
- create a file called config. Use something like this, adapted to your | |
paths/boot partition setup etc. This helps grub find itself, as | |
unfortunately we can't use the regular prefix stuff. | |
search.file /grub2/grub.cfg root | |
set prefix=($root)'/grub2' | |
configfile $prefix/grub.cfg | |
- Use the attached sign-grub.sh script -- appropriately modified to use your | |
paths -- to build a signed grub image. | |
- Install your grub image with dd, e.g.: | |
dd if=core.elf.signed of=/dev/sda1 | |
- Sign your kernel, e.g.: | |
sign-file SHA256 linux-signing.key linux-signing-certificate.der \ | |
/boot/vmlinux /boot/vmlinux.signed | |
- You should now be able to boot with new SLOF and qemu in | |
secure-boot mode. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -euo pipefail | |
set -x | |
cd $(dirname $0) | |
cur="`pwd`" | |
# sign-grub [--double] [--reserve-space] | |
function sign_single { | |
file="$1" | |
out="$2" | |
cp "$file" "$out.unsigned" | |
truncate -s -$SIG_SIZE "$out.unsigned" | |
# this is the base case, we split it out here just to show how simple it could be! | |
if [ $reserve_space == 'n' ]; then | |
../utils/sign-file SHA256 "../slof-to-grub/grub.key" \ | |
"../slof-to-grub/certificate.der.1" \ | |
"$out.unsigned" "$out.signed" | |
else | |
openssl cms -sign -binary -in "$out.unsigned" \ | |
-signer ../slof-to-grub/certificate.pem.1 -inkey ../slof-to-grub/grub.key \ | |
-out "$out.p7s" -outform DER -noattr -md sha256 -nocerts | |
# extend the size | |
truncate -s $EXTEND_SIZE "$out.p7s" | |
../utils/sign-file -s "$out.p7s" sha265 /dev/null \ | |
"$out.unsigned" "$out.signed" | |
fi | |
} | |
function sign_double { | |
file="$1" | |
out="$2" | |
cp "$file" "$out.unsigned" | |
truncate -s -$SIG_SIZE "$out.unsigned" | |
openssl cms -sign -binary -in "$out.unsigned" \ | |
-signer ../slof-to-grub/certificate.pem.1 -inkey ../slof-to-grub/grub.key \ | |
-signer ../slof-to-grub/certificate.pem.2 -inkey ../slof-to-grub/grub2.key \ | |
-out "$out.p7s" -outform DER -noattr -md sha256 -nocerts | |
if [ $reserve_space == 'y' ]; then | |
truncate -s $EXTEND_SIZE "$out.p7s" | |
fi | |
../utils/sign-file -s "$out.p7s" sha265 /dev/null \ | |
"$out.unsigned" "$out.signed" | |
} | |
if [ $# -gt 0 ] && [ "$1" == "--double" ]; then | |
shift; | |
sign=sign_double; | |
else | |
sign=sign_single; | |
fi | |
if [ $# -gt 0 ] && [ "$1" == "--reserve-space" ]; then | |
shift; | |
reserve_space=y; | |
else | |
reserve_space=n; | |
fi | |
if [ $reserve_space == 'n' ]; then | |
# We need to first figure out how much space the signature takes, | |
if [ -f empty ] || [ -f empty.signed ] || [ -f empty.unsigned ]; then | |
echo "please delete or move aside 'empty' and 'empty.{un,}signed' first" | |
exit 1 | |
fi | |
touch empty | |
SIG_SIZE=0 | |
$sign empty empty | |
SIG_SIZE=`stat -c '%s' empty.signed` | |
echo "Detected signature size: $SIG_SIZE bytes" | |
rm empty empty.signed empty.unsigned | |
else | |
# reserve 32k for this and future signatures. This will probably | |
# become the default upstream | |
EXTEND_SIZE=32768 | |
SIG_SIZE=$(( 32768 + 40 )) | |
fi | |
# build a grub image with that much space reserved | |
pushd ../grub | |
GRUB_MODULES="appendedsig gcry_sha256 all_video boot btrfs cat configfile echo ext2 fat font gfxmenu gfxterm gzio halt hfsplus http iso9660 jpeg loadenv loopback linux lvm mdraid09 mdraid1x minicmd net normal part_apple part_msdos part_gpt password_pbkdf2 png reboot regexp search search_fs_uuid search_fs_file search_label serial sleep syslinuxcfg test tftp video xfs" | |
./grub-mkimage -O powerpc-ieee1275 -o "$cur/core.elf" --appended-signature-size $SIG_SIZE -d ./grub-core/ -x ../keys/imprint-keys/kernel.der -p '' -c "$cur/config" $GRUB_MODULES | |
$sign "$cur/core.elf" "$cur/core.elf" | |
popd |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment