mirror of
https://git.proxmox.com/git/pve-edk2-firmware
synced 2025-10-04 15:09:01 +00:00
debian: sync tests with packaging upstream
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
parent
5b38a120b6
commit
d7274593bf
28
debian/python/UEFI/Filesystems.py
vendored
28
debian/python/UEFI/Filesystems.py
vendored
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2019-2021 Canonical Ltd.
|
||||
# Copyright 2019-2022 Canonical Ltd.
|
||||
# Authors:
|
||||
# - dann frazier <dann.frazier@canonical.com>
|
||||
#
|
||||
@ -87,35 +87,15 @@ class EfiBootableIsoImage:
|
||||
|
||||
|
||||
class GrubShellBootableIsoImage(EfiBootableIsoImage):
|
||||
def __init__(self, efi_arch, use_signed):
|
||||
EfiArchToGrubArch = {
|
||||
'X64': "x86_64",
|
||||
'AA64': "arm64",
|
||||
}
|
||||
def __init__(self, efi_arch, shim_path, grub_path):
|
||||
efi_img = FatFsImage(64)
|
||||
efi_img.makedirs(os.path.join('EFI', 'BOOT'))
|
||||
removable_media_path = os.path.join(
|
||||
'EFI', 'BOOT', 'BOOT%s.EFI' % (efi_arch.upper())
|
||||
)
|
||||
efi_ext = 'efi'
|
||||
grub_subdir = "%s-efi" % EfiArchToGrubArch[efi_arch.upper()]
|
||||
if use_signed:
|
||||
efi_ext = "%s.signed" % (efi_ext)
|
||||
grub_subdir = "%s-signed" % (grub_subdir)
|
||||
|
||||
shim_src = os.path.join(
|
||||
os.path.sep, 'usr', 'lib', 'shim',
|
||||
'shim%s.%s' % (efi_arch.lower(), efi_ext)
|
||||
)
|
||||
grub_src = os.path.join(
|
||||
os.path.sep, 'usr', 'lib', 'grub',
|
||||
'%s' % (grub_subdir),
|
||||
"" if use_signed else "monolithic",
|
||||
'grub%s.%s' % (efi_arch.lower(), efi_ext)
|
||||
)
|
||||
grub_dest = os.path.join(
|
||||
'EFI', 'BOOT', 'GRUB%s.EFI' % (efi_arch.upper())
|
||||
)
|
||||
efi_img.insert_file(shim_src, removable_media_path)
|
||||
efi_img.insert_file(grub_src, grub_dest)
|
||||
efi_img.insert_file(shim_path, removable_media_path)
|
||||
efi_img.insert_file(grub_path, grub_dest)
|
||||
super().__init__(efi_img)
|
||||
|
3
debian/python/UEFI/Qemu.py
vendored
3
debian/python/UEFI/Qemu.py
vendored
@ -43,11 +43,10 @@ class QemuEfiFlashSize(enum.Enum):
|
||||
|
||||
|
||||
class QemuCommand:
|
||||
# Based on the args used by ovmf-vars-generator
|
||||
Qemu_Common_Params = [
|
||||
'-no-user-config', '-nodefaults',
|
||||
'-m', '256',
|
||||
'-smp', '2,sockets=2,cores=1,threads=1',
|
||||
'-smp', '1,sockets=1,cores=1,threads=1',
|
||||
'-display', 'none',
|
||||
'-serial', 'stdio',
|
||||
]
|
||||
|
52
debian/python/UEFI/SignedBinary.py
vendored
Normal file
52
debian/python/UEFI/SignedBinary.py
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
#
|
||||
# Copyright 2022 Canonical Ltd.
|
||||
# Authors:
|
||||
# - dann frazier <dann.frazier@canonical.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 3, as published
|
||||
# by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
|
||||
# SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
|
||||
class SignedBinary:
|
||||
def __init__(self, binary_path, key_path, cert_path, password=None):
|
||||
openssl_password_args = []
|
||||
if password:
|
||||
openssl_password_args = [
|
||||
"-passin", f"pass:{password}"
|
||||
]
|
||||
with tempfile.NamedTemporaryFile() as keytmp:
|
||||
subprocess.check_call(
|
||||
[
|
||||
"openssl", "rsa",
|
||||
] + openssl_password_args + [
|
||||
"-in", f"{key_path}",
|
||||
"-out", f"{keytmp.name}",
|
||||
]
|
||||
)
|
||||
with tempfile.NamedTemporaryFile(delete=False) as f:
|
||||
self.path = f.name
|
||||
|
||||
subprocess.check_call(
|
||||
[
|
||||
"sbsign", "--key", f"{keytmp.name}",
|
||||
"--cert", f"{cert_path}",
|
||||
binary_path, "--output", f"{self.path}"
|
||||
]
|
||||
)
|
||||
|
||||
def __del__(self):
|
||||
os.unlink(self.path)
|
2
debian/tests/control
vendored
2
debian/tests/control
vendored
@ -5,6 +5,7 @@ Depends:
|
||||
grub-efi-amd64-signed [amd64],
|
||||
grub-efi-arm64-signed [arm64],
|
||||
mtools [amd64 arm64],
|
||||
openssl [amd64 arm64],
|
||||
ovmf,
|
||||
ovmf-ia32,
|
||||
python3-pexpect,
|
||||
@ -12,5 +13,6 @@ Depends:
|
||||
qemu-efi-arm,
|
||||
qemu-system-arm,
|
||||
qemu-system-x86,
|
||||
sbsigntool [amd64 arm64],
|
||||
shim-signed [amd64 arm64],
|
||||
xorriso [amd64 arm64],
|
||||
|
133
debian/tests/shell.py
vendored
133
debian/tests/shell.py
vendored
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright 2019-2021 Canonical Ltd.
|
||||
# Copyright 2019-2022 Canonical Ltd.
|
||||
# Authors:
|
||||
# - dann frazier <dann.frazier@canonical.com>
|
||||
#
|
||||
@ -18,12 +18,15 @@
|
||||
#
|
||||
|
||||
import enum
|
||||
import os
|
||||
import pexpect
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import unittest
|
||||
|
||||
from UEFI.Filesystems import GrubShellBootableIsoImage
|
||||
from UEFI.SignedBinary import SignedBinary
|
||||
from UEFI.Qemu import QemuEfiMachine, QemuEfiVariant, QemuEfiFlashSize
|
||||
from UEFI import Qemu
|
||||
|
||||
@ -31,15 +34,56 @@ DPKG_ARCH = subprocess.check_output(
|
||||
['dpkg', '--print-architecture']
|
||||
).decode().rstrip()
|
||||
|
||||
EfiArchToGrubArch = {
|
||||
'X64': "x86_64",
|
||||
'AA64': "arm64",
|
||||
}
|
||||
|
||||
TEST_TIMEOUT = 120
|
||||
|
||||
|
||||
def get_local_grub_path(efi_arch, signed=False):
|
||||
grub_subdir = "%s-efi" % EfiArchToGrubArch[efi_arch.upper()]
|
||||
ext = "efi"
|
||||
if signed:
|
||||
grub_subdir = f"{grub_subdir}-signed"
|
||||
ext = f"{ext}.signed"
|
||||
|
||||
grub_path = os.path.join(
|
||||
os.path.sep, 'usr', 'lib', 'grub',
|
||||
'%s' % (grub_subdir),
|
||||
"" if signed else "monolithic",
|
||||
'grub%s.%s' % (efi_arch.lower(), ext)
|
||||
)
|
||||
return grub_path
|
||||
|
||||
|
||||
def get_local_shim_path(efi_arch, signed=False):
|
||||
ext = 'efi'
|
||||
if signed:
|
||||
ext = f"{ext}.signed"
|
||||
shim_path = os.path.join(
|
||||
os.path.sep, 'usr', 'lib', 'shim',
|
||||
'shim%s.%s' % (efi_arch.lower(), ext)
|
||||
)
|
||||
return shim_path
|
||||
|
||||
|
||||
class BootToShellTest(unittest.TestCase):
|
||||
debug = True
|
||||
|
||||
def setUp(self):
|
||||
self.startTime = time.time()
|
||||
|
||||
def tearDown(self):
|
||||
t = time.time() - self.startTime
|
||||
sys.stdout.write("%s runtime: %.3fs\n" % (self.id(), t))
|
||||
|
||||
def run_cmd_check_shell(self, cmd):
|
||||
child = pexpect.spawn(' '.join(cmd))
|
||||
child = pexpect.spawn(' '.join(cmd), encoding='UTF-8')
|
||||
|
||||
if self.debug:
|
||||
child.logfile = sys.stdout.buffer
|
||||
child.logfile = sys.stdout
|
||||
try:
|
||||
while True:
|
||||
i = child.expect(
|
||||
@ -47,7 +91,7 @@ class BootToShellTest(unittest.TestCase):
|
||||
'Press .* or any other key to continue',
|
||||
'Shell> '
|
||||
],
|
||||
timeout=60,
|
||||
timeout=TEST_TIMEOUT,
|
||||
)
|
||||
if i == 0:
|
||||
child.sendline('\x1b')
|
||||
@ -56,7 +100,9 @@ class BootToShellTest(unittest.TestCase):
|
||||
child.sendline('reset -s\r')
|
||||
continue
|
||||
except pexpect.EOF:
|
||||
return
|
||||
child.close()
|
||||
if child.exitstatus != 0:
|
||||
self.fail("ERROR: exit code %d\n" % (child.exitstatus))
|
||||
except pexpect.TIMEOUT as err:
|
||||
self.fail("%s\n" % (err))
|
||||
|
||||
@ -65,10 +111,10 @@ class BootToShellTest(unittest.TestCase):
|
||||
PRE_EXEC = 1
|
||||
POST_EXEC = 2
|
||||
|
||||
child = pexpect.spawn(' '.join(cmd))
|
||||
child = pexpect.spawn(' '.join(cmd), encoding='UTF-8')
|
||||
|
||||
if self.debug:
|
||||
child.logfile = sys.stdout.buffer
|
||||
child.logfile = sys.stdout
|
||||
try:
|
||||
state = State.PRE_EXEC
|
||||
while True:
|
||||
@ -80,7 +126,7 @@ class BootToShellTest(unittest.TestCase):
|
||||
'grub> ',
|
||||
'Command Error Status: Access Denied',
|
||||
],
|
||||
timeout=60,
|
||||
timeout=TEST_TIMEOUT,
|
||||
)
|
||||
if i == 0:
|
||||
child.sendline('\x1b')
|
||||
@ -102,10 +148,12 @@ class BootToShellTest(unittest.TestCase):
|
||||
if i == 4:
|
||||
verified = False
|
||||
continue
|
||||
except pexpect.EOF:
|
||||
child.close()
|
||||
if child.exitstatus != 0:
|
||||
self.fail("ERROR: exit code %d\n" % (child.exitstatus))
|
||||
except pexpect.TIMEOUT as err:
|
||||
self.fail("%s\n" % (err))
|
||||
except pexpect.EOF:
|
||||
pass
|
||||
self.assertEqual(should_verify, verified)
|
||||
|
||||
def test_aavmf(self):
|
||||
@ -113,12 +161,20 @@ class BootToShellTest(unittest.TestCase):
|
||||
self.run_cmd_check_shell(q.command)
|
||||
|
||||
@unittest.skipUnless(DPKG_ARCH == 'arm64', "Requires grub-efi-arm64")
|
||||
@unittest.skipUnless(
|
||||
subprocess.run(
|
||||
['dpkg-vendor', '--derives-from', 'Ubuntu']
|
||||
).returncode == 0,
|
||||
"Debian does not provide a signed shim for arm64, see #992073"
|
||||
)
|
||||
def test_aavmf_ms_secure_boot_signed(self):
|
||||
q = Qemu.QemuCommand(
|
||||
QemuEfiMachine.AAVMF,
|
||||
variant=QemuEfiVariant.MS,
|
||||
)
|
||||
iso = GrubShellBootableIsoImage('AA64', use_signed=True)
|
||||
grub = get_local_grub_path('AA64', signed=True)
|
||||
shim = get_local_shim_path('AA64', signed=True)
|
||||
iso = GrubShellBootableIsoImage('AA64', shim, grub)
|
||||
q.add_disk(iso.path)
|
||||
self.run_cmd_check_secure_boot(q.command, 'aa64', True)
|
||||
|
||||
@ -128,7 +184,9 @@ class BootToShellTest(unittest.TestCase):
|
||||
QemuEfiMachine.AAVMF,
|
||||
variant=QemuEfiVariant.MS,
|
||||
)
|
||||
iso = GrubShellBootableIsoImage('AA64', use_signed=False)
|
||||
grub = get_local_grub_path('AA64', signed=False)
|
||||
shim = get_local_shim_path('AA64', signed=False)
|
||||
iso = GrubShellBootableIsoImage('AA64', shim, grub)
|
||||
q.add_disk(iso.path)
|
||||
self.run_cmd_check_secure_boot(q.command, 'aa64', False)
|
||||
|
||||
@ -178,7 +236,9 @@ class BootToShellTest(unittest.TestCase):
|
||||
variant=QemuEfiVariant.MS,
|
||||
flash_size=QemuEfiFlashSize.SIZE_2MB,
|
||||
)
|
||||
iso = GrubShellBootableIsoImage('X64', use_signed=True)
|
||||
grub = get_local_grub_path('X64', signed=True)
|
||||
shim = get_local_shim_path('X64', signed=True)
|
||||
iso = GrubShellBootableIsoImage('X64', shim, grub)
|
||||
q.add_disk(iso.path)
|
||||
self.run_cmd_check_secure_boot(q.command, 'x64', True)
|
||||
|
||||
@ -189,7 +249,9 @@ class BootToShellTest(unittest.TestCase):
|
||||
variant=QemuEfiVariant.MS,
|
||||
flash_size=QemuEfiFlashSize.SIZE_2MB,
|
||||
)
|
||||
iso = GrubShellBootableIsoImage('X64', use_signed=False)
|
||||
grub = get_local_grub_path('X64', signed=False)
|
||||
shim = get_local_shim_path('X64', signed=False)
|
||||
iso = GrubShellBootableIsoImage('X64', shim, grub)
|
||||
q.add_disk(iso.path)
|
||||
self.run_cmd_check_secure_boot(q.command, 'x64', False)
|
||||
|
||||
@ -230,7 +292,9 @@ class BootToShellTest(unittest.TestCase):
|
||||
variant=QemuEfiVariant.MS,
|
||||
flash_size=QemuEfiFlashSize.SIZE_4MB,
|
||||
)
|
||||
iso = GrubShellBootableIsoImage('X64', use_signed=True)
|
||||
grub = get_local_grub_path('X64', signed=True)
|
||||
shim = get_local_shim_path('X64', signed=True)
|
||||
iso = GrubShellBootableIsoImage('X64', shim, grub)
|
||||
q.add_disk(iso.path)
|
||||
self.run_cmd_check_secure_boot(q.command, 'x64', True)
|
||||
|
||||
@ -241,7 +305,44 @@ class BootToShellTest(unittest.TestCase):
|
||||
variant=QemuEfiVariant.MS,
|
||||
flash_size=QemuEfiFlashSize.SIZE_4MB,
|
||||
)
|
||||
iso = GrubShellBootableIsoImage('X64', use_signed=False)
|
||||
grub = get_local_grub_path('X64', signed=False)
|
||||
shim = get_local_shim_path('X64', signed=False)
|
||||
iso = GrubShellBootableIsoImage('X64', shim, grub)
|
||||
q.add_disk(iso.path)
|
||||
self.run_cmd_check_secure_boot(q.command, 'x64', False)
|
||||
|
||||
@unittest.skipUnless(DPKG_ARCH == 'amd64', "amd64-only")
|
||||
def test_ovmf_snakeoil_secure_boot_signed(self):
|
||||
q = Qemu.QemuCommand(
|
||||
QemuEfiMachine.OVMF_Q35,
|
||||
variant=QemuEfiVariant.SNAKEOIL,
|
||||
)
|
||||
shim = SignedBinary(
|
||||
get_local_shim_path('X64', signed=False),
|
||||
"/usr/share/ovmf/PkKek-1-snakeoil.key",
|
||||
"/usr/share/ovmf/PkKek-1-snakeoil.pem",
|
||||
"snakeoil",
|
||||
)
|
||||
grub = SignedBinary(
|
||||
get_local_grub_path('X64', signed=False),
|
||||
"/usr/share/ovmf/PkKek-1-snakeoil.key",
|
||||
"/usr/share/ovmf/PkKek-1-snakeoil.pem",
|
||||
"snakeoil",
|
||||
)
|
||||
iso = GrubShellBootableIsoImage('X64', shim.path, grub.path)
|
||||
q.add_disk(iso.path)
|
||||
self.run_cmd_check_secure_boot(q.command, 'x64', True)
|
||||
|
||||
@unittest.skipUnless(DPKG_ARCH == 'amd64', "amd64-only")
|
||||
def test_ovmf_snakeoil_secure_boot_unsigned(self):
|
||||
q = Qemu.QemuCommand(
|
||||
QemuEfiMachine.OVMF_Q35,
|
||||
variant=QemuEfiVariant.SNAKEOIL,
|
||||
flash_size=QemuEfiFlashSize.DEFAULT,
|
||||
)
|
||||
grub = get_local_grub_path('X64', signed=False)
|
||||
shim = get_local_shim_path('X64', signed=False)
|
||||
iso = GrubShellBootableIsoImage('X64', shim, grub)
|
||||
q.add_disk(iso.path)
|
||||
self.run_cmd_check_secure_boot(q.command, 'x64', False)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user