<refname>systemd-pcrphase-sysinit.service</refname>
<refname>systemd-pcrphase-initrd.service</refname>
<refname>systemd-pcrmachine.service</refname>
+ <refname>systemd-pcrproduct.service</refname>
<refname>systemd-pcrfs-root.service</refname>
<refname>systemd-pcrfs@.service</refname>
<refname>systemd-pcrextend</refname>
- <refpurpose>Measure boot phase into TPM2 PCR 11, machine ID and file system identity into PCR 15</refpurpose>
+ <refpurpose>Measure boot phases, machine ID, product UUID and file system identity into TPM PCRs and NvPCRs</refpurpose>
</refnamediv>
<refsynopsisdiv>
(see <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>) into
PCR 15.</para>
+ <para><filename>systemd-pcrproduct.service</filename> is a system service that measures the firmware
+ product UUID (as provided by one of SMBIOS, Devicetree, …) into a NvPCR named
+ <literal>hardware</literal>.</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
<term><option>--pcr=</option></term>
<listitem><para>Takes the index of the PCR to extend. If <option>--machine-id</option> or
- <option>--file-system=</option> are specified defaults to 15, otherwise defaults to 11. May not be
- combined with <option>--nvpcr=</option>.</para>
+ <option>--file-system=</option> are specified defaults to 15, otherwise (and unless
+ <option>--product-id</option> is specified) defaults to 11. May not be combined with
+ <option>--nvpcr=</option>.</para>
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
</varlistentry>
<listitem><para>Takes a name of an NvPCR to extend. NvPCRs are additional PCRs implemented via TPM NV
indexes. The name should be a short string such as <literal>hardware</literal> or
- <literal>disk-encryption</literal>. May not be combined with <option>--pcr=</option>.</para>
+ <literal>disk-encryption</literal>. If <option>--product-id</option> is specified defaults
+ <literal>hardware</literal>. May not be combined with <option>--pcr=</option>.</para>
<xi:include href="version-info.xml" xpointer="v259"/></listitem>
</varlistentry>
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--product-id</option></term>
+
+ <listitem><para>Instead of measuring a word specified on the command line into PCR 11, measure the
+ firmware's product UUID into an NvPCR named <literal>hardware</literal>.</para>
+
+ <xi:include href="version-info.xml" xpointer="v259"/></listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>--file-system=</option></term>
static char **arg_banks = NULL;
static char *arg_file_system = NULL;
static bool arg_machine_id = false;
+static bool arg_product_id = false;
static unsigned arg_pcr_index = UINT_MAX;
static char *arg_nvpcr_name = NULL;
static bool arg_varlink = false;
printf("%1$s [OPTIONS...] WORD\n"
"%1$s [OPTIONS...] --file-system=PATH\n"
"%1$s [OPTIONS...] --machine-id\n"
+ "%1$s [OPTIONS...] --product-id\n"
"\n%5$sExtend a TPM2 PCR with boot phase, machine ID, or file system ID.%6$s\n"
"\n%3$sOptions:%4$s\n"
" -h --help Show this help\n"
" --graceful Exit gracefully if no TPM2 device is found\n"
" --file-system=PATH Measure UUID/labels of file system into PCR 15\n"
" --machine-id Measure machine ID into PCR 15\n"
+ " --product-id Measure SMBIOS product ID into NvPCR 'hardware'\n"
" --early Run in early boot mode, without access to /var/\n"
"\nSee the %2$s for details.\n",
program_invocation_short_name,
ARG_GRACEFUL,
ARG_FILE_SYSTEM,
ARG_MACHINE_ID,
+ ARG_PRODUCT_ID,
ARG_EARLY,
};
{ "graceful", no_argument, NULL, ARG_GRACEFUL },
{ "file-system", required_argument, NULL, ARG_FILE_SYSTEM },
{ "machine-id", no_argument, NULL, ARG_MACHINE_ID },
+ { "product-id", no_argument, NULL, ARG_PRODUCT_ID },
{ "early", no_argument, NULL, ARG_EARLY },
{}
};
arg_machine_id = true;
break;
+ case ARG_PRODUCT_ID:
+ arg_product_id = true;
+ break;
+
case ARG_EARLY:
arg_early = true;
break;
assert_not_reached();
}
- if (!!arg_file_system + arg_machine_id > 1)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--file-system=, --machine-id may not be combined.");
+ if (!!arg_file_system + arg_machine_id + arg_product_id > 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--file-system=, --machine-id, --product-id may not be combined.");
if (arg_pcr_index != UINT_MAX && arg_nvpcr_name)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--pcr= and --nvpcr= may not be combined.");
return log_error_errno(r, "Failed to check if invoked in Varlink mode: %m");
if (r > 0)
arg_varlink = true;
- else if (arg_pcr_index == UINT_MAX && !arg_nvpcr_name)
- arg_pcr_index = (arg_file_system || arg_machine_id) ?
- TPM2_PCR_SYSTEM_IDENTITY : /* → PCR 15 */
- TPM2_PCR_KERNEL_BOOT; /* → PCR 11 */
+ else if (arg_pcr_index == UINT_MAX && !arg_nvpcr_name) {
+ arg_pcr_index =
+ (arg_file_system || arg_machine_id) ? TPM2_PCR_SYSTEM_IDENTITY : /* → PCR 15 */
+ !arg_product_id ? TPM2_PCR_KERNEL_BOOT : /* → PCR 11 */
+ UINT_MAX;
+
+ r = free_and_strdup_warn(&arg_nvpcr_name, arg_product_id ? "hardware" : NULL);
+ if (r < 0)
+ return r;
+ }
return 1;
}
return r;
event = TPM2_EVENT_MACHINE_ID;
+
+ } else if (arg_product_id) {
+
+ if (optind != argc)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected no argument.");
+
+ r = pcrextend_product_id_word(&word);
+ if (r < 0)
+ return r;
+
+ event = TPM2_EVENT_PRODUCT_ID;
} else {
if (optind+1 != argc)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected a single argument.");
#include "errno-util.h"
#include "escape.h"
#include "fd-util.h"
+#include "id128-util.h"
#include "log.h"
#include "mountpoint-util.h"
#include "pcrextend-util.h"
*ret = TAKE_PTR(word);
return 0;
}
+
+int pcrextend_product_id_word(char **ret) {
+ _cleanup_free_ char *word = NULL;
+ sd_id128_t pid;
+ int r;
+
+ assert(ret);
+
+ r = id128_get_product(&pid);
+ if (IN_SET(r, -ENOENT, -EADDRNOTAVAIL)) /* No product UUID field, or an all-zero or all-0xFF UUID */
+ word = strdup("product-id:missing");
+ else if (r < 0)
+ return log_error_errno(r, "Failed to acquire product ID: %m");
+ else
+ word = strjoin("product-id:", SD_ID128_TO_STRING(pid));
+ if (!word)
+ return log_oom();
+
+ *ret = TAKE_PTR(word);
+ return 0;
+}
int pcrextend_file_system_word(const char *path, char **ret, char **ret_normalized_path);
int pcrextend_machine_id_word(char **ret);
+int pcrextend_product_id_word(char **ret);
[TPM2_EVENT_FILESYSTEM] = "filesystem",
[TPM2_EVENT_VOLUME_KEY] = "volume-key",
[TPM2_EVENT_MACHINE_ID] = "machine-id",
+ [TPM2_EVENT_PRODUCT_ID] = "product-id",
};
DEFINE_STRING_TABLE_LOOKUP(tpm2_userspace_event_type, Tpm2UserspaceEventType);
TPM2_EVENT_FILESYSTEM,
TPM2_EVENT_VOLUME_KEY,
TPM2_EVENT_MACHINE_ID,
+ TPM2_EVENT_PRODUCT_ID,
_TPM2_USERSPACE_EVENT_TYPE_MAX,
_TPM2_USERSPACE_EVENT_TYPE_INVALID = -EINVAL,
} Tpm2UserspaceEventType;
]
if conf.get('ENABLE_BOOTLOADER') == 1 and conf.get('HAVE_OPENSSL') == 1 and conf.get('HAVE_TPM2') == 1
- nvpcrs = []
+ nvpcrs = [ 'hardware' ]
foreach n : nvpcrs
custom_target(
input : 'nvpcr/' + n + '.nvpcr.in',
--- /dev/null
+{
+ "name" : "hardware",
+ "algorithm" : "sha256",
+ "nvIndex" : {{TPM2_NVPCR_BASE + 0}}
+}
'conditions' : ['ENABLE_BOOTLOADER', 'HAVE_OPENSSL', 'HAVE_TPM2'],
'symlinks' : ['factory-reset.target.wants/'],
},
+ {
+ 'file' : 'systemd-pcrproduct.service.in',
+ 'conditions' : ['ENABLE_BOOTLOADER', 'HAVE_OPENSSL', 'HAVE_TPM2'],
+ 'symlinks' : ['sysinit.target.wants/'],
+ },
{
'file' : 'systemd-pcrphase-initrd.service.in',
'conditions' : ['ENABLE_BOOTLOADER', 'HAVE_OPENSSL', 'HAVE_TPM2', 'ENABLE_INITRD'],
--- /dev/null
+# 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 Product ID Measurement
+Documentation=man:systemd-pcrproduct.service(8)
+DefaultDependencies=no
+Conflicts=shutdown.target
+After=tpm2.target
+Before=sysinit.target shutdown.target
+ConditionPathExists=!/etc/initrd-release
+ConditionSecurity=measured-uki
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart={{LIBEXECDIR}}/systemd-pcrextend --graceful --product-id