#6 Enable aarch64 key enroll
Opened 2 years ago by jlinton. Modified 2 years ago
rpms/ jlinton/edk2 fix_enroll  into  rawhide

file modified
+91 -69
@@ -5,7 +5,6 @@ 

  %global edk2_stable_date 202008

  %global edk2_stable_str  edk2-stable%{edk2_stable_date}

  %global openssl_version  1.1.1g

- %global qosb_version     20190521-gitf158f12

  %global softfloat_version 20180726-gitb64af41

  

  # Enable this to skip secureboot enrollment, if problems pop up
@@ -13,9 +12,6 @@ 

  

  %define qosb_testing 0

  

- %ifarch x86_64

- %define qosb_testing 1

- %endif

  %if 0%{?fedora:1}

  %define cross 1

  %endif
@@ -55,8 +51,6 @@ 

  Source0:        https://github.com/tianocore/edk2/archive/%{edk2_stable_str}.tar.gz#/%{edk2_stable_str}.tar.gz

  Source1:        openssl-%{openssl_version}-hobbled.tar.xz

  Source2:        ovmf-whitepaper-c770f8c.txt

- #Source3:        https://github.com/puiterwijk/qemu-ovmf-secureboot/archive/v{qosb_version}/qemu-ovmf-secureboot-{qosb_version}.tar.gz

- Source3:        qemu-ovmf-secureboot-%{qosb_version}.tar.xz

  Source4:        softfloat-%{softfloat_version}.tar.xz

  Source5:        RedHatSecureBootPkKek1.pem

  Source10:       hobble-openssl
@@ -74,6 +68,15 @@ 

  Source20:       70-edk2-aarch64-verbose.json

  Source21:       70-edk2-arm-verbose.json

  

+ %if %{?qosb_testing}

+ # some kernels for verification

+ # sourced via https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/30/Server/$ARCH/os/images/pxeboot/vmlinuz"

+ # this is sort of "odd" but it works around the issue of the build vs deploy arch

+ # and sourcing things via the network at runtime

+ Source22:       vmlinuz-x86_64

+ Source23:       vmlinuz-aarch64

+ %endif

+ 

  # non-upstream patches

  Patch0001: 0001-OvmfPkg-silence-EFI_D_VERBOSE-0x00400000-in-NvmExpre.patch

  Patch0002: 0002-OvmfPkg-silence-EFI_D_VERBOSE-0x00400000-in-the-DXE-.patch
@@ -122,19 +125,9 @@ 

  BuildRequires:  bc

  BuildRequires:  sed

  

- # These are for QOSB

- BuildRequires:  python3-requests

  BuildRequires:  qemu-system-x86

- %if %{?qosb_testing}

- # This is used for testing the enrollment: builds are run in a chroot, lacking

- # a kernel. The testing is only performed on x86_64 for now, but we can't make

- # the BuildRequires only on a specific arch, as that'd come through in the SRPM

- # NOTE: The actual enrollment needs to happen in all builds for all architectures,

- # because OVMF is built as noarch, which means that koji enforces that the build

- # results don't actually differ per arch, and then it picks a random arches' build

- # for the actual RPM.

- BuildRequires:  kernel-core

- %endif

+ BuildRequires:  qemu-system-aarch64

+ BuildRequires:  expect

  

  %description

  EDK II is a development code base for creating UEFI drivers, applications
@@ -163,15 +156,6 @@ 

  This package documents the tools that are needed to

  build EFI executables and ROMs using the GNU tools.

  

- %package qosb

- Summary:        Tool to enroll secureboot

- Requires:       python3

- Buildarch:      noarch

- %description qosb

- This package contains QOSB (QEMU OVMF Secure Boot), which can enroll OVMF

- variable files to enforce Secure Boot.

- 

- 

  %if 0%{?build_ovmf_x64:1}

  %package ovmf

  Summary:        Open Virtual Machine Firmware
@@ -242,10 +226,11 @@ 

  # extract softfloat into place

  tar -xf %{SOURCE4} --strip-components=1 --directory ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3/

  

- # Extract QOSB

- tar -xf %{SOURCE3}

- mv qemu-ovmf-secureboot-%{qosb_version}/README.md README.qosb

- mv qemu-ovmf-secureboot-%{qosb_version}/LICENSE LICENSE.qosb

+ %if %{?qosb_testing}

+ # move known good kernels

+ cp -a -- %{SOURCE22} .

+ cp -a -- %{SOURCE23} .

+ %endif

  

  %autopatch -p1

  base64 --decode < MdeModulePkg/Logo/Logo-OpenSSL.bmp.b64 > MdeModulePkg/Logo/Logo-OpenSSL.bmp
@@ -261,6 +246,62 @@ 

  

  

  %build

+ 

+ # enroll_keys arch edk2firmware variablefile isofile

