Skip to content

Commit

Permalink
arch/x86: process DRTM policy
Browse files Browse the repository at this point in the history
Also, since this is done early, validate SLRT in the process.

The policy is looked at twice: at the very start near slaunch entrypoint
and in __start_xen().  Both times perform the same checks, but the first
time unsatisfied conditions just lead to doing no work as we can't
really report errors yet.  When the code is invoked from __start_xen(),
failed checks lead to abort() with an error message explaining the
issue.

An alternative is to store error code/message somewhere and print it
later, which would need a bit more code distributed in more than one
unit.

Signed-off-by: Sergii Dmytruk <[email protected]>
  • Loading branch information
SergiiDmytruk committed Oct 28, 2023
1 parent 91788d2 commit 5ed262b
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 14 deletions.
6 changes: 3 additions & 3 deletions xen/arch/x86/boot/head.S
Original file line number Diff line number Diff line change
Expand Up @@ -528,12 +528,12 @@ __start:
call txt_early_tests

/*
* txt_early_tests() returns MBI address, pass it to tpm_extend_mbi()
* txt_early_tests() returns MBI address, pass it to tpm_early_extend()
* and store for later in EBX.
*/
push %eax
movl %eax,%ebx
call tpm_extend_mbi
call tpm_early_extend

/* Move magic number expected by Multiboot 2 to EAX and fall through. */
movl $MULTIBOOT2_BOOTLOADER_MAGIC,%eax
Expand Down Expand Up @@ -864,7 +864,7 @@ txt_early_tests:
.incbin "txt_early.bin"

ALIGN
tpm_extend_mbi:
tpm_early_extend:
.incbin "tpm_early.bin"

ENTRY(trampoline_start)
Expand Down
27 changes: 18 additions & 9 deletions xen/arch/x86/include/asm/intel_txt.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,19 +348,28 @@ static inline void find_evt_log(void **evt_log, uint32_t *evt_log_size)
extern void protect_txt_mem_regions(void);
extern void txt_restore_mtrrs(bool e820_verbose);

#define DRTM_LOC 2
#define DRTM_CODE_PCR 17
#define DRTM_DATA_PCR 18
#define DRTM_LOC 2
#define DRTM_CODE_PCR 17
#define DRTM_DATA_PCR 18

/* TXT-defined use 0x4xx, TrenchBoot in Linux uses 0x5xx, use 0x6xx here. */
#define TXT_EVTYPE_MBI 0x600
#define TXT_EVTYPE_KERNEL 0x601
#define TXT_EVTYPE_INITRD 0x602

#define SHA1_DIGEST_SIZE 20
#define SHA256_DIGEST_SIZE 32
#define TXT_EVTYPE_MBI 0x600
#define TXT_EVTYPE_KERNEL 0x601
#define TXT_EVTYPE_INITRD 0x602
#define TXT_EVTYPE_KERNEL_CMDLINE 0x603
#define TXT_EVTYPE_SLRT 0x604
#define TXT_EVTYPE_OS2MLE 0x605
#define TXT_EVTYPE_MODULE 0x606
#define TXT_EVTYPE_MODULE_CMDLINE 0x607
#define TXT_EVTYPE_UEFI_MMAP 0x608
#define TXT_EVTYPE_UNKNOWN 0x6ff

#define SHA1_DIGEST_SIZE 20
#define SHA256_DIGEST_SIZE 32

void tpm_hash_extend(unsigned loc, unsigned pcr, uint8_t *buf, unsigned size,
uint32_t type, uint8_t *log_data, unsigned log_data_size);

void tpm_take_measurements(void);

#endif /* __ASSEMBLY__ */
4 changes: 4 additions & 0 deletions xen/arch/x86/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -1030,11 +1030,15 @@ void __init noreturn __start_xen(unsigned long mbi_p)
}

if ( sl_status )
{
tpm_take_measurements();

if ( mbi->mods_count > 2 )
{
mbi->mods_count = 2;
printk("Excessive multiboot modules for slaunch - limiting to 2\n");
}
}

bitmap_fill(module_map, mbi->mods_count);
__clear_bit(0, module_map); /* Dom0 kernel is always first */
Expand Down
143 changes: 141 additions & 2 deletions xen/arch/x86/tpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ asm (
" .text \n"
" .globl _start \n"
"_start: \n"
" jmp tpm_extend_mbi \n"
" jmp tpm_early_extend \n"
);

#include "boot/defs.h"
Expand Down Expand Up @@ -971,11 +971,150 @@ void tpm_hash_extend(unsigned loc, unsigned pcr, uint8_t *buf, unsigned size,
#endif
}

