aboutsummaryrefslogtreecommitdiffstats
path: root/stubdom
diff options
context:
space:
mode:
authorDaniel De Graaf <dgdegra@tycho.nsa.gov>2013-03-21 16:11:28 -0400
committerIan Campbell <ian.campbell@citrix.com>2013-04-12 14:28:18 +0100
commitd78dab3eca85f9ff14af55583d83829e96a76b76 (patch)
treec3081153e92b02b20d5441510b4295224205abcc /stubdom
parent4eea1da06217cf5b8ea83387b79dcc6f332354fb (diff)
downloadxen-d78dab3eca85f9ff14af55583d83829e96a76b76.tar.gz
xen-d78dab3eca85f9ff14af55583d83829e96a76b76.tar.bz2
xen-d78dab3eca85f9ff14af55583d83829e96a76b76.zip
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 <dgdegra@tycho.nsa.gov> Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org> Acked-by: Matthew Fioravante <matthew.fioravante@jhuapl.edu>
Diffstat (limited to 'stubdom')
-rw-r--r--stubdom/Makefile2
-rw-r--r--stubdom/grub/Makefile1
-rw-r--r--stubdom/grub/kexec.c54
-rw-r--r--stubdom/grub/minios.cfg1
4 files changed, 57 insertions, 1 deletions
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 <blkfront.h>
#include <netfront.h>
#include <fbfront.h>
+#include <tpmfront.h>
#include <shared.h>
+#include <byteswap.h>
#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