mirror of
https://git.proxmox.com/git/fwupd
synced 2025-06-02 10:23:25 +00:00

The Secure Boot Advanced Targeting (SBAT) [0] is a Generation Number Based Revocation mechanism that is meant to replace the DBX revocation file list. Binaries must contain a .sbat data section that has a set entries, each of them consisting of UTF-8 strings as comma separated values. Allow to embed this information into the fwupd EFI binary at build time. The SBAT metadata must contain at least two entries. One that defines the SBAT version used and another one that defines the component generation. Downstream users can add additional entries if have changes that make them diverge from the upstream code and potentially add other vulnerabilities. [0]: https://github.com/rhboot/shim/blob/sbat/SBAT.md
196 lines
4.6 KiB
Python
Executable File
196 lines
4.6 KiB
Python
Executable File
#!/usr/bin/python3
|
|
#
|
|
# Copyright (C) 2021 Javier Martinez Canillas <javierm@redhat.com>
|
|
# Copyright (C) 2021 Richard Hughes <richard@hughsie.com>
|
|
#
|
|
# SPDX-License-Identifier: LGPL-2.1+
|
|
#
|
|
# pylint: disable=missing-docstring, invalid-name
|
|
|
|
import subprocess
|
|
import sys
|
|
import argparse
|
|
import tempfile
|
|
|
|
|
|
def _run_objcopy_sbat(args):
|
|
""" append SBAT metadata """
|
|
FWUPD_SUMMARY = "Firmware update daemon"
|
|
FWUPD_URL = "https://github.com/fwupd/fwupd"
|
|
|
|
with tempfile.NamedTemporaryFile() as sfd:
|
|
|
|
# spec
|
|
sfd.write(
|
|
"{0},{1},{2},{0},{1},{3}\n".format(
|
|
"sbat",
|
|
args.sbat_version,
|
|
"UEFI shim",
|
|
"https://github.com/rhboot/shim/blob/main/SBAT.md",
|
|
).encode()
|
|
)
|
|
|
|
# fwupd
|
|
sfd.write(
|
|
"{0},{1},{2},{0},{3},{4}\n".format(
|
|
args.project_name,
|
|
args.sbat_generation,
|
|
"Firmware update daemon",
|
|
args.project_version,
|
|
FWUPD_URL,
|
|
).encode()
|
|
)
|
|
|
|
# distro specifics, falling back to the project defaults
|
|
if args.sbat_distro_id:
|
|
sfd.write(
|
|
"{0}-{1},{2},{3},{4},{5},{6}\n".format(
|
|
args.project_name,
|
|
args.sbat_distro_id,
|
|
args.sbat_distro_generation or args.sbat_generation,
|
|
args.sbat_distro_summary or FWUPD_SUMMARY,
|
|
args.sbat_distro_pkgname,
|
|
args.sbat_distro_version or args.project_version,
|
|
args.sbat_distro_url or FWUPD_URL,
|
|
).encode()
|
|
)
|
|
|
|
# all written
|
|
sfd.seek(0)
|
|
|
|
# add a section to the object; use `objdump -s -j .sbat` to verify
|
|
argv = [
|
|
args.objcopy,
|
|
"--add-section",
|
|
".sbat={}".format(sfd.name),
|
|
args.outfile,
|
|
]
|
|
subprocess.run(argv, check=True)
|
|
|
|
|
|
def _run_objcopy(args):
|
|
|
|
argv = [
|
|
args.objcopy,
|
|
"-j",
|
|
".text",
|
|
"-j",
|
|
".sdata",
|
|
"-j",
|
|
".dynamic",
|
|
"-j",
|
|
".rel*",
|
|
args.infile,
|
|
args.outfile,
|
|
]
|
|
|
|
# aarch64 and arm32 don't have an EFI capable objcopy
|
|
# Use 'binary' instead, and add required symbols manually
|
|
if args.arch in ["aarch64", "arm"]:
|
|
argv.extend(["-O", "binary"])
|
|
else:
|
|
argv.extend(["--target", "efi-app-{}".format(args.arch)])
|
|
try:
|
|
subprocess.run(argv, check=True)
|
|
except FileNotFoundError as e:
|
|
print(str(e))
|
|
sys.exit(1)
|
|
|
|
|
|
def _run_genpeimg(args):
|
|
|
|
# this is okay if it does not exist
|
|
argv = [
|
|
"genpeimg",
|
|
"-d",
|
|
"+d",
|
|
"+n",
|
|
"-d",
|
|
"+s",
|
|
args.outfile,
|
|
]
|
|
try:
|
|
subprocess.run(argv, check=True)
|
|
except FileNotFoundError as _:
|
|
pass
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument(
|
|
"--objcopy",
|
|
default="objcopy",
|
|
help="Binary file to use for objcopy",
|
|
)
|
|
parser.add_argument(
|
|
"--arch",
|
|
default="x86_64",
|
|
help="EFI architecture",
|
|
)
|
|
parser.add_argument(
|
|
"--project-name",
|
|
help="SBAT project name",
|
|
)
|
|
parser.add_argument(
|
|
"--project-version",
|
|
help="SBAT project version",
|
|
)
|
|
parser.add_argument(
|
|
"--sbat-version",
|
|
default=1,
|
|
type=int,
|
|
help="SBAT version",
|
|
)
|
|
parser.add_argument(
|
|
"--sbat-generation",
|
|
default=0,
|
|
type=int,
|
|
help="SBAT generation",
|
|
)
|
|
parser.add_argument(
|
|
"--sbat-distro-id",
|
|
default=None,
|
|
help="SBAT distribution ID"
|
|
)
|
|
parser.add_argument(
|
|
"--sbat-distro-generation",
|
|
default=None,
|
|
type=int,
|
|
help="SBAT distribution generation",
|
|
)
|
|
parser.add_argument(
|
|
"--sbat-distro-summary",
|
|
default=None,
|
|
help="SBAT distribution summary",
|
|
)
|
|
parser.add_argument(
|
|
"--sbat-distro-pkgname",
|
|
default=None,
|
|
help="SBAT distribution package name",
|
|
)
|
|
parser.add_argument(
|
|
"--sbat-distro-version",
|
|
default=None,
|
|
help="SBAT distribution version",
|
|
)
|
|
parser.add_argument(
|
|
"--sbat-distro-url",
|
|
default=None,
|
|
help="SBAT distribution URL",
|
|
)
|
|
parser.add_argument(
|
|
"infile",
|
|
help="Input file",
|
|
)
|
|
parser.add_argument(
|
|
"outfile",
|
|
help="Output file",
|
|
)
|
|
_args = parser.parse_args()
|
|
_run_objcopy(_args)
|
|
_run_objcopy_sbat(_args)
|
|
_run_genpeimg(_args)
|
|
|
|
sys.exit(0)
|