man: document the new .pcrsig/.pcrpkey sections for unified kernel images

This commit is contained in:
Lennart Poettering 2022-09-09 11:08:35 +02:00
parent f51b49c675
commit 2deca517f6
2 changed files with 148 additions and 26 deletions

View file

@ -37,12 +37,12 @@
<citerefentry><refentrytitle>systemd-stub</refentrytitle><manvolnum>7</manvolnum></citerefentry> is
booted up. It accepts paths to the ELF kernel image file, initial ram disk image file, devicetree file,
kernel command line file,
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry> file, and
boot splash file that make up the unified kernel image, and determines the PCR values expected to be in
place after booting the image. Calculation starts with a zero-initialized PCR 11, and is executed in a
fashion compatible with what <filename>systemd-stub</filename> does at boot. The result may optionally be
signed cryptographically, to allow TPM2 policies that can only be unlocked if a certain set of kernels is
booted, for which such a PCR signature can be provided.</para>
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry> file, boot
splash file, and TPM2 PCR PEM public key file that make up the unified kernel image, and determines the
PCR values expected to be in place after booting the image. Calculation starts with a zero-initialized
PCR 11, and is executed in a fashion compatible with what <filename>systemd-stub</filename> does at
boot. The result may optionally be signed cryptographically, to allow TPM2 policies that can only be
unlocked if a certain set of kernels is booted, for which such a PCR signature can be provided.</para>
</refsect1>
<refsect1>
@ -66,9 +66,9 @@
<listitem><para>Pre-calculate the expected values seen in PCR register 11 after boot-up of a unified
kernel image consisting of the components specified with <option>--linux=</option>,
<option>--osrel=</option>, <option>--cmdline=</option>, <option>--initrd=</option>,
<option>--splash=</option>, <option>--dtb=</option>, see below. Only <option>--linux=</option> is
mandatory. (Alternatively, specify <option>--current</option> to use the current values of PCR
register 11 instead.)</para></listitem>
<option>--splash=</option>, <option>--dtb=</option>, <option>--pcrpkey=</option> see below. Only
<option>--linux=</option> is mandatory. (Alternatively, specify <option>--current</option> to use the
current values of PCR register 11 instead.)</para></listitem>
</varlistentry>
<varlistentry>
@ -104,6 +104,7 @@
<term><option>--initrd=PATH</option></term>
<term><option>--splash=PATH</option></term>
<term><option>--dtb=PATH</option></term>
<term><option>--pcrpkey=PATH</option></term>
<listitem><para>When used with the <command>calculate</command> or <command>sign</command> verb,
configures the files to read the unified kernel image components from. Each option corresponds with
@ -135,7 +136,14 @@
<term><option>--public-key=PATH</option></term>
<listitem><para>These switches take paths to a pair of PEM encoded RSA key files, for use with
the <command>sign</command> command.</para></listitem>
the <command>sign</command> command.</para>
<para>Note the difference between the <option>--pcrpkey=</option> and <option>--public-key=</option>
switches. The former selects the data to include in the <literal>.pcrpkey</literal> PE section of the
unified kernel image, the latter picks the public key of the key pair used to sign the resulting PCR
11 values. The former is the key that the booted system will likely use to lock disk and credential
encryption to, the latter is the key used for unlocking such resources again. Hence, typically the
same PEM key should be supplied in both cases.</para></listitem>
</varlistentry>
<varlistentry>
@ -185,19 +193,11 @@
</example>
<example>
<title>Generate a private/public key pair, and a unified kernel image, and a TPM PCR 11 signature for it</title>
<title>Generate a private/public key pair, and a unified kernel image, and a TPM PCR 11 signature for
it, and embed the signature and the public key in the image</title>
<programlisting># openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out tpm2-pcr-private.pem
# openssl rsa -pubout -in tpm2-pcr-private.pem -out tpm2-pcr-public.pem
# objcopy \
--add-section .linux=vmlinux --change-section-vma .linux=0x2000000 \
--add-section .osrel=os-release.txt --change-section-vma .osrel=0x20000 \
--add-section .cmdline=cmdline.txt --change-section-vma .cmdline=0x30000 \
--add-section .initrd=initrd.cpio --change-section-vma .initrd=0x3000000 \
--add-section .splash=splash.bmp --change-section-vma .splash=0x100000 \
--add-section .dtb=devicetree.dtb --change-section-vma .dtb=0x40000 \
/usr/lib/systemd/boot/efi/linuxx64.efi.stub \
foo.efi
# systemd-measure sign \
--linux=vmlinux \
--osrel=os-release.txt \
@ -205,10 +205,22 @@
--initrd=initrd.cpio \
--splash=splash.bmp \
--dtb=devicetree.dtb \
--pcrpkey=tpm2-pcr-public.pem \
--bank=sha1 \
--bank=sha256 \
--private-key=tpm2-pcr-private.pem \
--public-key=tpm2-pcr-public.pem > tpm2-pcr-signature.json</programlisting>
--public-key=tpm2-pcr-public.pem > tpm2-pcr-signature.json
# objcopy \
--add-section .linux=vmlinux --change-section-vma .linux=0x2000000 \
--add-section .osrel=os-release.txt --change-section-vma .osrel=0x20000 \
--add-section .cmdline=cmdline.txt --change-section-vma .cmdline=0x30000 \
--add-section .initrd=initrd.cpio --change-section-vma .initrd=0x3000000 \
--add-section .splash=splash.bmp --change-section-vma .splash=0x100000 \
--add-section .dtb=devicetree.dtb --change-section-vma .dtb=0x40000 \
--add-section .pcrsig=tpm2-pcr-signature.json --change-section-vma .splash=0x80000 \
--add-section .pcrpkey=tpm2-pcr-public.pem --change-section-vma .splash=0x90000 \
/usr/lib/systemd/boot/efi/linuxx64.efi.stub \
foo.efi</programlisting>
<para>Later on, enroll the signed PCR policy on a LUKS volume:</para>
@ -217,6 +229,11 @@
<para>And then unlock the device with the signature:</para>
<programlisting># /usr/lib/systemd/systemd-cryptsetup attach myvolume /dev/sda5 - tpm2-device=auto,tpm2-signature=/path/to/tpm2-pcr-signature.json</programlisting>
<para>Note that when the generated unified kernel image <filename>foo.efi</filename> is booted the
signature and public key files will be placed at locations <command>systemd-cryptenroll</command> and
<command>systemd-cryptsetup</command> will look for anyway, and thus these paths do not actually need to
be specified.</para>
</example>
</refsect1>

