from mkosi.archive import can_extract_tar, extract_tar, make_cpio, make_tar
from mkosi.bootloader import (
- certificate_common_name,
efi_boot_binary,
extract_pe_section,
gen_kernel_images,
install_grub,
install_shim,
install_systemd_boot,
- pesign_prepare,
prepare_grub_config,
python_binary,
run_systemd_sign_tool,
assert context.config.secure_boot_key
assert context.config.secure_boot_certificate
- if context.config.secure_boot_sign_tool != SecureBootSignTool.pesign:
- cmd += [
- "--signtool", (
- "sbsign"
- if context.config.secure_boot_sign_tool == SecureBootSignTool.sbsign
- or not context.config.find_binary("systemd-sbsign", "/usr/lib/systemd/systemd-sbsign")
- else "systemd-sbsign"
- ),
- ] # fmt: skip
+ cmd += [
+ "--signtool", (
+ "sbsign"
+ if context.config.secure_boot_sign_tool == SecureBootSignTool.sbsign
+ or not context.config.find_binary("systemd-sbsign", "/usr/lib/systemd/systemd-sbsign")
+ else "systemd-sbsign"
+ ),
+ ] # fmt: skip
- if (
- context.config.secure_boot_key_source.type != KeySourceType.file
- or context.config.secure_boot_certificate_source.type != CertificateSourceType.file
- ):
- opt += ["--bind", "/run", "/run"]
+ if (
+ context.config.secure_boot_key_source.type != KeySourceType.file
+ or context.config.secure_boot_certificate_source.type != CertificateSourceType.file
+ ):
+ opt += ["--bind", "/run", "/run"]
- if context.config.secure_boot_key_source.type == KeySourceType.engine:
- cmd += ["--signing-engine", context.config.secure_boot_key_source.source]
- elif context.config.secure_boot_key_source.type == KeySourceType.provider:
- cmd += ["--signing-provider", context.config.secure_boot_key_source.source]
+ if context.config.secure_boot_key_source.type == KeySourceType.engine:
+ cmd += ["--signing-engine", context.config.secure_boot_key_source.source]
+ elif context.config.secure_boot_key_source.type == KeySourceType.provider:
+ cmd += ["--signing-provider", context.config.secure_boot_key_source.source]
- if context.config.secure_boot_key.exists():
- cmd += ["--secureboot-private-key", workdir(context.config.secure_boot_key)]
- opt += ["--ro-bind", context.config.secure_boot_key, workdir(context.config.secure_boot_key)]
- else:
- cmd += ["--secureboot-private-key", context.config.secure_boot_key]
+ if context.config.secure_boot_key.exists():
+ cmd += ["--secureboot-private-key", workdir(context.config.secure_boot_key)]
+ opt += ["--ro-bind", context.config.secure_boot_key, workdir(context.config.secure_boot_key)]
+ else:
+ cmd += ["--secureboot-private-key", context.config.secure_boot_key]
- if context.config.secure_boot_certificate_source.type == CertificateSourceType.provider:
- cmd += ["--certificate-provider", context.config.secure_boot_certificate_source.source]
+ if context.config.secure_boot_certificate_source.type == CertificateSourceType.provider:
+ cmd += ["--certificate-provider", context.config.secure_boot_certificate_source.source]
- if context.config.secure_boot_certificate.exists():
- cmd += ["--secureboot-certificate", workdir(context.config.secure_boot_certificate)]
- opt += [
- "--ro-bind", context.config.secure_boot_certificate, workdir(context.config.secure_boot_certificate), # noqa: E501
- ] # fmt: skip
- else:
- cmd += ["--secureboot-certificate", context.config.secure_boot_certificate]
- else:
- pesign_prepare(context)
- cmd += [
- "--signtool", "pesign",
- "--secureboot-certificate-dir", workdir(context.workspace / "pesign"),
- "--secureboot-certificate-name", certificate_common_name(context, context.config.secure_boot_certificate), # noqa: E501
+ if context.config.secure_boot_certificate.exists():
+ cmd += ["--secureboot-certificate", workdir(context.config.secure_boot_certificate)]
+ opt += [
+ "--ro-bind", context.config.secure_boot_certificate, workdir(context.config.secure_boot_certificate), # noqa: E501
] # fmt: skip
- opt += ["--ro-bind", context.workspace / "pesign", workdir(context.workspace / "pesign")]
+ else:
+ cmd += ["--secureboot-certificate", context.config.secure_boot_certificate]
run(
cmd,
return Path(f"efi/EFI/BOOT/grub{arch}.EFI")
-def certificate_common_name(context: Context, certificate: Path) -> str:
- output = run(
- [
- "openssl",
- "x509",
- "-noout",
- "-subject",
- "-nameopt", "multiline",
- "-in", workdir(certificate),
- ],
- stdout=subprocess.PIPE,
- sandbox=context.sandbox(options=["--ro-bind", certificate, workdir(certificate)]),
- ).stdout # fmt: skip
-
- for line in output.splitlines():
- if not line.strip().startswith("commonName"):
- continue
-
- _, sep, value = line.partition("=")
- if not sep:
- die("Missing '=' delimiter in openssl output")
-
- return value.strip()
-
- die(f"Certificate {certificate} is missing Common Name")
-
-
def run_systemd_sign_tool(
config: Config,
*,
)
-def pesign_prepare(context: Context) -> None:
- assert context.config.secure_boot_key
- assert context.config.secure_boot_certificate
-
- if (context.workspace / "pesign").exists():
- return
-
- (context.workspace / "pesign").mkdir()
-
- # pesign takes a certificate directory and a certificate common name as input arguments, so we have
- # to transform our input key and cert into that format. Adapted from
- # https://www.mankier.com/1/pesign#Examples-Signing_with_the_certificate_and_private_key_in_individual_files
- with open(context.workspace / "secure-boot.p12", "wb") as f:
- run(
- [
- "openssl",
- "pkcs12",
- "-export",
- # Arcane incantation to create a pkcs12 certificate without a password.
- "-keypbe", "NONE",
- "-certpbe", "NONE",
- "-nomaciter",
- "-passout", "pass:",
- "-inkey", workdir(context.config.secure_boot_key),
- "-in", workdir(context.config.secure_boot_certificate),
- ],
- stdout=f,
- sandbox=context.sandbox(
- options=[
- "--ro-bind", context.config.secure_boot_key, workdir(context.config.secure_boot_key),
- "--ro-bind", context.config.secure_boot_certificate, workdir(context.config.secure_boot_certificate), # noqa: E501
- ],
- ),
- ) # fmt: skip
-
- (context.workspace / "pesign").mkdir(exist_ok=True)
-
- run(
- [
- "pk12util",
- "-K", "",
- "-W", "",
- "-i", workdir(context.workspace / "secure-boot.p12"),
- "-d", workdir(context.workspace / "pesign"),
- ],
- sandbox=context.sandbox(
- options=[
- "--ro-bind", context.workspace / "secure-boot.p12", workdir(context.workspace / "secure-boot.p12"), # noqa: E501
- "--ro-bind", context.workspace / "pesign", workdir(context.workspace / "pesign"),
- ],
- ),
- ) # fmt: skip
-
-
def sign_efi_binary(context: Context, input: Path, output: Path) -> Path:
assert context.config.secure_boot_key
assert context.config.secure_boot_certificate
devices=context.config.secure_boot_key_source.type != KeySourceType.file,
),
)
- elif (
- context.config.secure_boot_sign_tool == SecureBootSignTool.pesign
- or context.config.secure_boot_sign_tool == SecureBootSignTool.auto
- and context.config.find_binary("pesign") is not None
- ):
- if context.config.secure_boot_certificate_source.type != CertificateSourceType.file:
- die("Secure boot certificate source must be 'file' when using pesign as the signing tool")
-
- pesign_prepare(context)
- run(
- [
- "pesign",
- "--certdir", workdir(context.workspace / "pesign"),
- "--certificate", certificate_common_name(context, context.config.secure_boot_certificate),
- "--sign",
- "--force",
- "--in", workdir(input),
- "--out", workdir(output),
- ],
- stdin=(
- sys.stdin
- if context.config.secure_boot_key_source.type != KeySourceType.file
- else subprocess.DEVNULL
- ),
- env=context.config.environment,
- sandbox=context.sandbox(
- options=[
- "--ro-bind", context.workspace / "pesign", workdir(context.workspace / "pesign"),
- "--ro-bind", input, workdir(input),
- "--bind", output.parent, workdir(output),
- ]
- ),
- ) # fmt: skip
else:
- die("One of sbsign or pesign is required to use SecureBoot=")
+ die("One of systemd-sbsign or sbsign is required to use SecureBoot=")
return output
class SecureBootSignTool(StrEnum):
auto = enum.auto()
sbsign = enum.auto()
- pesign = enum.auto()
systemd_sbsign = enum.auto()
UEFI kernel image, if `SecureBoot=` is used.
`SecureBootSignTool=`, `--secure-boot-sign-tool`
-: Tool to use to sign secure boot PE binaries. Takes one of `systemd-sbsign`, `sbsign`, `pesign` or `auto`.
- Defaults to `auto`. If set to `auto`, either `systemd-sbsign`, `sbsign` or `pesign` are used if
+: Tool to use to sign secure boot PE binaries. Takes one of `systemd-sbsign`, `sbsign` or `auto`.
+ Defaults to `auto`. If set to `auto`, either `systemd-sbsign` or `sbsign` are used if
available, with `systemd-sbsign` being preferred.
`Verity=`, `--verity=`
| `pkcs11-provider` | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ |
| `sed` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| `pacman` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | |
- | `pesign` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| `policycoreutils` | ✓ | ✓ | ✓ | ✓ | ✓ | | ✓ |
| `qemu` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| `sbsigntools` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
libseccomp
openssh
pacman
- pesign
pipewire
pipewire-audio
pkcs11-provider
[Content]
Packages=
edk2-ovmf
- pesign
openssh-client
ovmf
pacman-package-manager
- pesign
policycoreutils
python3-cryptography
python3-pefile
openssh-clients
ovmf
patterns-base-minimal_base
- pesign
pkcs11-provider
policycoreutils
python3-cryptography
"Source": "",
"Type": "file"
},
- "SecureBootSignTool": "pesign",
+ "SecureBootSignTool": "systemd-sbsign",
"Seed": "7496d7d8-7f08-4a2b-96c6-ec8c43791b60",
"ShimBootloader": "none",
"Sign": false,
secure_boot_certificate_source=CertificateSource(type=CertificateSourceType.file),
secure_boot_key=Path("/path/to/keyfile"),
secure_boot_key_source=KeySource(type=KeySourceType.file),
- secure_boot_sign_tool=SecureBootSignTool.pesign,
+ secure_boot_sign_tool=SecureBootSignTool.systemd_sbsign,
seed=uuid.UUID("7496d7d8-7f08-4a2b-96c6-ec8c43791b60"),
selinux_relabel=ConfigFeature.disabled,
shim_bootloader=ShimBootloader.none,