From d78dab3eca85f9ff14af55583d83829e96a76b76 Mon Sep 17 00:00:00 2001 From: Daniel De Graaf Date: Thu, 21 Mar 2013 16:11:28 -0400 Subject: stubdom/grub: send kernel measurements to vTPM This allows a domU with an arbitrary kernel and initrd to take advantage of the static root of trust provided by a vTPM. Signed-off-by: Daniel De Graaf Acked-by: Samuel Thibault Acked-by: Matthew Fioravante --- stubdom/Makefile | 2 +- stubdom/grub/Makefile | 1 + stubdom/grub/kexec.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ stubdom/grub/minios.cfg | 1 + 4 files changed, 57 insertions(+), 1 deletion(-) (limited to 'stubdom') diff --git a/stubdom/Makefile b/stubdom/Makefile index b7143431d9..427e4d66e8 100644 --- a/stubdom/Makefile +++ b/stubdom/Makefile @@ -400,7 +400,7 @@ grub-upstream: grub-$(GRUB_VERSION).tar.gz done .PHONY: grub -grub: grub-upstream $(CROSS_ROOT) +grub: cross-polarssl grub-upstream $(CROSS_ROOT) mkdir -p grub-$(XEN_TARGET_ARCH) CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= -C $@ OBJ_DIR=$(CURDIR)/grub-$(XEN_TARGET_ARCH) diff --git a/stubdom/grub/Makefile b/stubdom/grub/Makefile index d6e3a1e5b6..6bd2c4c9f1 100644 --- a/stubdom/grub/Makefile +++ b/stubdom/grub/Makefile @@ -60,6 +60,7 @@ NETBOOT_SOURCES:=$(addprefix netboot/,$(NETBOOT_SOURCES)) $(BOOT): DEF_CPPFLAGS+=-D__ASSEMBLY__ PV_GRUB_SOURCES = kexec.c mini-os.c +PV_GRUB_SOURCES += ../polarssl-$(XEN_TARGET_ARCH)/library/sha1.o SOURCES = $(NETBOOT_SOURCES) $(STAGE2_SOURCES) $(PV_GRUB_SOURCES) diff --git a/stubdom/grub/kexec.c b/stubdom/grub/kexec.c index b21c91ae99..cef357eff9 100644 --- a/stubdom/grub/kexec.c +++ b/stubdom/grub/kexec.c @@ -28,7 +28,9 @@ #include #include #include +#include #include +#include #include "mini-os.h" @@ -54,6 +56,22 @@ static unsigned long allocated; int pin_table(xc_interface *xc_handle, unsigned int type, unsigned long mfn, domid_t dom); +#define TPM_TAG_RQU_COMMAND 0xC1 +#define TPM_ORD_Extend 20 + +struct pcr_extend_cmd { + uint16_t tag; + uint32_t size; + uint32_t ord; + + uint32_t pcr; + unsigned char hash[20]; +} __attribute__((packed)); + +/* Not imported from polarssl's header since the prototype unhelpfully defines + * the input as unsigned char, which causes pointer type mismatches */ +void sha1(const void *input, size_t ilen, unsigned char output[20]); + /* We need mfn to appear as target_pfn, so exchange with the MFN there */ static void do_exchange(struct xc_dom_image *dom, xen_pfn_t target_pfn, xen_pfn_t source_mfn) { @@ -117,6 +135,40 @@ int kexec_allocate(struct xc_dom_image *dom, xen_vaddr_t up_to) return 0; } +static void tpm_hash2pcr(struct xc_dom_image *dom, char *cmdline) +{ + struct tpmfront_dev* tpm = init_tpmfront(NULL); + uint8_t *resp; + size_t resplen = 0; + struct pcr_extend_cmd cmd; + + /* If all guests have access to a vTPM, it may be useful to replace this + * with ASSERT(tpm) to prevent configuration errors from allowing a guest + * to boot without a TPM (or with a TPM that has not been sent any + * measurements, which could allow forging the measurements). + */ + if (!tpm) + return; + + cmd.tag = bswap_16(TPM_TAG_RQU_COMMAND); + cmd.size = bswap_32(sizeof(cmd)); + cmd.ord = bswap_32(TPM_ORD_Extend); + cmd.pcr = bswap_32(4); // PCR #4 for kernel + sha1(dom->kernel_blob, dom->kernel_size, cmd.hash); + + tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), &resp, &resplen); + + cmd.pcr = bswap_32(5); // PCR #5 for cmdline + sha1(cmdline, strlen(cmdline), cmd.hash); + tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), &resp, &resplen); + + cmd.pcr = bswap_32(5); // PCR #5 for initrd + sha1(dom->ramdisk_blob, dom->ramdisk_size, cmd.hash); + tpmfront_cmd(tpm, (void*)&cmd, sizeof(cmd), &resp, &resplen); + + shutdown_tpmfront(tpm); +} + void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline, unsigned long flags) { struct xc_dom_image *dom; @@ -151,6 +203,8 @@ void kexec(void *kernel, long kernel_size, void *module, long module_size, char dom->console_evtchn = start_info.console.domU.evtchn; dom->xenstore_evtchn = start_info.store_evtchn; + tpm_hash2pcr(dom, cmdline); + if ( (rc = xc_dom_boot_xen_init(dom, xc_handle, domid)) != 0 ) { grub_printf("xc_dom_boot_xen_init returned %d\n", rc); errnum = ERR_BOOT_FAILURE; diff --git a/stubdom/grub/minios.cfg b/stubdom/grub/minios.cfg index 40cfa68e87..8df49092cd 100644 --- a/stubdom/grub/minios.cfg +++ b/stubdom/grub/minios.cfg @@ -1,2 +1,3 @@ CONFIG_START_NETWORK=n CONFIG_SPARSE_BSS=n +CONFIG_TPMFRONT=y -- cgit v1.2.3