View file

@ -68,6 +68,14 @@
<listitem><para>A boot splash (in Windows <filename>.BMP</filename> format) to show on screen before
invoking the kernel will be looked for in the <literal>.splash</literal> PE section.</para></listitem>
<listitem><para>A set of cryptographic signatures for expected TPM2 PCR values when this kernel is
booted, in JSON format, in the <literal>.pcrsig</literal> section. This is useful for implementing TPM2
policies that bind disk encryption and similar to kernels that are signed by a specific
key.</para></listitem>
<listitem><para>A public key in PEM format matching this TPM2 PCR signature data in the
<literal>.pcrpkey</literal> section.</para></listitem>
</itemizedlist>
<para>If UEFI SecureBoot is enabled and the <literal>.cmdline</literal> section is present in the executed
@ -81,8 +89,25 @@
DeviceTree in the corresponding EFI configuration table. systemd-stub will ask the firmware via the
<literal>EFI_DT_FIXUP_PROTOCOL</literal> for hardware specific fixups to the DeviceTree.</para>
<para>The contents of these six PE sections are measured into TPM PCR 11, that is otherwise not
used. Thus, it can be pre-calculated without too much effort.</para>
<para>The contents of seven of these eight PE sections are measured into TPM PCR 11, that is otherwise
not used. Thus, it can be pre-calculated without too much effort. The <literal>.pcrsig</literal> section
is not included in this PCR measurement, since it's supposed to contain signatures for the expected
results for these measurements, i.e. of the outputs of the measurement operation, and thus cannot also be
input to it.</para>
<para>When <literal>.pcrsig</literal> and/or <literal>.pcrpkey</literal> are present in a unified kernel
image their contents are passed to the booted kernel in an synthetic initrd cpio archive that places them in the
<filename>/.extra/tpm2-pcr-signature.json</filename> and
<filename>/.extra/tpm2-pcr-public-key.pem</filename> files. Typically, a
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> line then
ensures they are copied into <filename>/run/systemd/tpm2-pcr-signature.json</filename> and
<filename>/run/systemd/tpm2-pcr-public-key.pem</filename> where they remain accessible even after the
system transitions out of the initrd environment into the host file system. Tools such
<citerefentry><refentrytitle>systemd-cryptsetup@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-cryptenroll</refentrytitle><manvolnum>1</manvolnum></citerefentry>
and <citerefentry><refentrytitle>systemd-creds</refentrytitle><manvolnum>1</manvolnum></citerefentry>
will automatically use files present under these paths to unlock protected resources (encrypted storage
or credentials) or bind encryption to booted kernels.</para>
</refsect1>
<refsect1>
@ -166,12 +191,12 @@
</row>
<row>
<entry>Boot splash (embedded in the unified PE binary)</entry>
<entry>Core kernel code (embedded in unified PE binary)</entry>
<entry>4 + 11</entry>
</row>
<row>
<entry>Core kernel code (embedded in unified PE binary)</entry>
<entry>OS release information (embedded in the unified PE binary)</entry>
<entry>4 + 11</entry>
</row>
@ -190,6 +215,21 @@
<entry>12</entry>
</row>
<row>
<entry>Boot splash (embedded in the unified PE binary)</entry>
<entry>4 + 11</entry>
</row>
<row>
<entry>TPM2 PCR signature JSON (embedded in unified PE binary, synthesized into initrd)</entry>
<entry>4 + 9</entry>
</row>
<row>
<entry>TPM2 PCR PEM public key (embedded in unified PE binary, synthesized into initrd)</entry>
<entry>4 + 9 + 11</entry>
</row>
<row>
<entry>Credentials (synthesized initrd from companion files)</entry>
<entry>9 + 12</entry>
@ -279,6 +319,66 @@
url="https://systemd.io/BOOT_LOADER_INTERFACE">Boot Loader Interface</ulink>.</para>
</refsect1>
<refsect1>
<title>initrd Resources</title>
<para>The following resources are passed as initrd cpio archives to the booted kernel, and thus make up
the initial file system hierarchy in the initrd execution environment:</para>
<variablelist>
<varlistentry>
<term><filename>/</filename></term>
<listitem><para>The main initrd from the <literal>.initrd</literal> PE section of the unified kernel image.</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>/.extra/credentials/*.cred</filename></term>
<listitem><para>Credential files (suffix <literal>.cred</literal>) that are placed next to the
unified kernel image (as described above) are copied into the
<filename>/.extra/credentials/</filename> directory in the initrd execution
environment.</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>/.extra/global_credentials/*.cred</filename></term>
<listitem><para>Similar, credential files in the <filename>/loader/credentials/</filename> directory
in the file system the unified kernel image is placed in are copied into the
<filename>/.extra/global_credentials/</filename> directory in the initrd execution
environment.</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>/.extra/sysext/*.raw</filename></term>
<listitem><para>System extension image files (suffix <literal>.raw</literal>) that are placed next to
the unified kernel image (as described above) are copied into the
<filename>/.extra/sysext/</filename> directory in the initrd execution environment.</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>/.extra/tpm2-pcr-signature.json</filename></term>
<listitem><para>The TPM2 PCR signature JSON object included in the <literal>.pcrsig</literal> PE
section of the unified kernel image is copied into the
<filename>/.extra/tpm2-pcr-signature.json</filename> file in the initrd execution
environment.</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>/.extra/tpm2-pcr-pkey.pem</filename></term>
<listitem><para>The PEM public key included in the <literal>.pcrpkey</literal> PE section of the
unified kernel image is copied into the <filename>/.extra/tpm2-pcr-public-key.pem</filename> file in
the initrd execution environment.</para></listitem>
</varlistentry>
</variablelist>
<para>Note that all these files are located in the <literal>tmpfs</literal> file system the kernel sets
up for the initrd file hierarchy and are thus lost when the system transitions from the initrd execution
environment into the host file system. If these resources shall be kept around over this transition they
need to be copied to a place that survives the transition first, for example via a suitable
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> line. By
default, this is done for the TPM2 PCR signature and public key files.</para>
</refsect1>
<refsect1>
<title>Assembling Kernel Images</title>
@ -313,6 +413,10 @@
<para>This expects a pair of X.509 private key and certificate as parameters and then signs the UEFI PE
executable we generated above for UEFI SecureBoot and generates a signed UEFI PE executable as
result.</para>
<para>See
<citerefentry><refentrytitle>systemd-measure</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
an example involving the <literal>.pcrsig</literal> and <literal>.pcrpkey</literal> sections.</para>
</refsect1>
<refsect1>
@ -325,7 +429,8 @@
<ulink url="https://systemd.io/BOOT_LOADER_SPECIFICATION">Boot Loader Specification</ulink>,
<ulink url="https://systemd.io/BOOT_LOADER_INTERFACE">Boot Loader Interface</ulink>,
<citerefentry project='man-pages'><refentrytitle>objcopy</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry project='archlinux'><refentrytitle>sbsign</refentrytitle><manvolnum>1</manvolnum></citerefentry>
<citerefentry project='archlinux'><refentrytitle>sbsign</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-measure</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>