[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 06/13] 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@xxxxxxxxxxxxx>
Acked-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxx>
Acked-by: Matthew Fioravante <matthew.fioravante@xxxxxxxxxx>
---
 docs/misc/vtpm.txt      | 41 ++++++++++++++++++++++++++++---------
 stubdom/Makefile        |  2 +-
 stubdom/grub/Makefile   |  1 +
 stubdom/grub/kexec.c    | 54 +++++++++++++++++++++++++++++++++++++++++++++++++
 stubdom/grub/minios.cfg |  1 +
 5 files changed, 89 insertions(+), 10 deletions(-)

diff --git a/docs/misc/vtpm.txt b/docs/misc/vtpm.txt
index c0a6054..b8979a3 100644
--- a/docs/misc/vtpm.txt
+++ b/docs/misc/vtpm.txt
@@ -1,7 +1,7 @@
 Copyright (c) 2010-2012 United States Government, as represented by
 the Secretary of Defense.  All rights reserved.
 November 12 2012
-Authors: Matthew Fioravante (JHUAPL),
+Authors: Matthew Fioravante (JHUAPL), Daniel De Graaf (NSA)
 
 This document describes the virtual Trusted Platform Module (vTPM) subsystem
 for Xen. The reader is assumed to have familiarity with building and installing
@@ -15,7 +15,8 @@ operating system (a DomU).  This allows programs to interact 
with a TPM in a
 virtual system the same way they interact with a TPM on the physical system.
 Each guest gets its own unique, emulated, software TPM.  However, each of the
 vTPM's secrets (Keys, NVRAM, etc) are managed by a vTPM Manager domain, which
-seals the secrets to the Physical TPM.  Thus, the vTPM subsystem extends the
+seals the secrets to the Physical TPM.  If the process of creating each of 
these
+domains (manager, vTPM, and guest) is trusted, the vTPM subsystem extends the
 chain of trust rooted in the hardware TPM to virtual machines in Xen. Each
 major component of vTPM is implemented as a separate domain, providing secure
 separation guaranteed by the hypervisor. The vTPM domains are implemented in
@@ -119,14 +120,17 @@ the stubdom tree.
 Compiling the LINUX dom0 kernel:
 --------------------------------
 
-The Linux dom0 kernel has no special prerequisites.
+The Linux dom0 kernel should not try accessing the TPM while the vTPM
+Manager domain is accessing it; the simplest way to accomplish this is
+to ensure the kernel is compiled without a driver for the TPM, or avoid
+loading the driver by blacklisting the module.
 
 Compiling the LINUX domU kernel:
 --------------------------------
 
-The domU kernel used by domains with vtpms must
-include the xen-tpmfront.ko driver. It can be built
-directly into the kernel or as a module.
+The domU kernel used by domains with vtpms must include the xen-tpmfront.ko
+driver. It can be built directly into the kernel or as a module; however, some
+features such as IMA require the TPM to be built in to the kernel.
 
 CONFIG_TCG_TPM=y
 CONFIG_TCG_XEN=y
@@ -160,9 +164,10 @@ disk=["file:/var/vtpmmgr-stubdom.img,hda,w"]
 name="vtpmmgr"
 iomem=["fed40,5"]
 
-The iomem line tells xl to allow access to the TPM
-IO memory pages, which are 5 pages that start at
-0xfed40000.
+The iomem line tells xl to allow access to all of the TPM IO memory
+pages, which are 5 pages (one per locality) that start at 0xfed40000. By
+default, the TPM manager uses locality 0 (so only the page at 0xfed40 is
+needed); this can be changed on the domain's command line.
 
 Starting and stopping the manager:
 ----------------------------------
@@ -285,6 +290,24 @@ On guest:
 You may wish to write a script to start your vtpm and guest together.
 
 ------------------------------
+INTEGRATION WITH PV-GRUB
+------------------------------
+
+The vTPM currently starts up with all PCRs set to their default values (all
+zeros for the lower 16).  This means that any decisions about the
+trustworthiness of the created domain must be made based on the environment 
that
+created the vTPM and the domU; for example, a system that only constructs 
images
+using a trusted configuration and guest kernel be able to provide guarantees
+about the guests and any measurements done that kernel (such as the IMA TCB
+log).  Guests wishing to use a custom kernel in such a secure environment are
+often started using the pv-grub bootloader as the kernel, which then can load
+the untrusted kernel without needing to parse an untrusted filesystem and 
kernel
+in dom0.  If the pv-grub stub domain succeeds in connecting to a vTPM, it will
+extend the hash of the kernel that it boots into PCR #4, and will extend the
+command line and initrd into PCR #5 before booting so that a domU booted in 
this
+way can attest to its early boot state.
+
+------------------------------
 MORE INFORMATION
 ------------------------------
 
diff --git a/stubdom/Makefile b/stubdom/Makefile
index 93b4181..4b4f74e 100644
--- a/stubdom/Makefile
+++ b/stubdom/Makefile
@@ -399,7 +399,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 d6e3a1e..6bd2c4c 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 b21c91a..cef357e 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 40cfa68..8df4909 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
-- 
1.8.1


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.