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 d97c368
Showing 1 changed file with 61 additions and 1 deletion.
62 changes: 61 additions & 1 deletion mkosi/qemu.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,20 +646,61 @@ 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-"))

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:
have_mok_json = False

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

Check failure

Code scanning / CodeQL

Potentially uninitialized local variable Error

Local variable 'have_mok_json' may be used before it is initialized.
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 +710,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 +721,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:

Check failure

Code scanning / CodeQL

Potentially uninitialized local variable Error

Local variable 'have_mok_json' may be used before it is initialized.
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

0 comments on commit d97c368

Please sign in to comment.