Home / Alt manpages / systemd-pcrlock(8)

  • systemd-pcrlock(8)
  • Admin command
  • linux

Build a TPM2 Boot Policy with systemd-pcrlock

systemd-pcrlock writes a TPM2 access policy that can survive a firmware or kernel update, instead of a fragile seal to fixed PCR values. This guide inspects the measurements and component definitions it can use, tests a prediction, then walks through the guarded command that actually writes the policy. The examples target systemd 255, including Ubuntu's 255.4-1ubuntu8.17 package.

Allow 15 to 30 minutes for inspection. Creating a policy needs more care than the commands themselves: it changes TPM state and can affect access to secrets such as an encrypted disk key. You need a UEFI system with a working TPM2 device, current-boot event logs, root privileges for commands that write under /var, and a recovery plan for firmware or bootloader changes.

1. Confirm the executable and TPM inputs

The installed executable is normally addressed by its absolute path, /usr/lib/systemd/systemd-pcrlock. This version is experimental, so its interface and behaviour may change. Check the version and both event-log paths before doing anything that writes state:

/usr/lib/systemd/systemd-pcrlock --version
test -r /sys/kernel/security/tpm0/binary_bios_measurements && echo "UEFI event log: readable"
test -r /run/log/systemd/tpm2-measure.log && echo "userspace event log: readable"

On the reference installation, the first command reports systemd 255 with TPM2 support in its feature set. A missing event log or TPM device is a stopping point, not an invitation to guess.

Tip

Predictions are deliberately conservative. Unrecognised measurements, mismatches with current PCR values, or components absent from the event log simply keep those PCRs out of the result, rather than guessing.

Checkpoint

Continue only when the machine has a TPM2 device and the logs belong to the boot you are analysing.

2. Inspect the current evidence

Start with a read-only component listing. Definitions are .pcrlock files found in the default directories, including /etc/pcrlock.d/, /run/pcrlock.d/, /var/lib/pcrlock.d/, /usr/local/pcrlock.d/ and /usr/lib/pcrlock.d/.

/usr/lib/systemd/systemd-pcrlock list-components --no-pager

The default location range is 760-:940-, covering the normal userspace runtime window from the initrd-side components towards the main system runtime. Narrow the analysis to a particular phase when needed:

/usr/lib/systemd/systemd-pcrlock list-components \
  --location=760-:940- --no-pager

Next, inspect the combined event log and its PCR matching. JSON is useful for saving output to review later; it does not create a policy:

/usr/lib/systemd/systemd-pcrlock log --json=pretty --no-pager

For a machine-readable event log in TCG Common Event Log Format, use cel instead. A successful command returns exit status 0. Treat a failure here as something to resolve before predicting.

3. Predict without changing TPM state

Run predict before make-policy, never the other way round. By default it considers PCRs 0 to 5, 7, and 11 to 15; select a narrower set explicitly when testing one measured boundary:

/usr/lib/systemd/systemd-pcrlock predict \
  --pcr=7 --pcr=11 --json=pretty --no-pager

The result is a prediction for every combination of recognised component variants, which lets one policy cover several trusted kernel or bootloader versions at once. A PCR is omitted when the current evidence cannot support a complete prediction: a safety feature, since a policy claiming to cover an unknown measurement would be misleading.

Checkpoint

The prediction must include every PCR you intend to bind to a secret. If it does not, fix the event-log or component-definition problem first; adding --force does not make an incomplete prediction safe.

4. Add only the protections you can maintain

Protection commands generate or remove component definitions under /var/lib/pcrlock.d/. They are root operations, and they change what future predictions accept.

  • lock-firmware-code records firmware and extension-card measurements in PCRs 0 and 2. It becomes stale after a firmware update.
  • lock-firmware-config records PCRs 1 and 3. Use this only on hardware whose firmware measurements are stable; volatile values such as temperatures can make it unreliable.
  • lock-secureboot-policy records the Secure Boot variables that contribute to PCR 7.
  • lock-secureboot-authority records the authorities actually used to validate the boot path.
  • lock-gpt records the partition table; lock-uki or lock-pe records selected boot binaries.
  • lock-machine-id and lock-file-system cover identity measurements in PCR 15; lock-kernel-cmdline and lock-kernel-initrd cover kernel measurements in PCR 9.

For example, this read-and-write pair is intentionally explicit:

sudo /usr/lib/systemd/systemd-pcrlock lock-machine-id
sudo /usr/lib/systemd/systemd-pcrlock lock-gpt
sudo /usr/lib/systemd/systemd-pcrlock list-components --no-pager

Warning

Do not lock firmware configuration casually. Before an approved firmware or Secure Boot change, remove the relevant generated definition with its matching unlock- command (each lock- command has a paired unlock- command), make the change, then regenerate it and run a fresh prediction. That command deletes files, so record it and review the component list before continuing.

5. Write the TPM2 policy

Warning

This is the state-changing step. make-policy allocates a TPM2 NV index on first use and updates it later. The metadata is written to /var/lib/systemd/pcrlock.json. The TPM must implement PolicyAuthorizeNV, specified by this systemd version as TPM 2.0 version 1.38 or newer.

sudo /usr/lib/systemd/systemd-pcrlock make-policy \
  --recovery-pin=yes --json=pretty --no-pager

The recovery PIN is requested interactively and stored in encrypted form in the policy metadata; keep it in an approved password store. Without --recovery-pin=yes, systemd-pcrlock generates a PIN automatically and stores it encrypted too, but that is less convenient when you need to recover a policy after a boot change.

Verify the metadata and the resulting policy without forcing another write:

sudo test -s /var/lib/systemd/pcrlock.json
sudo /usr/lib/systemd/systemd-pcrlock predict --json=pretty --no-pager

Repeated make-policy calls stop quickly when the prediction is unchanged. --force overrides that optimisation and writes the policy again; reserve it for a specific operational reason.

6. Recover from an intentional change

If a policy is no longer usable, use the recovery PIN through a deliberate maintenance path, then refresh the component definitions and run make-policy again.

Recovery

If the policy should be abandoned entirely, the irreversible-looking command is:

sudo /usr/lib/systemd/systemd-pcrlock remove-policy

This deletes /var/lib/systemd/pcrlock.json and deallocates the NV index. Confirm no disk-encryption or other TPM-protected consumer still depends on it before running the command. A backup of the JSON file alone does not restore an NV index or undo changes made inside the TPM.

Done means

  • Inputs available. The TPM2 device and both current-boot event logs are readable.
  • Read-only steps succeed. list-components, log and predict all work.
  • Coverage confirmed. The prediction contains every PCR the intended consumer requires.
  • Protections match maintenance capacity. Firmware, Secure Boot and identity locks match changes you can actually keep up with.
  • Recovery agreed. The recovery PIN and policy metadata have a protected recovery path.
  • Policy written once. The NV-backed policy was written, verified, and not forced without a reason.