stub: add new special PE sections ".pcrsig" and ".pcrpkey" in unified kernels

These aren't wired up yet to do anything useful. For now we just define
them.

This sections are supposed to carry a signature for expected
measurements on PCR 11 if this kernel is booted, in the JSON format
"systemd-measure sign" generates, and the public key used for the
signature.

The idea is to embedd the signature and the public key in unified
kernels and making them available to userspace, so that userspace can
easily access them and enroll (for which the public key is needed) or
unlock (for which the PCR signature is needed) LUKS2 volumes and
credentials that are bound to the currently used kernel version stream.

Why put these files in PE sections rather than just into simple files in
the initrd or into the host fs?

The signature cannot be in the initrd, since it is after all covering
the initrd, and thus the initrd as input for the calculation cannot
carry the result of the calculation. Putting the signature onto the root
fs sucks too, since we typically want to unlock the root fs with it,
hence it would be inaccessible for it's primary purpose then.

The public key could be in the initrd or in the root fs, there's no
technical restriction for that. However, I still think it's a good idea
to put it in a PE section as well, because this means the piece of code
that attaches the signature can also attach the public key easily in one
step, which is nice since it allows separating the roles of the
kernel/initrd/root fs builder, and the role of the signer, and the
former doesn't have to have knowledge about what the latter is going to
add to the image.

Note that the signature section is excluded from the TPM measurements
sd-stub does about its resource sections, since – as mentioned – it's
the expected output of the signing operation whose input are the
measurements, hence it cannot also be input to them. The public key
section is included in the measurements however.
This commit is contained in:
Lennart Poettering
2022-09-09 11:28:38 +02:00
parent e139565b01
commit df7ee6f8b0
4 changed files with 22 additions and 2 deletions
+5 -1
View File
@@ -190,11 +190,15 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
* into so far), so that we have one PCR that we can nicely write policies against because it
* contains all static data of this image, and thus can be easily be pre-calculated. */
for (UnifiedSection section = 0; section < _UNIFIED_SECTION_MAX; section++) {
m = false;
if (!unified_section_measure(section)) /* shall not measure? */
continue;
if (szs[section] == 0) /* not found */
continue;
m = false;
/* First measure the name of the section */
(void) tpm_log_event_ascii(
TPM_PCR_INDEX_KERNEL_IMAGE,
+5 -1
View File
@@ -68,6 +68,7 @@ static int help(int argc, char *argv[], void *userdata) {
" --initrd=PATH Path to initrd image\n"
" --splash=PATH Path to splash bitmap\n"
" --dtb=PATH Path to Devicetree file\n"
" --pcrpkey=PATH Path to public key for PCR signatures in DER format\n"
" -c --current Use current PCR values\n"
" --bank=DIGEST Select TPM bank (SHA1, SHA256)\n"
" --tpm2-device=PATH Use specified TPM2 device\n"
@@ -96,8 +97,10 @@ static int parse_argv(int argc, char *argv[]) {
ARG_CMDLINE,
ARG_INITRD,
ARG_SPLASH,
ARG_DTB,
_ARG_PCRSIG, /* the .pcrsig section is not input for signing, hence not actually an argument here */
_ARG_SECTION_LAST,
ARG_DTB = _ARG_SECTION_LAST,
ARG_PCRPKEY = _ARG_SECTION_LAST,
ARG_BANK,
ARG_PRIVATE_KEY,
ARG_PUBLIC_KEY,
@@ -115,6 +118,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "initrd", required_argument, NULL, ARG_INITRD },
{ "splash", required_argument, NULL, ARG_SPLASH },
{ "dtb", required_argument, NULL, ARG_DTB },
{ "pcrpkey", required_argument, NULL, ARG_PCRPKEY },
{ "current", no_argument, NULL, 'c' },
{ "bank", required_argument, NULL, ARG_BANK },
{ "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE },
+2
View File
@@ -11,5 +11,7 @@ const char* const unified_sections[_UNIFIED_SECTION_MAX + 1] = {
[UNIFIED_SECTION_INITRD] = ".initrd",
[UNIFIED_SECTION_SPLASH] = ".splash",
[UNIFIED_SECTION_DTB] = ".dtb",
[UNIFIED_SECTION_PCRSIG] = ".pcrsig",
[UNIFIED_SECTION_PCRPKEY] = ".pcrpkey",
NULL,
};
+10
View File
@@ -1,6 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "macro-fundamental.h"
/* The various TPM PCRs we measure into from sd-stub and sd-boot. */
/* This TPM PCR is where we extend the sd-stub "payloads" into, before using them. i.e. the kernel ELF image,
@@ -32,7 +34,15 @@ typedef enum UnifiedSection {
UNIFIED_SECTION_INITRD,
UNIFIED_SECTION_SPLASH,
UNIFIED_SECTION_DTB,
UNIFIED_SECTION_PCRSIG,
UNIFIED_SECTION_PCRPKEY,
_UNIFIED_SECTION_MAX,
} UnifiedSection;
extern const char* const unified_sections[_UNIFIED_SECTION_MAX + 1];
static inline bool unified_section_measure(UnifiedSection section) {
/* Don't include the PCR signature in the PCR measurements, since they sign the expected result of
* the measurement, and hence shouldn't be input to it. */
return section >= 0 && section < _UNIFIED_SECTION_MAX && section != UNIFIED_SECTION_PCRSIG;
}