efi: from the stub measure the ELF kernel + built-in initrd and so on into PCR 11
Here we grab a new – on Linux so far unused (by my Googling skills, that is) – and measure all static components of the PE kernel image into. This is useful since for the first time we'll have a PCR that contains only a PCR of the booted kernel, nothing else. That allows putting together TPM policies that bind to a specific kernel (+ builtin initrd), without having to have booted that kernel first. PCRs can be pre-calculated. Yay! You might wonder, why we measure just the discovered PE sections we are about to use, instead of the whole PE image. That's because of the next step I have in mind: PE images should also be able to carry an additional section that contains a signature for its own expected, pre-calculated PCR values. This signature data should then be passed into the booted kernel and can be used there in TPM policies. Benefit: TPM policies can now be bound to *signatures* of PCRs, instead of the raw hash values themselves. This makes update management a *lot* easier, as policies don't need to be updated whenever a kernel is updated, as long as the signature is available. Now, if the PCR signature is embedded in the kernel PE image it cannot be of a PCR hash of the kernel PE image itself, because that would be a chicken-and-egg problem. Hence, by only measuring the relavent payload sections (and that means excluding the future section that will contain the PCR hash signature) we avoid this problem, naturally.
This commit is contained in:
@@ -5,6 +5,12 @@
|
||||
#include <stdbool.h>
|
||||
#include <uchar.h>
|
||||
|
||||
/* This TPM PCR is where we extend the sd-stub "payloads" into, before using them. i.e. the kernel ELF image,
|
||||
* embedded initrd, and so on. In contrast to PCR 4 (which also contains this data, given the whole
|
||||
* surrounding PE image is measured into it) this should be reasonably pre-calculatable, because it *only*
|
||||
* consists of static data from the kernel PE image. */
|
||||
#define TPM_PCR_INDEX_KERNEL_IMAGE 11U
|
||||
|
||||
/* This TPM PCR is where sd-stub extends the kernel command line and any passed credentials into. */
|
||||
#define TPM_PCR_INDEX_KERNEL_PARAMETERS 12U
|
||||
|
||||
|
||||
+37
-2
@@ -149,7 +149,7 @@ static void export_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image) {
|
||||
|
||||
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
|
||||
enum {
|
||||
enum Section {
|
||||
SECTION_CMDLINE,
|
||||
SECTION_LINUX,
|
||||
SECTION_INITRD,
|
||||
@@ -178,7 +178,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
UINTN szs[_SECTION_MAX] = {};
|
||||
char *cmdline = NULL;
|
||||
_cleanup_free_ char *cmdline_owned = NULL;
|
||||
int parameters_measured = -1;
|
||||
int sections_measured = -1, parameters_measured = -1;
|
||||
EFI_STATUS err;
|
||||
bool m;
|
||||
|
||||
@@ -204,6 +204,41 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
return log_error_status_stall(err, L"Unable to locate embedded .linux section: %r", err);
|
||||
}
|
||||
|
||||
/* Measure all "payload" of this PE image into a separate PCR (i.e. where nothing else is written
|
||||
* 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 (enum Section section = 0; section < _SECTION_MAX; section++) {
|
||||
m = false;
|
||||
|
||||
if (szs[section] == 0) /* not found */
|
||||
continue;
|
||||
|
||||
/* First measure the name of the section */
|
||||
(void) tpm_log_event_ascii(
|
||||
TPM_PCR_INDEX_KERNEL_IMAGE,
|
||||
POINTER_TO_PHYSICAL_ADDRESS(sections[section]),
|
||||
strsize8(sections[section]), /* including NUL byte */
|
||||
sections[section],
|
||||
&m);
|
||||
|
||||
sections_measured = sections_measured < 0 ? m : (sections_measured && m);
|
||||
|
||||
/* Then measure the data of the section */
|
||||
(void) tpm_log_event_ascii(
|
||||
TPM_PCR_INDEX_KERNEL_IMAGE,
|
||||
POINTER_TO_PHYSICAL_ADDRESS(loaded_image->ImageBase) + addrs[section],
|
||||
szs[section],
|
||||
sections[section],
|
||||
&m);
|
||||
|
||||
sections_measured = sections_measured < 0 ? m : (sections_measured && m);
|
||||
}
|
||||
|
||||
/* After we are done, set an EFI variable that tells userspace this was done successfully, and encode
|
||||
* in it which PCR was used. */
|
||||
if (sections_measured > 0)
|
||||
(void) efivar_set_uint_string(LOADER_GUID, L"StubPcrKernelImage", TPM_PCR_INDEX_KERNEL_IMAGE, 0);
|
||||
|
||||
/* Show splash screen as early as possible */
|
||||
graphics_splash((const uint8_t*) loaded_image->ImageBase + addrs[SECTION_SPLASH], szs[SECTION_SPLASH], NULL);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user