Skip to content

Commit

Permalink
qemu: enroll certificate in MOK for dm-verity and kernel mods
Browse files Browse the repository at this point in the history
Automatically enroll the secure boot certificate in MOK, and also set
the boolean so that the kernel trusts it to verify kernel modules and
dm-verity volumes. This requires secure boot to be enabled to be
effective, otherwise the kernel will ignore it.
  • Loading branch information
bluca committed Sep 11, 2024
1 parent 3353937 commit 62800e0
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
# This is added by default, and it is often broken, but we don't need anything from it
sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get update
sudo apt-get install pandoc python3-pytest
sudo apt-get install pandoc python3-pytest python3-virt-firmware
python3 -m pip install --break-system-packages --upgrade setuptools wheel pip
python3 -m pip install --break-system-packages mypy ruff
npm install -g pyright
Expand Down
63 changes: 62 additions & 1 deletion mkosi/qemu.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,20 +646,62 @@ def finalize_firmware_variables(
stack: contextlib.ExitStack,
) -> tuple[Path, str]:
ovmf_vars = stack.enter_context(tempfile.NamedTemporaryFile(prefix="mkosi-ovmf-vars-"))
ovmf_json = stack.enter_context(tempfile.NamedTemporaryFile(prefix="mkosi-ovmf-vars-json-"))
have_mok_json = False

if config.secure_boot_certificate:
try:
from virt.firmware.efi import guids, siglist

# In order to make the kernel use mkosi.crt to verify dm-verity volumes, we need to
# create runtime and volatile EFI variables, MokListTrustedRT and MokListRT, as
# it's only from kernel 6.11 that db is used for this purpose. Note that, unlike
# certificates in db, the certificates in MOK are only used if secure boot is enabled.
# First create an efivar with the certificate, and then read it and convert to the
# json format that virt-fw-vars expects.
# attr=4 means EFI_VARIABLE_RUNTIME_ACCESS, and the GUID is the well-known MOK one.

mok_sigdb = siglist.EfiSigDB()
mok_sigdb.add_cert(guids.parse_str("605dab50-e046-4300-abb6-3dd810dd8b23"), config.secure_boot_certificate)
mok_json = dict(
version=2,
variables=[
dict(
name="MokListRT",
guid="605dab50-e046-4300-abb6-3dd810dd8b23",
attr=4,
data=bytes(mok_sigdb).hex(),
),
dict(
name="MokListTrustedRT",
guid="605dab50-e046-4300-abb6-3dd810dd8b23",
attr=4,
data="01",
),
],
)
ovmf_json.write(json.dumps(mok_json).encode())
ovmf_json.flush()
have_mok_json = True
except ImportError:
logging.info(f"virt.firmware module not found, will not enroll {config.secure_boot_certificate} in MOK")

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (certificate)
as clear text.

if config.qemu_firmware_variables in (None, Path("custom"), Path("microsoft")):
ovmf_vars_format = ovmf.vars_format
else:
ovmf_vars_format = "raw"

if config.qemu_firmware_variables == Path("custom"):
assert config.secure_boot_certificate
assert have_mok_json
run(
[
"virt-fw-vars",
"--input", ovmf.vars,
"--output", ovmf_vars.name,
"--enroll-cert", config.secure_boot_certificate,
"--add-db", "OvmfEnrollDefaultKeys", config.secure_boot_certificate,
"--set-json", ovmf_json.name,
"--no-microsoft",
"--secure-boot",
"--loglevel", "WARNING",
Expand All @@ -669,6 +711,7 @@ def finalize_firmware_variables(
options=[
"--bind", ovmf_vars.name, ovmf_vars.name,
"--ro-bind", config.secure_boot_certificate, config.secure_boot_certificate,
"--ro-bind", ovmf_json.name, ovmf_json.name,
],
),
)
Expand All @@ -679,7 +722,25 @@ def finalize_firmware_variables(
if config.qemu_firmware_variables == Path("microsoft") or not config.qemu_firmware_variables
else config.qemu_firmware_variables
)
shutil.copy2(vars, Path(ovmf_vars.name))
if have_mok_json:
run(
[
"virt-fw-vars",
"--input", vars,
"--output", ovmf_vars.name,
"--set-json", ovmf_json.name,
"--loglevel", "WARNING",
],
sandbox=config.sandbox(
binary=qemu,
options=[
"--bind", ovmf_vars.name, ovmf_vars.name,
"--ro-bind", ovmf_json.name, ovmf_json.name,
],
),
)
else:
shutil.copy2(vars, Path(ovmf_vars.name))

return Path(ovmf_vars.name), ovmf_vars_format

Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ pythonVersion = "3.9"

[tool.mypy]
python_version = 3.9
# Fails on external libraries like virt.firmware
ignore_missing_imports = true
# belonging to --strict
warn_unused_configs = true
disallow_any_generics = true
Expand Down

0 comments on commit 62800e0

Please sign in to comment.