[PATCH VTPM v9 1/8] add vtpm-stubdom code

Matthew Fioravante
Thu, 10 Jan 2013 23:01:00 -0000

Add the code base for vtpm-stubdom to the stubdom
heirarchy. Makefile changes in later patch.

Signed-off-by: Matthew Fioravante <matthew.fioravante@jhuapl.edu>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 stubdom/vtpm/Makefile    |   37 +++++
 stubdom/vtpm/minios.cfg  |   14 ++
 stubdom/vtpm/vtpm.c      |  404 ++++++++++++++++++++++++++++++++++++++++++++++
 stubdom/vtpm/vtpm.h      |   36 +++++
 stubdom/vtpm/vtpm_cmd.c  |  256 +++++++++++++++++++++++++++++
 stubdom/vtpm/vtpm_cmd.h  |   31 ++++
 stubdom/vtpm/vtpm_pcrs.c |   43 +++++
 stubdom/vtpm/vtpm_pcrs.h |   53 ++++++
 stubdom/vtpm/vtpmblk.c   |  307 +++++++++++++++++++++++++++++++++++
 stubdom/vtpm/vtpmblk.h   |   31 ++++
 10 files changed, 1212 insertions(+)
 create mode 100644 stubdom/vtpm/Makefile
 create mode 100644 stubdom/vtpm/minios.cfg
 create mode 100644 stubdom/vtpm/vtpm.c
 create mode 100644 stubdom/vtpm/vtpm.h
 create mode 100644 stubdom/vtpm/vtpm_cmd.c
 create mode 100644 stubdom/vtpm/vtpm_cmd.h
 create mode 100644 stubdom/vtpm/vtpm_pcrs.c
 create mode 100644 stubdom/vtpm/vtpm_pcrs.h
 create mode 100644 stubdom/vtpm/vtpmblk.c
 create mode 100644 stubdom/vtpm/vtpmblk.h

