Skip to content

Commit

Permalink
Switch to using Secure Launch Resource Table interface
Browse files Browse the repository at this point in the history
Signed-off-by: Ross Philipson <[email protected]>
Signed-off-by: Sergii Dmytruk <[email protected]>
  • Loading branch information
rossphilipson authored and SergiiDmytruk committed Oct 9, 2023
1 parent a46618c commit bcc3961
Show file tree
Hide file tree
Showing 4 changed files with 237 additions and 33 deletions.
21 changes: 21 additions & 0 deletions grub-core/loader/i386/linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,22 @@ allocate_pages (grub_size_t prot_size, grub_size_t *align,
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_PAGE_SIZE,
GRUB_PAGE_SIZE, GRUB_PAGE_SIZE,
GRUB_RELOCATOR_PREFERENCE_NONE, 1))
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);

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,
Expand Down Expand Up @@ -645,6 +661,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_base = ctx.real_mode_target;
}

grub_dprintf ("linux", "real_mode_mem = %p\n",
Expand Down Expand Up @@ -673,6 +692,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)
Expand Down
231 changes: 206 additions & 25 deletions grub-core/loader/i386/txt/txt.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
#include <grub/types.h>
#include <grub/dl.h>
#include <grub/acpi.h>
#include <grub/slr_table.h>
#include <grub/cpu/relocator.h>
#include <grub/i386/cpuid.h>
#include <grub/i386/msr.h>
Expand All @@ -74,6 +75,30 @@

#define OS_SINIT_DATA_MIN_VER OS_SINIT_DATA_TPM_12_VER

#define SLR_CURRENT_REVISION 1
#define SLR_MAX_POLICY_ENTRIES 7

struct grub_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;
};

/* Area to collect and build SLR Table information */
static grub_uint8_t slr_policy_buf[GRUB_PAGE_SIZE] = {0};
static struct grub_slr_entry_dl_info slr_dl_info_staging = {0};
static struct grub_slr_entry_log_info slr_log_info_staging = {0};
static struct grub_slr_entry_policy *slr_policy_staging =
(struct grub_slr_entry_policy *)slr_policy_buf;
static struct grub_slr_entry_intel_info slr_intel_info_staging = {0};
struct grub_slr_entry_hdr slr_end_staging;

static grub_err_t
enable_smx_mode (void)
{
Expand Down Expand Up @@ -244,31 +269,31 @@ grub_txt_prepare_cpu (void)
}

static void
save_mtrrs (struct grub_txt_os_mle_data *os_mle_data)
save_mtrrs (struct grub_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);
}
}
Expand Down Expand Up @@ -535,6 +560,138 @@ grub_txt_init_tpm_event_log (void *buf, grub_size_t size)
elog->next_event_offset = sizeof(*elog);
}

static void
init_slrt_storage (void)
{
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_log_info_staging.hdr.tag = GRUB_SLR_ENTRY_LOG_INFO;
slr_log_info_staging.hdr.size = sizeof(struct grub_slr_entry_log_info);

slr_policy_staging->hdr.tag = GRUB_SLR_ENTRY_ENTRY_POLICY;
slr_policy_staging->hdr.size = sizeof(struct grub_slr_entry_policy) +
SLR_MAX_POLICY_ENTRIES*sizeof(struct grub_slr_policy_entry);
slr_policy_staging->revision = SLR_CURRENT_REVISION;
slr_policy_staging->nr_entries = SLR_MAX_POLICY_ENTRIES;

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_end_staging.tag = GRUB_SLR_ENTRY_END;
slr_end_staging.size = sizeof(struct grub_slr_entry_hdr);
}

static void
setup_slrt_policy (struct grub_slaunch_params *slparams,
struct grub_txt_os_mle_data *os_mle_data)
{
struct grub_slr_policy_entry *entry =
(struct grub_slr_policy_entry *)((grub_uint8_t *)slr_policy_staging +
sizeof(struct grub_slr_entry_policy));
struct linux_kernel_params *boot_params = (void *) (grub_addr_t) slparams->boot_params_addr;
struct grub_efi_info *efi_info;

/* A bit of work to extract the v2.08 EFI info from the linux params */
efi_info = (struct grub_efi_info *)((grub_uint8_t *)&(boot_params->v0208)
+ 2*sizeof(grub_uint32_t));

/* the SLR table should be measured too, at least parts of it */
entry->pcr = 18;
entry->entity_type = GRUB_SLR_ET_SLRT;
entry->entity = slparams->slr_table_base;
entry->flags |= GRUB_SLR_POLICY_IMPLICIT_SIZE;
grub_strcpy (&entry->evt_info[0], "Measured SLR Table");
entry++;

/* boot params have everything needed to setup policy except OS2MLE data */
entry->pcr = 18;
entry->entity_type = GRUB_SLR_ET_BOOT_PARAMS;
entry->entity = (grub_uint64_t) (grub_addr_t) boot_params;
entry->size = GRUB_PAGE_SIZE;
grub_strcpy (&entry->evt_info[0], "Measured boot parameters");
entry++;

if (boot_params->setup_data)
{
entry->pcr = 18;
entry->entity_type = GRUB_SLR_ET_SETUP_DATA;
entry->entity = boot_params->setup_data;
entry->flags |= GRUB_SLR_POLICY_IMPLICIT_SIZE;
grub_strcpy (&entry->evt_info[0], "Measured Kernel setup_data");
}
else
entry->entity_type = GRUB_SLR_ET_UNUSED;
entry++;

entry->pcr = 18;
entry->entity_type = GRUB_SLR_ET_CMDLINE;
/* TODO the cmdline ptr can have hi bits but for now assume always < 32G */
entry->entity = boot_params->cmd_line_ptr;
entry->size = boot_params->cmdline_size;
grub_strcpy (&entry->evt_info[0], "Measured Kernel command line");
entry++;

if (!grub_memcmp(&efi_info->efi_signature, "EL64", sizeof(grub_uint32_t)))
{
grub_uint64_t mmap_hi;

entry->pcr = 18;
entry->entity_type = GRUB_SLR_ET_UEFI_MEMMAP;
entry->entity = efi_info->efi_mmap;
mmap_hi = efi_info->efi_mmap_hi;
entry->entity |= mmap_hi << 32;
entry->size = efi_info->efi_mmap_size;
grub_strcpy (&entry->evt_info[0], "Measured EFI memory map");
}
else
entry->entity_type = GRUB_SLR_ET_UNUSED;
entry++;

if (boot_params->ramdisk_image)
{
entry->pcr = 17;
entry->entity_type = GRUB_SLR_ET_RAMDISK;
/* TODO the initrd image and size can have hi bits but for now assume always < 32G */
entry->entity = boot_params->ramdisk_image;
entry->size = boot_params->ramdisk_size;
grub_strcpy (&entry->evt_info[0], "Measured Kernel initrd");
}
else
entry->entity_type = GRUB_SLR_ET_UNUSED;
entry++;

entry->pcr = 18;
entry->entity_type = GRUB_SLR_ET_TXT_OS2MLE;
entry->entity = (grub_uint64_t) (grub_addr_t) os_mle_data;
entry->size = sizeof(struct grub_txt_os_mle_data);
grub_strcpy (&entry->evt_info[0], "Measured TXT OS-MLE data");
}

