From: Michał Żygowski <michal.zygow...@3mdeb.com> The code makes sure the order of policy entries is correct: - MBI entry goes first, so the payload can measure it first on launch - then goes SLRT and other typical entries - MB2 modules are appended last
Signed-off-by: Michał Żygowski <michal.zygow...@3mdeb.com> Signed-off-by: Tomasz Żyjewski <tomasz.zyjew...@3mdeb.com> Signed-off-by: Krystian Hebel <krystian.he...@3mdeb.com> Signed-off-by: Sergii Dmytruk <sergii.dmyt...@3mdeb.com> --- grub-core/loader/multiboot.c | 11 +++ grub-core/loader/multiboot_elfxx.c | 90 +++++++++++++++++++- grub-core/loader/multiboot_mbi2.c | 132 +++++++++++++++++++++++++++++ grub-core/loader/slaunch/dlstub.c | 2 +- include/grub/i386/txt.h | 2 + include/grub/multiboot2.h | 3 + include/grub/slaunch.h | 1 + include/grub/slr_table.h | 2 + 8 files changed, 241 insertions(+), 2 deletions(-) diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index 98c1d5e99..07163739b 100644 --- a/grub-core/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -50,6 +50,7 @@ #include <grub/video.h> #include <grub/memory.h> #include <grub/i18n.h> +#include <grub/slaunch.h> GRUB_MOD_LICENSE ("GPLv3+"); @@ -191,6 +192,16 @@ grub_multiboot_boot (void) if (err) return err; +#ifdef GRUB_USE_MULTIBOOT2 + if (grub_slaunch_platform_type () != SLP_NONE) + { + err = grub_multiboot2_perform_slaunch (state.MULTIBOOT_MBI_REGISTER, + mbi_size); + if (err) + return grub_error (err, N_("failed to perform Multiboot2 slaunch")); + } +#endif + if (grub_efi_is_finished) normal_boot (GRUB_MULTIBOOT (relocator), state); else diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c index 1edad0594..ee05a4d99 100644 --- a/grub-core/loader/multiboot_elfxx.c +++ b/grub-core/loader/multiboot_elfxx.c @@ -44,7 +44,9 @@ #error "I'm confused" #endif +#include <grub/i386/txt.h> #include <grub/i386/relocator.h> +#include <grub/slaunch.h> #define CONCAT(a,b) CONCAT_(a, b) #define CONCAT_(a,b) a ## b @@ -73,6 +75,11 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld) grub_off_t phlimit; unsigned int i; void *source = NULL; +#ifdef GRUB_USE_MULTIBOOT2 + struct grub_slaunch_params *slparams = &grub_multiboot2_slparams; + grub_uint32_t mle_hdr_offset; + struct grub_txt_mle_header *mle_hdr; +#endif if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || ehdr->e_ident[EI_MAG1] != ELFMAG1 @@ -127,6 +134,18 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld) { load_size = highest_load - mld->link_base_addr; +#ifndef GRUB_USE_MULTIBOOT2 + if (grub_slaunch_platform_type () != SLP_NONE) + return grub_error (GRUB_ERR_BAD_OS, "Only multiboot2 supported for slaunch"); +#else + if (grub_slaunch_platform_type () == SLP_INTEL_TXT) + { + /* Do not go below GRUB_TXT_PMR_ALIGN. */ + if (mld->align < GRUB_TXT_PMR_ALIGN) + mld->align = GRUB_TXT_PMR_ALIGN; + } +#endif + grub_dprintf ("multiboot_loader", "align=0x%lx, preference=0x%x, " "load_size=0x%x, avoid_efi_boot_services=%d\n", (long) mld->align, mld->preference, load_size, @@ -148,9 +167,57 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld) mld->load_base_addr = get_physical_target_address (ch); source = get_virtual_current_address (ch); + +#ifdef GRUB_USE_MULTIBOOT2 + grub_memset (source, 0, load_size); + grub_dprintf ("multiboot_loader", "load_base_addr=0x%lx, source=0x%lx\n", + (long) mld->load_base_addr, (long) source); + + if (grub_slaunch_platform_type () != SLP_NONE) + { + slparams->mle_start = mld->load_base_addr; + slparams->mle_mem = source; + slparams->mle_ptab_size = 0; + } + + if (grub_slaunch_platform_type () == SLP_INTEL_TXT) + { + /* + * Allocate the binary together with the page tables to make one + * contiguous block for MLE. + */ + slparams->mle_ptab_size = grub_txt_get_mle_ptab_size (load_size); + slparams->mle_ptab_size = ALIGN_UP (slparams->mle_ptab_size, GRUB_TXT_PMR_ALIGN); + + err = grub_relocator_alloc_chunk_align_safe (GRUB_MULTIBOOT (relocator), &ch, + GRUB_MEMORY_MACHINE_UPPER_START, + mld->load_base_addr - slparams->mle_ptab_size, + slparams->mle_ptab_size, GRUB_TXT_PMR_ALIGN, + GRUB_RELOCATOR_PREFERENCE_NONE, 1); + if (err) + { + grub_dprintf ("multiboot_loader", "Cannot allocate memory for MLE page tables\n"); + return err; + } + + slparams->mle_ptab_mem = get_virtual_current_address (ch); + slparams->mle_ptab_target = (grub_uint64_t) get_physical_target_address (ch); + grub_dprintf ("multiboot_loader", "mle_ptab_mem = %p, mle_ptab_target = %lx, mle_ptab_size = %x\n", + slparams->mle_ptab_mem, (unsigned long) slparams->mle_ptab_target, + (unsigned) slparams->mle_ptab_size); + } +#endif } else - mld->load_base_addr = mld->link_base_addr; + { +#ifdef GRUB_USE_MULTIBOOT2 + /* TODO: support non-relocatable */ + if (grub_slaunch_platform_type () != SLP_NONE) + return grub_error (GRUB_ERR_BAD_OS, "Non-relocatable ELF not supported with slaunch"); +#endif + + mld->load_base_addr = mld->link_base_addr; + } grub_dprintf ("multiboot_loader", "relocatable=%d, link_base_addr=0x%x, " "load_base_addr=0x%x\n", mld->relocatable, @@ -213,6 +280,27 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld) } } +#ifdef GRUB_USE_MULTIBOOT2 + if (grub_slaunch_platform_type () != SLP_NONE) + { + /* TODO: decide on universal way of conveying location of MLE header */ + for (mle_hdr_offset = 0; mle_hdr_offset < 0x1000; mle_hdr_offset += 16) + { + mle_hdr = (struct grub_txt_mle_header *)((grub_addr_t)source + mle_hdr_offset); + if (!grub_memcmp (mle_hdr->uuid, GRUB_TXT_MLE_UUID, 16)) + { + break; + } + } + + if (mle_hdr_offset >= 0x1000) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "MLE header not found"); + + slparams->mle_header_offset = mle_hdr_offset; + slparams->mle_size = mle_hdr->mle_end - mle_hdr->mle_start; + } +#endif + for (i = 0; i < phnum; i++) if (phdr(i)->p_vaddr <= ehdr->e_entry && phdr(i)->p_vaddr + phdr(i)->p_memsz > ehdr->e_entry) diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c index 1945b3ac6..dcbfbed1f 100644 --- a/grub-core/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -36,6 +36,10 @@ #include <grub/i18n.h> #include <grub/net.h> #include <grub/lib/cmdline.h> +#include <grub/i386/memory.h> +#include <grub/i386/txt.h> +#include <grub/slaunch.h> +#include <grub/slr_table.h> #if defined (GRUB_MACHINE_EFI) #include <grub/efi/efi.h> @@ -63,6 +67,12 @@ struct module int cmdline_size; }; +struct fill_policy_hook_data +{ + grub_uint32_t mbi_target; + grub_uint32_t mbi_size; +}; + static struct module *modules, *modules_last; static grub_size_t cmdline_size; static grub_size_t total_modcmd; @@ -76,6 +86,8 @@ static void *elf_sections; static int keep_bs = 0; static grub_uint32_t load_base_addr; +struct grub_slaunch_params grub_multiboot2_slparams = {0}; + void grub_multiboot2_add_elfsyms (grub_size_t num, grub_size_t entsize, unsigned shndx, void *data) @@ -119,6 +131,7 @@ grub_multiboot2_load (grub_file_t file, const char *filename) grub_uint32_t console_required = 0; struct multiboot_header_tag_framebuffer *fbtag = NULL; int accepted_consoles = GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT; + struct grub_slaunch_params *slparams = &grub_multiboot2_slparams; mbi_load_data_t mld; mld.mbi_ver = 2; @@ -275,8 +288,18 @@ grub_multiboot2_load (grub_file_t file, const char *filename) "load address tag without entry address tag"); } + if (grub_slaunch_platform_type () != SLP_NONE) + { + slparams->relocator = grub_multiboot2_relocator; + slparams->boot_type = GRUB_SL_BOOT_TYPE_MB2; + slparams->platform_type = grub_slaunch_platform_type (); + } + if (addr_tag) { + if (slparams->platform_type != SLP_NONE) + return grub_error (GRUB_ERR_BAD_OS, "Slaunch not supported with multiboot addr tag"); + grub_uint64_t load_addr = (addr_tag->load_addr + 1) ? addr_tag->load_addr : (addr_tag->header_addr - ((char *) header - (char *) mld.buffer)); @@ -390,6 +413,35 @@ grub_multiboot2_load (grub_file_t file, const char *filename) err = grub_multiboot2_set_console (GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT, accepted_consoles, 0, 0, 0, console_required); + + if (slparams->platform_type != SLP_NONE) + { + grub_relocator_chunk_t ch; + + if (grub_relocator_alloc_chunk_align_safe (grub_multiboot2_relocator, &ch, 0x1000000, + UP_TO_TOP32 (GRUB_SLAUNCH_TPM_EVT_LOG_SIZE), + GRUB_SLAUNCH_TPM_EVT_LOG_SIZE, GRUB_PAGE_SIZE, + GRUB_RELOCATOR_PREFERENCE_HIGH, 1)) + { + grub_free (mld.buffer); + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Could not allocate TPM event log area"); + } + + slparams->tpm_evt_log_base = get_physical_target_address (ch); + slparams->tpm_evt_log_size = GRUB_SLAUNCH_TPM_EVT_LOG_SIZE; + + if (slparams->platform_type == SLP_INTEL_TXT) + grub_txt_init_tpm_event_log (get_virtual_current_address (ch), + slparams->tpm_evt_log_size); + + grub_dprintf ("multiboot_loader", "tpm_evt_log_base = 0x%lx, tpm_evt_log_size = 0x%x\n", + (unsigned long) slparams->tpm_evt_log_base, + (unsigned) slparams->tpm_evt_log_size); + + if (slparams->platform_type == SLP_INTEL_TXT) + grub_txt_setup_mle_ptab (slparams); + } + return err; } @@ -1128,3 +1180,83 @@ grub_multiboot2_set_bootdev (void) bootdev_set = 1; } + +static int +fill_policy_hook(int is_start, int available_entries, + struct grub_slr_policy_entry *next_entry, void *data) +{ + int i = 0; + unsigned m; + struct module *cur; + struct fill_policy_hook_data *hook_data = data; + + if (is_start) + { + if (available_entries < 1) + return -1; + + next_entry->pcr = 18; + next_entry->entity_type = GRUB_SLR_ET_MULTIBOOT2_INFO; + next_entry->entity = hook_data->mbi_target; + next_entry->size = hook_data->mbi_size; + next_entry->flags = 0; + grub_strcpy (next_entry->evt_info, "Measured MB2 information"); + i = 1; + } + else + { + if (available_entries < (int)modcnt) + return -1; + + for (m = 0, cur = modules; m < modcnt; m++, cur = cur->next) + { + next_entry[i].pcr = 17; + next_entry[i].entity_type = GRUB_SLR_ET_MULTIBOOT2_MODULE; + next_entry[i].entity = cur->start; + next_entry[i].size = cur->size; + next_entry[i].flags = 0; + grub_strcpy (next_entry[i].evt_info, "Measured MB2 module"); + i++; + } + } + + return i; +} + +grub_err_t +grub_multiboot2_perform_slaunch (grub_uint32_t mbi_target, + grub_uint32_t mbi_size) +{ + grub_err_t err; + struct grub_slaunch_params *slparams = &grub_multiboot2_slparams; + struct grub_slr_entry_dl_info *dlinfo; + struct fill_policy_hook_data hook_data = { + .mbi_target = mbi_target, + .mbi_size = mbi_size, + }; + + slparams->boot_params_base = mbi_target; + + slparams->fill_policy_hook = &fill_policy_hook; + slparams->fill_policy_hook_data = &hook_data; + + if (slparams->platform_type == SLP_INTEL_TXT) + { + err = grub_txt_boot_prepare (slparams); + if (err != GRUB_ERR_NONE) + return grub_error (err, "TXT boot preparation failed"); + } + else + return grub_error (GRUB_ERR_BAD_DEVICE, + N_("Unknown secure launcher platform type: %d\n"), slparams->platform_type); + + grub_dprintf ("multiboot_loader", "slr_table_base = 0x%lx, slr_table_size = 0x%x\n", + (unsigned long) slparams->slr_table_base, + (unsigned) slparams->slr_table_size); + + dlinfo = grub_slr_next_entry_by_tag (slparams->slr_table_mem, NULL, GRUB_SLR_ENTRY_DL_INFO); + dl_entry ((grub_uint64_t)(grub_addr_t) &dlinfo->bl_context); + + /* If this returns, something failed miserably */ + return GRUB_ERR_BAD_DEVICE; +} diff --git a/grub-core/loader/slaunch/dlstub.c b/grub-core/loader/slaunch/dlstub.c index d3c28645e..2cdbdd886 100644 --- a/grub-core/loader/slaunch/dlstub.c +++ b/grub-core/loader/slaunch/dlstub.c @@ -73,7 +73,7 @@ void dl_entry (grub_uint64_t dl_ctx) return; } - if (slparams->boot_type == GRUB_SL_BOOT_TYPE_LINUX) + if (slparams->boot_type == GRUB_SL_BOOT_TYPE_LINUX || slparams->boot_type == GRUB_SL_BOOT_TYPE_MB2) { /* Configure relocator GETSEC[SENTER] call. */ state.eax = GRUB_SMX_LEAF_SENTER; diff --git a/include/grub/i386/txt.h b/include/grub/i386/txt.h index d4a6d1cd1..d2ae7b21e 100644 --- a/include/grub/i386/txt.h +++ b/include/grub/i386/txt.h @@ -420,6 +420,8 @@ struct grub_txt_sinit_memory_descriptor_records /* 2.1 MLE Architecture Overview */ /* Table 1. MLE Header structure */ +#define GRUB_TXT_MLE_UUID "\x5a\xac\x82\x90\x6f\x47\xa7\x74\x0f\x5c\x55\xa2\xcb\x51\xb6\x42" + struct grub_txt_mle_header { grub_uint8_t uuid[16]; diff --git a/include/grub/multiboot2.h b/include/grub/multiboot2.h index 3417a1447..1a3be5f48 100644 --- a/include/grub/multiboot2.h +++ b/include/grub/multiboot2.h @@ -28,6 +28,7 @@ #include <grub/err.h> extern struct grub_relocator *grub_multiboot2_relocator; +extern struct grub_slaunch_params grub_multiboot2_slparams; void grub_multiboot2 (int argc, char *argv[]); void grub_module2 (int argc, char *argv[]); @@ -43,6 +44,8 @@ void grub_multiboot2_set_bootdev (void); void grub_multiboot2_add_elfsyms (grub_size_t num, grub_size_t entsize, unsigned shndx, void *data); +grub_err_t grub_multiboot2_perform_slaunch (grub_uint32_t mbi_target, + grub_uint32_t mbi_size); grub_uint32_t grub_multiboot2_get_mmap_count (void); grub_err_t grub_multiboot2_set_video_mode (void); diff --git a/include/grub/slaunch.h b/include/grub/slaunch.h index f7bea641e..f63b8b379 100644 --- a/include/grub/slaunch.h +++ b/include/grub/slaunch.h @@ -32,6 +32,7 @@ #define GRUB_SL_BOOT_TYPE_INVALID 0 #define GRUB_SL_BOOT_TYPE_LINUX 1 #define GRUB_SL_BOOT_TYPE_EFI 2 +#define GRUB_SL_BOOT_TYPE_MB2 3 #define GRUB_KERNEL_INFO_HEADER "LToP" #define GRUB_KERNEL_INFO_MIN_SIZE_TOTAL 12 diff --git a/include/grub/slr_table.h b/include/grub/slr_table.h index 9dff3d0d5..b9302472b 100644 --- a/include/grub/slr_table.h +++ b/include/grub/slr_table.h @@ -72,6 +72,8 @@ #define GRUB_SLR_ET_CMDLINE 0x0004 #define GRUB_SLR_ET_UEFI_MEMMAP 0x0005 #define GRUB_SLR_ET_RAMDISK 0x0006 +#define GRUB_SLR_ET_MULTIBOOT2_INFO 0x0007 +#define GRUB_SLR_ET_MULTIBOOT2_MODULE 0x0008 #define GRUB_SLR_ET_TXT_OS2MLE 0x0010 #define GRUB_SLR_ET_UNUSED 0xffff -- 2.47.1 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel