diff --git a/LICENSE.qosb b/LICENSE.qosb deleted file mode 100644 index 9849381..0000000 --- a/LICENSE.qosb +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 Patrick Uiterwijk - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/RedHatSecureBootPkKek1.pem b/RedHatSecureBootPkKek1.pem deleted file mode 100644 index d302362..0000000 --- a/RedHatSecureBootPkKek1.pem +++ /dev/null @@ -1,22 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDoDCCAoigAwIBAgIJAP71iOjzlsDxMA0GCSqGSIb3DQEBCwUAMFExKzApBgNV -BAMTIlJlZCBIYXQgU2VjdXJlIEJvb3QgKFBLL0tFSyBrZXkgMSkxIjAgBgkqhkiG -9w0BCQEWE3NlY2FsZXJ0QHJlZGhhdC5jb20wHhcNMTQxMDMxMTExNTM3WhcNMzcx -MDI1MTExNTM3WjBRMSswKQYDVQQDEyJSZWQgSGF0IFNlY3VyZSBCb290IChQSy9L -RUsga2V5IDEpMSIwIAYJKoZIhvcNAQkBFhNzZWNhbGVydEByZWRoYXQuY29tMIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkB+Ee42865cmgm2Iq4rJjGhw -+d9LB7I3gwsCyGdoMJ7j8PCZSrhZV8ZB9jiL/mZMSek3N5IumAEeWxRQ5qiNJQ31 -huarMMtAFuqNixaGcEM38s7Akd9xFI6ZDom2TG0kHozkL08l0LoG+MboGRh2cx2B -bajYBc86yHsoyDajFg0pjJmaaNyrwE2Nv1q7K6k5SwSXHPk2u8U6hgSur9SCe+Cr -3kkFaPz2rmgabJBNVxk8ZGYD9sdSm/eUz5NqoWjJqs+Za7yqXgjnORz3+A+6Bn7x -y+h23f4i2q06Xls06rPJ4E0EKX64YLkF77XZF1hWFmC5MDLwNkrD8nmNEkBw8wID -AQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVy -YXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUPOlg4/8ZoQp7o0L0jUIutNWccuww -HwYDVR0jBBgwFoAUPOlg4/8ZoQp7o0L0jUIutNWccuwwDQYJKoZIhvcNAQELBQAD -ggEBAFxNkoi0gl8drYsR7N8GpnqlK583VQyNbgUArbcMQYlpz9ZlBptReNKtx7+c -3AVzf+ceORO06rYwfUB1q5xDC9+wwhu/MOD0/sDbYiGY9sWv3jtPSQrmHvmGsD8N -1tRGN9tUdF7/EcJgxnBYxRxv7LLYbm/DvDOHOKTzRGScNDsolCZ4J58WF+g7aQol -qXM2fp43XOzoP9uR+RKzPc7n3RXDrowFIGGbld6br/qxXBzll+fDNBGF9YonJqRw -NuwM9oM9kPc28/nzFdSQYr5TtK/TSa/v9HPoe3bkRCo3uoGkmQw6MSRxoOTktxrL -R+SqIs/vdWGA40O3SFdzET14m2k= ------END CERTIFICATE----- diff --git a/edk2.spec b/edk2.spec index bf1376a..4812b77 100644 --- a/edk2.spec +++ b/edk2.spec @@ -14,11 +14,6 @@ ExclusiveArch: x86_64 aarch64 %define TOOLCHAIN GCC5 %define OPENSSL_VER 1.1.1k -%define qosb_testing 0 -%ifarch x86_64 -%define qosb_testing 1 -%endif - %if %{defined rhel} %define build_ovmf 0 %define build_aarch64 0 @@ -52,9 +47,6 @@ URL: http://www.tianocore.org Source0: edk2-%{GITCOMMIT}.tar.xz Source1: ovmf-whitepaper-c770f8c.txt Source2: openssl-rhel-bdd048e929dcfcf2f046d74e812e0e3d5fc58504.tar.xz -Source3: ovmf-vars-generator -Source4: LICENSE.qosb -Source5: RedHatSecureBootPkKek1.pem Source10: edk2-aarch64-verbose.json Source11: edk2-aarch64.json @@ -119,13 +111,6 @@ BuildRequires: xorriso # enrolled. BuildRequires: python3-virt-firmware -%if %{qosb_testing} -# For verifying SB enablement in the above variable store template, we need a -# guest kernel that prints "Secure boot enabled". -BuildRequires: kernel-core >= 4.18.0-161 -BuildRequires: rpmdevtools -%endif - # endif build_ovmf %endif @@ -217,14 +202,6 @@ License: BSD-2-Clause-Patent and OpenSSL EFI Development Kit II ARMv7 UEFI Firmware -%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. - %package tools-python Summary: EFI Development Kit II Tools Requires: python3 @@ -250,27 +227,13 @@ git config am.keepcr true # -D is passed to %%setup to not delete the existing archive dir %autosetup -T -D -n edk2-%{GITCOMMIT} -S git_am -cp -a -- %{SOURCE1} %{SOURCE3} . +cp -a -- %{SOURCE1} . cp -a -- %{SOURCE10} %{SOURCE11} %{SOURCE12} %{SOURCE13} %{SOURCE14} . tar -C CryptoPkg/Library/OpensslLib -a -f %{SOURCE2} -x -# Format the Red Hat-issued certificate that is to be enrolled as both Platform -# Key and first Key Exchange Key, as an SMBIOS OEM String. This means stripping -# the PEM header and footer, and prepending the textual representation of the -# GUID that identifies this particular OEM String to "EnrollDefaultKeys.efi", -# plus the separator ":". For details, see -# comments 2, 7, 14. -sed \ - -e 's/^-----BEGIN CERTIFICATE-----$/4e32566d-8e9e-4f52-81d3-5bb9715f9727:/' \ - -e '/^-----END CERTIFICATE-----$/d' \ - %{SOURCE5} \ - > PkKek1.oemstr - # Done by %setup, but we do not use it for the auxiliary tarballs chmod -Rf a+rX,u+w,g-w,o-w . -# Fedora specific -cp -a -- %{SOURCE4} . # extract softfloat into place tar -xf %{SOURCE50} --strip-components=1 --directory ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3/ @@ -584,24 +547,15 @@ done %py_byte_compile %{python3} %{buildroot}%{_datadir}/edk2/Python %endif -# edk2-qosb install -install -p ovmf-vars-generator %{buildroot}%{_bindir} - # endif defined fedora %endif %check - -%if %{qosb_testing} virt-fw-vars --input Build/Ovmf3264/DEBUG_%{TOOLCHAIN}/FV/OVMF_VARS.secboot.fd \ --print | grep "SecureBootEnable.*ON" -# endif qosb_testing -%endif - - %global common_files \ %%license License.txt License.OvmfPkg.txt License-History.txt LICENSE.openssl \ %%dir %%{_datadir}/%%{name}/ \ @@ -726,11 +680,6 @@ virt-fw-vars --input Build/Ovmf3264/DEBUG_%{TOOLCHAIN}/FV/OVMF_VARS.secboot.fd \ %dir %{_datadir}/%{name} %{_datadir}/%{name}/Python - -%files qosb -%license LICENSE.qosb -%{_bindir}/ovmf-vars-generator - # endif fedora %endif diff --git a/ovmf-vars-generator b/ovmf-vars-generator deleted file mode 100755 index 111e438..0000000 --- a/ovmf-vars-generator +++ /dev/null @@ -1,295 +0,0 @@ -#!/bin/python3 -# Copyright (C) 2017 Red Hat -# Authors: -# - Patrick Uiterwijk -# - Kashyap Chamarthy -# -# Licensed under MIT License, for full text see LICENSE -# -# Purpose: Launch a QEMU guest and enroll ithe UEFI keys into an OVMF -# variables ("VARS") file. Then boot a Linux kernel with QEMU. -# Finally, perform a check to verify if Secure Boot -# is enabled. - -from __future__ import print_function - -import argparse -import os -import logging -import tempfile -import shutil -import string -import subprocess - - -def strip_special(line): - return ''.join([c for c in str(line) if c in string.printable]) - - -def generate_qemu_cmd(args, readonly, *extra_args): - if args.disable_smm: - machinetype = 'pc' - else: - machinetype = 'q35,smm=on' - machinetype += ',accel=%s' % ('kvm' if args.enable_kvm else 'tcg') - - if args.oem_string is None: - oemstrings = [] - else: - oemstring_values = [ - ",value=" + s.replace(",", ",,") for s in args.oem_string ] - oemstrings = [ - '-smbios', - "type=11" + ''.join(oemstring_values) ] - - return [ - args.qemu_binary, - '-machine', machinetype, - '-display', 'none', - '-no-user-config', - '-nodefaults', - '-m', '768', - '-smp', '2,sockets=2,cores=1,threads=1', - '-chardev', 'pty,id=charserial1', - '-device', 'isa-serial,chardev=charserial1,id=serial1', - '-global', 'driver=cfi.pflash01,property=secure,value=%s' % ( - 'off' if args.disable_smm else 'on'), - '-drive', - 'file=%s,if=pflash,format=raw,unit=0,readonly=on' % ( - args.ovmf_binary), - '-drive', - 'file=%s,if=pflash,format=raw,unit=1,readonly=%s' % ( - args.out_temp, 'on' if readonly else 'off'), - '-serial', 'stdio'] + oemstrings + list(extra_args) - - -def download(url, target, suffix, no_download): - istemp = False - if target and os.path.exists(target): - return target, istemp - if not target: - temped = tempfile.mkstemp(prefix='qosb.', suffix='.%s' % suffix) - os.close(temped[0]) - target = temped[1] - istemp = True - if no_download: - raise Exception('%s did not exist, but downloading was disabled' % - target) - import requests - logging.debug('Downloading %s to %s', url, target) - r = requests.get(url, stream=True) - with open(target, 'wb') as f: - for chunk in r.iter_content(chunk_size=1024): - if chunk: - f.write(chunk) - return target, istemp - - -def enroll_keys(args): - shutil.copy(args.ovmf_template_vars, args.out_temp) - - logging.info('Starting enrollment') - - cmd = generate_qemu_cmd( - args, - False, - '-drive', - 'file=%s,format=raw,if=none,media=cdrom,id=drive-cd1,' - 'readonly=on' % args.uefi_shell_iso, - '-device', - 'ide-cd,drive=drive-cd1,id=cd1,' - 'bootindex=1') - p = subprocess.Popen(cmd, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - logging.info('Performing enrollment') - # Wait until the UEFI shell starts (first line is printed) - read = p.stdout.readline() - if b'char device redirected' in read: - read = p.stdout.readline() - # Skip passed QEMU warnings, like the following one we see in Ubuntu: - # qemu-system-x86_64: warning: TCG doesn't support requested feature: CPUID.01H:ECX.vmx [bit 5] - while b'qemu-system-x86_64: warning:' in read: - read = p.stdout.readline() - if args.print_output: - print(strip_special(read), end='') - print() - # Send the escape char to enter the UEFI shell early - p.stdin.write(b'\x1b') - p.stdin.flush() - # And then run the following three commands from the UEFI shell: - # change into the first file system device; install the default - # keys and certificates, and reboot - p.stdin.write(b'fs0:\r\n') - p.stdin.write(b'EnrollDefaultKeys.efi\r\n') - p.stdin.write(b'reset -s\r\n') - p.stdin.flush() - while True: - read = p.stdout.readline() - if args.print_output: - print('OUT: %s' % strip_special(read), end='') - print() - if b'info: success' in read: - break - p.wait() - if args.print_output: - print(strip_special(p.stdout.read()), end='') - logging.info('Finished enrollment') - - -def test_keys(args): - logging.info('Grabbing test kernel') - kernel, kerneltemp = download(args.kernel_url, args.kernel_path, - 'kernel', args.no_download) - - logging.info('Starting verification') - try: - cmd = generate_qemu_cmd( - args, - True, - '-append', 'console=tty0 console=ttyS0,115200n8', - '-kernel', kernel) - p = subprocess.Popen(cmd, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - logging.info('Performing verification') - while True: - read = p.stdout.readline() - if args.print_output: - print('OUT: %s' % strip_special(read), end='') - print() - if b'Secure boot disabled' in read: - raise Exception('Secure Boot was disabled') - elif b'Secure boot enabled' in read: - logging.info('Confirmed: Secure Boot is enabled') - break - elif b'Kernel is locked down from EFI secure boot' in read: - logging.info('Confirmed: Secure Boot is enabled') - break - p.kill() - if args.print_output: - print(strip_special(p.stdout.read()), end='') - logging.info('Finished verification') - finally: - if kerneltemp: - os.remove(kernel) - - -def parse_args(): - parser = argparse.ArgumentParser() - parser.add_argument('output', help='Filename for output vars file') - parser.add_argument('--out-temp', help=argparse.SUPPRESS) - parser.add_argument('--force', help='Overwrite existing output file', - action='store_true') - parser.add_argument('--print-output', help='Print the QEMU guest output', - action='store_true') - parser.add_argument('--verbose', '-v', help='Increase verbosity', - action='count') - parser.add_argument('--quiet', '-q', help='Decrease verbosity', - action='count') - parser.add_argument('--qemu-binary', help='QEMU binary path', - default='/usr/bin/qemu-system-x86_64') - parser.add_argument('--enable-kvm', help='Enable KVM acceleration', - action='store_true') - parser.add_argument('--ovmf-binary', help='OVMF secureboot code file', - default='/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd') - parser.add_argument('--ovmf-template-vars', help='OVMF empty vars file', - default='/usr/share/edk2/ovmf/OVMF_VARS.fd') - parser.add_argument('--uefi-shell-iso', help='Path to uefi shell iso', - default='/usr/share/edk2/ovmf/UefiShell.iso') - parser.add_argument('--skip-enrollment', - help='Skip enrollment, only test', action='store_true') - parser.add_argument('--skip-testing', - help='Skip testing generated "VARS" file', - action='store_true') - parser.add_argument('--kernel-path', - help='Specify a consistent path for kernel') - parser.add_argument('--no-download', action='store_true', - help='Never download a kernel') - parser.add_argument('--fedora-version', - help='Fedora version to get kernel for checking', - default='27') - parser.add_argument('--kernel-url', help='Kernel URL', - default='https://download.fedoraproject.org/pub/fedora' - '/linux/releases/%(version)s/Everything/x86_64' - '/os/images/pxeboot/vmlinuz') - parser.add_argument('--disable-smm', - help=('Don\'t restrict varstore pflash writes to ' - 'guest code that executes in SMM. Use this ' - 'option only if your OVMF binary doesn\'t have ' - 'the edk2 SMM driver stack built into it ' - '(possibly because your QEMU binary lacks SMM ' - 'emulation). Note that without restricting ' - 'varstore pflash writes to guest code that ' - 'executes in SMM, a malicious guest kernel, ' - 'used for testing, could undermine Secure ' - 'Boot.'), - action='store_true') - parser.add_argument('--oem-string', - help=('Pass the argument to the guest as a string in ' - 'the SMBIOS Type 11 (OEM Strings) table. ' - 'Multiple occurrences of this option are ' - 'collected into a single SMBIOS Type 11 table. ' - 'A pure ASCII string argument is strongly ' - 'suggested.'), - action='append') - args = parser.parse_args() - args.kernel_url = args.kernel_url % {'version': args.fedora_version} - - validate_args(args) - return args - - -def validate_args(args): - if (os.path.exists(args.output) - and not args.force - and not args.skip_enrollment): - raise Exception('%s already exists' % args.output) - - if args.skip_enrollment and not os.path.exists(args.output): - raise Exception('%s does not yet exist' % args.output) - - verbosity = (args.verbose or 1) - (args.quiet or 0) - if verbosity >= 2: - logging.basicConfig(level=logging.DEBUG) - elif verbosity == 1: - logging.basicConfig(level=logging.INFO) - elif verbosity < 0: - logging.basicConfig(level=logging.ERROR) - else: - logging.basicConfig(level=logging.WARN) - - if args.skip_enrollment: - args.out_temp = args.output - else: - temped = tempfile.mkstemp(prefix='qosb.', suffix='.vars') - os.close(temped[0]) - args.out_temp = temped[1] - logging.debug('Temp output: %s', args.out_temp) - - -def move_to_dest(args): - shutil.copy(args.out_temp, args.output) - os.remove(args.out_temp) - - -def main(): - args = parse_args() - if not args.skip_enrollment: - enroll_keys(args) - if not args.skip_testing: - test_keys(args) - if not args.skip_enrollment: - move_to_dest(args) - if args.skip_testing: - logging.info('Created %s' % args.output) - else: - logging.info('Created and verified %s' % args.output) - else: - logging.info('Verified %s', args.output) - - -if __name__ == '__main__': - main()