Skip to content

Commit 5663316

Browse files
apalosardbiesheuvel
authored andcommitted
efi/libstub: refactor the initrd measuring functions
Currently, from the efi-stub, we are only measuring the loaded initrd, using the TCG2 measured boot protocols. A following patch is introducing measurements of additional components, such as the kernel command line. On top of that, we will shortly have to support other types of measured boot that don't expose the TCG2 protocols. So let's prepare for that, by rejigging the efi_measure_initrd() routine into something that we should be able to reuse for measuring other assets, and which can be extended later to support other measured boot protocols. Co-developed-by: Ilias Apalodimas <[email protected]> Signed-off-by: Ilias Apalodimas <[email protected]> Signed-off-by: Ard Biesheuvel <[email protected]>
1 parent 24e88ab commit 5663316

File tree

1 file changed

+77
-43
lines changed

1 file changed

+77
-43
lines changed

drivers/firmware/efi/libstub/efi-stub-helper.c

Lines changed: 77 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,79 @@ void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_si
334334
*load_options_size = load_option_unpacked.optional_data_size;
335335
}
336336

337+
enum efistub_event {
338+
EFISTUB_EVT_INITRD,
339+
EFISTUB_EVT_COUNT,
340+
};
341+
342+
#define STR_WITH_SIZE(s) sizeof(s), s
343+
344+
static const struct {
345+
u32 pcr_index;
346+
u32 event_id;
347+
u32 event_data_len;
348+
u8 event_data[52];
349+
} events[] = {
350+
[EFISTUB_EVT_INITRD] = {
351+
9,
352+
INITRD_EVENT_TAG_ID,
353+
STR_WITH_SIZE("Linux initrd")
354+
},
355+
};
356+
357+
static efi_status_t efi_measure_tagged_event(unsigned long load_addr,
358+
unsigned long load_size,
359+
enum efistub_event event)
360+
{
361+
efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
362+
efi_tcg2_protocol_t *tcg2 = NULL;
363+
efi_status_t status;
364+
365+
efi_bs_call(locate_protocol, &tcg2_guid, NULL, (void **)&tcg2);
366+
if (tcg2) {
367+
struct efi_measured_event {
368+
efi_tcg2_event_t event_data;
369+
efi_tcg2_tagged_event_t tagged_event;
370+
u8 tagged_event_data[];
371+
} *evt;
372+
int size = sizeof(*evt) + events[event].event_data_len;
373+
374+
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
375+
(void **)&evt);
376+
if (status != EFI_SUCCESS)
377+
goto fail;
378+
379+
evt->event_data = (struct efi_tcg2_event){
380+
.event_size = size,
381+
.event_header.header_size = sizeof(evt->event_data.event_header),
382+
.event_header.header_version = EFI_TCG2_EVENT_HEADER_VERSION,
383+
.event_header.pcr_index = events[event].pcr_index,
384+
.event_header.event_type = EV_EVENT_TAG,
385+
};
386+
387+
evt->tagged_event = (struct efi_tcg2_tagged_event){
388+
.tagged_event_id = events[event].event_id,
389+
.tagged_event_data_size = events[event].event_data_len,
390+
};
391+
392+
memcpy(evt->tagged_event_data, events[event].event_data,
393+
events[event].event_data_len);
394+
395+
status = efi_call_proto(tcg2, hash_log_extend_event, 0,
396+
load_addr, load_size, &evt->event_data);
397+
efi_bs_call(free_pool, evt);
398+
399+
if (status != EFI_SUCCESS)
400+
goto fail;
401+
return EFI_SUCCESS;
402+
}
403+
404+
return EFI_UNSUPPORTED;
405+
fail:
406+
efi_warn("Failed to measure data for event %d: 0x%lx\n", event, status);
407+
return status;
408+
}
409+
337410
/*
338411
* Convert the unicode UEFI command line to ASCII to pass to kernel.
339412
* Size of memory allocated return in *cmd_line_len.
@@ -607,47 +680,6 @@ efi_status_t efi_load_initrd_cmdline(efi_loaded_image_t *image,
607680
&initrd->base, &initrd->size);
608681
}
609682

610-
static const struct {
611-
efi_tcg2_event_t event_data;
612-
efi_tcg2_tagged_event_t tagged_event;
613-
u8 tagged_event_data[];
614-
} initrd_tcg2_event = {
615-
{
616-
sizeof(initrd_tcg2_event) + sizeof("Linux initrd"),
617-
{
618-
sizeof(initrd_tcg2_event.event_data.event_header),
619-
EFI_TCG2_EVENT_HEADER_VERSION,
620-
9,
621-
EV_EVENT_TAG,
622-
},
623-
},
624-
{
625-
INITRD_EVENT_TAG_ID,
626-
sizeof("Linux initrd"),
627-
},
628-
{ "Linux initrd" },
629-
};
630-
631-
static void efi_measure_initrd(unsigned long load_addr, unsigned long load_size)
632-
{
633-
efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
634-
efi_tcg2_protocol_t *tcg2 = NULL;
635-
efi_status_t status;
636-
637-
efi_bs_call(locate_protocol, &tcg2_guid, NULL, (void **)&tcg2);
638-
if (tcg2) {
639-
status = efi_call_proto(tcg2, hash_log_extend_event,
640-
0, load_addr, load_size,
641-
&initrd_tcg2_event.event_data);
642-
if (status != EFI_SUCCESS)
643-
efi_warn("Failed to measure initrd data: 0x%lx\n",
644-
status);
645-
else
646-
efi_info("Measured initrd data into PCR %d\n",
647-
initrd_tcg2_event.event_data.event_header.pcr_index);
648-
}
649-
}
650-
651683
/**
652684
* efi_load_initrd() - Load initial RAM disk
653685
* @image: EFI loaded image protocol
@@ -671,8 +703,10 @@ efi_status_t efi_load_initrd(efi_loaded_image_t *image,
671703
status = efi_load_initrd_dev_path(&initrd, hard_limit);
672704
if (status == EFI_SUCCESS) {
673705
efi_info("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n");
674-
if (initrd.size > 0)
675-
efi_measure_initrd(initrd.base, initrd.size);
706+
if (initrd.size > 0 &&
707+
efi_measure_tagged_event(initrd.base, initrd.size,
708+
EFISTUB_EVT_INITRD) == EFI_SUCCESS)
709+
efi_info("Measured initrd data into PCR 9\n");
676710
} else if (status == EFI_NOT_FOUND) {
677711
status = efi_load_initrd_cmdline(image, &initrd, soft_limit,
678712
hard_limit);

0 commit comments

Comments
 (0)