From a3a84b25e88141cc91c3b0b2d69a366c011ed3dc Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Fri, 17 May 2024 15:12:00 +0200 Subject: [PATCH] image: support shim usage for uefi and disk Fixes #5230 --- repos/base/ports/grub2.hash | 2 +- repos/base/ports/grub2.port | 3 +- tool/run/image/disk | 45 ++++++++++++++++++++++--- tool/run/image/uefi | 10 +++++- tool/run/shim.inc | 65 +++++++++++++++++++++++++++++++++++++ 5 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 tool/run/shim.inc diff --git a/repos/base/ports/grub2.hash b/repos/base/ports/grub2.hash index 698fb7e4db..1c312c0143 100644 --- a/repos/base/ports/grub2.hash +++ b/repos/base/ports/grub2.hash @@ -1 +1 @@ -80d41dfe8a1d8d8a80c51f446553b7d28c3ce395 +8c6a21b5e837a9491ebcb21611f5f865411544f5 diff --git a/repos/base/ports/grub2.port b/repos/base/ports/grub2.port index bcf5e86675..8624760b78 100644 --- a/repos/base/ports/grub2.port +++ b/repos/base/ports/grub2.port @@ -3,10 +3,11 @@ VERSION := git DOWNLOADS := g2fg.git URL(g2fg) := https://github.com/alex-ab/g2fg.git -REV(g2fg) := 0d94ee016a3a4f991f502d04ef59e7d0d8e75346 +REV(g2fg) := 95c79d8ca590eefaab7297c7a631125a64973266 DIR(g2fg) := boot default: $(DOWNLOADS) $(VERBOSE)tar -C boot -xJf boot/grub2.tar.xz $(VERBOSE)unxz -kf boot/grub2-head.img.xz + $(VERBOSE)unxz -kf boot/grub2-head-big.img.xz $(VERBOSE)unxz -kf boot/font.pf2.xz diff --git a/tool/run/image/disk b/tool/run/image/disk index 7b2aec889a..c4c791dc19 100644 --- a/tool/run/image/disk +++ b/tool/run/image/disk @@ -1,15 +1,53 @@ ## # Create disk image with contents of the run directory # -# \param --image-disk-size disk size in MiB +# \param --image-disk_size disk size in MiB +# \param --image-disk_shim nickname of certificate to use to sign GRUB2 # source [genode_dir]/tool/run/grub2.inc +source [genode_dir]/tool/run/shim.inc -proc image_disk_size { } { return [get_cmd_arg --image-disk-size 0] } +proc image_disk_size { } { return [get_cmd_arg --image-disk_size 0] } +proc image_disk_shim { } { return [get_cmd_arg --image-disk_shim ""] } +proc prepare_grub2_files { } { + + set sgdisk [installed_command sgdisk] + set mcopy [installed_command mcopy] + + # make copy of template grub2 header, for signing use the larger header + if {[image_disk_shim] == ""} { + exec cp [get_grub2_dir]/boot/grub2-head.img [run_dir].header + } else { + exec cp [get_grub2_dir]/boot/grub2-head-big.img [run_dir].header + } + + set efi_partition_info [exec $sgdisk -i 2 [run_dir].header] + set efi_first_sector [regexp -all -line -inline {First sector: ([0-9]+)} $efi_partition_info] + set efi_first_sector [lindex $efi_first_sector 1] + set efi_partition_offset [expr $efi_first_sector * 512] + + exec mkdir -p [run_dir]/tmp/efi/boot + + if {[image_disk_shim] == ""} { + # use unsigned efi binaries + exec cp [get_grub2_dir]/boot/grub2/grub2_32.efi [run_dir]/tmp/efi/boot/bootia32.efi + exec cp [get_grub2_dir]/boot/grub2/grub2_64.efi [run_dir]/tmp/efi/boot/bootx64.efi + } else { + # sign grub2 efi binary + setup_shim_and_sign_grub2 [image_disk_shim] [run_dir]/tmp/efi/boot + } + + foreach file [exec ls [run_dir]/tmp/efi/boot] { + exec $mcopy -i [run_dir].header@@$efi_partition_offset -s [run_dir]/tmp/efi/boot/$file ::efi/boot/$file + } + + exec rm -rf [run_dir]/tmp +} + ## # Create disk image with the content of the run directory # @@ -17,8 +55,7 @@ proc run_image { } { set sgdisk [installed_command sgdisk] - # make copy of template grub2 header image - exec cp [get_grub2_dir]/boot/grub2-head.img [run_dir].header + prepare_grub2_files # remove template partition exec $sgdisk --delete=3 [run_dir].header diff --git a/tool/run/image/uefi b/tool/run/image/uefi index 2f3afedccb..e7dcfc953e 100644 --- a/tool/run/image/uefi +++ b/tool/run/image/uefi @@ -1,12 +1,15 @@ source [genode_dir]/tool/run/grub2.inc +source [genode_dir]/tool/run/shim.inc ## # Create GPT disk image with UEFI boot loaders and content of the run directory # -# \param --image-uefi-size disk size in MiB +# \param --image-uefi_size disk size in MiB +# \param --image-disk_shim nickname of certificate to use to sign GRUB2 # proc image_uefi_size { } { return [get_cmd_arg --image-uefi_size 0] } +proc image_uefi_shim { } { return [get_cmd_arg --image-uefi_shim ""] } ## @@ -45,6 +48,11 @@ proc install_uefi_bootloader_to_run_dir { } { exec mkdir -p [run_dir]/efi/boot exec cp [get_grub2_dir]/boot/grub2/grub2_32.efi [run_dir]/efi/boot/bootia32.efi exec cp [get_grub2_dir]/boot/grub2/grub2_64.efi [run_dir]/efi/boot/bootx64.efi + + if {[image_uefi_shim] != ""} { + setup_shim_and_sign_grub2 [image_uefi_shim] [run_dir]/efi/boot + } + exec mkdir -p [run_dir]/boot/grub exec cp [genode_dir]/tool/boot/bender [run_dir]/boot/bender diff --git a/tool/run/shim.inc b/tool/run/shim.inc new file mode 100644 index 0000000000..e4731d657e --- /dev/null +++ b/tool/run/shim.inc @@ -0,0 +1,65 @@ +proc setup_shim_and_sign_grub2 { nickname target_dir } { + + set host_shim_path "/usr/lib/shim" + set check_binaries "mmx64.efi shimx64.efi" + set host_binaries "" + + foreach binary $check_binaries { + set filename "$host_shim_path/$binary" + if {[file exists "$filename.signed"]} { + lappend host_binaries $binary.signed + continue + } + + if {[file exists "$filename"]} { + lappend host_binaries $binary + continue + } + + puts "Error: shim binary file $host_shim_path/$binary missing" + puts "shim packages of your distribution are required" + exit -1 + } + + foreach binary $host_binaries { + catch {exec [installed_command sbverify] --list $host_shim_path/$binary} result + + puts "using $host_shim_path/$binary " + puts $result + + if {[regexp "No signature table present" $result]} { + puts "$binary has no signatures attached" + exit -1 + } + } + + exec cp $host_shim_path/[lindex $host_binaries 0] $target_dir/mmx64.efi + exec cp $host_shim_path/[lindex $host_binaries 1] $target_dir/bootx64.efi + + puts "Export certificate for nickname '$nickname' to $target_dir/$nickname.cer" + try { + exec [installed_command sudo] [installed_command certutil] \ + -d /etc/pki/pesign -n $nickname -Lr >$target_dir/$nickname.cer + } on error { } { + puts "" + puts "Certificate with nickname '$nickname' not found!" + puts "" + puts "Notes for creating a certificate:" + puts "" + puts " sudo efikeygen --self-sign --common-name 'CN=YOUR COMPANY' --nickname '$nickname'" + puts "" + puts " Hint: newer efikeygen version may require --kernel" + puts "" + puts " The public and private keys are stored in the /etc/pki/pesign/ directory." + puts " For more detailed information please consider documentation of efikeygen." + puts "" + + exit -1 + } + + puts "Invoking 'pesign' for grub2 efi image" + exec [installed_command sudo] [installed_command pesign] \ + --in=[get_grub2_dir]/boot/grub2/grub2_64.efi \ + --out=$target_dir/grubx64.efi \ + -c $nickname --sign +}