// guide

Secure Boot

What Visor verifies, what the firmware verifies, and what neither does.

Behavior under Secure Boot

When the firmware rejects an image, Visor logs the exact EFI status code and says plainly that Secure Boot refused it (EFI_SECURITY_VIOLATION / EFI_ACCESS_DENIED), with a hint to sign/enroll the image or disable Secure Boot — no more guessing from a vague failure.

Getting a fully signed chain

Two workable models:

  1. Your own keys (sbctl) — enroll custom keys, then sign visor_x64.efi, your kernels/UKIs, and any EfiFs driver. The installer offers this (install.sh --sign), and visor sign re-signs everything installed on the ESP, drivers included.
  2. Shim — boot Visor via shimx64.efi; shim then validates your kernels against the enrolled db/MOK certificates, and Visor consults shim for every image it launches.
USB sticks: a hotplugged stick's loader must also be trusted. A Ventoy stick created without its Secure Boot option carries an unsigned GRUB that the firmware will (correctly) refuse — recreate the stick with Secure Boot support, sign its loader with sbctl sign, or disable Secure Boot for that boot.

Shim and MOK

Visor can be booted through shimx64.efi, which validates Visor itself and every image Visor launches against the enrolled db/MOK certificates. The full walkthrough lives in the repo's Secure Boot via shim + MOK guide: add the SBAT section to drivers that lack one, sign Visor and every driver, enroll the key with mokutil --import, then reboot and choose Enroll MOK in MokManager. Run the signing steps in a root shell, and repeat them after every Visor update.

Builds embed an .sbat section generated from sbat.csv.in and stamped with the Visor version, so shim does not refuse the image for missing SBAT metadata. A Secure Boot revocation list update can still revoke Visor through SBAT, exactly as it can revoke any other bootloader; the fix is a newer signed build.

Windows and BitLocker

When Windows is chainloaded from Visor, shim and Visor are part of Windows' measured boot. BitLocker can then lose its PCR 7 binding, or bind to PCR 4, and ask for the recovery key after every Visor or shim update. Set windows_bootnext=1 to hand Windows to the firmware's own Windows Boot Manager entry with BootNext plus a reset, so Windows starts without shim or Visor in its measured path. Visor only uses a firmware entry on the selected partition, skips the handoff when no matching entry exists or the handoff marker cannot be stored, and falls back to a normal chainload if the handoff did not start Windows. An entry that pins sha256= always stays on the verified chainload path.

Scope of the guarantee — read this part

Secure Boot / shim verification covers the kernel or UKI image only. It does not cover the initrd, the kernel command line, or boot.conf — an attacker with write access to the ESP could alter those without failing verification. (This is true of most boot managers; systemd-boot has the same property for non-UKI entries.) To close that gap:

Measured boot (TPM2)

When a EFI_TCG2_PROTOCOL is present Visor measures the on-disk boot.conf into PCR 5 and the exact kernel command line (NUL-inclusive) into PCR 12 via HashLogExtendEvent. The PCR 5 event uses EV_EVENT_TAG 0xf5bc582a so a Visor boot and an sd-boot boot land the same log entry; PCR 12 matches systemd's tpm_log_load_options layout so a LUKS2 sealed-key policy for PCR 12 stays portable.

The active PCR banks are published as volatile LoaderTpm2ActivePcrBanks and advertised in LoaderFeatures (TPM2_ACTIVE_PCR_BANKS). Configure with tpm=1 (default, alias measure) and tpm_pcr_config / tpm_pcr_cmdline (0–23, defaults 5 and 12). Set tpm=0 to skip entirely. The firmware log is checked — if the measured data would be silently ignored, Visor logs and continues rather than pretending to measure.

An unusable firmware TPM cannot hang the boot. Visor arms the VisorTpmStage NVRAM marker before the EFI_TCG2_PROTOCOL probe and clears it after; a boot that finds the marker still armed concludes the previous boot died inside the probe, skips measured boot for that boot, and leaves it off on subsequent boots instead of risking a hang every Nth boot. Clear the variable to re-enable measured boot. If the marker cannot be stored, the probe is skipped, and the capability block is validated against a full struct and a sane manufacturer ID before any bank is trusted.

Tip — combine a UKI (signed, therefore verified) with a TPM-sealed LUKS key for PCR 12 and you cover both Secure Boot (the image) and measured boot (the cmdline) without extra tooling.

Other hardening in the load path