+ enroll_keys() {

+     local MACHTYPE=$1

+     local FIRMWARE="-drive file=$2,if=pflash,format=raw,unit=0,readonly=on"

+     local VARS="-drive file=$3,if=pflash,format=raw,unit=1,readonly"

+     local CDROM="-drive file=$4,format=raw,if=virtio,media=cdrom,id=drive-cd1,readonly=on"

+     local COMMON="-display none -no-reboot -no-user-config -nodefaults -m 768 -serial stdio"

+     local SMBIOS="-smbios type=11,value=$(< PkKek1.oemstr)"

+ 

+     case "$MACHTYPE" in

+ 	aarch64)

+ 	    QEMU_ARCH="-machine virt -cpu cortex-a57"

+ 	    ;;

+ 	x86_64)

+ 	    QEMU_ARCH="-machine q35,smm=on -chardev pty,id=charserial1 "

+ 	    QEMU_ARCH+="-global driver=cfi.pflash01,property=secure,value=on "

+ 	    ;;

+ 	*)

+ 	    echo "unsupported architecture $MACHTYPE"

+ 	    exit 1

+ 	    ;;

+     esac

+ 

+   /usr/bin/expect <<EOF

+ spawn /usr/bin/qemu-system-${MACHTYPE} ${QEMU_ARCH} ${COMMON} $FIRMWARE ${VARS}=off $CDROM $SMBIOS

+ set timeout 60

+ expect -exact "Shell>"

+ send -- "\r\nfs0:\r\n"

+ send -- "EnrollDefaultKeys.efi\r\n"

+ send -- "reset -s\r\n"

+ expect eof

+ EOF

+ 

+ %if %{?qosb_testing}

+   # now verify the image

+   local KERNEL="-append console=ttyS0,115200n8 -kernel vmlinuz-"$MACHTYPE

+ 

+   /usr/bin/expect <<EOF

+ spawn /usr/bin/qemu-system-${MACHTYPE} ${QEMU_ARCH} ${COMMON} $FIRMWARE ${VARS}=on $SMBIOS $KERNEL

+ set timeout 60

+ expect {

+        -ex "Secure boot disabled" { puts "\ndisabled";  exit 1 }

+        -ex "Secure boot enabled" { puts "\nenabled"; exit 0 }

+        -ex "Kernel is locked down from EFI" { puts "\nenabled"; exit 0 }

+        -ex "The image doesn't pass verification" { puts "\enabled"; exit 1 }

+ }

+ expect eof

+ EOF

+   if [[ "$?" == "1" ]]; then

+       echo "Image verification failure!"

+       exit 1

+   fi

+ %endif

+ }

+ 

  export PYTHON_COMMAND=%{__python3}

  source ./edksetup.sh

  
@@ -292,7 +333,7 @@ 

  OVMF_SB_FLAGS="${OVMF_SB_FLAGS} -D EXCLUDE_SHELL_FROM_FD"

  

  # arm firmware features

- ARM_FLAGS="${CC_FLAGS}"

+ ARM_FLAGS="${CC_FLAGS} -D SECURE_BOOT_ENABLE"

  

  unset MAKEFLAGS

  %make_build -C BaseTools \
@@ -324,19 +365,10 @@ 

  cp Build/Ovmf3264/*/X64/EnrollDefaultKeys.efi ovmf

  sh %{_sourcedir}/build-iso.sh ovmf/

  

- %if !%{skip_enroll}

- python3 qemu-ovmf-secureboot-%{qosb_version}/ovmf-vars-generator \

-     --qemu-binary /usr/bin/qemu-system-x86_64 \

-     --ovmf-binary ovmf/OVMF_CODE.secboot.fd \

-     --ovmf-template-vars ovmf/OVMF_VARS.fd \

-     --uefi-shell-iso ovmf/UefiShell.iso \

-     --oem-string "$(< PkKek1.oemstr)" \

-     --skip-testing \

-     ovmf/OVMF_VARS.secboot.fd

- %else

- # This isn't going to actually give secureboot, but makes json files happy

- # if we need to test disabling ovmf-vars-generator

  cp ovmf/OVMF_VARS.fd ovmf/OVMF_VARS.secboot.fd

+ 

+ %if !%{skip_enroll}

+ enroll_keys  "x86_64" "ovmf/OVMF_CODE.secboot.fd" "ovmf/OVMF_VARS.secboot.fd"  "ovmf/UefiShell.iso"

  %endif

  %endif

  
@@ -365,10 +397,22 @@ 

  %if 0%{?build_aavmf_aarch64:1}

  mkdir -p aarch64

  build $ARM_FLAGS -a AARCH64 -p ArmVirtPkg/ArmVirtQemu.dsc

+ 

  cp Build/ArmVirtQemu-AARCH64/DEBUG_*/FV/*.fd aarch64

  dd of="aarch64/QEMU_EFI-pflash.raw" if="/dev/zero" bs=1M count=64

  dd of="aarch64/QEMU_EFI-pflash.raw" if="aarch64/QEMU_EFI.fd" conv=notrunc

  dd of="aarch64/vars-template-pflash.raw" if="/dev/zero" bs=1M count=64

+ 

+ # build aavmf shell iso with EnrollDefaultKeys

+ cp Build/ArmVirtQemu-AARCH64/DEBUG_*/AARCH64/Shell.efi aarch64

