[PATCH v4 13/23] x86/slaunch: measure MBI into TPM
Sergii Dmytruk <[email protected]> Sun, 2 Aug 2026 16:09:29 +0300
| Newsgroups | gmane.comp.emulators.xen.devel |
|---|---|
| Message-ID | <8e971b5b87d6b5dd7aebba55a40ddaeed7b97616.1785668458.git.sergii.dmytruk@3mdeb.com> |
From: Krystian Hebel <[email protected]> Make slaunch-tpm.c compile in early boot environment use it to measure MBI in early 32b code without paging (gets triggered from head.S). The fact of the measurement is not yet stored anywhere as there is no code for TPM event log discovery and modification. Signed-off-by: Krystian Hebel <[email protected]> Signed-off-by: Sergii Dmytruk <[email protected]> --- Notes: v4: was part of "x86/tpm.c: code for early hashing and extending PCRs (for TPM1.2)" v4: tpm_extend_mbi => slaunch_measure_mbi v4: doesn't touch tpm.c, uses slaunch-tpm.c instead v4: use `const multiboot2_fixed_t *` instead of `uint32_t *` for MBI xen/arch/x86/boot/Makefile | 7 +- xen/arch/x86/boot/head.S | 5 ++ xen/arch/x86/include/asm/slaunch-tpm.h | 7 ++ xen/arch/x86/include/asm/slaunch.h | 14 ++++ xen/arch/x86/slaunch-tpm.c | 112 +++++++++++++++++++++++++ xen/arch/x86/slaunch.c | 4 + 6 files changed, 148 insertions(+), 1 deletion(-) diff --git a/xen/arch/x86/boot/Makefile b/xen/arch/x86/boot/Makefile index 02f690d34a..b31c96be18 100644 --- a/xen/arch/x86/boot/Makefile +++ b/xen/arch/x86/boot/Makefile @@ -7,6 +7,7 @@ obj32 += reloc.32.o obj32 += reloc-trampoline.32.o ifeq ($(CONFIG_SLAUNCH),y) obj32 += slaunch-early.32.o +obj32 += slaunch-tpm-early.32.o endif obj32 += tpm-early.32.o @@ -14,7 +15,7 @@ obj64 := reloc-trampoline.o exports := cmdline_parse_early,reloc,reloc_trampoline32 ifeq ($(CONFIG_SLAUNCH),y) -exports := $(exports),slaunch_early_init +exports := $(exports),slaunch_early_init,slaunch_measure_mbi endif nocov-y += $(obj32) $(obj64) @@ -39,6 +40,10 @@ $(obj)/%.32.o: $(src)/%.c FORCE $(obj)/slaunch-early.32.o: XEN_CFLAGS += -D__EARLY_SLAUNCH__ +$(obj)/slaunch-tpm-early.32.o: XEN_CFLAGS += -D__EARLY_SLAUNCH__ +$(obj)/slaunch-tpm-early.32.o: $(src)/../slaunch-tpm.c FORCE + $(call if_changed_rule,cc_o_c) + $(obj)/tpm-early.32.o: XEN_CFLAGS += -D__EARLY_TPM__ $(obj)/tpm-early.32.o: $(src)/../tpm.c FORCE $(call if_changed_rule,cc_o_c) diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index 700d1d850e..2c1a0f6306 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -539,6 +539,11 @@ __start: pop sym_esi(slaunch_slrt) /* save physical address of SLRT for C code */ + mov sym_esi(slaunch_slrt), %edx /* physical SLRT address */ + mov %ebx, %eax /* physical MBI address */ + /* slaunch_measure_mbi(mbi/eax, slrt/edx) using fastcall. */ + call slaunch_measure_mbi + /* Move magic number expected by Multiboot 2 to EAX and fall through. */ movl $MULTIBOOT2_BOOTLOADER_MAGIC, %eax #endif diff --git a/xen/arch/x86/include/asm/slaunch-tpm.h b/xen/arch/x86/include/asm/slaunch-tpm.h index 68e9c8358a..79154f505b 100644 --- a/xen/arch/x86/include/asm/slaunch-tpm.h +++ b/xen/arch/x86/include/asm/slaunch-tpm.h @@ -16,4 +16,11 @@ struct slr_table; void slaunch_find_log(const struct slr_table *slrt, paddr_t *evt_log, uint32_t *evt_log_size); +/* + * Log data is optional (pass in NULL and/or zero size to indicate its absence). + */ +void slaunch_hash_extend(unsigned int loc, unsigned int pcr, const uint8_t *buf, + unsigned int size, uint32_t type, + const uint8_t *log_data, unsigned int log_data_size); + #endif /* X86_SLAUNCH_TPM_H */ diff --git a/xen/arch/x86/include/asm/slaunch.h b/xen/arch/x86/include/asm/slaunch.h index 459fc83388..65aab01f04 100644 --- a/xen/arch/x86/include/asm/slaunch.h +++ b/xen/arch/x86/include/asm/slaunch.h @@ -17,6 +17,20 @@ #include <xen/slr-table.h> #include <xen/types.h> +#define DRTM_LOC 2 +#define DRTM_CODE_PCR 17 +#define DRTM_DATA_PCR 18 + +/* + * Secure Launch event log entry types. The TXT specification defines the base + * event value as 0x400 for DRTM values, use it regardless of the DRTM for + * consistency. + */ +#define DLE_EVTYPE_BASE 0x400 +#define DLE_EVTYPE_SLAUNCH (DLE_EVTYPE_BASE + 0x102) +#define DLE_EVTYPE_SLAUNCH_START (DLE_EVTYPE_BASE + 0x103) +#define DLE_EVTYPE_SLAUNCH_END (DLE_EVTYPE_BASE + 0x104) + struct slaunch_early_init_results { uint32_t mbi_pa; diff --git a/xen/arch/x86/slaunch-tpm.c b/xen/arch/x86/slaunch-tpm.c index f59170594d..21dec67dca 100644 --- a/xen/arch/x86/slaunch-tpm.c +++ b/xen/arch/x86/slaunch-tpm.c @@ -2,13 +2,71 @@ /* * Slaunch functions related to TPM. * + * This file is built twice: + * 1. For early 32b mode without paging when it also provides + * slaunch_measure_mbi() to be called from assembly. + * 2. For 64b code. + * * Copyright (c) 2022-2026 3mdeb Sp. z o.o. All rights reserved. */ +#include <xen/compiler.h> +#include <xen/lib.h> #include <xen/macros.h> +#include <xen/multiboot2.h> +#include <xen/sha1.h> +#include <xen/sha2.h> #include <xen/slr-table.h> #include <xen/types.h> +#include <asm/intel-txt.h> +#include <asm/slaunch.h> +#include <asm/slaunch-tpm.h> +#include <asm/tpm.h> +#include <asm/tpm2.h> + +#ifdef __EARLY_SLAUNCH__ + +#ifdef __va +#error "__va defined in non-paged mode!" +#endif + +#define __va(x) _p(x) + +static uint32_t slrt_location; + +/* + * The code is being compiled as a standalone binary without linking to any + * other part of Xen. Providing implementation of builtin functions in this + * case is necessary if compiler chooses to not use an inline builtin. + */ +void *(memset)(void *s, int c, size_t n) +{ + uint8_t *d = s; + + while ( n-- ) + *d++ = c; + + return s; +} + +struct slr_table *slaunch_get_slrt(void) +{ + return _p(slrt_location); +} + +void asmlinkage slaunch_measure_mbi(const multiboot2_fixed_t *mbi, + uint32_t slrt_pa) +{ + /* Need this to implement slaunch_get_slrt() for early TPM code. */ + slrt_location = slrt_pa; + + slaunch_hash_extend(DRTM_LOC, DRTM_DATA_PCR, (const uint8_t *)mbi, + mbi->total_size, DLE_EVTYPE_SLAUNCH, NULL, 0); +} + +#endif /* __EARLY_SLAUNCH__ */ + void slaunch_find_log(const struct slr_table *slrt, paddr_t *evt_log, uint32_t *evt_log_size) { @@ -34,3 +92,57 @@ void slaunch_find_log(const struct slr_table *slrt, paddr_t *evt_log, *evt_log_size = 0; } } + +void slaunch_hash_extend(unsigned int loc, unsigned int pcr, const uint8_t *buf, + unsigned int size, uint32_t type, + const uint8_t *log_data, unsigned int log_data_size) +{ + paddr_t evt_log_paddr; + uint32_t evt_log_size; + struct tpm_log_hashes log_hashes; + uint8_t discarded_digests[SHA2_256_DIGEST_SIZE]; + uint32_t rc; + + slaunch_find_log(slaunch_get_slrt(), &evt_log_paddr, &evt_log_size); + + if ( tpm_is_tpm1() ) + { + log_hashes = (struct tpm_log_hashes) { + .count = 1, + .hashes = { + { + .alg = TPM_ALG_SHA1, + .size = SHA1_DIGEST_SIZE, + .data = discarded_digests, + }, + }, + }; + } + else + { + log_hashes = (struct tpm_log_hashes) { + .count = 2, + .hashes = { + { + .alg = TPM_ALG_SHA1, + .size = SHA1_DIGEST_SIZE, + .data = discarded_digests, + }, + { + .alg = TPM_ALG_SHA256, + .size = SHA2_256_DIGEST_SIZE, + .data = discarded_digests, + }, + }, + }; + } + + rc = tpm_hash_extend(loc, pcr, buf, size, &log_hashes); + if (rc != 0) + { +#ifndef __EARLY_SLAUNCH__ + printk(XENLOG_ERR "Extending PCR-%u failed with an error: 0x%08x\n", + pcr, rc); +#endif + } +} diff --git a/xen/arch/x86/slaunch.c b/xen/arch/x86/slaunch.c index ba1ba61c47..83dce3d57d 100644 --- a/xen/arch/x86/slaunch.c +++ b/xen/arch/x86/slaunch.c @@ -18,6 +18,7 @@ #include <asm/setup.h> #include <asm/slaunch.h> #include <asm/slaunch-tpm.h> +#include <asm/tpm.h> /* * These variables are assigned to by the code near Xen's entry point. @@ -78,6 +79,9 @@ void __init slaunch_map_mem_regions(void) paddr_t evt_log_addr; uint32_t evt_log_size; + rc = slaunch_map_l2(TPM_MMIO_BASE, TPM_MMIO_SIZE); + BUG_ON(rc != 0); + /* Vendor-specific part. */ txt_map_mem_regions(); -- 2.55.0