static struct slr_entry_policy *tpm_get_policy(void)
{
#ifdef __EARLY_TPM__
#define TPM_PANIC(...) return NULL;
#else
#define TPM_PANIC(args...) panic(args)
#endif

struct txt_os_mle_data *os_mle;
struct slr_table *slrt;
struct slr_entry_policy *policy;
struct slr_policy_entry *policy_entry;

os_mle = txt_os_mle_data_start(__va(read_txt_reg(TXTCR_HEAP_BASE)));

slrt = __va(os_mle->slrt);
if ( slrt->magic != SLR_TABLE_MAGIC )
TPM_PANIC("SLRT has invalid magic value: %#08x!\n", slrt->magic);
/* XXX: are newer revisions allowed? */
if ( slrt->revision != SLR_TABLE_REVISION )
TPM_PANIC("SLRT is of unsupported revision: %#04x!\n", slrt->revision);
if ( slrt->architecture != SLR_INTEL_TXT )
TPM_PANIC("SLRT is for unexpected architecture: %#04x!\n",
slrt->architecture);
if ( slrt->size > slrt->max_size )
TPM_PANIC("SLRT is larger than its max size: %#08x > %#08x!\n",
slrt->size, slrt->max_size);
if ( slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_INTEL_INFO) == NULL )
TPM_PANIC("SLRT is missing Intel-specific information!\n");

policy = (struct slr_entry_policy *)
slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_DRTM_POLICY);
if (policy == NULL)
TPM_PANIC("SLRT is missing DRTM policy!\n");

/* SLRT policy entry must be the first one (so measuring order matches
* policy order) and point to SLRT. */
/* XXX: are newer revisions allowed? */
if ( policy->revision != SLR_POLICY_REVISION )
TPM_PANIC("DRTM policy in SLRT is of unsupported revision: %#04x!\n",
slrt->revision);
if ( policy->nr_entries == 0 )
TPM_PANIC("DRTM policy in SLRT is empty!\n");

policy_entry = (struct slr_policy_entry *)
((uint8_t *)policy + sizeof(*policy));
if ( policy_entry->entity_type != SLR_ET_SLRT )
TPM_PANIC("First entry of DRTM policy in SLRT is empty!\n");
if ( policy_entry->entity != os_mle->slrt )
TPM_PANIC("SLRT entry of DRTM policy points to wrong location!\n");

return policy;

#undef TPM_PANIC
}

#ifdef __EARLY_TPM__
void __stdcall tpm_extend_mbi(uint32_t *mbi)
static void tpm_extend_mbi(uint32_t *mbi)
{
/* MBI starts with uint32_t total_size. */
tpm_hash_extend(DRTM_LOC, DRTM_DATA_PCR, (uint8_t *)mbi, *mbi,
TXT_EVTYPE_MBI, NULL, 0);
}

static void tpm_extend_slrt(void)
{
struct txt_os_mle_data *os_mle;
struct slr_table *slrt;
struct slr_entry_policy *policy;
struct slr_policy_entry *policy_entry;

os_mle = txt_os_mle_data_start(__va(read_txt_reg(TXTCR_HEAP_BASE)));
slrt = __va(os_mle->slrt);

/* All errors are handled by doing nothing here, the checks will be repeated
* and handled for real once more things are initialized. */
policy = tpm_get_policy();
if ( policy == NULL )
return;

policy_entry = (struct slr_policy_entry *)
((uint8_t *)policy + sizeof(*policy));
tpm_hash_extend(DRTM_LOC, policy_entry->pcr, (uint8_t *)slrt,
policy_entry->size, TXT_EVTYPE_SLRT, NULL, 0);
}

void __stdcall tpm_early_extend(uint32_t *mbi)
{
tpm_extend_mbi(mbi);
tpm_extend_slrt();
}
#else
void tpm_take_measurements(void)
{
struct txt_os_mle_data *os_mle;
struct slr_table *slrt;
struct slr_entry_policy *policy;
struct slr_policy_entry *policy_entry;
uint16_t i;

os_mle = txt_os_mle_data_start(__va(read_txt_reg(TXTCR_HEAP_BASE)));
slrt = __va(os_mle->slrt);

policy = tpm_get_policy();
policy_entry = (struct slr_policy_entry *)
((uint8_t *)policy + sizeof(*policy));

for (i = 1; i < policy->nr_entries; i++) {
uint64_t start = policy_entry[i].entity;
uint64_t size = policy_entry[i].size;
uint32_t event_type = TXT_EVTYPE_UNKNOWN;

switch (policy_entry[i].entity_type) {
case SLR_ET_SLRT:
event_type = TXT_EVTYPE_SLRT;
break;
case SLR_ET_CMDLINE:
event_type = TXT_EVTYPE_KERNEL_CMDLINE;
break;
case SLR_ET_UEFI_MEMMAP:
event_type = TXT_EVTYPE_UEFI_MMAP;
break;
case SLR_ET_RAMDISK:
event_type = TXT_EVTYPE_INITRD;
break;
case SLR_ET_TXT_OS2MLE:
event_type = TXT_EVTYPE_OS2MLE;
break;
case SLR_ET_MODULE:
event_type = TXT_EVTYPE_MODULE;
break;
case SLR_ET_MODULE_CMDLINE:
event_type = TXT_EVTYPE_MODULE_CMDLINE;
break;

case SLR_ET_UNUSED:
continue;
}

map_pages_to_xen(start, maddr_to_mfn(start), PFN_UP(size),
__PAGE_HYPERVISOR_RO);
tpm_hash_extend(DRTM_LOC, policy_entry[i].pcr, (uint8_t *)start, size,
event_type, NULL, 0);
destroy_xen_mappings(start, start + PFN_UP(size) * PAGE_SIZE);
}
}
#endif

0 comments on commit 5ed262b

Please sign in to comment.