units: measure a separator event into PCR 9 after completing NvPCR initialization

We do this in a separate service (rather than inside of
systemd-tpm2-setup), since we want failures of this measurement to
result in an instant reboot, like for most our measurements.

Failures to initialize nvpcrs, or allocate an SRK are somewhat OK (and
more likely), as long as this separator communicates clearly where they
have to have taken place, if they worked.
This commit is contained in:
Lennart Poettering
2025-11-13 14:47:57 +01:00
parent 86dc140b9f
commit 867e64737a
7 changed files with 53 additions and 7 deletions

View File

@@ -260,6 +260,15 @@ colon-separated strings, identifying the file system type, UUID, label as well
as the GPT partition entry UUID, entry type UUID and entry label (in UTF-8,
without trailing NUL bytes).
### PCR 9, NvPCR initialization separator
After completion of `systemd-tpm2-setup.service` (which initializes all NvPCRs
and measures their initial state) at arly boot the `systemd-pcrnvdone.service`
service will measure a separator event into PCR 9, isolating the early-boot
NvPCR initializations from any later additions.
**Measured hash** covers the string `nvpcr-separator`.
## PCR/NvPCR Measurements Made by `systemd-cryptsetup` (Userspace)
### PCR 15, volume key

View File

@@ -1106,6 +1106,7 @@ manpages = [
'systemd-pcrfs-root.service',
'systemd-pcrfs@.service',
'systemd-pcrmachine.service',
'systemd-pcrnvdone.service',
'systemd-pcrphase-initrd.service',
'systemd-pcrphase-sysinit.service'],
'ENABLE_BOOTLOADER HAVE_OPENSSL HAVE_TPM2'],

View File

@@ -24,6 +24,7 @@
<refname>systemd-pcrproduct.service</refname>
<refname>systemd-pcrfs-root.service</refname>
<refname>systemd-pcrfs@.service</refname>
<refname>systemd-pcrnvdone.service</refname>
<refname>systemd-pcrextend</refname>
<refpurpose>Measure boot phases, machine ID, product UUID and file system identity into TPM PCRs and NvPCRs</refpurpose>
</refnamediv>
@@ -35,6 +36,7 @@
<para><filename>systemd-pcrmachine.service</filename></para>
<para><filename>systemd-pcrfs-root.service</filename></para>
<para><filename>systemd-pcrfs@.service</filename></para>
<para><filename>systemd-pcrnvdone.service</filename></para>
<para><filename>/usr/lib/systemd/systemd-pcrextend</filename> <optional><replaceable>STRING</replaceable></optional></para>
</refsynopsisdiv>
@@ -54,6 +56,9 @@
product UUID (as provided by one of SMBIOS, Devicetree, …) into a NvPCR named
<literal>hardware</literal>.</para>
<para><filename>systemd-pcrnvdone.service</filename> is a system service that measures a separator event
into PCR 9 once all NvPCRs have completed initialization.</para>
<para><filename>systemd-pcrfs-root.service</filename> and <filename>systemd-pcrfs@.service</filename> are
services that measure file system identity information (i.e. mount point, file system type, label and
UUID, partition label and UUID) into PCR 15. <filename>systemd-pcrfs-root.service</filename> does so for

View File

@@ -6420,13 +6420,14 @@ static int json_dispatch_tpm2_algorithm(const char *name, sd_json_variant *varia
}
static const char* tpm2_userspace_event_type_table[_TPM2_USERSPACE_EVENT_TYPE_MAX] = {
[TPM2_EVENT_PHASE] = "phase",
[TPM2_EVENT_FILESYSTEM] = "filesystem",
[TPM2_EVENT_VOLUME_KEY] = "volume-key",
[TPM2_EVENT_MACHINE_ID] = "machine-id",
[TPM2_EVENT_PRODUCT_ID] = "product-id",
[TPM2_EVENT_KEYSLOT] = "keyslot",
[TPM2_EVENT_NVPCR_INIT] = "nvpcr-init",
[TPM2_EVENT_PHASE] = "phase",
[TPM2_EVENT_FILESYSTEM] = "filesystem",
[TPM2_EVENT_VOLUME_KEY] = "volume-key",
[TPM2_EVENT_MACHINE_ID] = "machine-id",
[TPM2_EVENT_PRODUCT_ID] = "product-id",
[TPM2_EVENT_KEYSLOT] = "keyslot",
[TPM2_EVENT_NVPCR_INIT] = "nvpcr-init",
[TPM2_EVENT_NVPCR_SEPARATOR] = "nvpcr-separator",
};
DEFINE_STRING_TABLE_LOOKUP(tpm2_userspace_event_type, Tpm2UserspaceEventType);

View File

@@ -145,6 +145,7 @@ typedef enum Tpm2UserspaceEventType {
TPM2_EVENT_PRODUCT_ID,
TPM2_EVENT_KEYSLOT,
TPM2_EVENT_NVPCR_INIT,
TPM2_EVENT_NVPCR_SEPARATOR,
_TPM2_USERSPACE_EVENT_TYPE_MAX,
_TPM2_USERSPACE_EVENT_TYPE_INVALID = -EINVAL,
} Tpm2UserspaceEventType;

View File

@@ -581,6 +581,11 @@ units = [
'conditions' : ['ENABLE_BOOTLOADER', 'HAVE_OPENSSL', 'HAVE_TPM2'],
'symlinks' : ['sysinit.target.wants/'],
},
{
'file' : 'systemd-pcrnvdone.service.in',
'conditions' : ['ENABLE_BOOTLOADER', 'HAVE_OPENSSL', 'HAVE_TPM2'],
'symlinks' : ['sysinit.target.wants/'],
},
{
'file' : 'systemd-tpm2-clear.service.in',
'conditions' : ['ENABLE_BOOTLOADER', 'HAVE_OPENSSL', 'HAVE_TPM2'],

View File

@@ -0,0 +1,24 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=TPM PCR NvPCR Initialization Separator
Documentation=man:systemd-pcrnvdone.service(8)
DefaultDependencies=no
Conflicts=shutdown.target
After=systemd-tpm2-setup-early.service systemd-tpm2-setup.service
Before=sysinit.target shutdown.target
ConditionSecurity=measured-uki
ConditionPathExists=!/etc/initrd-release
FailureAction=reboot-force
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart={{LIBEXECDIR}}/systemd-pcrextend --graceful --pcr=kernel-initrd --event-type=nvpcr-separator nvpcr-separator