mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
Merge pull request #28891 from poettering/pcrlock
new pcrlock tool for generating signed PCR policies for PCR 0, 1, 4, …
This commit is contained in:
95
TODO
95
TODO
@@ -147,6 +147,23 @@ Features:
|
||||
root=nvme:<trtype>:<traddr>:<trsvcid>:<nqn>:<partition> to boot directly from
|
||||
nvme-oF
|
||||
|
||||
* pcrlock:
|
||||
- make signed PCR work together with pcrlock
|
||||
- add kernel-install plugin that automatically creates UKI .pcrlock file when
|
||||
UKI is installed, and removes it when it is removed again
|
||||
- automatically install PE measurement of sd-boot on "bootctl install"
|
||||
- write generated pcrlock signature files to the ESP as credential, one for
|
||||
each installed OS & pick up generated pcrlock signature file in sd-stub,
|
||||
pass it via initrd to OS
|
||||
- pre-calc sysext + kernel cmdline measurements
|
||||
- pre-calc cryptsetup root key measurement
|
||||
- maybe make systemd-repart generate .pcrlock for old and new GPT header in
|
||||
/run?
|
||||
- Add support for more than 8 branches per PCR OR
|
||||
- add "systemd-pcrlock lock-kernel-current" or so which synthesizes .pcrlock
|
||||
policy from currently booted kernel/event log, to close gap for first boot
|
||||
for pre-built images
|
||||
|
||||
* add a new systemd-project@.service that is very similar to user@.service but
|
||||
uses DynamicUser=1 and no PAMName= to invoke an unprivileged somewhat
|
||||
light-weight service manager. Use HOME=/var/lib/systemd/projects/%i as home
|
||||
@@ -299,54 +316,6 @@ Features:
|
||||
* systemd-mount should only consider modern file systems when mounting, similar
|
||||
to systemd-dissect
|
||||
|
||||
* new "systemd-pcrlock" component for dealing with PCR4. Design idea:
|
||||
1. define /{etc,usr,var/lib}/pcrlock.d/<component>/<version>.pcrlock
|
||||
2. these files contain list of hashes that will be measured when component is
|
||||
run, per PCR
|
||||
3. each component involved in the boot that is deterministically measured can
|
||||
place one or more of these files in those dirs (shim, sd-boot,
|
||||
sd-stub/UKI, cryptsetup, pcrphase, pcrfs, …)
|
||||
4. since each component has its own dir, with multiple files in them, package
|
||||
such as kernels (of which there can be multiple installed at the same
|
||||
time) can be grouped together: only one of them is measured at a time.
|
||||
5. whenever a new component is added or an old one removed, or the PCR lock
|
||||
shall be relaxed or tightened the systemd-pcrlock tool is invoked.
|
||||
6. tool iterates through all these files, orders them alphabetically by
|
||||
component, then matches them up with current measurements (as per uefi
|
||||
event log), identifying by hash, accepting that the "beginning" of the
|
||||
measurements might not be recognizable.
|
||||
7. Then calculates expected PCR values starting with the "unrecognized
|
||||
head" from the event log, then continuing with all of components
|
||||
defined via the .pcrlock files (but dropping out the "recognized tail"
|
||||
from the uefi event log). (This might mean combinatorial explosion, if
|
||||
there are multiple shims, multiple sd-boot, and so on.)
|
||||
8. Generates a public/private key pair on the TPM
|
||||
9. Generates a counter object in the TPM, with a policy that allows only
|
||||
one-by-one increase with signature policy by the public/private key pair.
|
||||
10. now signs policies of all expected PCR values with the generated keypair,
|
||||
using all combinations of components defined in the .pcrlock files
|
||||
restricting it to the counter + 1.
|
||||
11. locks down the keypair with a signed policy with its own public key
|
||||
12. generates JSON file of all these policies with their signatures, drops
|
||||
them as singleton in ESP
|
||||
13. increases the counter by one.
|
||||
14. after boot sd-stub picks JSON up from ESP, passes it to userspace via
|
||||
.extra
|
||||
15. JSON contained policies can now be used to unlock disk as well as the
|
||||
public/key itself for signing further policies, as well as increment for
|
||||
the counter
|
||||
16. whenever any of the components above is added/removed new JSON file with
|
||||
signatures for counter + 1 is generated, dropped in ESP, then counter
|
||||
increased. (i.e. this means the "recognized tail" of the event log is
|
||||
deterministically swapped out)
|
||||
17. when firmware update is expected, relaxed signed policy is generated for
|
||||
next boot only valid if counter is increased (this means the
|
||||
"unrecognized head" for the event log can change without losing access)
|
||||
18. on every boot checks if releaxed policy is in effect, if so, new strict
|
||||
policy is generated and counter increased.
|
||||
Net result: Removes downgrade attack surface + Locks OS to firmware + Allows
|
||||
downgrades within bounds
|
||||
|
||||
* add another PE section ".fname" or so that encodes the intended filename for
|
||||
PE file, and validate that when loading add-ons and similar before using
|
||||
it. This is particularly relevant when we load multiple add-ons and want to
|
||||
@@ -469,30 +438,6 @@ Features:
|
||||
* SIGRTMIN+18 and memory pressure handling should still be added to: hostnamed,
|
||||
localed, oomd, timedated.
|
||||
|
||||
* in order to make binding to PCR 4 realistic:
|
||||
- generate one keypair "U" and store it in a tpm2 nvindex.
|
||||
- Generate another keypair "P" and store it in a second tpm2 nvindex.
|
||||
- allocate a persistent counter object "C" in the tpm2
|
||||
- Enroll all user objects (i.e. luks volumes, creds, …) to a tpm2 policy
|
||||
signed by U.
|
||||
- Lock both U and P down with a tpm2 policy signed by P (yes, P can only be
|
||||
used if a signature by P itself can be provided)
|
||||
- For regular reboots generate a signature for a restrictive PCR4 + counter C
|
||||
based policy with key P. Place signature in EFI var, so it can be found on
|
||||
next boot
|
||||
- For reboots where a firmware update is expected generate a signature with a
|
||||
more open policy against just counter C. Place signature in same EFI var.
|
||||
- Increase C whenever switching between these two signature types.
|
||||
- During early boot, use the signature from the EFI var to unlock U and P.
|
||||
Use it to generate a signature for unlocking user objects given the current
|
||||
PCR 4 value, store that away into /run somewhere, for user during the whole
|
||||
later boot.
|
||||
- When booting up automatically update the mentioned efi var so that it
|
||||
contains the restrictive signature. But also generate a signature ahead of
|
||||
time that could be used in case during the current boot we later detect we might
|
||||
need to reboot for a firmware update. Store that in /run somewhere, so that
|
||||
it can be placed in the EFI var, if needed.
|
||||
|
||||
* repart/gpt-auto/DDIs: maybe introduce a concept of "extension" partitions,
|
||||
that have a new type uuid and can "extend" earlier partitions, to work around
|
||||
the fact that systemd-repart can only grow the last partition defined. During
|
||||
@@ -1027,12 +972,6 @@ Features:
|
||||
set up the directory so that it can only be accessed if host and app are in
|
||||
order.
|
||||
|
||||
* TPM2: extend unlock policy to protect against version downgrades in signed
|
||||
policies: policy probably must take some nvram based generation counter into
|
||||
account that can only monotonically increase and can be used to invalidate
|
||||
old PCR signatures. Otherwise people could downgrade to old signed PCR sets
|
||||
whenever they want.
|
||||
|
||||
* update HACKING.md to suggest developing systemd with the ideas from:
|
||||
https://0pointer.net/blog/testing-my-system-code-in-usr-without-modifying-usr.html
|
||||
https://0pointer.net/blog/running-an-container-off-the-host-usr.html
|
||||
|
||||
@@ -808,6 +808,22 @@
|
||||
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>tpm2-pcrlock=</option></term>
|
||||
|
||||
<listitem><para>Takes an absolute path to a TPM2 pcrlock policy file, as produced by the
|
||||
<citerefentry><refentrytitle>systemd-pcrlock</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
tool. This permits locking LUKS2 volumes to a local policy of allowed PCR values with
|
||||
variants. See
|
||||
<citerefentry><refentrytitle>systemd-cryptenroll</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
for details on enrolling TPM2 pcrlock policies. If this option is not specified but it is attempted
|
||||
to unlock a LUKS2 volume with a TPM2 pcrlock enrollment a suitable signature file
|
||||
<filename>pcrlock.json</filename> is searched for in <filename>/run/systemd/</filename> and
|
||||
<filename>/var/lib/systemd/</filename> (in this order).</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>tpm2-measure-pcr=</option></term>
|
||||
|
||||
|
||||
@@ -1004,6 +1004,16 @@ manpages = [
|
||||
['systemd-nspawn', '1', [], ''],
|
||||
['systemd-oomd.service', '8', ['systemd-oomd'], 'ENABLE_OOMD'],
|
||||
['systemd-path', '1', [], ''],
|
||||
['systemd-pcrlock',
|
||||
'8',
|
||||
['systemd-pcrlock-file-system.service',
|
||||
'systemd-pcrlock-firmware-code.service',
|
||||
'systemd-pcrlock-firmware-config.service',
|
||||
'systemd-pcrlock-machine-id.service',
|
||||
'systemd-pcrlock-make-policy.service',
|
||||
'systemd-pcrlock-secureboot-authority.service',
|
||||
'systemd-pcrlock-secureboot-policy.service'],
|
||||
'ENABLE_BOOTLOADER'],
|
||||
['systemd-pcrphase.service',
|
||||
'8',
|
||||
['systemd-pcrextend',
|
||||
@@ -1139,6 +1149,7 @@ manpages = [
|
||||
['systemd.nspawn', '5', [], ''],
|
||||
['systemd.offline-updates', '7', [], ''],
|
||||
['systemd.path', '5', [], ''],
|
||||
['systemd.pcrlock', '5', ['systemd.pcrlock.d'], ''],
|
||||
['systemd.preset', '5', [], ''],
|
||||
['systemd.resource-control', '5', [], ''],
|
||||
['systemd.scope', '5', [], ''],
|
||||
|
||||
@@ -519,6 +519,20 @@
|
||||
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--tpm2-pcrlock=</option><arg>PATH</arg></term>
|
||||
|
||||
<listitem><para>Configures a TPM2 pcrlock policy to bind encryption to. Expects a path to a pcrlock
|
||||
policy file as generated by the
|
||||
<citerefentry><refentrytitle>systemd-pcrlock</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
tool. If a TPM2 device is enrolled and this option is not used but a file
|
||||
<filename>pcrlock.json</filename> is found in <filename>/run/systemd/</filename> or
|
||||
<filename>/var/lib/systemd/</filename> it is automatically used. Assign an empty string to turn this
|
||||
behaviour off.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--wipe-slot=</option><arg rep="repeat">SLOT</arg></term>
|
||||
|
||||
|
||||
559
man/systemd-pcrlock.xml
Normal file
559
man/systemd-pcrlock.xml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -388,6 +388,16 @@
|
||||
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--tpm2-pcrlock=</option><arg>PATH</arg></term>
|
||||
|
||||
<listitem><para>Configures a TPM2 pcrlock policy to bind encryption to. See
|
||||
<citerefentry><refentrytitle>systemd-cryptenroll</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
for details on this option.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--split=</option><arg>BOOL</arg></term>
|
||||
|
||||
|
||||
298
man/systemd.pcrlock.xml
Normal file
298
man/systemd.pcrlock.xml
Normal file
@@ -0,0 +1,298 @@
|
||||
<?xml version='1.0'?>
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
<refentry id="systemd.pcrlock"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
|
||||
<refentryinfo>
|
||||
<title>systemd.pcrlock</title>
|
||||
<productname>systemd</productname>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>systemd.pcrlock</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>systemd.pcrlock</refname>
|
||||
<refname>systemd.pcrlock.d</refname>
|
||||
<refpurpose>PCR measurement prediction files</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<para><literallayout>
|
||||
<filename>/etc/pcrlock.d/*.pcrlock</filename>
|
||||
<filename>/etc/pcrlock.d/*.pcrlock.d/*.pcrlock</filename>
|
||||
<filename>/run/pcrlock.d/*.pcrlock</filename>
|
||||
<filename>/run/pcrlock.d/*.pcrlock.d/*.pcrlock</filename>
|
||||
<filename>/var/lib/pcrlock.d/*.pcrlock</filename>
|
||||
<filename>/var/lib/pcrlock.d/*.pcrlock.d/*.pcrlock</filename>
|
||||
<filename>/usr/local/pcrlock.d/*.pcrlock</filename>
|
||||
<filename>/usr/local/pcrlock.d/*.pcrlock.d/*.pcrlock</filename>
|
||||
<filename>/usr/lib/pcrlock.d/*.pcrlock</filename>
|
||||
<filename>/usr/lib/pcrlock.d/*.pcrlock.d/*.pcrlock</filename></literallayout></para>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para><filename>*.pcrlock</filename> files define expected TPM2 PCR measurements of components involved
|
||||
in the boot
|
||||
process. <citerefentry><refentrytitle>systemd-pcrlock</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
uses such pcrlock files to analyze and predict TPM2 PCR measurements. The pcrlock files are JSON arrays
|
||||
that follow a subset of the <ulink
|
||||
url="https://trustedcomputinggroup.org/resource/canonical-event-log-format/">TCG Common Event Log Format
|
||||
(CEL-JSON)</ulink> specification. Specifically the <literal>recnum</literal>, <literal>content</literal>,
|
||||
and <literal>content_type</literal> record fields are not used and ignored if present. Each pcrlock file
|
||||
defines one set of expected, ordered PCR measurements of a specific component of the boot.</para>
|
||||
|
||||
<para>*.pcrlock files may be placed in various <filename>.d/</filename> drop-in directores (see above for
|
||||
a full list). All matching files discovered in these directories are sorted alphabetically by their file
|
||||
name (without taking the actual directory they were found in into account): pcrlock files with
|
||||
alphabetically earlier names are expected to cover measurements done before those with alphabetically
|
||||
later names. In order to make positioning pcrlock files in the boot process convenient the files are
|
||||
expected (by convention, this is not enforced) to be named
|
||||
<literal><replaceable>NNN</replaceable>-<replaceable>component</replaceable>.pcrlock</literal> (where
|
||||
<replaceable>NNN</replaceable> is a three-digit decimal number), for example
|
||||
<filename>750-enter-initrd.pcrlock</filename>.</para>
|
||||
|
||||
<para>For various components of the boot process more than one alternative pcrlock file shall be
|
||||
supported (i.e. "variants"). For example to cover multiple kernels installed in parallel in the access
|
||||
policy, or multiple versions of the boot loader. This can be done by placing
|
||||
<filename>*.pcrlock.d/*.pcrlock</filename> in the drop-in dirs, i.e. a common directory for a specific
|
||||
component, that contains one or more pcrlock files each covering one <emphasis>variant</emphasis> of the
|
||||
component. Example: <filename>650-kernel.pcrlock.d/6.5.5-200.fc38.x86_64.pcrlock</filename> and
|
||||
<filename>650-kernel.pcrlock.d/6.5.7-100.fc38.x86_64.pcrlock</filename></para>
|
||||
|
||||
<para>Use <command>systemd-pcrlock list-components</command> to list all pcrlock files currently
|
||||
installed.</para>
|
||||
|
||||
<para>Use the various <command>lock-*</command> commands of <command>systemd-pcrlock</command> to
|
||||
automatically generate suitable pcrlock files for various types of resources.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Well-known Components</title>
|
||||
|
||||
<para>Components of the boot process may be defined freely by the administrator or OS vendor. The
|
||||
following components are well-known however, and are defined by systemd. The list below is useful for
|
||||
ordering local pcrlock files properly against these components of the boot.</para>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>240-secureboot-policy.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>The SecureBoot policy, as recorded to PCR 7. May be generated via
|
||||
<command>systemd-pcrlock lock-secureboot-policy</command>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>250-firmware-code-early.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>Firmware code measurements, as recorded to PCR 0 and 2, up to the separator
|
||||
measurement (see <filename>400-secureboot-separator.pcrlock.</filename> below). May be generated via
|
||||
<command>systemd-pcrlock lock-firmware-code</command>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>250-firmware-config-early.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>Firmware configuration measurements, as recorded to PCR 1 and 3, up to the separator
|
||||
measurement (see <filename>400-secureboot-separator.pcrlock.</filename> below). May be generated via
|
||||
<command>systemd-pcrlock lock-firmware-config</command>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>350-action-efi-application.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>The EFI "Application" measurement done once by the firmware. Statically defined.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>400-secureboot-separator.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>The EFI "separator" measurement on PCR 7 done once by the firmware to indicate where
|
||||
firmware control transitions into boot loader/OS control. Statically defined.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>500-separator.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>The EFI "separator" measurements on PCRs 0-6 done once by the firmware to indicate
|
||||
where firmware control transitions into boot loader/OS control. Statically defined.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>550-firmware-code-late.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>Firmware code measurements, as recorded to PCR 0 and 2, after the separator
|
||||
measurement (see <filename>400-secureboot-separator.pcrlock.</filename> above). May be generated via
|
||||
<command>systemd-pcrlock lock-firmware-code</command>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>550-firmware-config-late.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>Firmware configuration measurements, as recorded to PCR 1 and 3, after the separator
|
||||
measurement (see <filename>400-secureboot-separator.pcrlock.</filename> above). May be generated via
|
||||
<command>systemd-pcrlock lock-firmware-config</command>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>600-gpt.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>The GPT partition table of the booted medium, as recorded to PCR 5 by the
|
||||
firmware. May be generated via <command>systemd-pcrlock lock-gpt</command>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>620-secureboot-authority.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>The SecureBoot authority, as recorded to PCR 7. May be generated via
|
||||
<command>systemd-pcrlock lock-secureboot-authority</command>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>700-action-efi-exit-boot-services.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>The EFI action generated when <function>ExitBootServices()</function> is generated,
|
||||
i.e. the UEFI environment is left and the OS takes over. Covers the PCR 5 measurement. Statically
|
||||
defined.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>710-kernel-cmdline.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>The kernel command line, as measured by the Linux kernel to PCR 9. May be generated
|
||||
via <command>systemd-pcrlock lock-kernel-cmdline</command>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>720-kernel-initrd.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>The kernel initrd, as measured by the Linux kernel to PCR 9. May be generated
|
||||
via <command>systemd-pcrlock lock-kernel-initrd</command>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>750-enter-initrd.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>The measurement to PCR 11
|
||||
<citerefentry><refentrytitle>systemd-pcrphase-initrd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
makes when the initrd initializes. Statically defined.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>800-leave-initrd.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>The measurement to PCR 11
|
||||
<citerefentry><refentrytitle>systemd-pcrphase-initrd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
makes when the initrd finishes. Statically defined.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>820-machine-id.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>The measurement to PCR 15
|
||||
<citerefentry><refentrytitle>systemd-pcrmachine.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
makes at boot, covering <filename>/etc/machine-id</filename> contents. May be generated via
|
||||
<command>systemd-pcrlock lock-machine-id</command>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>830-root-file-system.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>The measurement to PCR 15
|
||||
<citerefentry><refentrytitle>systemd-pcrfs-root.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
makes at boot, covering the root file system identity. May be generated
|
||||
via <command>systemd-pcrlock lock-file-system</command>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>850-sysinit.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>The measurement to PCR 11
|
||||
<citerefentry><refentrytitle>systemd-pcrphase-sysinit.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
makes when the main userspace did basic initialization and will now proceed to start regular system
|
||||
services. Statically defined.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>900-ready.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>The measurement to PCR 11
|
||||
<citerefentry><refentrytitle>systemd-pcrphase.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
makes when the system fully booted up. Statically defined.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>950-shutdown.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>The measurement to PCR 11
|
||||
<citerefentry><refentrytitle>systemd-pcrphase.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
makes when the system begins shutdown. Statically defined.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><filename>990-final.pcrlock</filename></term>
|
||||
|
||||
<listitem><para>The measurement to PCR 11
|
||||
<citerefentry><refentrytitle>systemd-pcrphase-sysinit.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
makes when the system is close to finishing shutdown. Statically defined.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<para>
|
||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>systemd-pcrlock</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
@@ -174,6 +174,7 @@ profiledir = libexecdir / 'portable' / 'profile'
|
||||
repartdefinitionsdir = libexecdir / 'repart/definitions'
|
||||
ntpservicelistdir = prefixdir / 'lib/systemd/ntp-units.d'
|
||||
credstoredir = prefixdir / 'lib/credstore'
|
||||
pcrlockdir = prefixdir / 'lib/pcrlock.d'
|
||||
|
||||
configfiledir = get_option('configfiledir')
|
||||
if configfiledir == ''
|
||||
@@ -2176,6 +2177,7 @@ subdir('src/oom')
|
||||
subdir('src/partition')
|
||||
subdir('src/path')
|
||||
subdir('src/pcrextend')
|
||||
subdir('src/pcrlock')
|
||||
subdir('src/portable')
|
||||
subdir('src/pstore')
|
||||
subdir('src/quotacheck')
|
||||
|
||||
@@ -13,12 +13,14 @@
|
||||
#include "efivars-fundamental.h"
|
||||
#include "time-util.h"
|
||||
|
||||
#define EFI_VENDOR_LOADER SD_ID128_MAKE(4a,67,b0,82,0a,4c,41,cf,b6,c7,44,0b,29,bb,8c,4f)
|
||||
#define EFI_VENDOR_LOADER_STR SD_ID128_MAKE_UUID_STR(4a,67,b0,82,0a,4c,41,cf,b6,c7,44,0b,29,bb,8c,4f)
|
||||
#define EFI_VENDOR_GLOBAL SD_ID128_MAKE(8b,e4,df,61,93,ca,11,d2,aa,0d,00,e0,98,03,2b,8c)
|
||||
#define EFI_VENDOR_GLOBAL_STR SD_ID128_MAKE_UUID_STR(8b,e4,df,61,93,ca,11,d2,aa,0d,00,e0,98,03,2b,8c)
|
||||
#define EFI_VENDOR_SYSTEMD SD_ID128_MAKE(8c,f2,64,4b,4b,0b,42,8f,93,87,6d,87,60,50,dc,67)
|
||||
#define EFI_VENDOR_SYSTEMD_STR SD_ID128_MAKE_UUID_STR(8c,f2,64,4b,4b,0b,42,8f,93,87,6d,87,60,50,dc,67)
|
||||
#define EFI_VENDOR_LOADER SD_ID128_MAKE(4a,67,b0,82,0a,4c,41,cf,b6,c7,44,0b,29,bb,8c,4f)
|
||||
#define EFI_VENDOR_LOADER_STR SD_ID128_MAKE_UUID_STR(4a,67,b0,82,0a,4c,41,cf,b6,c7,44,0b,29,bb,8c,4f)
|
||||
#define EFI_VENDOR_GLOBAL SD_ID128_MAKE(8b,e4,df,61,93,ca,11,d2,aa,0d,00,e0,98,03,2b,8c)
|
||||
#define EFI_VENDOR_GLOBAL_STR SD_ID128_MAKE_UUID_STR(8b,e4,df,61,93,ca,11,d2,aa,0d,00,e0,98,03,2b,8c)
|
||||
#define EFI_VENDOR_DATABASE SD_ID128_MAKE(d7,19,b2,cb,3d,3a,45,96,a3,bc,da,d0,0e,67,65,6f)
|
||||
#define EFI_VENDOR_DATABASE_STR SD_ID128_MAKE_UUID_STR(d7,19,b2,cb,3d,3a,45,96,a3,bc,da,d0,0e,67,65,6f)
|
||||
#define EFI_VENDOR_SYSTEMD SD_ID128_MAKE(8c,f2,64,4b,4b,0b,42,8f,93,87,6d,87,60,50,dc,67)
|
||||
#define EFI_VENDOR_SYSTEMD_STR SD_ID128_MAKE_UUID_STR(8c,f2,64,4b,4b,0b,42,8f,93,87,6d,87,60,50,dc,67)
|
||||
|
||||
#define EFI_VARIABLE_NON_VOLATILE UINT32_C(0x00000001)
|
||||
#define EFI_VARIABLE_BOOTSERVICE_ACCESS UINT32_C(0x00000002)
|
||||
|
||||
@@ -139,7 +139,8 @@ int enroll_tpm2(struct crypt_device *cd,
|
||||
const char *pubkey_path,
|
||||
uint32_t pubkey_pcr_mask,
|
||||
const char *signature_path,
|
||||
bool use_pin) {
|
||||
bool use_pin,
|
||||
const char *pcrlock_path) {
|
||||
|
||||
_cleanup_(erase_and_freep) void *secret = NULL;
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *signature_json = NULL;
|
||||
@@ -207,6 +208,15 @@ int enroll_tpm2(struct crypt_device *cd,
|
||||
return log_debug_errno(r, "Failed to read TPM PCR signature: %m");
|
||||
}
|
||||
|
||||
_cleanup_(tpm2_pcrlock_policy_done) Tpm2PCRLockPolicy pcrlock_policy = {};
|
||||
if (pcrlock_path) {
|
||||
r = tpm2_pcrlock_policy_load(pcrlock_path, &pcrlock_policy);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
flags |= TPM2_FLAGS_USE_PCRLOCK;
|
||||
}
|
||||
|
||||
_cleanup_(tpm2_context_unrefp) Tpm2Context *tpm2_context = NULL;
|
||||
r = tpm2_context_new(device, &tpm2_context);
|
||||
if (r < 0)
|
||||
@@ -248,6 +258,7 @@ int enroll_tpm2(struct crypt_device *cd,
|
||||
n_hash_pcr_values,
|
||||
pubkey ? &public : NULL,
|
||||
use_pin,
|
||||
pcrlock_path ? &pcrlock_policy : NULL,
|
||||
&policy);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -288,6 +299,7 @@ int enroll_tpm2(struct crypt_device *cd,
|
||||
pubkey_pcr_mask,
|
||||
signature_json,
|
||||
pin_str,
|
||||
pcrlock_path ? &pcrlock_policy : NULL,
|
||||
/* primary_alg= */ 0,
|
||||
blob, blob_size,
|
||||
policy.buffer, policy.size,
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
#include "tpm2-util.h"
|
||||
|
||||
#if HAVE_TPM2
|
||||
int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, uint32_t seal_key_handle, Tpm2PCRValue *hash_pcrs, size_t n_hash_pcrs, const char *pubkey_path, uint32_t pubkey_pcr_mask, const char *signature_path, bool use_pin);
|
||||
int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, uint32_t seal_key_handle, Tpm2PCRValue *hash_pcrs, size_t n_hash_pcrs, const char *pubkey_path, uint32_t pubkey_pcr_mask, const char *signature_path, bool use_pin, const char *pcrlock_path);
|
||||
#else
|
||||
static inline int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, uint32_t seal_key_handle, Tpm2PCRValue *hash_pcrs, size_t n_hash_pcrs, const char *pubkey_path, uint32_t pubkey_pcr_mask, const char *signature_path, bool use_pin) {
|
||||
static inline int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, uint32_t seal_key_handle, Tpm2PCRValue *hash_pcrs, size_t n_hash_pcrs, const char *pubkey_path, uint32_t pubkey_pcr_mask, const char *signature_path, bool use_pin, const char *pcrlock_path) {
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"TPM2 key enrollment not supported.");
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ static bool arg_tpm2_pin = false;
|
||||
static char *arg_tpm2_public_key = NULL;
|
||||
static uint32_t arg_tpm2_public_key_pcr_mask = 0;
|
||||
static char *arg_tpm2_signature = NULL;
|
||||
static char *arg_tpm2_pcrlock = NULL;
|
||||
static char *arg_node = NULL;
|
||||
static int *arg_wipe_slots = NULL;
|
||||
static size_t arg_n_wipe_slots = 0;
|
||||
@@ -65,6 +66,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_hash_pcr_values, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_public_key, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_signature, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_pcrlock, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_node, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_wipe_slots, freep);
|
||||
|
||||
@@ -144,6 +146,8 @@ static int help(void) {
|
||||
" --tpm2-signature=PATH\n"
|
||||
" Validate public key enrollment works with JSON signature\n"
|
||||
" file\n"
|
||||
" --tpm2-pcrlock=PATH\n"
|
||||
" Specify pcrlock policy to lock against\n"
|
||||
" --tpm2-with-pin=BOOL\n"
|
||||
" Whether to require entering a PIN to unlock the volume\n"
|
||||
"\nSee the %2$s for details.\n",
|
||||
@@ -173,6 +177,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_TPM2_PUBLIC_KEY_PCRS,
|
||||
ARG_TPM2_SIGNATURE,
|
||||
ARG_TPM2_PIN,
|
||||
ARG_TPM2_PCRLOCK,
|
||||
ARG_WIPE_SLOT,
|
||||
ARG_FIDO2_WITH_PIN,
|
||||
ARG_FIDO2_WITH_UP,
|
||||
@@ -200,11 +205,12 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "tpm2-public-key-pcrs", required_argument, NULL, ARG_TPM2_PUBLIC_KEY_PCRS },
|
||||
{ "tpm2-signature", required_argument, NULL, ARG_TPM2_SIGNATURE },
|
||||
{ "tpm2-with-pin", required_argument, NULL, ARG_TPM2_PIN },
|
||||
{ "tpm2-pcrlock", required_argument, NULL, ARG_TPM2_PCRLOCK },
|
||||
{ "wipe-slot", required_argument, NULL, ARG_WIPE_SLOT },
|
||||
{}
|
||||
};
|
||||
|
||||
bool auto_hash_pcr_values = true, auto_public_key_pcr_mask = true;
|
||||
bool auto_hash_pcr_values = true, auto_public_key_pcr_mask = true, auto_pcrlock = true;
|
||||
int c, r;
|
||||
|
||||
assert(argc >= 0);
|
||||
@@ -412,6 +418,14 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
break;
|
||||
|
||||
case ARG_TPM2_PCRLOCK:
|
||||
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm2_pcrlock);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
auto_pcrlock = false;
|
||||
break;
|
||||
|
||||
case ARG_WIPE_SLOT: {
|
||||
const char *p = optarg;
|
||||
|
||||
@@ -500,12 +514,23 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
if (auto_pcrlock) {
|
||||
assert(!arg_tpm2_pcrlock);
|
||||
|
||||
r = tpm2_pcrlock_search_file(NULL, NULL, &arg_tpm2_pcrlock);
|
||||
if (r < 0) {
|
||||
if (r != -ENOENT)
|
||||
log_warning_errno(r, "Search for pcrlock.json failed, assuming it does not exist: %m");
|
||||
} else
|
||||
log_info("Automatically using pcrlock policy '%s'.", arg_tpm2_pcrlock);
|
||||
}
|
||||
|
||||
if (auto_public_key_pcr_mask) {
|
||||
assert(arg_tpm2_public_key_pcr_mask == 0);
|
||||
arg_tpm2_public_key_pcr_mask = INDEX_TO_MASK(uint32_t, TPM2_PCR_KERNEL_BOOT);
|
||||
}
|
||||
|
||||
if (auto_hash_pcr_values) {
|
||||
if (auto_hash_pcr_values && !arg_tpm2_pcrlock) { /* Only lock to PCR 7 by default if no pcrlock policy is around (which is a better replacement) */
|
||||
assert(arg_tpm2_n_hash_pcr_values == 0);
|
||||
|
||||
if (!GREEDY_REALLOC_APPEND(
|
||||
@@ -690,7 +715,7 @@ static int run(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ENROLL_TPM2:
|
||||
slot = enroll_tpm2(cd, vk, vks, arg_tpm2_device, arg_tpm2_seal_key_handle, arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values, arg_tpm2_public_key, arg_tpm2_public_key_pcr_mask, arg_tpm2_signature, arg_tpm2_pin);
|
||||
slot = enroll_tpm2(cd, vk, vks, arg_tpm2_device, arg_tpm2_seal_key_handle, arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values, arg_tpm2_public_key, arg_tpm2_public_key_pcr_mask, arg_tpm2_signature, arg_tpm2_pin, arg_tpm2_pcrlock);
|
||||
break;
|
||||
|
||||
case _ENROLL_TYPE_INVALID:
|
||||
|
||||
@@ -109,6 +109,7 @@ _public_ int cryptsetup_token_open_pin(
|
||||
pubkey_pcr_mask,
|
||||
params.signature_path,
|
||||
pin_string,
|
||||
params.pcrlock_path,
|
||||
primary_alg,
|
||||
blob,
|
||||
blob_size,
|
||||
@@ -239,6 +240,7 @@ _public_ void cryptsetup_token_dump(
|
||||
crypt_log(cd, "\ttpm2-blob: %s\n", blob_str);
|
||||
crypt_log(cd, "\ttpm2-policy-hash:" CRYPT_DUMP_LINE_SEP "%s\n", policy_hash_str);
|
||||
crypt_log(cd, "\ttpm2-pin: %s\n", true_false(flags & TPM2_FLAGS_USE_PIN));
|
||||
crypt_log(cd, "\ttpm2-pcrlock: %s\n", true_false(flags & TPM2_FLAGS_USE_PCRLOCK));
|
||||
crypt_log(cd, "\ttpm2-salt: %s\n", true_false(salt));
|
||||
crypt_log(cd, "\ttpm2-srk: %s\n", true_false(srk_buf));
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ int acquire_luks2_key(
|
||||
uint32_t pubkey_pcr_mask,
|
||||
const char *signature_path,
|
||||
const char *pin,
|
||||
const char *pcrlock_path,
|
||||
uint16_t primary_alg,
|
||||
const void *key_data,
|
||||
size_t key_data_size,
|
||||
@@ -76,6 +77,13 @@ int acquire_luks2_key(
|
||||
return log_error_errno(r, "Failed to load PCR signature: %m");
|
||||
}
|
||||
|
||||
_cleanup_(tpm2_pcrlock_policy_done) Tpm2PCRLockPolicy pcrlock_policy = {};
|
||||
if (FLAGS_SET(flags, TPM2_FLAGS_USE_PCRLOCK)) {
|
||||
r = tpm2_pcrlock_policy_load(pcrlock_path, &pcrlock_policy);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
_cleanup_(tpm2_context_unrefp) Tpm2Context *tpm2_context = NULL;
|
||||
r = tpm2_context_new(device, &tpm2_context);
|
||||
if (r < 0)
|
||||
@@ -88,6 +96,7 @@ int acquire_luks2_key(
|
||||
pubkey_pcr_mask,
|
||||
signature_json,
|
||||
pin,
|
||||
FLAGS_SET(flags, TPM2_FLAGS_USE_PCRLOCK) ? &pcrlock_policy : NULL,
|
||||
primary_alg,
|
||||
key_data, key_data_size,
|
||||
policy_hash, policy_hash_size,
|
||||
|
||||
@@ -14,6 +14,7 @@ int acquire_luks2_key(
|
||||
size_t pubkey_size,
|
||||
uint32_t pubkey_pcr_mask,
|
||||
const char *signature_path,
|
||||
const char *pcrlock_path,
|
||||
const char *pin,
|
||||
uint16_t primary_alg,
|
||||
const void *key_data,
|
||||
|
||||
@@ -62,6 +62,7 @@ int acquire_tpm2_key(
|
||||
size_t pubkey_size,
|
||||
uint32_t pubkey_pcr_mask,
|
||||
const char *signature_path,
|
||||
const char *pcrlock_path,
|
||||
uint16_t primary_alg,
|
||||
const char *key_file,
|
||||
size_t key_file_size,
|
||||
@@ -129,6 +130,14 @@ int acquire_tpm2_key(
|
||||
return log_error_errno(r, "Failed to load pcr signature: %m");
|
||||
}
|
||||
|
||||
_cleanup_(tpm2_pcrlock_policy_done) Tpm2PCRLockPolicy pcrlock_policy = {};
|
||||
|
||||
if (FLAGS_SET(flags, TPM2_FLAGS_USE_PCRLOCK)) {
|
||||
r = tpm2_pcrlock_policy_load(pcrlock_path, &pcrlock_policy);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
_cleanup_(tpm2_context_unrefp) Tpm2Context *tpm2_context = NULL;
|
||||
r = tpm2_context_new(device, &tpm2_context);
|
||||
if (r < 0)
|
||||
@@ -142,6 +151,7 @@ int acquire_tpm2_key(
|
||||
pubkey_pcr_mask,
|
||||
signature_json,
|
||||
/* pin= */ NULL,
|
||||
FLAGS_SET(flags, TPM2_FLAGS_USE_PCRLOCK) ? &pcrlock_policy : NULL,
|
||||
primary_alg,
|
||||
blob,
|
||||
blob_size,
|
||||
@@ -189,6 +199,7 @@ int acquire_tpm2_key(
|
||||
pubkey_pcr_mask,
|
||||
signature_json,
|
||||
b64_salted_pin,
|
||||
pcrlock_path ? &pcrlock_policy : NULL,
|
||||
primary_alg,
|
||||
blob,
|
||||
blob_size,
|
||||
|
||||
@@ -20,6 +20,7 @@ int acquire_tpm2_key(
|
||||
size_t pubkey_size,
|
||||
uint32_t pubkey_pcr_mask,
|
||||
const char *signature_path,
|
||||
const char *pcrlock_path,
|
||||
uint16_t primary_alg,
|
||||
const char *key_file,
|
||||
size_t key_file_size,
|
||||
@@ -72,6 +73,7 @@ static inline int acquire_tpm2_key(
|
||||
size_t pubkey_size,
|
||||
uint32_t pubkey_pcr_mask,
|
||||
const char *signature_path,
|
||||
const char *pcrlock_path,
|
||||
uint16_t primary_alg,
|
||||
const char *key_file,
|
||||
size_t key_file_size,
|
||||
|
||||
@@ -100,6 +100,7 @@ static bool arg_tpm2_device_auto = false;
|
||||
static uint32_t arg_tpm2_pcr_mask = UINT32_MAX;
|
||||
static char *arg_tpm2_signature = NULL;
|
||||
static bool arg_tpm2_pin = false;
|
||||
static char *arg_tpm2_pcrlock = NULL;
|
||||
static bool arg_headless = false;
|
||||
static usec_t arg_token_timeout_usec = 30*USEC_PER_SEC;
|
||||
static unsigned arg_tpm2_measure_pcr = UINT_MAX; /* This and the following field is about measuring the unlocked volume key to the local TPM */
|
||||
@@ -116,6 +117,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_fido2_rp_id, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_signature, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_measure_banks, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_pcrlock, freep);
|
||||
|
||||
static const char* const passphrase_type_table[_PASSPHRASE_TYPE_MAX] = {
|
||||
[PASSPHRASE_REGULAR] = "passphrase",
|
||||
@@ -424,6 +426,16 @@ static int parse_one_option(const char *option) {
|
||||
|
||||
arg_tpm2_pin = r;
|
||||
|
||||
} else if ((val = startswith(option, "tpm2-pcrlock="))) {
|
||||
|
||||
if (!path_is_absolute(val))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"TPM2 pcrlock policy path \"%s\" is not absolute, refusing.", val);
|
||||
|
||||
r = free_and_strdup(&arg_tpm2_pcrlock, val);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
} else if ((val = startswith(option, "tpm2-measure-pcr="))) {
|
||||
unsigned pcr;
|
||||
|
||||
@@ -1605,6 +1617,7 @@ static int attach_luks2_by_tpm2_via_plugin(
|
||||
.search_pcr_mask = arg_tpm2_pcr_mask,
|
||||
.device = arg_tpm2_device,
|
||||
.signature_path = arg_tpm2_signature,
|
||||
.pcrlock_path = arg_tpm2_pcrlock,
|
||||
};
|
||||
|
||||
if (!libcryptsetup_plugins_support())
|
||||
@@ -1664,6 +1677,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
|
||||
/* pubkey= */ NULL, /* pubkey_size= */ 0,
|
||||
/* pubkey_pcr_mask= */ 0,
|
||||
/* signature_path= */ NULL,
|
||||
/* pcrlock_path= */ NULL,
|
||||
/* primary_alg= */ 0,
|
||||
key_file, arg_keyfile_size, arg_keyfile_offset,
|
||||
key_data, key_data_size,
|
||||
@@ -1761,6 +1775,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
|
||||
pubkey, pubkey_size,
|
||||
pubkey_pcr_mask,
|
||||
arg_tpm2_signature,
|
||||
arg_tpm2_pcrlock,
|
||||
primary_alg,
|
||||
/* key_file= */ NULL, /* key_file_size= */ 0, /* key_file_offset= */ 0, /* no key file */
|
||||
blob, blob_size,
|
||||
|
||||
@@ -152,6 +152,7 @@ static Tpm2PCRValue *arg_tpm2_hash_pcr_values = NULL;
|
||||
static size_t arg_tpm2_n_hash_pcr_values = 0;
|
||||
static char *arg_tpm2_public_key = NULL;
|
||||
static uint32_t arg_tpm2_public_key_pcr_mask = 0;
|
||||
static char *arg_tpm2_pcrlock = NULL;
|
||||
static bool arg_split = false;
|
||||
static GptPartitionType *arg_filter_partitions = NULL;
|
||||
static size_t arg_n_filter_partitions = 0;
|
||||
@@ -175,6 +176,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_certificate, X509_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_hash_pcr_values, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_public_key, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_pcrlock, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_filter_partitions, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_copy_from, strv_freep);
|
||||
@@ -3821,8 +3823,21 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta
|
||||
return log_error_errno(r, "Could not get hash mask: %m");
|
||||
}
|
||||
|
||||
_cleanup_(tpm2_pcrlock_policy_done) Tpm2PCRLockPolicy pcrlock_policy = {};
|
||||
if (arg_tpm2_pcrlock) {
|
||||
r = tpm2_pcrlock_policy_load(arg_tpm2_pcrlock, &pcrlock_policy);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
TPM2B_DIGEST policy = TPM2B_DIGEST_MAKE(NULL, TPM2_SHA256_DIGEST_SIZE);
|
||||
r = tpm2_calculate_sealing_policy(arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values, pubkey ? &public : NULL, /* use_pin= */ false, &policy);
|
||||
r = tpm2_calculate_sealing_policy(
|
||||
arg_tpm2_hash_pcr_values,
|
||||
arg_tpm2_n_hash_pcr_values,
|
||||
pubkey ? &public : NULL,
|
||||
/* use_pin= */ false,
|
||||
arg_tpm2_pcrlock ? &pcrlock_policy : NULL,
|
||||
&policy);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not calculate sealing policy digest: %m");
|
||||
|
||||
@@ -6435,6 +6450,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_TPM2_PCRS,
|
||||
ARG_TPM2_PUBLIC_KEY,
|
||||
ARG_TPM2_PUBLIC_KEY_PCRS,
|
||||
ARG_TPM2_PCRLOCK,
|
||||
ARG_SPLIT,
|
||||
ARG_INCLUDE_PARTITIONS,
|
||||
ARG_EXCLUDE_PARTITIONS,
|
||||
@@ -6472,6 +6488,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "tpm2-pcrs", required_argument, NULL, ARG_TPM2_PCRS },
|
||||
{ "tpm2-public-key", required_argument, NULL, ARG_TPM2_PUBLIC_KEY },
|
||||
{ "tpm2-public-key-pcrs", required_argument, NULL, ARG_TPM2_PUBLIC_KEY_PCRS },
|
||||
{ "tpm2-pcrlock", required_argument, NULL, ARG_TPM2_PCRLOCK },
|
||||
{ "split", required_argument, NULL, ARG_SPLIT },
|
||||
{ "include-partitions", required_argument, NULL, ARG_INCLUDE_PARTITIONS },
|
||||
{ "exclude-partitions", required_argument, NULL, ARG_EXCLUDE_PARTITIONS },
|
||||
@@ -6485,7 +6502,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{}
|
||||
};
|
||||
|
||||
bool auto_hash_pcr_values = true, auto_public_key_pcr_mask = true;
|
||||
bool auto_hash_pcr_values = true, auto_public_key_pcr_mask = true, auto_pcrlock = true;
|
||||
int c, r;
|
||||
|
||||
assert(argc >= 0);
|
||||
@@ -6728,6 +6745,14 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
break;
|
||||
|
||||
case ARG_TPM2_PCRLOCK:
|
||||
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm2_pcrlock);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
auto_pcrlock = false;
|
||||
break;
|
||||
|
||||
case ARG_SPLIT:
|
||||
r = parse_boolean_argument("--split=", optarg, NULL);
|
||||
if (r < 0)
|
||||
@@ -6935,12 +6960,23 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"A path to an image file must be specified when --split is used.");
|
||||
|
||||
if (auto_pcrlock) {
|
||||
assert(!arg_tpm2_pcrlock);
|
||||
|
||||
r = tpm2_pcrlock_search_file(NULL, NULL, &arg_tpm2_pcrlock);
|
||||
if (r < 0) {
|
||||
if (r != -ENOENT)
|
||||
log_warning_errno(r, "Search for pcrlock.json failed, assuming it does not exist: %m");
|
||||
} else
|
||||
log_info("Automatically using pcrlock policy '%s'.", arg_tpm2_pcrlock);
|
||||
}
|
||||
|
||||
if (auto_public_key_pcr_mask) {
|
||||
assert(arg_tpm2_public_key_pcr_mask == 0);
|
||||
arg_tpm2_public_key_pcr_mask = INDEX_TO_MASK(uint32_t, TPM2_PCR_KERNEL_BOOT);
|
||||
}
|
||||
|
||||
if (auto_hash_pcr_values) {
|
||||
if (auto_hash_pcr_values && !arg_tpm2_pcrlock) { /* Only lock to PCR 7 if no pcr policy is specified. */
|
||||
assert(arg_tpm2_n_hash_pcr_values == 0);
|
||||
|
||||
if (!GREEDY_REALLOC_APPEND(
|
||||
|
||||
37
src/pcrlock/meson.build
Normal file
37
src/pcrlock/meson.build
Normal file
@@ -0,0 +1,37 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
executables += [
|
||||
libexec_template + {
|
||||
'name' : 'systemd-pcrlock',
|
||||
'conditions' : [
|
||||
'HAVE_OPENSSL',
|
||||
'HAVE_TPM2'
|
||||
],
|
||||
'sources' : files(
|
||||
'pcrlock.c',
|
||||
'pcrlock-firmware.c',
|
||||
'pehash.c',
|
||||
),
|
||||
'dependencies' : [
|
||||
libm,
|
||||
libopenssl,
|
||||
tpm2,
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
if conf.get('HAVE_OPENSSL') == 1 and conf.get('HAVE_TPM2') == 1
|
||||
install_data('pcrlock.d/350-action-efi-application.pcrlock', install_dir : pcrlockdir)
|
||||
install_data('pcrlock.d/400-secureboot-separator.pcrlock.d/300-0x00000000.pcrlock', install_dir : pcrlockdir / '400-secureboot-separator.pcrlock.d')
|
||||
install_data('pcrlock.d/400-secureboot-separator.pcrlock.d/600-0xffffffff.pcrlock', install_dir : pcrlockdir / '400-secureboot-separator.pcrlock.d')
|
||||
install_data('pcrlock.d/500-separator.pcrlock.d/300-0x00000000.pcrlock', install_dir : pcrlockdir / '500-separator.pcrlock.d')
|
||||
install_data('pcrlock.d/500-separator.pcrlock.d/600-0xffffffff.pcrlock', install_dir : pcrlockdir / '500-separator.pcrlock.d')
|
||||
install_data('pcrlock.d/700-action-efi-exit-boot-services.pcrlock.d/300-present.pcrlock', install_dir : pcrlockdir / '700-action-efi-exit-boot-services.pcrlock.d')
|
||||
install_data('pcrlock.d/700-action-efi-exit-boot-services.pcrlock.d/600-absent.pcrlock', install_dir : pcrlockdir / '700-action-efi-exit-boot-services.pcrlock.d')
|
||||
install_data('pcrlock.d/750-enter-initrd.pcrlock', install_dir : pcrlockdir)
|
||||
install_data('pcrlock.d/800-leave-initrd.pcrlock', install_dir : pcrlockdir)
|
||||
install_data('pcrlock.d/850-sysinit.pcrlock', install_dir : pcrlockdir)
|
||||
install_data('pcrlock.d/900-ready.pcrlock', install_dir : pcrlockdir)
|
||||
install_data('pcrlock.d/950-shutdown.pcrlock', install_dir : pcrlockdir)
|
||||
install_data('pcrlock.d/990-final.pcrlock', install_dir : pcrlockdir)
|
||||
endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user