From 1f6905c732daf4620effa23857cec39c2075944b Mon Sep 17 00:00:00 2001 From: Ross Philipson Date: Wed, 21 Sep 2022 14:49:18 -0400 Subject: [PATCH 1/3] Rename grub_slaunch_params:sinit_acm_* fields sinit_acm_base -> dce_base sinit_acm_size -> dce_size "sinit_acm" is Intel-specific. DCE stands for Dynamic Configuration Environment and ACM is considered to be a DCE. Signed-off-by: Ross Philipson Signed-off-by: Sergii Dmytruk --- grub-core/loader/i386/linux.c | 4 ++-- grub-core/loader/i386/txt/txt.c | 4 ++-- grub-core/loader/multiboot.c | 4 ++-- include/grub/i386/slaunch.h | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index 3c123b90a..26f183f84 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -723,8 +723,8 @@ grub_linux_boot (void) /* Configure relocator GETSEC[SENTER] call. */ state.eax = GRUB_SMX_LEAF_SENTER; - state.ebx = slparams->sinit_acm_base; - state.ecx = slparams->sinit_acm_size; + state.ebx = slparams->dce_base; + state.ecx = slparams->dce_size; state.edx = 0; } else diff --git a/grub-core/loader/i386/txt/txt.c b/grub-core/loader/i386/txt/txt.c index 8fc103b64..15ba8153f 100644 --- a/grub-core/loader/i386/txt/txt.c +++ b/grub-core/loader/i386/txt/txt.c @@ -956,8 +956,8 @@ grub_txt_boot_prepare (struct grub_slaunch_params *slparams) mle_header->first_valid_page = 0; mle_header->mle_end = slparams->mle_size; - slparams->sinit_acm_base = (grub_uint32_t)(grub_addr_t) sinit_base; - slparams->sinit_acm_size = sinit_base->size * 4; + slparams->dce_base = (grub_uint32_t)(grub_addr_t) sinit_base; + slparams->dce_size = sinit_base->size * 4; /* * Access to locality 4 isn't available to software, skip it. Don't bother diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index 049efd04c..75413c110 100644 --- a/grub-core/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -181,8 +181,8 @@ normal_boot (struct grub_relocator *rel, struct grub_relocator32_state state) /* Configure relocator GETSEC[SENTER] call. */ state.eax = GRUB_SMX_LEAF_SENTER; - state.ebx = slparams->sinit_acm_base; - state.ecx = slparams->sinit_acm_size; + state.ebx = slparams->dce_base; + state.ecx = slparams->dce_size; state.edx = 0; } diff --git a/include/grub/i386/slaunch.h b/include/grub/i386/slaunch.h index ee1777d86..f7160d5fa 100644 --- a/include/grub/i386/slaunch.h +++ b/include/grub/i386/slaunch.h @@ -43,8 +43,8 @@ struct grub_slaunch_params grub_uint32_t mle_header_offset; grub_uint32_t ap_wake_block; grub_uint32_t ap_wake_block_size; - grub_uint32_t sinit_acm_base; - grub_uint32_t sinit_acm_size; + grub_uint32_t dce_base; + grub_uint32_t dce_size; grub_uint64_t tpm_evt_log_base; grub_uint32_t tpm_evt_log_size; }; From 2e90b440803755c87d9c5d145e597116f20e041b Mon Sep 17 00:00:00 2001 From: Ross Philipson Date: Mon, 9 Jan 2023 12:55:42 -0500 Subject: [PATCH 2/3] Initial commit of the Secure Launch Resource Table (SLRT) Provide definitions of structures and basic functions for constructing and parsing of SLRT. Signed-off-by: Ross Philipson Signed-off-by: Sergii Dmytruk --- grub-core/Makefile.am | 3 + include/grub/slr_table.h | 296 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 299 insertions(+) create mode 100644 include/grub/slr_table.h diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 769bf013d..44ba9ac40 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -104,6 +104,7 @@ KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/slaunch.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/slr_table.h endif if COND_i386_xen_pvh @@ -124,6 +125,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/slaunch.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/slr_table.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h @@ -186,6 +188,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/slaunch.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/slr_table.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h diff --git a/include/grub/slr_table.h b/include/grub/slr_table.h new file mode 100644 index 000000000..9e9f90ad6 --- /dev/null +++ b/include/grub/slr_table.h @@ -0,0 +1,296 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2023 Oracle and/or its affiliates. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + * + * Secure Launch Resource Table definitions + */ + +#ifndef GRUB_SLR_TABLE_H +#define GRUB_SLR_TABLE_H 1 + +#define GRUB_UEFI_SLR_TABLE_GUID \ + { 0x877a9b2a, 0x0385, 0x45d1, { 0xa0, 0x34, 0x9d, 0xac, 0x9c, 0x9e, 0x56, 0x5f }} + +/* SLR table header values */ +#define GRUB_SLR_TABLE_MAGIC 0x4452544d +#define GRUB_SLR_TABLE_REVISION 1 + +/* Current revisions for the policy and UEFI config */ +#define GRUB_SLR_POLICY_REVISION 1 +#define GRUB_SLR_UEFI_CONFIG_REVISION 1 + +/* SLR defined architectures */ +#define GRUB_SLR_INTEL_TXT 1 +#define GRUB_SLR_AMD_SKINIT 2 + +/* SLR defined bootloaders */ +#define GRUB_SLR_BOOTLOADER_INVALID 0 +#define GRUB_SLR_BOOTLOADER_GRUB 1 + +/* Log formats */ +#define GRUB_SLR_DRTM_TPM12_LOG 1 +#define GRUB_SLR_DRTM_TPM20_LOG 2 + +/* DRTM Policy Entry Flags */ +#define GRUB_SLR_POLICY_FLAG_MEASURED 0x1 +#define GRUB_SLR_POLICY_IMPLICIT_SIZE 0x2 + +/* Array Lengths */ +#define GRUB_TPM_EVENT_INFO_LENGTH 32 +#define GRUB_TXT_VARIABLE_MTRRS_LENGTH 32 + +/* Tags */ +#define GRUB_SLR_ENTRY_INVALID 0x0000 +#define GRUB_SLR_ENTRY_DL_INFO 0x0001 +#define GRUB_SLR_ENTRY_LOG_INFO 0x0002 +#define GRUB_SLR_ENTRY_DRTM_POLICY 0x0003 +#define GRUB_SLR_ENTRY_INTEL_INFO 0x0004 +#define GRUB_SLR_ENTRY_AMD_INFO 0x0005 +#define GRUB_SLR_ENTRY_ARM_INFO 0x0006 +#define GRUB_SLR_ENTRY_UEFI_INFO 0x0007 +#define GRUB_SLR_ENTRY_UEFI_CONFIG 0x0008 +#define GRUB_SLR_ENTRY_END 0xffff + +/* Entity Types */ +#define GRUB_SLR_ET_UNSPECIFIED 0x0000 +#define GRUB_SLR_ET_SLRT 0x0001 +#define GRUB_SLR_ET_BOOT_PARAMS 0x0002 +#define GRUB_SLR_ET_SETUP_DATA 0x0003 +#define GRUB_SLR_ET_CMDLINE 0x0004 +#define GRUB_SLR_ET_UEFI_MEMMAP 0x0005 +#define GRUB_SLR_ET_RAMDISK 0x0006 +#define GRUB_SLR_ET_TXT_OS2MLE 0x0010 +#define GRUB_SLR_ET_UNUSED 0xffff + +/* + * Primary SLR Table Header + */ +struct grub_slr_table +{ + grub_uint32_t magic; + grub_uint16_t revision; + grub_uint16_t architecture; + grub_uint32_t size; + grub_uint32_t max_size; + /* entries[] */ +} GRUB_PACKED; + +/* + * Common SLRT Table Header + */ +struct grub_slr_entry_hdr +{ + grub_uint16_t tag; + grub_uint16_t size; +} GRUB_PACKED; + +/* + * Boot loader context + */ +struct grub_slr_bl_context +{ + grub_uint16_t bootloader; + grub_uint16_t reserved; + grub_uint64_t context; +} GRUB_PACKED; + +/* + * DRTM Dynamic Launch Configuration + */ +struct grub_slr_entry_dl_info +{ + struct grub_slr_entry_hdr hdr; + struct grub_slr_bl_context bl_context; + grub_uint64_t dl_handler; + grub_uint64_t dce_base; + grub_uint32_t dce_size; + grub_uint64_t dlme_entry; +} GRUB_PACKED; + +/* + * TPM Log Information + */ +struct grub_slr_entry_log_info +{ + struct grub_slr_entry_hdr hdr; + grub_uint16_t format; + grub_uint16_t reserved; + grub_uint64_t addr; + grub_uint32_t size; +} GRUB_PACKED; + +/* + * DRTM Measurement Policy + */ +struct grub_slr_entry_policy +{ + struct grub_slr_entry_hdr hdr; + grub_uint16_t revision; + grub_uint16_t nr_entries; + /* policy_entries[] */ +} GRUB_PACKED; + +/* + * DRTM Measurement Entry + */ +struct grub_slr_policy_entry +{ + grub_uint16_t pcr; + grub_uint16_t entity_type; + grub_uint16_t flags; + grub_uint16_t reserved; + grub_uint64_t entity; + grub_uint64_t size; + char evt_info[GRUB_TPM_EVENT_INFO_LENGTH]; +} GRUB_PACKED; + +/* + * Secure Launch defined MTRR saving structures + */ +struct grub_slr_txt_mtrr_pair +{ + grub_uint64_t mtrr_physbase; + grub_uint64_t mtrr_physmask; +} GRUB_PACKED; + +struct grub_slr_txt_mtrr_state +{ + grub_uint64_t default_mem_type; + grub_uint64_t mtrr_vcnt; + struct grub_slr_txt_mtrr_pair mtrr_pair[GRUB_TXT_VARIABLE_MTRRS_LENGTH]; +} GRUB_PACKED; + +/* + * Intel TXT Info table + */ +struct grub_slr_entry_intel_info +{ + struct grub_slr_entry_hdr hdr; + grub_uint64_t saved_misc_enable_msr; + struct grub_slr_txt_mtrr_state saved_bsp_mtrrs; +} GRUB_PACKED; + +/* + * AMD SKINIT Info table + */ +struct grub_slr_entry_amd_info +{ + struct grub_slr_entry_hdr hdr; +} GRUB_PACKED; + +/* + * ARM DRTM Info table + */ +struct grub_slr_entry_arm_info +{ + struct grub_slr_entry_hdr hdr; +} GRUB_PACKED; + +struct grub_slr_entry_uefi_config +{ + struct grub_slr_entry_hdr hdr; + grub_uint16_t revision; + grub_uint16_t nr_entries; + /* uefi_cfg_entries[] */ +} GRUB_PACKED; + +struct grub_slr_uefi_cfg_entry +{ + grub_uint16_t pcr; + grub_uint16_t reserved; + grub_uint64_t cfg; /* address or value */ + grub_uint32_t size; + char evt_info[GRUB_TPM_EVENT_INFO_LENGTH]; +} GRUB_PACKED; + +static inline void * +grub_slr_end_of_entries (struct grub_slr_table *table) +{ + return (grub_uint8_t *) table + table->size; +} + +static inline struct grub_slr_entry_hdr * +grub_slr_next_entry (struct grub_slr_table *table, + struct grub_slr_entry_hdr *curr) +{ + struct grub_slr_entry_hdr *next = (struct grub_slr_entry_hdr *) + ((grub_uint8_t *) curr + curr->size); + + if ((void *)next >= grub_slr_end_of_entries (table)) + return NULL; + if (next->tag == GRUB_SLR_ENTRY_END) + return NULL; + + return next; +} + +static inline struct grub_slr_entry_hdr * +grub_slr_next_entry_by_tag (struct grub_slr_table *table, + struct grub_slr_entry_hdr *entry, + grub_uint16_t tag) +{ + if (!entry) /* Start from the beginning */ + entry = (struct grub_slr_entry_hdr *)((grub_uint8_t *) table + sizeof(*table)); + + for ( ; ; ) + { + if (entry->tag == tag) + return entry; + + entry = grub_slr_next_entry (table, entry); + if (!entry) + return NULL; + } + + return NULL; +} + +static inline int +grub_slr_add_entry (struct grub_slr_table *table, + struct grub_slr_entry_hdr *entry) +{ + struct grub_slr_entry_hdr *end; + + if ((table->size + entry->size) > table->max_size) + return -1; + + grub_memcpy ((grub_uint8_t *) table + table->size - sizeof(*end), entry, entry->size); + table->size += entry->size; + + end = (struct grub_slr_entry_hdr *)((grub_uint8_t *) table + table->size - sizeof(*end)); + end->tag = GRUB_SLR_ENTRY_END; + end->size = sizeof(*end); + + return 0; +} + +static inline void +grub_slr_init_table(struct grub_slr_table *slrt, grub_uint16_t architecture, + grub_uint32_t max_size) +{ + struct grub_slr_entry_hdr *end; + + slrt->magic = GRUB_SLR_TABLE_MAGIC; + slrt->revision = GRUB_SLR_TABLE_REVISION; + slrt->architecture = architecture; + slrt->size = sizeof(*slrt) + sizeof(*end); + slrt->max_size = max_size; + end = (struct grub_slr_entry_hdr *)((grub_uint8_t *) slrt + sizeof(*slrt)); + end->tag = GRUB_SLR_ENTRY_END; + end->size = sizeof(*end); +} + +#endif /* GRUB_SLR_TABLE_H */ From d77df306d145844fdbbfa93d27f1df78f9c4c9b7 Mon Sep 17 00:00:00 2001 From: Ross Philipson Date: Fri, 13 Jan 2023 15:11:26 -0500 Subject: [PATCH 3/3] Switch to using Secure Launch Resource Table interface Signed-off-by: Ross Philipson Signed-off-by: Sergii Dmytruk --- grub-core/loader/i386/linux.c | 106 +++++++++++++++++++++++++++-- grub-core/loader/i386/slaunch.c | 87 +++++++++++++++++++++++ grub-core/loader/i386/txt/txt.c | 86 +++++++++++++++-------- grub-core/loader/multiboot.c | 2 + grub-core/loader/multiboot_elfxx.c | 1 + include/grub/i386/slaunch.h | 15 +++- include/grub/i386/txt.h | 25 ++----- 7 files changed, 269 insertions(+), 53 deletions(-) diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index 26f183f84..a585c73f9 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -39,6 +39,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -69,6 +70,18 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define KERNEL_INFO_HEADER "LToP" #define KERNEL_INFO_MIN_SIZE_TOTAL 12 +struct linux_params_efi_info +{ + grub_uint32_t efi_signature; + grub_uint32_t efi_system_table; + grub_uint32_t efi_mem_desc_size; + grub_uint32_t efi_mem_desc_version; + grub_uint32_t efi_mmap; + grub_uint32_t efi_mmap_size; + grub_uint32_t efi_system_table_hi; + grub_uint32_t efi_mmap_hi; +}; + static grub_dl_t my_mod; static grub_size_t linux_mem_size; @@ -248,16 +261,35 @@ allocate_pages (grub_size_t prot_size, grub_size_t *align, slparams->mle_start = prot_mode_target; slparams->mle_size = prot_size; + slparams->mle_mem = prot_mode_mem; grub_dprintf ("linux", "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); - if (grub_relocator_alloc_chunk_align (relocator, &ch, 0x1000000, - 0xffffffff - GRUB_SLAUNCH_TPM_EVT_LOG_SIZE, - GRUB_SLAUNCH_TPM_EVT_LOG_SIZE, GRUB_PAGE_SIZE, - GRUB_RELOCATOR_PREFERENCE_NONE, 1)) - goto fail; + err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x1000000, + 0xffffffff - GRUB_PAGE_SIZE, + GRUB_PAGE_SIZE, GRUB_PAGE_SIZE, + GRUB_RELOCATOR_PREFERENCE_NONE, 1); + if (err) + goto fail; + + slparams->slr_table_base = get_physical_target_address (ch); + slparams->slr_table_size = GRUB_PAGE_SIZE; + slparams->slr_table_mem = get_virtual_current_address (ch); + + grub_memset (slparams->slr_table_mem, 0, slparams->slr_table_size); + + grub_dprintf ("linux", "slr_table_base = %lx, slr_table_size = %x\n", + (unsigned long) slparams->slr_table_base, + (unsigned) slparams->slr_table_size); + + err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x1000000, + 0xffffffff - GRUB_SLAUNCH_TPM_EVT_LOG_SIZE, + GRUB_SLAUNCH_TPM_EVT_LOG_SIZE, GRUB_PAGE_SIZE, + GRUB_RELOCATOR_PREFERENCE_NONE, 1); + if (err) + goto fail; slparams->tpm_evt_log_base = get_physical_target_address (ch); slparams->tpm_evt_log_size = GRUB_SLAUNCH_TPM_EVT_LOG_SIZE; @@ -468,6 +500,60 @@ grub_linux_boot_mmap_fill (grub_uint64_t addr, grub_uint64_t size, return 0; } +static void +grub_linux_setup_slr_table (struct grub_slaunch_params *slparams) +{ + struct linux_kernel_params *boot_params = (void *) (grub_addr_t) slparams->boot_params_addr; + struct linux_params_efi_info *efi_info; + + /* A bit of work to extract the v2.08 EFI info from the linux params */ + efi_info = (void *)((grub_uint8_t *)&boot_params->v0208 + 2*sizeof(grub_uint32_t)); + + grub_slaunch_add_slrt_policy_entry (18, + GRUB_SLR_ET_BOOT_PARAMS, + /*flags=*/0, + (grub_addr_t) boot_params, + GRUB_PAGE_SIZE, + "Measured boot parameters"); + + if (boot_params->setup_data) + grub_slaunch_add_slrt_policy_entry (18, + GRUB_SLR_ET_SETUP_DATA, + GRUB_SLR_POLICY_IMPLICIT_SIZE, + boot_params->setup_data, + /*size=*/0, + "Measured Kernel setup_data"); + + /* TODO the cmdline ptr can have hi bits but for now assume always < 4G */ + grub_slaunch_add_slrt_policy_entry (18, + GRUB_SLR_ET_CMDLINE, + /*flags=*/0, + boot_params->cmd_line_ptr, + boot_params->cmdline_size, + "Measured Kernel command line"); + + if (!grub_memcmp(&efi_info->efi_signature, "EL64", sizeof(grub_uint32_t))) + { + grub_uint64_t mmap_addr = + ((grub_uint64_t) efi_info->efi_mmap_hi << 32) | efi_info->efi_mmap; + grub_slaunch_add_slrt_policy_entry (18, + GRUB_SLR_ET_UEFI_MEMMAP, + /*flags=*/0, + mmap_addr, + efi_info->efi_mmap_size, + "Measured EFI memory map"); + } + + if (boot_params->ramdisk_image) + /* TODO the initrd image and size can have hi bits but for now assume always < 4G */ + grub_slaunch_add_slrt_policy_entry (17, + GRUB_SLR_ET_RAMDISK, + /*flags=*/0, + boot_params->ramdisk_image, + boot_params->ramdisk_size, + "Measured Kernel initrd"); +} + static grub_err_t grub_linux_boot (void) { @@ -645,6 +731,9 @@ grub_linux_boot (void) grub_dprintf ("linux", "ap_wake_block = %lx, ap_wake_block_size = %lx\n", (unsigned long) slparams->ap_wake_block, (unsigned long) ap_wake_block_size); + + /* Grab the real mode target address, this is the boot params page. */ + slparams->boot_params_addr = ctx.real_mode_target; } grub_dprintf ("linux", "real_mode_mem = %p\n", @@ -673,6 +762,8 @@ grub_linux_boot (void) ctx.params->secure_boot = grub_efi_get_secureboot (); + grub_dprintf ("linux", "EFI exit boot services\n"); + err = grub_efi_finish_boot_services (&efi_mmap_size, efi_mmap_buf, NULL, &efi_desc_size, &efi_desc_version); if (err) @@ -714,13 +805,14 @@ grub_linux_boot (void) if (state.edi == SLP_INTEL_TXT) { - slparams->boot_params_addr = (grub_uint32_t) ctx.real_mode_target; - err = grub_txt_boot_prepare (slparams); if (err != GRUB_ERR_NONE) return err; + grub_linux_setup_slr_table (slparams); + grub_slaunch_finish_slr_table (); + /* Configure relocator GETSEC[SENTER] call. */ state.eax = GRUB_SMX_LEAF_SENTER; state.ebx = slparams->dce_base; diff --git a/grub-core/loader/i386/slaunch.c b/grub-core/loader/i386/slaunch.c index 093eddef8..de22d2b80 100644 --- a/grub-core/loader/i386/slaunch.c +++ b/grub-core/loader/i386/slaunch.c @@ -23,11 +23,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include GRUB_MOD_LICENSE ("GPLv3+"); @@ -38,6 +40,13 @@ static void *slaunch_module = NULL; static struct grub_slaunch_params slparams; +/* Area to collect and build SLR Table information. */ +static struct grub_slr_entry_dl_info slr_dl_info_staging; +static struct grub_slr_entry_log_info slr_log_info_staging; +static grub_uint8_t slr_policy_buf[GRUB_PAGE_SIZE]; +static struct grub_slr_entry_policy *slr_policy_staging = + (struct grub_slr_entry_policy *)slr_policy_buf; + grub_uint32_t grub_slaunch_platform_type (void) { @@ -56,6 +65,84 @@ grub_slaunch_params (void) return &slparams; } +void +grub_slaunch_init_slrt_storage (int arch) +{ + struct grub_txt_mle_header *mle_header = + (void *) ((grub_uint8_t *) slparams.mle_mem + slparams.mle_header_offset); + + /* Setup the generic bits of the SLRT. */ + grub_slr_init_table(slparams.slr_table_mem, arch, slparams.slr_table_size); + + /* Setup DCE and DLME information. */ + slr_dl_info_staging.hdr.tag = GRUB_SLR_ENTRY_DL_INFO; + slr_dl_info_staging.hdr.size = sizeof(struct grub_slr_entry_dl_info); + slr_dl_info_staging.dce_base = slparams.dce_base; + slr_dl_info_staging.dce_size = slparams.dce_size; + slr_dl_info_staging.dlme_entry = mle_header->entry_point; + + slr_log_info_staging.hdr.tag = GRUB_SLR_ENTRY_LOG_INFO; + slr_log_info_staging.hdr.size = sizeof(struct grub_slr_entry_log_info); + slr_log_info_staging.addr = slparams.tpm_evt_log_base; + slr_log_info_staging.size = slparams.tpm_evt_log_size; + slr_log_info_staging.format = + (grub_get_tpm_ver () == GRUB_TPM_20) ? + GRUB_SLR_DRTM_TPM20_LOG : GRUB_SLR_DRTM_TPM12_LOG; + + slr_policy_staging->hdr.tag = GRUB_SLR_ENTRY_DRTM_POLICY; + slr_policy_staging->hdr.size = sizeof(struct grub_slr_entry_policy); + slr_policy_staging->revision = GRUB_SLR_TABLE_REVISION; + slr_policy_staging->nr_entries = 0; + + /* The SLR table should be measured too, at least parts of it. */ + grub_slaunch_add_slrt_policy_entry (18, + GRUB_SLR_ET_SLRT, + GRUB_SLR_POLICY_IMPLICIT_SIZE, + slparams.slr_table_base, + /*size=*/0, + "Measured SLR Table"); +} + +void +grub_slaunch_add_slrt_policy_entry (grub_uint16_t pcr, + grub_uint16_t entity_type, + grub_uint16_t flags, + grub_uint64_t entity, + grub_uint64_t size, + const char *evt_info) +{ + struct grub_slr_policy_entry *entry = + (void *)((grub_uint8_t *)slr_policy_staging + + sizeof(struct grub_slr_entry_policy) + + slr_policy_staging->nr_entries*sizeof(*entry)); + + if (slr_policy_staging->hdr.size + sizeof(*entry) > sizeof(slr_policy_buf)) + grub_fatal("Not enough space for adding policy entry: %s! The buffer is full.", + evt_info); + + entry->pcr = pcr; + entry->entity_type = entity_type; + entry->flags = flags; + entry->entity = entity; + entry->size = size; + + grub_strncpy(entry->evt_info, evt_info, sizeof(entry->evt_info) - 1); + entry->evt_info[sizeof(entry->evt_info) - 1] = '\0'; + + slr_policy_staging->hdr.size += sizeof(*entry); + ++slr_policy_staging->nr_entries; +} + +void +grub_slaunch_finish_slr_table (void) +{ + struct grub_slr_table *slr_table = slparams.slr_table_mem; + + grub_slr_add_entry (slr_table, &slr_dl_info_staging.hdr); + grub_slr_add_entry (slr_table, &slr_log_info_staging.hdr); + grub_slr_add_entry (slr_table, &slr_policy_staging->hdr); +} + static grub_err_t grub_cmd_slaunch (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), diff --git a/grub-core/loader/i386/txt/txt.c b/grub-core/loader/i386/txt/txt.c index 15ba8153f..9c5424003 100644 --- a/grub-core/loader/i386/txt/txt.c +++ b/grub-core/loader/i386/txt/txt.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,8 @@ #define OS_SINIT_DATA_MIN_VER OS_SINIT_DATA_TPM_12_VER +static struct grub_slr_entry_intel_info slr_intel_info_staging = {0}; + static grub_err_t enable_smx_mode (void) { @@ -244,33 +247,39 @@ grub_txt_prepare_cpu (void) } static void -save_mtrrs (struct grub_txt_os_mle_data *os_mle_data) +save_mtrrs (struct grub_slr_txt_mtrr_state *saved_bsp_mtrrs) { grub_uint64_t i; - os_mle_data->saved_bsp_mtrrs.default_mem_type = + saved_bsp_mtrrs->default_mem_type = grub_rdmsr (GRUB_MSR_X86_MTRR_DEF_TYPE); - os_mle_data->saved_bsp_mtrrs.mtrr_vcnt = + saved_bsp_mtrrs->mtrr_vcnt = grub_rdmsr (GRUB_MSR_X86_MTRRCAP) & GRUB_MSR_X86_VCNT_MASK; - if (os_mle_data->saved_bsp_mtrrs.mtrr_vcnt > GRUB_SL_MAX_VARIABLE_MTRRS) + if (saved_bsp_mtrrs->mtrr_vcnt > GRUB_TXT_VARIABLE_MTRRS_LENGTH) { /* Print warning but continue saving what we can... */ grub_printf ("WARNING: Actual number of variable MTRRs (%" PRIuGRUB_UINT64_T ") > GRUB_SL_MAX_VARIABLE_MTRRS (%d)\n", - os_mle_data->saved_bsp_mtrrs.mtrr_vcnt, - GRUB_SL_MAX_VARIABLE_MTRRS); - os_mle_data->saved_bsp_mtrrs.mtrr_vcnt = GRUB_SL_MAX_VARIABLE_MTRRS; + saved_bsp_mtrrs->mtrr_vcnt, + GRUB_TXT_VARIABLE_MTRRS_LENGTH); + saved_bsp_mtrrs->mtrr_vcnt = GRUB_TXT_VARIABLE_MTRRS_LENGTH; } - for (i = 0; i < os_mle_data->saved_bsp_mtrrs.mtrr_vcnt; ++i) + for (i = 0; i < saved_bsp_mtrrs->mtrr_vcnt; ++i) { - os_mle_data->saved_bsp_mtrrs.mtrr_pair[i].mtrr_physmask = + saved_bsp_mtrrs->mtrr_pair[i].mtrr_physmask = grub_rdmsr (GRUB_MSR_X86_MTRR_PHYSMASK0 + i * 2); - os_mle_data->saved_bsp_mtrrs.mtrr_pair[i].mtrr_physbase = + saved_bsp_mtrrs->mtrr_pair[i].mtrr_physbase = grub_rdmsr (GRUB_MSR_X86_MTRR_PHYSBASE0 + i * 2); } + /* Zero unused array items. */ + for ( ; i < GRUB_TXT_VARIABLE_MTRRS_LENGTH; ++i) + { + saved_bsp_mtrrs->mtrr_pair[i].mtrr_physmask = 0; + saved_bsp_mtrrs->mtrr_pair[i].mtrr_physbase = 0; + } } static void @@ -535,6 +544,20 @@ grub_txt_init_tpm_event_log (void *buf, grub_size_t size) elog->next_event_offset = sizeof(*elog); } +static void +setup_txt_slrt_entry (struct grub_slaunch_params *slparams, + struct grub_txt_os_mle_data *os_mle_data) +{ + struct grub_slr_table *slr_table = slparams->slr_table_mem; + struct grub_slr_entry_hdr *txt_info; + + grub_slr_add_entry (slr_table, &slr_intel_info_staging.hdr); + + txt_info = grub_slr_next_entry_by_tag (slr_table, NULL, GRUB_SLR_ENTRY_INTEL_INFO); + os_mle_data->txt_info = (grub_addr_t) slparams->slr_table_base + + ((grub_addr_t) txt_info - (grub_addr_t) slparams->slr_table_mem); +} + static grub_err_t init_txt_heap (struct grub_slaunch_params *slparams, struct grub_txt_acm_header *sinit) { @@ -567,16 +590,20 @@ init_txt_heap (struct grub_slaunch_params *slparams, struct grub_txt_acm_header os_mle_data->version = GRUB_SL_OS_MLE_STRUCT_VERSION; os_mle_data->boot_params_addr = slparams->boot_params_addr; - os_mle_data->saved_misc_enable_msr = grub_rdmsr (GRUB_MSR_X86_MISC_ENABLE); + os_mle_data->slrt = slparams->slr_table_base; os_mle_data->ap_wake_block = slparams->ap_wake_block; os_mle_data->ap_wake_block_size = slparams->ap_wake_block_size; - os_mle_data->evtlog_addr = slparams->tpm_evt_log_base; - os_mle_data->evtlog_size = slparams->tpm_evt_log_size; + /* Setup the TXT specific SLR information */ + slr_intel_info_staging.hdr.tag = GRUB_SLR_ENTRY_INTEL_INFO; + slr_intel_info_staging.hdr.size = sizeof(struct grub_slr_entry_intel_info); + slr_intel_info_staging.saved_misc_enable_msr = + grub_rdmsr (GRUB_MSR_X86_MISC_ENABLE); + /* Save the BSPs MTRR state so post launch can restore it. */ grub_dprintf ("slaunch", "Saving MTRRs to OS MLE data\n"); - save_mtrrs (os_mle_data); + save_mtrrs (&slr_intel_info_staging.saved_bsp_mtrrs); /* OS/loader to SINIT data. */ grub_dprintf ("slaunch", "Get supported OS SINIT data version\n"); @@ -934,9 +961,10 @@ grub_err_t grub_txt_boot_prepare (struct grub_slaunch_params *slparams) { grub_err_t err; + grub_uint8_t *txt_heap; + struct grub_txt_os_mle_data *os_mle_data; struct grub_txt_mle_header *mle_header; struct grub_txt_acm_header *sinit_base; - int i; sinit_base = grub_txt_sinit_select (grub_slaunch_module ()); @@ -952,24 +980,28 @@ grub_txt_boot_prepare (struct grub_slaunch_params *slparams) grub_dprintf ("slaunch", "TXT heap successfully prepared\n"); /* Update the MLE header. */ - mle_header = (struct grub_txt_mle_header *)(grub_addr_t) (slparams->mle_start + slparams->mle_header_offset); + mle_header = + (struct grub_txt_mle_header *) ((grub_uint8_t *) slparams->mle_mem + slparams->mle_header_offset); mle_header->first_valid_page = 0; mle_header->mle_end = slparams->mle_size; slparams->dce_base = (grub_uint32_t)(grub_addr_t) sinit_base; slparams->dce_size = sinit_base->size * 4; - /* - * Access to locality 4 isn't available to software, skip it. Don't bother - * checking TPM status, we have no tools for recovering from bad state better - * than command abort, which is part of locality relinquish. Write performed - * by the following function is no-op if locality is neither active nor - * requested. - */ - for (i = 0; i < 4; ++i) - grub_tpm_relinquish_locality (i); - - grub_dprintf ("slaunch", "TPM localities relinquished\n"); + /* Setup of SLR table. */ + grub_slaunch_init_slrt_storage (GRUB_SLR_INTEL_TXT); + txt_heap = grub_txt_get_heap (); + os_mle_data = grub_txt_os_mle_data_start (txt_heap); + setup_txt_slrt_entry (slparams, os_mle_data); + grub_slaunch_add_slrt_policy_entry (18, + GRUB_SLR_ET_TXT_OS2MLE, + /*flags=*/0, + (grub_addr_t) os_mle_data, + sizeof(*os_mle_data), + "Measured TXT OS-MLE data"); + + grub_tpm_relinquish_locality (0); + grub_dprintf ("slaunch", "Relinquished TPM locality 0\n"); err = set_mtrrs_for_acmod (sinit_base); if (err) diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index 75413c110..47fa6faa6 100644 --- a/grub-core/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -179,6 +179,8 @@ normal_boot (struct grub_relocator *rel, struct grub_relocator32_state state) return; } + grub_slaunch_finish_slr_table (); + /* Configure relocator GETSEC[SENTER] call. */ state.eax = GRUB_SMX_LEAF_SENTER; state.ebx = slparams->dce_base; diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c index 47ba4c3f2..a92082533 100644 --- a/grub-core/loader/multiboot_elfxx.c +++ b/grub-core/loader/multiboot_elfxx.c @@ -164,6 +164,7 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld) return grub_error (GRUB_ERR_BAD_OS, "Only multiboot2 supported for slaunch"); #else slparams->mle_start = mld->load_base_addr; + slparams->mle_mem = source; err = grub_relocator_alloc_chunk_align_safe (GRUB_MULTIBOOT (relocator), &ch, GRUB_MEMORY_MACHINE_UPPER_START, diff --git a/include/grub/i386/slaunch.h b/include/grub/i386/slaunch.h index f7160d5fa..6df6fa0da 100644 --- a/include/grub/i386/slaunch.h +++ b/include/grub/i386/slaunch.h @@ -35,11 +35,15 @@ struct grub_slaunch_params { grub_uint32_t boot_params_addr; + grub_uint64_t slr_table_base; + grub_uint32_t slr_table_size; + void *slr_table_mem; grub_uint32_t mle_start; grub_uint32_t mle_size; - void *mle_ptab_mem; + void *mle_mem; grub_uint64_t mle_ptab_target; grub_uint32_t mle_ptab_size; + void *mle_ptab_mem; grub_uint32_t mle_header_offset; grub_uint32_t ap_wake_block; grub_uint32_t ap_wake_block_size; @@ -53,6 +57,15 @@ extern grub_uint32_t grub_slaunch_platform_type (void); extern void *grub_slaunch_module (void); extern struct grub_slaunch_params *grub_slaunch_params (void); +extern void grub_slaunch_init_slrt_storage (int arch); +extern void grub_slaunch_add_slrt_policy_entry (grub_uint16_t pcr, + grub_uint16_t entity_type, + grub_uint16_t flags, + grub_uint64_t entity, + grub_uint64_t size, + const char *evt_info); +extern void grub_slaunch_finish_slr_table (void); + #endif /* ASM_FILE */ #endif /* GRUB_I386_SLAUNCH_H */ diff --git a/include/grub/i386/txt.h b/include/grub/i386/txt.h index 53355d511..dec4a47e2 100644 --- a/include/grub/i386/txt.h +++ b/include/grub/i386/txt.h @@ -353,32 +353,16 @@ struct grub_txt_bios_data /* GRUB SLAUNCH specific definitions OS-MLE data */ #define GRUB_SL_BOOTPARAMS_OFFSET 0x12c #define GRUB_SL_MAX_EVENT_LOG_SIZE (5*4*1024) /* 4k*5 */ -#define GRUB_SL_MAX_VARIABLE_MTRRS 32 #define GRUB_SL_OS_MLE_STRUCT_VERSION 1 -struct grub_slaunch_mtrr_pair -{ - grub_uint64_t mtrr_physbase; - grub_uint64_t mtrr_physmask; -} GRUB_PACKED; - -struct grub_slaunch_mtrr_state -{ - grub_uint64_t default_mem_type; - grub_uint64_t mtrr_vcnt; - struct grub_slaunch_mtrr_pair mtrr_pair[GRUB_SL_MAX_VARIABLE_MTRRS]; -} GRUB_PACKED; - struct grub_txt_os_mle_data { grub_uint32_t version; grub_uint32_t boot_params_addr; - grub_uint64_t saved_misc_enable_msr; - struct grub_slaunch_mtrr_state saved_bsp_mtrrs; + grub_uint32_t slrt; + grub_uint32_t txt_info; grub_uint32_t ap_wake_block; grub_uint32_t ap_wake_block_size; - grub_uint64_t evtlog_addr; - grub_uint32_t evtlog_size; grub_uint8_t mle_scratch[64]; } GRUB_PACKED; @@ -730,6 +714,11 @@ extern void grub_txt_setup_mle_ptab (struct grub_slaunch_params *slparams); extern grub_err_t grub_txt_init (void); extern void grub_txt_shutdown (void); extern void grub_txt_state_show (void); +/* + * This function doesn't finish building of SLRT. It's caller's responsibility + * to call grub_slaunch_finish_slr_table() after possibly making some + * grub_slr_add_entry() and grub_slaunch_add_slrt_policy_entry() calls. + */ extern grub_err_t grub_txt_boot_prepare (struct grub_slaunch_params *slparams); #endif