Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import SLRT support for secure launch #13

Merged
merged 3 commits into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions grub-core/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
110 changes: 101 additions & 9 deletions grub-core/loader/i386/linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <grub/linux.h>
#include <grub/machine/kernel.h>
#include <grub/safemath.h>
#include <grub/slr_table.h>

GRUB_MOD_LICENSE ("GPLv3+");

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -714,17 +805,18 @@ 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->sinit_acm_base;
state.ecx = slparams->sinit_acm_size;
state.ebx = slparams->dce_base;
state.ecx = slparams->dce_size;
state.edx = 0;
}
else
Expand Down
87 changes: 87 additions & 0 deletions grub-core/loader/i386/slaunch.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@
#include <grub/misc.h>
#include <grub/types.h>
#include <grub/dl.h>
#include <grub/slr_table.h>
#include <grub/cpu/relocator.h>
#include <grub/i386/cpuid.h>
#include <grub/i386/msr.h>
#include <grub/i386/mmio.h>
#include <grub/i386/slaunch.h>
#include <grub/i386/tpm.h>
#include <grub/i386/txt.h>

GRUB_MOD_LICENSE ("GPLv3+");
Expand All @@ -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)
{
Expand All @@ -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)),
Expand Down
Loading