systemd/0559-man-systemd-cryptenrol...

398 lines
23 KiB
Diff

From 5d389e870101a3906f45f2f1b276a319d23c7440 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Wed, 5 Apr 2023 09:30:52 +0200
Subject: [PATCH] man/systemd-cryptenroll: update list of PCRs, link to uapi
docs
Entia non sunt multiplicanda praeter necessitatem. We had a list of PCRs in the
man page which was already half out-of-date. Instead, link to web page with the
"authoritative" list. Here, drop the descriptions of what shim and grub do. Instead,
just give some short descriptions and mention what systemd components do.
systemd-pcrmachine.service and systemd-pcrfs@.service are now mentioned too.
https://github.com/uapi-group/specifications/commit/d0e590b1e2648e76ece66157ceade3f45b165b14
extended the table in the specs repo.
https://github.com/uapi-group/specifications/pull/59 adds some more text there
too.
Also, rework the recommendation: hint that PCR 11 is useful, and recommend
binding to policy signatures instead of direct PCR values. This new text is
intentionally vague: doing this correctly is hard, but let's at least not imply
that just binding to PCR 7 is useful in any way.
Also, change "string alias" to "name" in discussion of PCR names.
Inspired by https://discussion.fedoraproject.org/t/future-of-encryption-in-fedora/80397/17
(cherry picked from commit 10fa7251c0d8a465c932f2c4cf4496efb1637458)
Related: RHEL-16182
---
man/systemd-cryptenroll.xml | 336 +++++++++++++++++++-----------------
1 file changed, 177 insertions(+), 159 deletions(-)
diff --git a/man/systemd-cryptenroll.xml b/man/systemd-cryptenroll.xml
index af5269aa7a..5ddaab40bc 100644
--- a/man/systemd-cryptenroll.xml
+++ b/man/systemd-cryptenroll.xml
@@ -58,6 +58,162 @@
<para>The tool supports only LUKS2 volumes, as it stores token meta-information in the LUKS2 JSON token
area, which is not available in other encryption formats.</para>
+
+ <refsect2>
+ <title>TPM2 PCRs and policies</title>
+
+ <para>PCRs allow binding of the encryption of secrets to specific software versions and system state,
+ so that the enrolled key is only accessible (may be "unsealed") if specific trusted software and/or
+ configuration is used. Such bindings may be created with the option <option>--tpm2-pcrs=</option>
+ described below.</para>
+
+ <para>Secrets may also be bound indirectly: a signed policy for a state of some combination of PCR
+ values is provided, and the secret is bound to the public part of the key used to sign this policy.
+ This means that the owner of a key can generate a sequence of signed policies, for specific software
+ versions and system states, and the secret can be decrypted as long as the machine state matches one of
+ those policies. For example, a vendor may provide such a policy for each kernel+initrd update, allowing
+ users to encrypt secrets so that they can be decrypted when running any kernel+initrd signed by the
+ vendor. Such bindings may be created with the options <option>--tpm2-public-key=</option>,
+ <option>--tpm2-public-key-pcrs=</option>, <option>--tpm2-signature=</option> described below.
+ </para>
+
+ <para>See <ulink url="https://uapi-group.org/specifications/specs/linux_tpm_pcr_registry/">Linux TPM
+ PCR Registry</ulink> for an authoritative list of PCRs and how they are updated. The table below
+ contains a quick reference, describing in particular the PCRs modified by systemd.</para>
+
+ <table>
+ <title>Well-known PCR Definitions</title>
+
+ <!-- See: https://trustedcomputinggroup.org/resource/pc-client-specific-platform-firmware-profile-specification/ -->
+ <!-- See: https://github.com/rhboot/shim/blob/main/README.tpm -->
+ <!-- See: https://www.gnu.org/software/grub/manual/grub/html_node/Measured-Boot.html -->
+ <!-- See: https://sourceforge.net/p/linux-ima/wiki/Home/ -->
+ <!-- See: https://github.com/tianocore-docs/edk2-TrustedBootChain/blob/main/4_Other_Trusted_Boot_Chains.md -->
+ <!-- See: https://wiki.archlinux.org/title/Trusted_Platform_Module#Accessing_PCR_registers -->
+
+ <tgroup cols='3' align='left' colsep='1' rowsep='1'>
+ <colspec colname="pcr" />
+ <colspec colname="name" />
+ <colspec colname="definition" />
+
+ <thead>
+ <row>
+ <entry>PCR</entry>
+ <entry>name</entry>
+ <entry>Explanation</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>0</entry>
+ <entry>platform-code</entry>
+ <entry>Core system firmware executable code; changes on firmware updates</entry>
+ </row>
+
+ <row>
+ <entry>1</entry>
+ <entry>platform-config</entry>
+ <entry>Core system firmware data/host platform configuration; typically contains serial and model numbers, changes on basic hardware/CPU/RAM replacements</entry>
+ </row>
+
+ <row>
+ <entry>2</entry>
+ <entry>external-code</entry>
+ <entry>Extended or pluggable executable code; includes option ROMs on pluggable hardware</entry>
+ </row>
+
+ <row>
+ <entry>3</entry>
+ <entry>external-config</entry>
+ <entry>Extended or pluggable firmware data; includes information about pluggable hardware</entry>
+ </row>
+
+ <row>
+ <entry>4</entry>
+ <entry>boot-loader-code</entry>
+ <entry>Boot loader and additional drivers, PE binaries invoked by the boot loader; changes on boot loader updates. <citerefentry><refentrytitle>sd-stub</refentrytitle><manvolnum>7</manvolnum></citerefentry> measures system extension images read from the ESP here too (see <citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry>).</entry>
+ </row>
+
+ <row>
+ <entry>5</entry>
+ <entry>boot-loader-config</entry>
+ <entry>GPT/Partition table; changes when the partitions are added, modified, or removed</entry>
+ </row>
+
+ <row>
+ <entry>7</entry>
+ <entry>secure-boot-policy</entry>
+ <entry>Secure Boot state; changes when UEFI SecureBoot mode is enabled/disabled, or firmware certificates (PK, KEK, db, dbx, …) changes.</entry>
+ </row>
+
+ <row>
+ <entry>9</entry>
+ <entry>kernel-initrd</entry>
+ <entry>The Linux kernel measures all initrds it receives into this PCR.</entry>
+ <!-- Strictly speaking only Linux >= 5.17 using the LOAD_FILE2 protocol, see https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f046fff8bc4c4d8f8a478022e76e40b818f692df -->
+ </row>
+
+ <row>
+ <entry>10</entry>
+ <entry>ima</entry>
+ <entry>The IMA project measures its runtime state into this PCR.</entry>
+ </row>
+
+ <row>
+ <entry>11</entry>
+ <entry>kernel-boot</entry>
+ <entry><citerefentry><refentrytitle>systemd-stub</refentrytitle><manvolnum>7</manvolnum></citerefentry> measures the ELF kernel image, embedded initrd and other payload of the PE image it is placed in into this PCR. <citerefentry><refentrytitle>systemd-pcrphase.service</refentrytitle><manvolnum>8</manvolnum></citerefentry> measures boot phase strings into this PCR at various milestones of the boot process.</entry>
+ </row>
+
+ <row>
+ <entry>12</entry>
+ <entry>kernel-config</entry>
+ <entry><citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry> measures the kernel command line into this PCR. <citerefentry><refentrytitle>systemd-stub</refentrytitle><manvolnum>7</manvolnum></citerefentry> measures any manually specified kernel command line (i.e. a kernel command line that overrides the one embedded in the unified PE image) and loaded credentials into this PCR.</entry>
+ </row>
+
+ <row>
+ <entry>13</entry>
+ <entry>sysexts</entry>
+ <entry><citerefentry><refentrytitle>systemd-stub</refentrytitle><manvolnum>7</manvolnum></citerefentry> measures any <citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry> images it passes to the booted kernel into this PCR.</entry>
+ </row>
+
+ <row>
+ <entry>14</entry>
+ <entry>shim-policy</entry>
+ <entry>The shim project measures its "MOK" certificates and hashes into this PCR.</entry>
+ </row>
+
+ <row>
+ <entry>15</entry>
+ <entry>system-identity</entry>
+ <entry><citerefentry><refentrytitle>systemd-cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry> optionally measures the volume key of activated LUKS volumes into this PCR. <citerefentry><refentrytitle>systemd-pcrmachine.service</refentrytitle><manvolnum>8</manvolnum></citerefentry> measures the <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry> into this PCR. <citerefentry><refentrytitle>systemd-pcrfs@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry> measures mount points, file system UUIDs, labels, partion UUIDs of the root and <filename>/var/</filename> filesystems into this PCR.</entry>
+ </row>
+
+ <row>
+ <entry>16</entry>
+ <entry>debug</entry>
+ <entry>Debug</entry>
+ </row>
+
+ <row>
+ <entry>23</entry>
+ <entry>application-support</entry>
+ <entry>Application Support</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>In general, encrypted volumes would be bound to some combination of PCRs 7, 11, and 14 (if
+ shim/MOK is used). In order to allow firmware and OS version updates, it is typically not advisable to
+ use PCRs such as 0 and 2, since the program code they cover should already be covered indirectly
+ through the certificates measured into PCR 7. Validation through certificates hashes is typically
+ preferable over validation through direct measurements as it is less brittle in context of OS/firmware
+ updates: the measurements will change on every update, but signatures should remain unchanged. See the
+ <ulink url="https://uapi-group.org/specifications/specs/linux_tpm_pcr_registry/">Linux TPM PCR
+ Registry</ulink> for more discussion.</para>
+ </refsect2>
</refsect1>
<refsect1>
@@ -222,154 +378,15 @@
<varlistentry>
<term><option>--tpm2-pcrs=</option><arg rep="repeat">PCR</arg></term>
- <listitem><para>Configures the TPM2 PCRs (Platform Configuration Registers) to bind the enrollment
- requested via <option>--tpm2-device=</option> to. Takes a <literal>+</literal> separated list of
- numeric PCR indexes in the range 0…23. If not used, defaults to PCR 7 only. If an empty string is
- specified, binds the enrollment to no PCRs at all.
- Registers may also be specified using string aliases.</para>
- <para>For instance <option>--tpm2-pcrs=boot-loader-code+platform-config+boot-loader-config</option> to bind to the registers
- 4, 1, and 5. Check the PCR definitions table below for a full list
- of available string aliases.
- PCRs allow binding the enrollment to specific
- software versions and system state, so that the enrolled unlocking key is only accessible (may be
- "unsealed") if specific trusted software and/or configuration is used.</para>
-
- <table>
- <title>Well-known PCR Definitions</title>
-
- <!-- See: https://trustedcomputinggroup.org/resource/pc-client-specific-platform-firmware-profile-specification/ -->
- <!-- See: https://github.com/rhboot/shim/blob/main/README.tpm -->
- <!-- See: https://www.gnu.org/software/grub/manual/grub/html_node/Measured-Boot.html -->
- <!-- See: https://sourceforge.net/p/linux-ima/wiki/Home/ -->
- <!-- See: https://github.com/tianocore-docs/edk2-TrustedBootChain/blob/main/4_Other_Trusted_Boot_Chains.md -->
- <!-- See: https://wiki.archlinux.org/title/Trusted_Platform_Module#Accessing_PCR_registers -->
-
- <tgroup cols='3' align='left' colsep='1' rowsep='1'>
- <colspec colname="pcr" />
- <colspec colname="string_alias" />
- <colspec colname="definition" />
-
- <thead>
- <row>
- <entry>PCR</entry>
- <entry>alias</entry>
- <entry>Explanation</entry>
- </row>
- </thead>
-
- <tbody>
- <row>
- <entry>0</entry>
- <entry>platform-code</entry>
- <entry>Core system firmware executable code; changes on firmware updates</entry>
- </row>
-
- <row>
- <entry>1</entry>
- <entry>platform-config</entry>
- <entry>Core system firmware data/host platform configuration; typically contains serial and model numbers, changes on basic hardware/CPU/RAM replacements</entry>
- </row>
-
- <row>
- <entry>2</entry>
- <entry>external-code</entry>
- <entry>Extended or pluggable executable code; includes option ROMs on pluggable hardware</entry>
- </row>
-
- <row>
- <entry>3</entry>
- <entry>external-config</entry>
- <entry>Extended or pluggable firmware data; includes information about pluggable hardware</entry>
- </row>
-
- <row>
- <entry>4</entry>
- <entry>boot-loader-code</entry>
- <entry>Boot loader and additional drivers; changes on boot loader updates. The shim project will measure the PE binary it chain loads into this PCR. If the Linux kernel is invoked as UEFI PE binary, it is measured here, too. <citerefentry><refentrytitle>sd-stub</refentrytitle><manvolnum>7</manvolnum></citerefentry> measures system extension images read from the ESP here too (see <citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry>).</entry>
- </row>
-
- <row>
- <entry>5</entry>
- <entry>boot-loader-config</entry>
- <entry>GPT/Partition table; changes when the partitions are added, modified or removed</entry>
- </row>
-
- <row>
- <entry>7</entry>
- <entry>secure-boot-policy</entry>
- <entry>Secure boot state; changes when UEFI SecureBoot mode is enabled/disabled, or firmware certificates (PK, KEK, db, dbx, …) changes. The shim project will measure most of its (non-MOK) certificates and SBAT data into this PCR.</entry>
- </row>
-
- <!-- Grub measures all its commands and the kernel command line into PCR 8… -->
- <!-- Grub measures all files it reads (including kernel image, initrd, …) into PCR 9… -->
-
- <row>
- <entry>9</entry>
- <entry>kernel-initrd</entry>
- <entry>The Linux kernel measures all initrds it receives into this PCR.</entry>
- <!-- Strictly speaking only Linux >= 5.17 using the LOAD_FILE2 protocol, see https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f046fff8bc4c4d8f8a478022e76e40b818f692df -->
- </row>
-
- <row>
- <entry>10</entry>
- <entry>ima</entry>
- <entry>The IMA project measures its runtime state into this PCR.</entry>
- </row>
-
- <row>
- <entry>11</entry>
- <entry>kernel-boot</entry>
- <entry><citerefentry><refentrytitle>systemd-stub</refentrytitle><manvolnum>7</manvolnum></citerefentry> measures the ELF kernel image, embedded initrd and other payload of the PE image it is placed in into this PCR. Unlike PCR 4 (where the same data should be measured into), this PCR value should be easy to pre-calculate, as this only contains static parts of the PE binary. Use this PCR to bind TPM policies to a specific kernel image, possibly with an embedded initrd. <citerefentry><refentrytitle>systemd-pcrphase.service</refentrytitle><manvolnum>8</manvolnum></citerefentry> measures boot phase strings into this PCR at various milestones of the boot process.</entry>
- </row>
-
- <row>
- <entry>12</entry>
- <entry>kernel-config</entry>
- <entry><citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry> measures any specified kernel command line into this PCR. <citerefentry><refentrytitle>systemd-stub</refentrytitle><manvolnum>7</manvolnum></citerefentry> measures any manually specified kernel command line (i.e. a kernel command line that overrides the one embedded in the unified PE image) and loaded credentials into this PCR. (Note that if <command>systemd-boot</command> and <command>systemd-stub</command> are used in combination the command line might be measured twice!)</entry>
- </row>
-
- <row>
- <entry>13</entry>
- <entry>sysexts</entry>
- <entry><citerefentry><refentrytitle>systemd-stub</refentrytitle><manvolnum>7</manvolnum></citerefentry> measures any <citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry> images it loads and passed to the booted kernel into this PCR.</entry>
- </row>
-
- <row>
- <entry>14</entry>
- <entry>shim-policy</entry>
- <entry>The shim project measures its "MOK" certificates and hashes into this PCR.</entry>
- </row>
-
- <row>
- <entry>15</entry>
- <entry>system-identity</entry>
- <entry><citerefentry><refentrytitle>systemd-cryptsetup</refentrytitle><manvolnum>7</manvolnum></citerefentry> optionally measures the volume key of activated LUKS volumes into this PCR.</entry>
- </row>
-
- <row>
- <entry>16</entry>
- <entry>debug</entry>
- <entry>Debug</entry>
- </row>
-
- <row>
- <entry>23</entry>
- <entry>application-support</entry>
- <entry>Application Support</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>For most applications it should be sufficient to bind against PCR 7 (and possibly PCR 14, if
- shim/MOK is desired), as this includes measurements of the trusted certificates (and possibly hashes)
- that are used to validate all components of the boot process up to and including the OS kernel. In
- order to simplify firmware and OS version updates it's typically not advisable to include PCRs such
- as 0 and 2 in the binding of the enrollment, since the program code they cover should already be
- protected indirectly through the certificates measured into PCR 7. Validation through these
- certificates is typically preferable over validation through direct measurements as it is less
- brittle in context of OS/firmware updates: the measurements will change on every update, but code
- signatures likely will validate against pre-existing certificates.</para></listitem>
+ <listitem><para>Configures the TPM2 PCRs (Platform Configuration Registers) to bind to when
+ enrollment is requested via <option>--tpm2-device=</option>. Takes a list of PCR names or numeric
+ indices in the range 0…23. Multiple PCR indexes are separated by <literal>+</literal>. If not
+ specified, the default is to use PCR 7 only. If an empty string is specified, binds the enrollment to
+ no PCRs at all. See the table above for a list of available PCRs.</para>
+
+ <para>Example: <option>--tpm2-pcrs=boot-loader-code+platform-config+boot-loader-config</option>
+ specifies that PCR registers 4, 1, and 5 should be used.</para>
+ </listitem>
</varlistentry>
<varlistentry>
@@ -410,20 +427,21 @@
<option>--tpm2-public-key-pcrs=</option>: the former binds decryption to the current, specific PCR
values; the latter binds decryption to any set of PCR values for which a signature by the specified
public key can be provided. The latter is hence more useful in scenarios where software updates shell
- be possible without losing access to all previously encrypted LUKS2 volumes.
- Like with <option>--tpm2-pcrs=</option>, string aliases as defined in the table above can also be used
- to specify the registers, for instance <option>--tpm2-public-key-pcrs=boot-loader-code+system-identity</option>.</para>
+ be possible without losing access to all previously encrypted LUKS2 volumes. Like with
+ <option>--tpm2-pcrs=</option>, names defined in the table above can also be used to specify the
+ registers, for instance
+ <option>--tpm2-public-key-pcrs=boot-loader-code+system-identity</option>.</para>
- <para>The <option>--tpm2-signature=</option> option takes a path to a TPM2 PCR signature file
- as generated by the
+ <para>The <option>--tpm2-signature=</option> option takes a path to a TPM2 PCR signature file as
+ generated by the
<citerefentry><refentrytitle>systemd-measure</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- tool. If this this is not specified explicitly a suitable signature file
+ tool. If this is not specified explicitly, a suitable signature file
<filename>tpm2-pcr-signature.json</filename> is searched for in <filename>/etc/systemd/</filename>,
- <filename>/run/systemd/</filename>, <filename>/usr/lib/systemd/</filename> (in this order) and
- used. If a signature file is specified or found it is used to verify if the volume can be unlocked
- with it given the current PCR state, before the new slot is written to disk. This is intended as
- safety net to ensure that access to a volume is not lost if a public key is enrolled for which no
- valid signature for the current PCR state is available. If the supplied signature does not unlock the
+ <filename>/run/systemd/</filename>, <filename>/usr/lib/systemd/</filename> (in this order) and used.
+ If a signature file is specified or found it is used to verify if the volume can be unlocked with it
+ given the current PCR state, before the new slot is written to disk. This is intended as safety net
+ to ensure that access to a volume is not lost if a public key is enrolled for which no valid
+ signature for the current PCR state is available. If the supplied signature does not unlock the
current PCR state and public key combination, no slot is enrolled and the operation will fail. If no
signature file is specified or found no such safety verification is done.</para></listitem>
</varlistentry>