static void
setup_slr_table (struct grub_slaunch_params *slparams)
{
struct grub_slr_table *slr_table = (void *) slparams->slr_table_base;

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);
grub_slr_add_entry (slr_table, &slr_intel_info_staging.hdr);
grub_slr_add_entry (slr_table, &slr_end_staging);
}

static void
set_txt_info_ptr (struct grub_slaunch_params *slparams,
struct grub_txt_os_mle_data *os_mle_data)
{
struct grub_slr_entry_hdr *txt_info;

txt_info = grub_slr_next_entry_by_tag ((struct grub_slr_table *) slparams->slr_table_base,
NULL,
GRUB_SLR_ENTRY_INTEL_INFO);
os_mle_data->txt_info = (grub_addr_t) txt_info;
}

static grub_err_t
init_txt_heap (struct grub_slaunch_params *slparams, struct grub_txt_acm_header *sinit)
{
Expand All @@ -549,13 +706,17 @@ init_txt_heap (struct grub_slaunch_params *slparams, struct grub_txt_acm_header
#ifdef GRUB_MACHINE_EFI
struct grub_acpi_rsdp_v20 *rsdp;
#endif
struct grub_txt_mtrr_state saved_mtrrs_state = {0};

/* BIOS data already verified in grub_txt_verify_platform(). */

txt_heap = grub_txt_get_heap ();

grub_dprintf ("slaunch", "TXT heap %p\n", txt_heap);

/* Prepare SLR table staging area. */
init_slrt_storage ();

/* OS/loader to MLE data. */

os_mle_data = grub_txt_os_mle_data_start (txt_heap);
Expand All @@ -567,16 +728,29 @@ 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;
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;

/* 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 (&saved_mtrrs_state);

/* Setup the TXT specific SLR information */
slr_intel_info_staging.saved_misc_enable_msr =
grub_rdmsr (GRUB_MSR_X86_MISC_ENABLE);
grub_memcpy (&(slr_intel_info_staging.saved_bsp_mtrrs), &saved_mtrrs_state,
sizeof(struct grub_txt_mtrr_state));

/* Create the SLR security policy. */
setup_slrt_policy (slparams, os_mle_data);

/* OS/loader to SINIT data. */
grub_dprintf ("slaunch", "Get supported OS SINIT data version\n");
Expand Down Expand Up @@ -934,9 +1108,14 @@ 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;
struct grub_slr_table *slrt = slparams->slr_table_mem;

/* Setup the generic bits of the SLRT. */
grub_slr_init_table(slrt, GRUB_SLR_INTEL_TXT, slparams->slr_table_size);

sinit_base = grub_txt_sinit_select (grub_slaunch_module ());

Expand All @@ -959,17 +1138,19 @@ grub_txt_boot_prepare (struct grub_slaunch_params *slparams)
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);
/* Setup DCE and DLME information */
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;

/* Final setup of SLR table */
txt_heap = grub_txt_get_heap ();
os_mle_data = grub_txt_os_mle_data_start (txt_heap);
setup_slr_table (slparams);
set_txt_info_ptr (slparams, os_mle_data);

grub_dprintf ("slaunch", "TPM localities relinquished\n");
grub_tpm_relinquish_locality (0);
grub_dprintf ("slaunch", "Relinquished TPM locality 0\n");

err = set_mtrrs_for_acmod (sinit_base);
if (err)
Expand Down
6 changes: 5 additions & 1 deletion include/grub/i386/slaunch.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,22 @@
struct grub_slaunch_params
{
grub_uint32_t boot_params_addr;
grub_uint32_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;
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;
grub_uint32_t dce_base;
grub_uint32_t dce_size;
grub_uint64_t tpm_evt_log_base;
grub_uint32_t tpm_evt_log_size;
grub_uint32_t boot_params_base;
};

extern grub_uint32_t grub_slaunch_platform_type (void);
Expand Down
Loading

0 comments on commit bcc3961

Please sign in to comment.