diff --git a/stubdom/vtpm/Makefile b/stubdom/vtpm/Makefile
new file mode 100644
index 0000000..686c0ea
--- /dev/null
+++ b/stubdom/vtpm/Makefile
@@ -0,0 +1,37 @@
+# Copyright (c) 2010-2012 United States Government, as represented by
+# the Secretary of Defense.  All rights reserved.
+#
+# THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
+# ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
+# INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
+# FOR A PARTICULAR  PURPOSE, AND NONINFRINGEMENT ARE HEREBY
+# DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
+# SOFTWARE.
+#
+
+XEN_ROOT=../..
+
+PSSL_DIR=../polarssl-$(XEN_TARGET_ARCH)/library
+PSSL_OBJS=aes.o sha1.o entropy.o ctr_drbg.o sha4.o
+
+TARGET=vtpm.a
+OBJS=vtpm.o vtpm_cmd.o vtpmblk.o vtpm_pcrs.o
+
+
+CPPFLAGS+=-I../tpm_emulator-$(XEN_TARGET_ARCH)/build
+CPPFLAGS+=-I../tpm_emulator-$(XEN_TARGET_ARCH)/tpm
+CPPFLAGS+=-I../tpm_emulator-$(XEN_TARGET_ARCH)/crypto
+CPPFLAGS+=-I../tpm_emulator-$(XEN_TARGET_ARCH)
+
+$(TARGET): $(OBJS)
+	ar -cr $@ $(OBJS) $(TPMEMU_OBJS) $(foreach
obj,$(PSSL_OBJS),$(PSSL_DIR)/$(obj))
+
+$(OBJS): vtpm_manager.h
+
+vtpm_manager.h:
+	ln -s ../vtpmmgr/vtpm_manager.h vtpm_manager.h
+
+clean:
+	-rm $(TARGET) $(OBJS) vtpm_manager.h
+
+.PHONY: clean
diff --git a/stubdom/vtpm/minios.cfg b/stubdom/vtpm/minios.cfg
new file mode 100644
index 0000000..31652ee
--- /dev/null
+++ b/stubdom/vtpm/minios.cfg
@@ -0,0 +1,14 @@
+CONFIG_TPMFRONT=y
+CONFIG_TPM_TIS=n
+CONFIG_TPMBACK=y
+CONFIG_START_NETWORK=n
+CONFIG_TEST=n
+CONFIG_PCIFRONT=n
+CONFIG_BLKFRONT=y
+CONFIG_NETFRONT=n
+CONFIG_FBFRONT=n
+CONFIG_KBDFRONT=n
+CONFIG_CONSFRONT=n
+CONFIG_XENBUS=y
+CONFIG_LWIP=n
+CONFIG_XC=n
diff --git a/stubdom/vtpm/vtpm.c b/stubdom/vtpm/vtpm.c
new file mode 100644
index 0000000..71aef78
--- /dev/null
+++ b/stubdom/vtpm/vtpm.c
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense.  All rights reserved.
+ *
+ * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
+ * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
+ * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR  PURPOSE, AND NONINFRINGEMENT ARE HEREBY
+ * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
+ * SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <syslog.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <xen/xen.h>
+#include <tpmback.h>
+#include <tpmfront.h>
+
+#include <polarssl/entropy.h>
+#include <polarssl/ctr_drbg.h>
+
+#include "tpm/tpm_emulator_extern.h"
+#include "tpm/tpm_marshalling.h"
+#include "vtpm.h"
+#include "vtpm_cmd.h"
+#include "vtpm_pcrs.h"
+#include "vtpmblk.h"
+
+#define TPM_LOG_INFO LOG_INFO
+#define TPM_LOG_ERROR LOG_ERR
+#define TPM_LOG_DEBUG LOG_DEBUG
+
+/* Global commandline options - default values */
+struct Opt_args opt_args = {
+   .startup = ST_CLEAR,
+   .loglevel = TPM_LOG_INFO,
+   .hwinitpcrs = VTPM_PCRNONE,
+   .tpmconf = 0,
+   .enable_maint_cmds = false,
+};
+
+static uint32_t badords[32];
+static unsigned int n_badords = 0;
+
+entropy_context entropy;
+ctr_drbg_context ctr_drbg;
+
+struct tpmfront_dev* tpmfront_dev;
+
+void vtpm_get_extern_random_bytes(void *buf, size_t nbytes)
+{
+   ctr_drbg_random(&ctr_drbg, buf, nbytes);
+}
+
+int vtpm_read_from_file(uint8_t **data, size_t *data_length) {
+   return read_vtpmblk(tpmfront_dev, data, data_length);
+}
+
+int vtpm_write_to_file(uint8_t *data, size_t data_length) {
+   return write_vtpmblk(tpmfront_dev, data, data_length);
+}
+
+int vtpm_extern_init_fake(void) {
+   return 0;
+}
+
+void vtpm_extern_release_fake(void) {
+}
+
+
+void vtpm_log(int priority, const char *fmt, ...)
+{
+   if(opt_args.loglevel >= priority) {
+      va_list v;
+      va_start(v, fmt);
+      vprintf(fmt, v);
+      va_end(v);
+   }
+}
+
+static uint64_t vtpm_get_ticks(void)
+{
+  static uint64_t old_t = 0;
+  uint64_t new_t, res_t;
+  struct timeval tv;
+  gettimeofday(&tv, NULL);
+  new_t = (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec;
+  res_t = (old_t > 0) ? new_t - old_t : 0;
+  old_t = new_t;
+  return res_t;
+}
+
+
+static int tpm_entropy_source(void* dummy, unsigned char* data, size_t len,
size_t* olen) {
+   UINT32 sz = len;
+   TPM_RESULT rc = VTPM_GetRandom(tpmfront_dev, data, &sz);
+   *olen = sz;
+   return rc == TPM_SUCCESS ? 0 : POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
+}
+
+int init_random(void) {
+   /* Initialize the rng */
+   entropy_init(&entropy);
+   entropy_add_source(&entropy, tpm_entropy_source, NULL, 0);
+   entropy_gather(&entropy);
+   ctr_drbg_init(&ctr_drbg, entropy_func, &entropy, NULL, 0);
+   ctr_drbg_set_prediction_resistance( &ctr_drbg, CTR_DRBG_PR_OFF );
+
+   return 0;
+}
+
+int check_ordinal(tpmcmd_t* tpmcmd) {
+   TPM_COMMAND_CODE ord;
+   UINT32 len = 4;
+   BYTE* ptr;
+   unsigned int i;
+
+   if(tpmcmd->req_len < 10) {
+      return true;
+   }
+
+   ptr = tpmcmd->req + 6;
+   tpm_unmarshal_UINT32(&ptr, &len, &ord);
+
+   for(i = 0; i < n_badords; ++i) {
+      if(ord == badords[i]) {
+         error("Disabled command ordinal (%" PRIu32")
requested!\n");
+         return false;
+      }
+   }
+   return true;
+}
+
+static void main_loop(void) {
+   tpmcmd_t* tpmcmd = NULL;
+   domid_t domid;		/* Domid of frontend */
+   unsigned int handle;	/* handle of frontend */
+   int res = -1;
+
+   info("VTPM Initializing\n");
+
+   /* Set required tpm config args */
+   opt_args.tpmconf |= TPM_CONF_STRONG_PERSISTENCE;
+   opt_args.tpmconf &= ~TPM_CONF_USE_INTERNAL_PRNG;
+   opt_args.tpmconf |= TPM_CONF_GENERATE_EK;
+   opt_args.tpmconf |= TPM_CONF_GENERATE_SEED_DAA;
+
+   /* Initialize the emulator */
+   tpm_emulator_init(opt_args.startup, opt_args.tpmconf);
+
+   /* Initialize any requested PCRs with hardware TPM values */
+   if(vtpm_initialize_hw_pcrs(tpmfront_dev, opt_args.hwinitpcrs) !=
TPM_SUCCESS) {
+      error("Failed to initialize PCRs with hardware TPM values");
+      goto abort_postpcrs;
+   }
+
+   /* Wait for the frontend domain to connect */
+   info("Waiting for frontend domain to connect..");
+   if(tpmback_wait_for_frontend_connect(&domid, &handle) == 0) {
+      info("VTPM attached to Frontend %u/%u", (unsigned int) domid,
handle);
+   } else {
+      error("Unable to attach to a frontend");
+   }
+
+   tpmcmd = tpmback_req(domid, handle);
+   while(tpmcmd) {
+      /* Handle the request */
+      if(tpmcmd->req_len) {
+	 tpmcmd->resp = NULL;
+	 tpmcmd->resp_len = 0;
+
+         /* First check for disabled ordinals */
+         if(!check_ordinal(tpmcmd)) {
+            create_error_response(tpmcmd, TPM_BAD_ORDINAL);
+         }
+         /* If not disabled, do the command */
+         else {
+            if((res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len,
&tpmcmd->resp, &tpmcmd->resp_len)) != 0) {
+               error("tpm_handle_command() failed");
+               create_error_response(tpmcmd, TPM_FAIL);
+            }
+         }
+      }
+
+      /* Send the response */
+      tpmback_resp(tpmcmd);
+
+      /* Wait for the next request */
+      tpmcmd = tpmback_req(domid, handle);
+
+   }
+
+abort_postpcrs:
+   info("VTPM Shutting down\n");
+
+   tpm_emulator_shutdown();
+}
+
+int parse_cmd_line(int argc, char** argv)
+{
+   char sval[25];
+   char* logstr = NULL;
+   /* Parse the command strings */
+   for(unsigned int i = 1; i < argc; ++i) {
+      if (sscanf(argv[i], "loglevel=%25s", sval) == 1){
+	 if (!strcmp(sval, "debug")) {
+	    opt_args.loglevel = TPM_LOG_DEBUG;
+	    logstr = "debug";
+	 }
+	 else if (!strcmp(sval, "info")) {
+	    logstr = "info";
+	    opt_args.loglevel = TPM_LOG_INFO;
+	 }
+	 else if (!strcmp(sval, "error")) {
+	    logstr = "error";
+	    opt_args.loglevel = TPM_LOG_ERROR;
+	 }
+      }
+      else if (!strcmp(argv[i], "clear")) {
+	 opt_args.startup = ST_CLEAR;
+      }
+      else if (!strcmp(argv[i], "save")) {
+	 opt_args.startup = ST_SAVE;
+      }
+      else if (!strcmp(argv[i], "deactivated")) {
+	 opt_args.startup = ST_DEACTIVATED;
+      }
+      else if (!strncmp(argv[i], "maintcmds=", 10)) {
+         if(!strcmp(argv[i] + 10, "1")) {
+            opt_args.enable_maint_cmds = true;
+         } else if(!strcmp(argv[i] + 10, "0")) {
+            opt_args.enable_maint_cmds = false;
+         }
+      }
+      else if(!strncmp(argv[i], "hwinitpcr=", 10)) {
+         char *pch = argv[i] + 10;
+         unsigned int v1, v2;
+         pch = strtok(pch, ",");
+         while(pch != NULL) {
+            if(!strcmp(pch, "all")) {
+               //Set all
+               opt_args.hwinitpcrs = VTPM_PCRALL;
+            } else if(!strcmp(pch, "none")) {
+               //Set none
+               opt_args.hwinitpcrs = VTPM_PCRNONE;
+            } else if(sscanf(pch, "%u", &v1) == 1) {
+               //Set one
+               if(v1 >= TPM_NUM_PCR) {
+                  error("hwinitpcr error: Invalid PCR index %u", v1);
+                  return -1;
+               }
+               opt_args.hwinitpcrs |= (1 << v1);
+            } else if(sscanf(pch, "%u-%u", &v1, &v2) == 2) {
+               //Set range
+               if(v1 >= TPM_NUM_PCR) {
+                  error("hwinitpcr error: Invalid PCR index %u", v1);
+                  return -1;
+               }
+               if(v2 >= TPM_NUM_PCR) {
+                  error("hwinitpcr error: Invalid PCR index %u", v1);
+                  return -1;
+               }
+               if(v2 < v1) {
+                  unsigned tp = v1;
+                  v1 = v2;
+                  v2 = tp;
+               }
+               for(unsigned int i = v1; i <= v2; ++i) {
+                  opt_args.hwinitpcrs |= (1 << i);
+               }
+            } else {
+               error("hwintipcr error: Invalid PCR specification :
%s", pch);
+               return -1;
+            }
+            pch = strtok(NULL, ",");
+         }
+      }
+      else {
+	 error("Invalid command line option `%s''", argv[i]);
+      }
+
+   }
+
+   /* Check Errors and print results */
+   switch(opt_args.startup) {
+      case ST_CLEAR:
+	 info("Startup mode is `clear''");
+	 break;
+      case ST_SAVE:
+	 info("Startup mode is `save''");
+	 break;
+      case ST_DEACTIVATED:
+	 info("Startup mode is `deactivated''");
+	 break;
+      default:
+	 error("Invalid startup mode %d", opt_args.startup);
+	 return -1;
+   }
+
+   if(opt_args.hwinitpcrs & (VTPM_PCRALL))
+   {
+      char pcrstr[1024];
+      char* ptr = pcrstr;
+
+      pcrstr[0] = ''\0'';
+      info("The following PCRs will be initialized with values from the
hardware TPM:");
+      for(unsigned int i = 0; i < TPM_NUM_PCR; ++i) {
+         if(opt_args.hwinitpcrs & (1 << i)) {
+            ptr += sprintf(ptr, "%u, ", i);
+         }
+      }
+      /* get rid of the last comma if any numbers were printed */
+      *(ptr -2) = ''\0'';
+
+      info("\t%s", pcrstr);
+   } else {
+      info("All PCRs initialized to default values");
+   }
+
+   if(!opt_args.enable_maint_cmds) {
+      info("TPM Maintenance Commands disabled");
+      badords[n_badords++] = TPM_ORD_CreateMaintenanceArchive;
+      badords[n_badords++] = TPM_ORD_LoadMaintenanceArchive;
+      badords[n_badords++] = TPM_ORD_KillMaintenanceFeature;
+      badords[n_badords++] = TPM_ORD_LoadManuMaintPub;
+      badords[n_badords++] = TPM_ORD_ReadManuMaintPub;
+   } else {
+      info("TPM Maintenance Commands enabled");
+   }
+
+   info("Log level set to %s", logstr);
+
+   return 0;
+}
+
+void cleanup_opt_args(void) {
+}
+
+int main(int argc, char **argv)
+{
+   //FIXME: initializing blkfront without this sleep causes the domain to crash
on boot
+   sleep(2);
+
+   /* Setup extern function pointers */
+   tpm_extern_init = vtpm_extern_init_fake;
+   tpm_extern_release = vtpm_extern_release_fake;
+   tpm_malloc = malloc;
+   tpm_free = free;
+   tpm_log = vtpm_log;
+   tpm_get_ticks = vtpm_get_ticks;
+   tpm_get_extern_random_bytes = vtpm_get_extern_random_bytes;
+   tpm_write_to_storage = vtpm_write_to_file;
+   tpm_read_from_storage = vtpm_read_from_file;
+
+   info("starting TPM Emulator (1.2.%d.%d-%d)", VERSION_MAJOR,
VERSION_MINOR, VERSION_BUILD);
+   if(parse_cmd_line(argc, argv)) {
+      error("Error parsing commandline\n");
+      return -1;
+   }
+
+   /* Initialize devices */
+   init_tpmback();
+   if((tpmfront_dev = init_tpmfront(NULL)) == NULL) {
+      error("Unable to initialize tpmfront device");
+      goto abort_posttpmfront;
+   }
+
+   /* Seed the RNG with entropy from hardware TPM */
+   if(init_random()) {
+      error("Unable to initialize RNG");
+      goto abort_postrng;
+   }
+
+   /* Initialize blkfront device */
+   if(init_vtpmblk(tpmfront_dev)) {
+      error("Unable to initialize Blkfront persistent storage");
+      goto abort_postvtpmblk;
+   }
+
+   /* Run main loop */
+   main_loop();
+
+   /* Shutdown blkfront */
+   shutdown_vtpmblk();
+abort_postvtpmblk:
+abort_postrng:
+
+   /* Close devices */
+   shutdown_tpmfront(tpmfront_dev);
+abort_posttpmfront:
+   shutdown_tpmback();
+
+   cleanup_opt_args();
+
+   return 0;
+}
diff --git a/stubdom/vtpm/vtpm.h b/stubdom/vtpm/vtpm.h
new file mode 100644
index 0000000..5919e44
--- /dev/null
+++ b/stubdom/vtpm/vtpm.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense.  All rights reserved.
+ *
+ * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
+ * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
+ * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR  PURPOSE, AND NONINFRINGEMENT ARE HEREBY
+ * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
+ * SOFTWARE.
+ */
+
+#ifndef VTPM_H
+#define VTPM_H
+
+#include <stdbool.h>
+
+/* For testing */
+#define VERS_CMD
"\x00\xC1\x00\x00\x00\x16\x00\x00\x00\x65\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x01\x03"
+#define VERS_CMD_LEN 22
+
+/* Global commandline options */
+struct Opt_args {
+   enum StartUp {
+      ST_CLEAR = 1,
+      ST_SAVE = 2,
+      ST_DEACTIVATED = 3
+   } startup;
+   unsigned long hwinitpcrs;
+   int loglevel;
+   uint32_t tpmconf;
+   bool enable_maint_cmds;
+};
+extern struct Opt_args opt_args;
+
+#endif
diff --git a/stubdom/vtpm/vtpm_cmd.c b/stubdom/vtpm/vtpm_cmd.c
new file mode 100644
index 0000000..7eae98b
--- /dev/null
+++ b/stubdom/vtpm/vtpm_cmd.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense.  All rights reserved.
+ *
+ * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
+ * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
+ * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR  PURPOSE, AND NONINFRINGEMENT ARE HEREBY
+ * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
+ * SOFTWARE.
+ */
+
+#include <types.h>
+#include <xen/xen.h>
+#include <mm.h>
+#include <gnttab.h>
+#include "tpm/tpm_marshalling.h"
+#include "vtpm_manager.h"
+#include "vtpm_cmd.h"
+#include <tpmback.h>
+
+#define TRYFAILGOTO(C) \
+   if((C)) { \
+      status = TPM_FAIL; \
+      goto abort_egress; \
+   }
+#define TRYFAILGOTOMSG(C, msg) \
+   if((C)) { \
+      status = TPM_FAIL; \
+      error(msg); \
+      goto abort_egress; \
+   }
+#define CHECKSTATUSGOTO(ret, fname) \
+   if((ret) != TPM_SUCCESS) { \
+      error("%s failed with error code (%lu)", fname, (unsigned long)
ret); \
+      status = ord; \
+      goto abort_egress; \
+   }
+
+#define ERR_MALFORMED "Malformed response from backend"
+#define ERR_TPMFRONT "Error sending command through frontend device"
+
+struct shpage {
+   void* page;
+   grant_ref_t grantref;
+};
+
+typedef struct shpage shpage_t;
+
+static inline int pack_header(uint8_t** bptr, UINT32* len, TPM_TAG tag, UINT32
size, TPM_COMMAND_CODE ord)
+{
+   return *bptr == NULL ||
+	 tpm_marshal_UINT16(bptr, len, tag) ||
+	 tpm_marshal_UINT32(bptr, len, size) ||
+	 tpm_marshal_UINT32(bptr, len, ord);
+}
+
+static inline int unpack_header(uint8_t** bptr, UINT32* len, TPM_TAG* tag,
UINT32* size, TPM_COMMAND_CODE* ord)
+{
+   return *bptr == NULL ||
+	 tpm_unmarshal_UINT16(bptr, len, tag) ||
+	 tpm_unmarshal_UINT32(bptr, len, size) ||
+	 tpm_unmarshal_UINT32(bptr, len, ord);
+}
+
+int create_error_response(tpmcmd_t* tpmcmd, TPM_RESULT errorcode)
+{
+   TPM_TAG tag;
+   UINT32 len = tpmcmd->req_len;
+   uint8_t* respptr;
+   uint8_t* cmdptr = tpmcmd->req;
+
+   if(!tpm_unmarshal_UINT16(&cmdptr, &len, &tag)) {
+      switch (tag) {
+         case TPM_TAG_RQU_COMMAND:
+            tag = TPM_TAG_RSP_COMMAND;
+            break;
+         case TPM_TAG_RQU_AUTH1_COMMAND:
+            tag = TPM_TAG_RQU_AUTH2_COMMAND;
+            break;
+         case TPM_TAG_RQU_AUTH2_COMMAND:
+            tag = TPM_TAG_RQU_AUTH2_COMMAND;
+            break;
+      }
+   } else {
+      tag = TPM_TAG_RSP_COMMAND;
+   }
+
+   tpmcmd->resp_len = len = 10;
+   tpmcmd->resp = respptr = tpm_malloc(tpmcmd->resp_len);
+
+   return pack_header(&respptr, &len, tag, len, errorcode);
+}
+
+TPM_RESULT VTPM_GetRandom(struct tpmfront_dev* tpmfront_dev, BYTE* bytes,
UINT32 *numbytes) {
+   TPM_RESULT status = TPM_SUCCESS;
+   uint8_t* cmdbuf, *resp, *bptr;
+   size_t resplen = 0;
+   UINT32 len;
+
+   /*Ask the real tpm for random bytes for the seed */
+   TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+   UINT32 size;
+   TPM_COMMAND_CODE ord = TPM_ORD_GetRandom;
+   len = size = sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_COMMAND_CODE) +
sizeof(UINT32);
+
+   /*Create the raw tpm command */
+   bptr = cmdbuf = malloc(size);
+   TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
+   TRYFAILGOTO(tpm_marshal_UINT32(&bptr, &len, *numbytes));
+
+   /* Send cmd, wait for response */
+   TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp,
&resplen),
+      ERR_TPMFRONT);
+
+   bptr = resp; len = resplen;
+   TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size,
&ord), ERR_MALFORMED);
+
+   //Check return status of command
+   CHECKSTATUSGOTO(ord, "TPM_GetRandom()");
+
+   // Get the number of random bytes in the response
+   TRYFAILGOTOMSG(tpm_unmarshal_UINT32(&bptr, &len, &size),
ERR_MALFORMED);
+   *numbytes = size;
+
+   //Get the random bytes out, tpm may give us less bytes than what we wanrt
+   TRYFAILGOTOMSG(tpm_unmarshal_BYTE_ARRAY(&bptr, &len, bytes,
*numbytes), ERR_MALFORMED);
+
+   goto egress;
+abort_egress:
+egress:
+   free(cmdbuf);
+   return status;
+
+}
+
+TPM_RESULT VTPM_LoadHashKey(struct tpmfront_dev* tpmfront_dev, uint8_t** data,
size_t* data_length)
+{
+   TPM_RESULT status = TPM_SUCCESS;
+   uint8_t* bptr, *resp;
+   uint8_t* cmdbuf = NULL;
+   size_t resplen = 0;
+   UINT32 len;
+
+   TPM_TAG tag = VTPM_TAG_REQ;
+   UINT32 size;
+   TPM_COMMAND_CODE ord = VTPM_ORD_LOADHASHKEY;
+
+   /*Create the command*/
+   len = size = VTPM_COMMAND_HEADER_SIZE;
+   bptr = cmdbuf = malloc(size);
+   TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
+
+   /* Send the command to vtpm_manager */
+   info("Requesting Encryption key from backend");
+   TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp,
&resplen), ERR_TPMFRONT);
+
+   /* Unpack response header */
+   bptr = resp;
+   len = resplen;
+   TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size,
&ord), ERR_MALFORMED);
+
+   /* Check return code */
+   CHECKSTATUSGOTO(ord, "VTPM_LoadHashKey()");
+
+   /* Get the size of the key */
+   *data_length = size - VTPM_COMMAND_HEADER_SIZE;
+
+   /* Copy the key bits */
+   *data = malloc(*data_length);
+   memcpy(*data, bptr, *data_length);
+
+   goto egress;
+abort_egress:
+   error("VTPM_LoadHashKey failed");
+egress:
+   free(cmdbuf);
+   return status;
+}
+
+TPM_RESULT VTPM_SaveHashKey(struct tpmfront_dev* tpmfront_dev, uint8_t* data,
size_t data_length)
+{
+   TPM_RESULT status = TPM_SUCCESS;
+   uint8_t* bptr, *resp;
+   uint8_t* cmdbuf = NULL;
+   size_t resplen = 0;
+   UINT32 len;
+
+   TPM_TAG tag = VTPM_TAG_REQ;
+   UINT32 size;
+   TPM_COMMAND_CODE ord = VTPM_ORD_SAVEHASHKEY;
+
+   /*Create the command*/
+   len = size = VTPM_COMMAND_HEADER_SIZE + data_length;
+   bptr = cmdbuf = malloc(size);
+   TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
+   memcpy(bptr, data, data_length);
+   bptr += data_length;
+
+   /* Send the command to vtpm_manager */
+   info("Sending encryption key to backend");
+   TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp,
&resplen), ERR_TPMFRONT);
+
+   /* Unpack response header */
+   bptr = resp;
+   len = resplen;
+   TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size,
&ord), ERR_MALFORMED);
+
+   /* Check return code */
+   CHECKSTATUSGOTO(ord, "VTPM_SaveHashKey()");
+
+   goto egress;
+abort_egress:
+   error("VTPM_SaveHashKey failed");
+egress:
+   free(cmdbuf);
+   return status;
+}
+
+TPM_RESULT VTPM_PCRRead(struct tpmfront_dev* tpmfront_dev, UINT32 pcrIndex,
BYTE* outDigest)
+{
+   TPM_RESULT status = TPM_SUCCESS;
+   uint8_t *cmdbuf, *resp, *bptr;
+   size_t resplen = 0;
+   UINT32 len;
+
+   /*Just send a TPM_PCRRead Command to the HW tpm */
+   TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+   UINT32 size;
+   TPM_COMMAND_CODE ord = TPM_ORD_PCRRead;
+   len = size = sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_COMMAND_CODE) +
sizeof(UINT32);
+
+   /*Create the raw tpm cmd */
+   bptr = cmdbuf = malloc(size);
+   TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
+   TRYFAILGOTO(tpm_marshal_UINT32(&bptr, &len, pcrIndex));
+
+   /*Send Cmd wait for response */
+   TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp,
&resplen), ERR_TPMFRONT);
+
+   bptr = resp; len = resplen;
+   TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size,
&ord), ERR_MALFORMED);
+
+   //Check return status of command
+   CHECKSTATUSGOTO(ord, "TPM_PCRRead");
+
+   //Get the ptr value
+   memcpy(outDigest, bptr, sizeof(TPM_PCRVALUE));
+
+   goto egress;
+abort_egress:
+egress:
+   free(cmdbuf);
+   return status;
+
+}
diff --git a/stubdom/vtpm/vtpm_cmd.h b/stubdom/vtpm/vtpm_cmd.h
new file mode 100644
index 0000000..b0bfa22
--- /dev/null
+++ b/stubdom/vtpm/vtpm_cmd.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense.  All rights reserved.
+ *
+ * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
+ * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
+ * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR  PURPOSE, AND NONINFRINGEMENT ARE HEREBY
+ * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
+ * SOFTWARE.
+ */
+
+#ifndef MANAGER_H
+#define MANAGER_H
+
+#include <tpmfront.h>
+#include <tpmback.h>
+#include "tpm/tpm_structures.h"
+
+/* Create a command response error header */
+int create_error_response(tpmcmd_t* tpmcmd, TPM_RESULT errorcode);
+/* Request random bytes from hardware tpm, returns 0 on success */
+TPM_RESULT VTPM_GetRandom(struct tpmfront_dev* tpmfront_dev, BYTE* bytes,
UINT32* numbytes);
+/* Retreive 256 bit AES encryption key from manager */
+TPM_RESULT VTPM_LoadHashKey(struct tpmfront_dev* tpmfront_dev, uint8_t** data,
size_t* data_length);
+/* Manager securely saves our 256 bit AES encryption key */
+TPM_RESULT VTPM_SaveHashKey(struct tpmfront_dev* tpmfront_dev, uint8_t* data,
size_t data_length);
+/* Send a TPM_PCRRead command passthrough the manager to the hw tpm */
+TPM_RESULT VTPM_PCRRead(struct tpmfront_dev* tpmfront_dev, UINT32 pcrIndex,
BYTE* outDigest);
+
+#endif
diff --git a/stubdom/vtpm/vtpm_pcrs.c b/stubdom/vtpm/vtpm_pcrs.c
new file mode 100644
index 0000000..22a6cef
--- /dev/null
+++ b/stubdom/vtpm/vtpm_pcrs.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense.  All rights reserved.
+ *
+ * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
+ * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
+ * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR  PURPOSE, AND NONINFRINGEMENT ARE HEREBY
+ * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
+ * SOFTWARE.
+ */
+
+#include "vtpm_pcrs.h"
+#include "vtpm_cmd.h"
+#include "tpm/tpm_data.h"
+
+#define PCR_VALUE      tpmData.permanent.data.pcrValue
+
+static int write_pcr_direct(unsigned int pcrIndex, uint8_t* val) {
+   if(pcrIndex > TPM_NUM_PCR) {
+      return TPM_BADINDEX;
+   }
+   memcpy(&PCR_VALUE[pcrIndex], val, sizeof(TPM_PCRVALUE));
+   return TPM_SUCCESS;
+}
+
+TPM_RESULT vtpm_initialize_hw_pcrs(struct tpmfront_dev* tpmfront_dev, unsigned
long pcrs)
+{
+   TPM_RESULT rc = TPM_SUCCESS;
+   uint8_t digest[sizeof(TPM_PCRVALUE)];
+
+   for(unsigned int i = 0; i < TPM_NUM_PCR; ++i) {
+      if(pcrs & 1 << i) {
+         if((rc = VTPM_PCRRead(tpmfront_dev, i, digest)) != TPM_SUCCESS) {
+            error("TPM_PCRRead failed with error : %d", rc);
+            return rc;
+         }
+         write_pcr_direct(i, digest);
+      }
+   }
+
+   return rc;
+}
diff --git a/stubdom/vtpm/vtpm_pcrs.h b/stubdom/vtpm/vtpm_pcrs.h
new file mode 100644
index 0000000..11835f9
--- /dev/null
+++ b/stubdom/vtpm/vtpm_pcrs.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense.  All rights reserved.
+ *
+ * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
+ * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
+ * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR  PURPOSE, AND NONINFRINGEMENT ARE HEREBY
+ * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
+ * SOFTWARE.
+ */
+
+#ifndef VTPM_PCRS_H
+#define VTPM_PCRS_H
+
+#include "tpm/tpm_structures.h"
+
+#define VTPM_PCR0 1
+#define VTPM_PCR1 1 << 1
+#define VTPM_PCR2 1 << 2
+#define VTPM_PCR3 1 << 3
+#define VTPM_PCR4 1 << 4
+#define VTPM_PCR5 1 << 5
+#define VTPM_PCR6 1 << 6
+#define VTPM_PCR7 1 << 7
+#define VTPM_PCR8 1 << 8
+#define VTPM_PCR9 1 << 9
+#define VTPM_PCR10 1 << 10
+#define VTPM_PCR11 1 << 11
+#define VTPM_PCR12 1 << 12
+#define VTPM_PCR13 1 << 13
+#define VTPM_PCR14 1 << 14
+#define VTPM_PCR15 1 << 15
+#define VTPM_PCR16 1 << 16
+#define VTPM_PCR17 1 << 17
+#define VTPM_PCR18 1 << 18
+#define VTPM_PCR19 1 << 19
+#define VTPM_PCR20 1 << 20
+#define VTPM_PCR21 1 << 21
+#define VTPM_PCR22 1 << 22
+#define VTPM_PCR23 1 << 23
+
+#define VTPM_PCRALL (1 << TPM_NUM_PCR) - 1
+#define VTPM_PCRNONE 0
+
+#define VTPM_NUMPCRS 24
+
+struct tpmfront_dev;
+
+TPM_RESULT vtpm_initialize_hw_pcrs(struct tpmfront_dev* tpmfront_dev, unsigned
long pcrs);
+
+
+#endif
diff --git a/stubdom/vtpm/vtpmblk.c b/stubdom/vtpm/vtpmblk.c
new file mode 100644
index 0000000..b343bd8
--- /dev/null
+++ b/stubdom/vtpm/vtpmblk.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense.  All rights reserved.
+ *
+ * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
+ * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
+ * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR  PURPOSE, AND NONINFRINGEMENT ARE HEREBY
+ * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
+ * SOFTWARE.
+ */
+
+#include <mini-os/byteorder.h>
+#include "vtpmblk.h"
+#include "tpm/tpm_marshalling.h"
+#include "vtpm_cmd.h"
+#include "polarssl/aes.h"
+#include "polarssl/sha1.h"
+#include <blkfront.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+/*Encryption key and block sizes */
+#define BLKSZ 16
+
+static struct blkfront_dev* blkdev = NULL;
+static int blkfront_fd = -1;
+
+int init_vtpmblk(struct tpmfront_dev* tpmfront_dev)
+{
+   struct blkfront_info blkinfo;
+   info("Initializing persistent NVM storage\n");
+
+   if((blkdev = init_blkfront(NULL, &blkinfo)) == NULL) {
+      error("BLKIO: ERROR Unable to initialize blkfront");
+      return -1;
+   }
+   if (blkinfo.info & VDISK_READONLY || blkinfo.mode != O_RDWR) {
+      error("BLKIO: ERROR block device is read only!");
+      goto error;
+   }
+   if((blkfront_fd = blkfront_open(blkdev)) == -1) {
+      error("Unable to open blkfront file descriptor!");
+      goto error;
+   }
+
+   return 0;
+error:
+   shutdown_blkfront(blkdev);
+   blkdev = NULL;
+   return -1;
+}
+
+void shutdown_vtpmblk(void)
+{
+   close(blkfront_fd);
+   blkfront_fd = -1;
+   blkdev = NULL;
+}
+
+int write_vtpmblk_raw(uint8_t *data, size_t data_length)
+{
+   int rc;
+   uint32_t lenbuf;
+   debug("Begin Write data=%p len=%u", data, data_length);
+
+   lenbuf = cpu_to_be32((uint32_t)data_length);
+
+   lseek(blkfront_fd, 0, SEEK_SET);
+   if((rc = write(blkfront_fd, (uint8_t*)&lenbuf, 4)) != 4) {
+      error("write(length) failed! error was %s", strerror(errno));
+      return -1;
+   }
+   if((rc = write(blkfront_fd, data, data_length)) != data_length) {
+      error("write(data) failed! error was %s", strerror(errno));
+      return -1;
+   }
+
+   info("Wrote %u bytes to NVM persistent storage", data_length);
+
+   return 0;
+}
+
+int read_vtpmblk_raw(uint8_t **data, size_t *data_length)
+{
+   int rc;
+   uint32_t lenbuf;
+
+   lseek(blkfront_fd, 0, SEEK_SET);
+   if(( rc = read(blkfront_fd, (uint8_t*)&lenbuf, 4)) != 4) {
+      error("read(length) failed! error was %s", strerror(errno));
+      return -1;
+   }
+   *data_length = (size_t) cpu_to_be32(lenbuf);
+   if(*data_length == 0) {
+      error("read 0 data_length for NVM");
+      return -1;
+   }
+
+   *data = tpm_malloc(*data_length);
+   if((rc = read(blkfront_fd, *data, *data_length)) != *data_length) {
+      error("read(data) failed! error was %s", strerror(errno));
+      return -1;
+   }
+
+   info("Read %u bytes from NVM persistent storage", *data_length);
+   return 0;
+}
+
+int encrypt_vtpmblk(uint8_t* clear, size_t clear_len, uint8_t** cipher, size_t*
cipher_len, uint8_t* symkey)
+{
+   int rc = 0;
+   uint8_t iv[BLKSZ];
+   aes_context aes_ctx;
+   UINT32 temp;
+   int mod;
+
+   uint8_t* clbuf = NULL;
+
+   uint8_t* ivptr;
+   int ivlen;
+
+   uint8_t* cptr;	//Cipher block pointer
+   int clen;	//Cipher block length
+
+   /*Create a new 256 bit encryption key */
+   if(symkey == NULL) {
+      rc = -1;
+      goto abort_egress;
+   }
+   tpm_get_extern_random_bytes(symkey, NVMKEYSZ);
+
+   /*Setup initialization vector - random bits and then 4 bytes clear text size
at the end*/
+   temp = sizeof(UINT32);
+   ivlen = BLKSZ - temp;
+   tpm_get_extern_random_bytes(iv, ivlen);
+   ivptr = iv + ivlen;
+   tpm_marshal_UINT32(&ivptr, &temp, (UINT32) clear_len);
+
+   /*The clear text needs to be padded out to a multiple of BLKSZ */
+   mod = clear_len % BLKSZ;
+   clen = mod ? clear_len + BLKSZ - mod : clear_len;
+   clbuf = malloc(clen);
+   if (clbuf == NULL) {
+      rc = -1;
+      goto abort_egress;
+   }
+   memcpy(clbuf, clear, clear_len);
+   /* zero out the padding bits - FIXME: better / more secure way to handle
these? */
+   if(clen - clear_len) {
+      memset(clbuf + clear_len, 0, clen - clear_len);
+   }
+
+   /* Setup the ciphertext buffer */
+   *cipher_len = BLKSZ + clen;		/*iv + ciphertext */
+   cptr = *cipher = malloc(*cipher_len);
+   if (*cipher == NULL) {
+      rc = -1;
+      goto abort_egress;
+   }
+
+   /* Copy the IV to cipher text blob*/
+   memcpy(cptr, iv, BLKSZ);
+   cptr += BLKSZ;
+
+   /* Setup encryption */
+   aes_setkey_enc(&aes_ctx, symkey, 256);
+
+   /* Do encryption now */
+   aes_crypt_cbc(&aes_ctx, AES_ENCRYPT, clen, iv, clbuf, cptr);
+
+   goto egress;
+abort_egress:
+egress:
+   free(clbuf);
+   return rc;
+}
+int decrypt_vtpmblk(uint8_t* cipher, size_t cipher_len, uint8_t** clear,
size_t* clear_len, uint8_t* symkey)
+{
+   int rc = 0;
+   uint8_t iv[BLKSZ];
+   uint8_t* ivptr;
+   UINT32 u32, temp;
+   aes_context aes_ctx;
+
+   uint8_t* cptr = cipher;	//cipher block pointer
+   int clen = cipher_len;	//cipher block length
+
+   /* Pull out the initialization vector */
+   memcpy(iv, cipher, BLKSZ);
+   cptr += BLKSZ;
+   clen -= BLKSZ;
+
+   /* Setup the clear text buffer */
+   if((*clear = malloc(clen)) == NULL) {
+      rc = -1;
+      goto abort_egress;
+   }
+
+   /* Get the length of clear text from last 4 bytes of iv */
+   temp = sizeof(UINT32);
+   ivptr = iv + BLKSZ - temp;
+   tpm_unmarshal_UINT32(&ivptr, &temp, &u32);
+   *clear_len = u32;
+
+   /* Setup decryption */
+   aes_setkey_dec(&aes_ctx, symkey, 256);
+
+   /* Do decryption now */
+   if ((clen % BLKSZ) != 0) {
+      error("Decryption Error: Cipher block size was not a multiple of
%u", BLKSZ);
+      rc = -1;
+      goto abort_egress;
+   }
+   aes_crypt_cbc(&aes_ctx, AES_DECRYPT, clen, iv, cptr, *clear);
+
+   goto egress;
+abort_egress:
+egress:
+   return rc;
+}
+
+int write_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t
data_length) {
+   int rc;
+   uint8_t* cipher = NULL;
+   size_t cipher_len = 0;
+   uint8_t hashkey[HASHKEYSZ];
+   uint8_t* symkey = hashkey + HASHSZ;
+
+   /* Encrypt the data */
+   if((rc = encrypt_vtpmblk(data, data_length, &cipher, &cipher_len,
symkey))) {
+      goto abort_egress;
+   }
+   /* Write to disk */
+   if((rc = write_vtpmblk_raw(cipher, cipher_len))) {
+      goto abort_egress;
+   }
+   /* Get sha1 hash of data */
+   sha1(cipher, cipher_len, hashkey);
+
+   /* Send hash and key to manager */
+   if((rc = VTPM_SaveHashKey(tpmfront_dev, hashkey, HASHKEYSZ)) != TPM_SUCCESS)
{
+      goto abort_egress;
+   }
+   goto egress;
+abort_egress:
+egress:
+   free(cipher);
+   return rc;
+}
+
+int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t
*data_length) {
+   int rc;
+   uint8_t* cipher = NULL;
+   size_t cipher_len = 0;
+   size_t keysize;
+   uint8_t* hashkey = NULL;
+   uint8_t hash[HASHSZ];
+   uint8_t* symkey;
+
+   /* Retreive the hash and the key from the manager */
+   if((rc = VTPM_LoadHashKey(tpmfront_dev, &hashkey, &keysize)) !=
TPM_SUCCESS) {
+      goto abort_egress;
+   }
+   if(keysize != HASHKEYSZ) {
+      error("Manager returned a hashkey of invalid size! expected %d,
actual %d", NVMKEYSZ, keysize);
+      rc = -1;
+      goto abort_egress;
+   }
+   symkey = hashkey + HASHSZ;
+
+   /* Read from disk now */
+   if((rc = read_vtpmblk_raw(&cipher, &cipher_len))) {
+      goto abort_egress;
+   }
+
+   /* Compute the hash of the cipher text and compare */
+   sha1(cipher, cipher_len, hash);
+   if(memcmp(hash, hashkey, HASHSZ)) {
+      int i;
+      error("NVM Storage Checksum failed!");
+      printf("Expected: ");
+      for(i = 0; i < HASHSZ; ++i) {
+	 printf("%02hhX ", hashkey[i]);
+      }
+      printf("\n");
+      printf("Actual:   ");
+      for(i = 0; i < HASHSZ; ++i) {
+	 printf("%02hhX ", hash[i]);
+      }
+      printf("\n");
+      rc = -1;
+      goto abort_egress;
+   }
+
+   /* Decrypt the blob */
+   if((rc = decrypt_vtpmblk(cipher, cipher_len, data, data_length, symkey))) {
+      goto abort_egress;
+   }
+   goto egress;
+abort_egress:
+egress:
+   free(cipher);
+   free(hashkey);
+   return rc;
+}
diff --git a/stubdom/vtpm/vtpmblk.h b/stubdom/vtpm/vtpmblk.h
new file mode 100644
index 0000000..282ce6a
--- /dev/null
+++ b/stubdom/vtpm/vtpmblk.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2010-2012 United States Government, as represented by
+ * the Secretary of Defense.  All rights reserved.
+ *
+ * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT
+ * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES
+ * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR  PURPOSE, AND NONINFRINGEMENT ARE HEREBY
+ * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE
+ * SOFTWARE.
+ */
+
+#ifndef NVM_H
+#define NVM_H
+#include <mini-os/types.h>
+#include <xen/xen.h>
+#include <tpmfront.h>
+
+#define NVMKEYSZ 32
+#define HASHSZ 20
+#define HASHKEYSZ (NVMKEYSZ + HASHSZ)
+
+int init_vtpmblk(struct tpmfront_dev* tpmfront_dev);
+void shutdown_vtpmblk(void);
+
+/* Encrypts and writes data to blk device */
+int write_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t *data, size_t
data_length);
+/* Reads, Decrypts, and returns data from blk device */
+int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t **data, size_t
*data_length);
+
+#endif
--
1.7.10.4