recorded as `EV_IPL`, for compatibility reasons. However, `EV_IPL` will not be
used for new, additional measurements.
+## NvPCR Measurements
+
+Since the PCR number space is very small, systemd userspace supports additional
+PCRs implemented via TPM2 NV Indexes (here called *NvPCRs*, even though they
+are no less volatile than classic PCRs), using the `TPM2_NT_EXTEND` type. These
+mostly behave like real PCRs, but we can allocate them relatively freely from
+the NV index handle space.
+
+The NV index range to use for this is configurable at build time, so that
+downstreams have some flexibility to change this if they want. This uses the
+0x01d10200 NV index as base by default. To abstract the actual nvindex number
+away there's a naming concept, so that nvindexes are referenced by name string
+rather than number.
+
+NvPCRs are defined in little JSON snippets in `/usr/lib/nvpcr/*.nvpcr`, that
+match up index number and name, as well as pick a hash algorithm.
+
+There's one complication: these NV indexes (like any NV indexes) can be deleted
+by anyone with access to the TPM, and then be recreated. This could be used to
+reset the NvPCRs to zero during runtime, which defeats the whole point of
+them. Our way out: we measure a secret as first thing after creation into the
+NvPCRs. (Or actually, we measure a per-NvPCR secret we derive from a system
+secret via an HMAC of the NvPCR name and the NV index handle). This "anchoring"
+secret is stored in `/run/` + `/var/lib/` + ESP/XBOOTLDR (the latter encrypted
+as credential, locked to the TPM), to make it available at the whole runtime of
+the OS. It's only accessible to privileged processes with access to the
+TPM. Due to this, any process with access to the TPM and read access to any of
+the storage locations of the anchor secret is considered part of the TCB, as
+they are able to replay the NvPCR with their own content at will, so due care
+must be employed when designing a system that uses this feature.
+
## PCR Measurements Made by `systemd-boot` (UEFI)
### PCR 5, `EV_EVENT_TAG`, `loader.conf`
→ **Measured hash** covers the per-UKI sysext cpio archive (which is generated
on-the-fly by `systemd-stub`).
-## PCR Measurements Made by `systemd-pcrextend` (Userspace)
+## PCR/NvPCR Measurements Made by `systemd-pcrextend` (Userspace)
### PCR 11, boot phases
formatted in hexadecimal lowercase characters (in UTF-8, without trailing NUL
bytes).
+### NvPCR `hardware` (base+0), product UUID
+
+The `systemd-pcrproduct.service` service will measure the product UUID (as
+available from SMBIOS or Devicetree) of the host system, once at boot.
+
+→ **Measured hash** covers the string "product-id:" suffixed by the product
+UUID formatted in hexadecimal lowercase characters, without separators. If no
+product UUID of the local system could be determined the string
+"product-id:missing" is measured instead. Example string:
+`product-id:4691595be6a345f1833cc75fab63e475`.
+
### PCR 15, file system
The `systemd-pcrfs-root.service` and `systemd-pcrfs@.service` services will
as the GPT partition entry UUID, entry type UUID and entry label (in UTF-8,
without trailing NUL bytes).
-## PCR Measurements Made by `systemd-cryptsetup` (Userspace)
+## PCR/NvPCR Measurements Made by `systemd-cryptsetup` (Userspace)
### PCR 15, volume key
→ **Measured hash** covers the (binary) result of the HMAC(V,S) calculation where V
is the LUKS volume key, and S is the string "cryptsetup:" followed by the LUKS
volume name and the UUID of the LUKS superblock.
+
+### NvPCR `cryptsetup` (base+1), LUKS unlock mechanism/key slot
+
+The `systemd-cryptsetup@.service` service will measure information about the
+used LUKS keyslot, and in particular include the used unlock mechanism (pkcs11,
+tpm2, fido2, …) in it.
+
+→ **Measured hash** covers the string "cryptsetup-keyslot:", suffixed by the DM
+volume name, a ":" separator, the UUID of the LUKS superblock, a ":" separator,
+a brief string identifying the unlock mechanism, a ":" separator, and finally
+the LUKS slot number used. Example string:
+`cryptsetup-keyslot:root:1e023a55-60f9-4b6b-9b80-67438dc5f065:tpm2:1`