+ cp Build/ArmVirtQemu-AARCH64/DEBUG_*/AARCH64/EnrollDefaultKeys.efi aarch64

+ sh %{_sourcedir}/build-iso.sh aarch64/

+ 

+ %if !%{skip_enroll}

+ enroll_keys  "aarch64" "aarch64/QEMU_EFI-pflash.raw" \

+ 	     "aarch64/vars-template-pflash.raw"  "aarch64/UefiShell.iso"

+ %endif

+ 

  %endif

  

  
@@ -385,23 +429,7 @@ 

  

  

  %check

- %if 0%{?build_ovmf_x64:1}

- %if 0%{?qosb_testing}

- %if !%{skip_enroll}

- python3 qemu-ovmf-secureboot-%{qosb_version}/ovmf-vars-generator \

-     --qemu-binary /usr/bin/qemu-system-x86_64 \

-     --ovmf-binary ovmf/OVMF_CODE.secboot.fd \

-     --ovmf-template-vars ovmf/OVMF_VARS.fd \

-     --uefi-shell-iso ovmf/UefiShell.iso \

-     --skip-enrollment \

-     --print-output \

-     --no-download \

-     --kernel-path `rpm -ql kernel-core | grep "\/vmlinuz$" -m 1` \

-     ovmf/OVMF_VARS.secboot.fd

- %endif

- %endif

- %endif

- 

+ # key verification done as part of the enroll now

  

  

  %install
@@ -488,9 +516,6 @@ 

  %endif

  

  

- install qemu-ovmf-secureboot-%{qosb_version}/ovmf-vars-generator %{buildroot}%{_bindir}

- 

- 

  %files tools

  %license License.txt

  %license LICENSE.openssl
@@ -529,11 +554,6 @@ 

  %files tools-doc

  %doc BaseTools/UserManuals/*.rtf

  

- %files qosb

- %license LICENSE.qosb

- %doc README.qosb

- %{_bindir}/ovmf-vars-generator

- 

  %if 0%{?build_ovmf_x64:1}

  %files ovmf

  %license OvmfPkg/License.txt
@@ -574,6 +594,8 @@ 

  %dir /usr/share/qemu/firmware

  /usr/share/%{name}/aarch64/QEMU*.fd

  /usr/share/%{name}/aarch64/*.raw

+ /usr/share/%{name}/aarch64/*.efi

+ /usr/share/%{name}/aarch64/*.iso

  /usr/share/qemu/firmware/*edk2-aarch64*.json

  /usr/share/AAVMF/AAVMF_*

  %endif

This patch enables key enroll using "expect" rather than the qosb utility which is large, unwieldy and doesn't support !x86. This is a far more concise way to create preprogrammed scripts that interact with utilities (in this case a running qemu/edk).

I also added code to validate the enrolled keys (last patch) but left it disabled because it will break the build when it detects an unsigned aarch64 kernel. Once the kernel/etc is signed it can be re-enabled.

I rebased this (and dropped the fixup commit required for the older edk2).

rebased onto b2c2372

2 years ago

Thanks for the patches. Can you file a Fedora edk2 bug about this? I will CC some people for feedback and bugzilla is the more natural forum for non-fedora devs. Just mention the goal and a summary of what the changes are with a link back to this PR

Thanks. Will wait for feedback in the bug. One comment about the patches as is: please separate out the shell code from the spec file, into a shell script stored in dist-git. Will make it easier to test manually for one thing

Shell code? I assume your just talking about the enroll_keys() function? Rather than some larger part of the %build block.

Its pretty straightforward to toss that function into a source'd file similar to edksetup.sh. Which I can do simply. Although I'm not sure if the .spec conditionals (in particular the "qosb_testing" flow into sourced files.

OTOH, I also have what is mostly a replacement of the python script with a getops block, but it is like the python script subject to the brittleness of the idea that it should be run in arbitrary environments (rather than a fixed known one where its possible to control paths/etc). In that environment it becomes subject to "whatifism" discussions that haven't good answers, particularly when you start to have conflicting command line options.

I think what everyone will discover is that the way expect works, results in far more robust handling of unexpected conditions (like for example the expected sequence never appearing, or happening out of order/etc) and needs far less fine twitting.

Anyway, I can provide that script as a testing tool if someone is interested it trying to test/break things. But I'm hesitant to make it a formal tool for the above reasons. Particularly as there is already the python tool.

I will attach that script to the BZ...

I wasn't thinking formal tool. Just separate from the spec file, only used at build time, not installed. At some point something is going to go wrong with a build and I'd rather be able to run the script locally outside of the RPM than have to kick off a full build to debug the failure. In my experience maintaining any interesting logic in a spec file is just painful so I'd prefer to avoid it if I can. My 2 cents