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

[Xen-devel] PATCH [base vtpm and libxl patches 2/6] Bug fixes and breakout of vtpm_manager functionality



Fix numerous memory leaks, IO deadlocks, and other bugs that make
vtpm_manager barely usable. Also breakout the vtpm_manager compilation
into separate libraries to facilitate reusing parts of it in mini-os
domains. Finally, add new programs for communicating with the manager
correctly to avoid IO deadlock errors.

Signed off by Matthew Fioravante matthew.fioravante@xxxxxxxxxx

---
Changed since previous:
* rebased off of latest xen-unstable

diff --git a/tools/vtpm_manager/Makefile b/tools/vtpm_manager/Makefile
--- a/tools/vtpm_manager/Makefile
+++ b/tools/vtpm_manager/Makefile
@@ -1,9 +1,9 @@
-XEN_ROOT = $(CURDIR)/../..
+XEN_ROOT = $(realpath ../..)
 
 # Base definitions and rules
-include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+include Rules.mk
 
-SUBDIRS        = crypto tcs util manager migration
+SUBDIRS        = crypto tcs util manager migration vtpmmgrtalk vtpmconnd
 OPENSSL_HEADER    = /usr/include/openssl/crypto.h
 
 .PHONY: all clean install
diff --git a/tools/vtpm_manager/README b/tools/vtpm_manager/README
--- a/tools/vtpm_manager/README
+++ b/tools/vtpm_manager/README
@@ -43,9 +43,6 @@ Compile Flags
 LOGGING_MODULES              -> How extensive logging happens
                                 see util/log.h for more info
 
-VTPM_MULTI_VM                -> Defined: VTPMs run in their own VMs
-                                Not Defined (default): VTPMs are processes
-
 # Debugging flags that may disappear without notice in the future
 
 DUMMY_BACKEND                -> vtpm_manager listens on /tmp/in.fifo and
@@ -59,6 +56,10 @@ WELL_KNOWN_OWNER_AUTH        -> Rather than randomly
generating the password for
                                 lost. However this has no protection
from malicious app
                                 issuing a TPM_OwnerClear to wipe the TPM
 
+VTPM_STUBDOM             -> vtpm_manager runs in vtpm_stubdom mode with
+                vtpm instances running in mini-os domains
+                (see: stubdom/vtpm/README for details)
+
 Requirements
 ============
 - xen-unstable
diff --git a/tools/vtpm_manager/Rules.mk b/tools/vtpm_manager/Rules.mk
--- a/tools/vtpm_manager/Rules.mk
+++ b/tools/vtpm_manager/Rules.mk
@@ -6,7 +6,7 @@ include $(XEN_ROOT)/tools/Rules.mk
 #
 
 # General compiler flags
-CFLAGS    = -Werror -g3
+CFLAGS    = -Werror -g3 -I.
 
 # Generic project files
 HDRS    = $(wildcard *.h)
@@ -31,18 +31,18 @@ $(OBJS): $(SRCS)
 CFLAGS += -D_GNU_SOURCE
 
 # Logging Level. See utils/tools.h for usage
-CFLAGS +=
-DLOGGING_MODULES="(BITMASK(VTPM_LOG_TCS)|BITMASK(VTPM_LOG_VTSP)|BITMASK(VTPM_LOG_VTPM))"
+#CFLAGS +=
-DLOGGING_MODULES="(BITMASK(VTPM_LOG_TCS)|BITMASK(VTPM_LOG_VTSP)|BITMASK(VTPM_LOG_VTPM))"
 
 # Silent Mode
 #CFLAGS += -DLOGGING_MODULES=0x0
-#CFLAGS += -DLOGGING_MODULES=0xff
-
-# Use frontend/backend pairs between manager & DMs?
-#CFLAGS += -DVTPM_MULTI_VM
+CFLAGS += -DLOGGING_MODULES=0xff
 
 # vtpm_manager listens on fifo's rather than backend
 #CFLAGS += -DDUMMY_BACKEND
 
+# Build for use with vtpm-stubdom
+#CFLAGS += -DVTPM_STUBDOM
+
 # TCS talks to fifo's rather than /dev/tpm. TPM Emulator assumed on fifos
 #CFLAGS += -DDUMMY_TPM
 
@@ -52,8 +52,3 @@ CFLAGS +=
-DLOGGING_MODULES="(BITMASK(VTPM_LOG_TCS)|BITMASK(VTPM_LOG_VTSP)|BITMA
 # Fixed OwnerAuth
 #CFLAGS += -DWELL_KNOWN_OWNER_AUTH
 
-# Include
-CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/crypto
-CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/util
-CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/tcs
-CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/manager
diff --git a/tools/vtpm_manager/crypto/Makefile
b/tools/vtpm_manager/crypto/Makefile
--- a/tools/vtpm_manager/crypto/Makefile
+++ b/tools/vtpm_manager/crypto/Makefile
@@ -1,5 +1,9 @@
-XEN_ROOT = $(CURDIR)/../../..
-include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+XEN_ROOT = $(realpath ../../..)
+include ../Rules.mk
+
+CFLAGS += -I../util
+CFLAGS += -I../tcs
+CFLAGS += -I../manager
 
 BIN        = libtcpaCrypto.a
 
diff --git a/tools/vtpm_manager/crypto/crypto.c
b/tools/vtpm_manager/crypto/crypto.c
--- a/tools/vtpm_manager/crypto/crypto.c
+++ b/tools/vtpm_manager/crypto/crypto.c
@@ -45,6 +45,8 @@
 #include "crypto.h"
 #include "log.h"
 
+extern const EVP_CIPHER * SYM_CIPHER;
+
 /**
  * Initialize cryptography library
  * @rand: random seed
@@ -83,6 +85,6 @@ void Crypto_GetRandom(void* data, int size) {
   result = RAND_pseudo_bytes((BYTE*) data, size);
  
   if (result <= 0)
-    vtpmlogerror (VTPM_LOG_CRYPTO, "RAND_pseudo_bytes failed: %s\n",
-         ERR_error_string (ERR_get_error(), NULL));
+    vtpmlogerror (VTPM_LOG_CRYPTO, "RAND_pseudo_bytes failed: rc=%d
errstr=%s\n",
+      result, ERR_error_string (ERR_get_error(), NULL));
 }
diff --git a/tools/vtpm_manager/crypto/crypto.h
b/tools/vtpm_manager/crypto/crypto.h
--- a/tools/vtpm_manager/crypto/crypto.h
+++ b/tools/vtpm_manager/crypto/crypto.h
@@ -76,7 +76,7 @@ typedef struct CRYPTO_INFO {
 
 void Crypto_Init(const BYTE* rand, int size);
 
-void Crypto_Exit();
+void Crypto_Exit(void);
 
 void Crypto_GetRandom(void* data, int size);
 
@@ -127,6 +127,8 @@ void Crypto_RSABuildCryptoInfoPublic(   /*[IN]*/
UINT32 pubExpSize,
                                         /*[IN]*/ BYTE *modulus,
                                         CRYPTO_INFO* cryptoInfo);
 
+void Crypto_RSACryptoInfoFree(CRYPTO_INFO* cryptoInfo);
+
 //
 // symmetric pack and unpack operations
 //
diff --git a/tools/vtpm_manager/crypto/rsa.c
b/tools/vtpm_manager/crypto/rsa.c
--- a/tools/vtpm_manager/crypto/rsa.c
+++ b/tools/vtpm_manager/crypto/rsa.c
@@ -149,6 +149,10 @@ void Crypto_RSABuildCryptoInfoPublic(   /*[IN]*/
UINT32 pubExpSize,
  
 }
 
+void Crypto_RSACryptoInfoFree(CRYPTO_INFO* cryptoInfo) {
+   RSA_free(cryptoInfo->keyInfo);
+}
+
 int Crypto_RSAEnc(  CRYPTO_INFO *key,
             UINT32 inDataSize,
             BYTE *inData,
@@ -161,6 +165,7 @@ int Crypto_RSAEnc(  CRYPTO_INFO *key,
    
   if (paddedData == NULL)
     return -1;
+  memset(paddedData, 0, sizeof(BYTE) * paddedDataSize);
 
   *outDataSize = 0;
  
diff --git a/tools/vtpm_manager/crypto/sym_crypto.c
b/tools/vtpm_manager/crypto/sym_crypto.c
--- a/tools/vtpm_manager/crypto/sym_crypto.c
+++ b/tools/vtpm_manager/crypto/sym_crypto.c
@@ -41,8 +41,16 @@
 #include <openssl/rand.h>
 
 #include "tcg.h"
+#include "log.h"
 #include "sym_crypto.h"
 
+struct symkey_t {
+  buffer_t key;
+
+  EVP_CIPHER_CTX context;
+  const EVP_CIPHER * cipher;
+};
+
 typedef enum crypt_op_type_t {
   CRYPT_ENCRYPT,
   CRYPT_DECRYPT
@@ -61,19 +69,22 @@ const EVP_CIPHER * SYM_CIPHER = NULL;
 const BYTE ZERO_IV[EVP_MAX_IV_LENGTH] = {0};
 
 
-TPM_RESULT Crypto_symcrypto_initkey (symkey_t * key, const buffer_t*
keybits) {
+TPM_RESULT Crypto_symcrypto_initkey (symkey_t ** key, const buffer_t*
keybits) {
   TPM_RESULT status = TPM_SUCCESS;
  
-  EVP_CIPHER_CTX_init (&key->context);
+  *key = malloc(sizeof(symkey_t));
+
+  EVP_CIPHER_CTX_init (&(*key)->context);
  
-  key->cipher = SYM_CIPHER;
+  (*key)->cipher = SYM_CIPHER;
  
-  TPMTRYRETURN( buffer_init_copy (&key->key, keybits));
+  TPMTRYRETURN( buffer_init_copy (&(*key)->key, keybits));
    
   goto egress;
  
  abort_egress:
-  EVP_CIPHER_CTX_cleanup (&key->context);
+  EVP_CIPHER_CTX_cleanup (&(*key)->context);
+  free(key);
  
  egress:
  
@@ -82,19 +93,21 @@ TPM_RESULT Crypto_symcrypto_initkey (symkey_t * key,
const buffer_t* keybits) {
 
 
 
-TPM_RESULT Crypto_symcrypto_genkey (symkey_t * key) {
+TPM_RESULT Crypto_symcrypto_genkey (symkey_t ** key) {
   int res;
   TPM_RESULT status = TPM_SUCCESS;
+
+  *key = malloc(sizeof(symkey_t));
  
   // hmm, EVP_CIPHER_CTX_init does not return a value
-  EVP_CIPHER_CTX_init (&key->context);
+  EVP_CIPHER_CTX_init (&(*key)->context);
  
-  key->cipher = SYM_CIPHER;
+  (*key)->cipher = SYM_CIPHER;
  
-  TPMTRYRETURN( buffer_init (&key->key,
EVP_CIPHER_key_length(key->cipher), NULL)) ;
+  TPMTRYRETURN( buffer_init (&(*key)->key,
EVP_CIPHER_key_length((*key)->cipher), NULL)) ;
  
   // and generate the key material
-  res = RAND_pseudo_bytes (key->key.bytes, key->key.size);
+  res = RAND_pseudo_bytes ((*key)->key.bytes, (*key)->key.size);
   if (res < 0)
     ERRORDIE (TPM_SHORTRANDOM);
  
@@ -102,8 +115,9 @@ TPM_RESULT Crypto_symcrypto_genkey (symkey_t * key) {
   goto egress;
  
  abort_egress:
-  EVP_CIPHER_CTX_cleanup (&key->context);
-  buffer_free (&key->key);
+  EVP_CIPHER_CTX_cleanup (&(*key)->context);
+  buffer_free (&(*key)->key);
+  free(key);
  
  egress:
   return status; 
@@ -119,11 +133,11 @@ TPM_RESULT Crypto_symcrypto_encrypt (symkey_t* key,
  
   buffer_init_const (&iv, EVP_MAX_IV_LENGTH, ZERO_IV);
  
-  buffer_init (o_cipher,
-           clear->size +
-           EVP_CIPHER_iv_length(key->cipher) +
-           EVP_CIPHER_block_size (key->cipher),
-                 0);
+  TPMTRYRETURN( buffer_init (o_cipher,
+                  clear->size +
+                  EVP_CIPHER_iv_length(key->cipher) +
+                  EVP_CIPHER_block_size (key->cipher),
+                 0) );
  
   // copy the IV into the front
   buffer_copy (o_cipher, &iv);
@@ -139,6 +153,7 @@ TPM_RESULT Crypto_symcrypto_encrypt (symkey_t* key,
   goto egress;
  
  abort_egress:
+  buffer_free(o_cipher);
  
  egress:
  
@@ -170,7 +185,7 @@ TPM_RESULT Crypto_symcrypto_decrypt (symkey_t* key,
  
   // and decrypt
   TPMTRYRETURN ( ossl_symcrypto_op (key, &cipher_alias, &iv, o_clear,
CRYPT_DECRYPT) );
- 
+
   goto egress;
  
  abort_egress:
@@ -188,6 +203,8 @@ TPM_RESULT Crypto_symcrypto_freekey (symkey_t * key) {
   buffer_free (&key->key);
  
   EVP_CIPHER_CTX_cleanup (&key->context);
+
+  free(key);
  
   return TPM_SUCCESS;
 }
@@ -235,3 +252,8 @@ TPM_RESULT ossl_symcrypto_op (symkey_t* key,
  
   return status;
 }
+
+buffer_t* Crypto_symkey_getkey(symkey_t* key)
+{
+   return &key->key;
+}
diff --git a/tools/vtpm_manager/crypto/sym_crypto.h
b/tools/vtpm_manager/crypto/sym_crypto.h
--- a/tools/vtpm_manager/crypto/sym_crypto.h
+++ b/tools/vtpm_manager/crypto/sym_crypto.h
@@ -40,21 +40,15 @@
 #ifndef _SYM_CRYPTO_H
 #define _SYM_CRYPTO_H
 
-#include <openssl/evp.h>
 #include "buffer.h"
 
-typedef struct symkey_t {
-  buffer_t key;
- 
-  EVP_CIPHER_CTX context;
-  const EVP_CIPHER * cipher;
-} symkey_t;
+typedef struct symkey_t symkey_t;
 
-extern const EVP_CIPHER * SYM_CIPHER;
+//Allocates a symkey with random bits
+TPM_RESULT Crypto_symcrypto_genkey (symkey_t ** key);
 
-TPM_RESULT Crypto_symcrypto_genkey (symkey_t * key);
-
-TPM_RESULT Crypto_symcrypto_initkey (symkey_t * key, const buffer_t*
keybits);
+//Allocates a symkey with given keybits
+TPM_RESULT Crypto_symcrypto_initkey (symkey_t ** key, const buffer_t*
keybits);
 
 
 // these functions will allocate their output buffers
@@ -66,7 +60,10 @@ TPM_RESULT Crypto_symcrypto_decrypt (symkey_t* key,
                               const buffer_t* cipher,
                               buffer_t* o_clear);
 
-// only free the internal parts, not the 'key' ptr
+//Frees the symkey
 TPM_RESULT Crypto_symcrypto_freekey (symkey_t * key);
 
+//Get the raw key byte buffer
+buffer_t* Crypto_symkey_getkey(symkey_t* key);
+
 #endif /* _SYM_CRYPTO_H */
diff --git a/tools/vtpm_manager/manager/Makefile
b/tools/vtpm_manager/manager/Makefile
--- a/tools/vtpm_manager/manager/Makefile
+++ b/tools/vtpm_manager/manager/Makefile
@@ -1,7 +1,18 @@
-XEN_ROOT = $(CURDIR)/../../..
-include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+XEN_ROOT = $(realpath ../../..)
+include ../Rules.mk
+
+CFLAGS += -I../crypto
+CFLAGS += -I../util
+CFLAGS += -I../tcs
+
+
+MAINS         := vtpmd.o
+MGRLIB         := libvtpmmanager.a
+VTSPOBJS    := vtsp.o
+VTSPLIB        := libvtsp.a
+BIN        := vtpm_managerd
+OBJS         := $(filter-out $(MAINS) $(VTSPOBJS), $(OBJS))
 
-BIN        = vtpm_managerd
 
 .PHONY: all
 all: build
@@ -28,8 +39,14 @@ clean:
 mrproper: clean
     rm -f *~
 
-$(BIN): $(OBJS)
-    $(CC) $(LDFLAGS) $^ $(LIBS) -o $@
+$(BIN): $(MAINS) $(MGRLIB) $(VTSPLIB)
+    $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LIBS) -o $@
+
+$(VTSPLIB): $(VTSPOBJS)
+    $(AR) rcs $@ $^
+
+$(MGRLIB): $(OBJS)
+    $(AR) rcs $@ $^
 
 # libraries
 LIBS += ../tcs/libTCS.a ../util/libTCGUtils.a ../crypto/libtcpaCrypto.a
diff --git a/tools/vtpm_manager/manager/dmictl.c
b/tools/vtpm_manager/manager/dmictl.c
--- a/tools/vtpm_manager/manager/dmictl.c
+++ b/tools/vtpm_manager/manager/dmictl.c
@@ -40,6 +40,9 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdlib.h>
 
 #include "vtpmpriv.h"
 #include "bsg.h"
@@ -51,6 +54,13 @@
 
 #define TPM_EMULATOR_PATH "/usr/bin/vtpmd"
 
+#ifndef VTPM_STUBDOM
+// This is needed to all extra_close_dmi to close this to prevent a
+// broken pipe when no DMIs are left.
+vtpm_ipc_handle_t *g_rx_tpm_ipc_h;
+#endif
+
+
 // if dmi_res is non-null, then return a pointer to new object.
 // Also, this does not fill in the measurements. They should be filled by
 // design dependent code or saveNVM
@@ -81,7 +91,7 @@ TPM_RESULT init_dmi(UINT32 dmi_id, BYTE dmi_type,
VTPM_DMI_RESOURCE **dmi_res) {
 
   // install into map
   if (!hashtable_insert(vtpm_globals->dmi_map, dmi_id_key, new_dmi)){
-    vtpmlogerror(VTPM_LOG_VTPM, "Failed to insert instance into table.
Aborting.\n", dmi_id);
+    vtpmlogerror(VTPM_LOG_VTPM, "Failed to insert instance %" PRIu32
"into table. Aborting.\n", dmi_id);
     status = TPM_FAIL;
     goto abort_egress;
   }
@@ -116,6 +126,161 @@ TPM_RESULT close_dmi(VTPM_DMI_RESOURCE *dmi_res) {
 
   return (VTPM_Close_DMI_Extra(dmi_res) );
 }
+
+void free_dmi(VTPM_DMI_RESOURCE *dmi_res) {
+   if(dmi_res != NULL) {
+      free(dmi_res->NVMLocation);
+   }
+   free(dmi_res);
+}
+
+TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res, BYTE vm_type,
BYTE startup_mode) {
+
+  TPM_RESULT status = TPM_SUCCESS;
+#ifndef VTPM_STUBDOM
+  int fh;
+  char dmi_id_str[11]; // UINT32s are up to 10 digits + NULL
+  char *tx_vtpm_name, *tx_tpm_name, *vm_type_string;
+  struct stat file_info;
+
+  if (dmi_res->dmi_id == VTPM_CTL_DM) {
+    dmi_res->tx_tpm_ipc_h = NULL;
+    dmi_res->rx_tpm_ipc_h = NULL;
+    dmi_res->tx_vtpm_ipc_h = NULL;
+    dmi_res->rx_vtpm_ipc_h = NULL;
+  } else {
+    // Create a pair of fifo pipes
+    dmi_res->rx_tpm_ipc_h = NULL;
+    dmi_res->rx_vtpm_ipc_h = NULL;
+
+    if ( ((dmi_res->tx_tpm_ipc_h = (vtpm_ipc_handle_t *) malloc
(sizeof(vtpm_ipc_handle_t))) == NULL ) ||
+         ((dmi_res->tx_vtpm_ipc_h =(vtpm_ipc_handle_t *) malloc
(sizeof(vtpm_ipc_handle_t))) == NULL ) ||
+         ((tx_tpm_name = (char *) malloc(11 +
strlen(VTPM_TX_TPM_FNAME))) == NULL ) ||
+         ((tx_vtpm_name =(char *) malloc(11 +
strlen(VTPM_TX_VTPM_FNAME))) == NULL) ) {
+      status =TPM_RESOURCES;
+      goto abort_egress;
+    }
+
+    sprintf(tx_tpm_name, VTPM_TX_TPM_FNAME, (uint32_t) dmi_res->dmi_id);
+    sprintf(tx_vtpm_name, VTPM_TX_VTPM_FNAME, (uint32_t) dmi_res->dmi_id);
+
+    if ( (vtpm_ipc_init(dmi_res->tx_tpm_ipc_h, tx_tpm_name, O_WRONLY |
O_NONBLOCK, TRUE, FALSE) != 0) ||
+         (vtpm_ipc_init(dmi_res->tx_vtpm_ipc_h, tx_vtpm_name, O_WRONLY,
TRUE, FALSE) != 0) ) { //FIXME: O_NONBLOCK?
+      status = TPM_IOERROR;
+      goto abort_egress;
+    }
+
+    // Measure DMI
+    // FIXME: This will measure DMI. Until then use a fixed
DMI_Measurement value
+    // Also, this mechanism is specific to 1 VM architecture.
+    /*
+    fh = open(TPM_EMULATOR_PATH, O_RDONLY);
+    stat_ret = fstat(fh, &file_stat);
+    if (stat_ret == 0)
+      dmi_size = file_stat.st_size;
+    else {
+      vtpmlogerror(VTPM_LOG_VTPM, "Could not open vtpmd!!\n");
+      status = TPM_IOERROR;
+      goto abort_egress;
+    }
+    dmi_buffer
+    */
+    memset(&dmi_res->DMI_measurement, 0xcc, sizeof(TPM_DIGEST));
+
+    if (vm_type == VTPM_TYPE_PVM)
+      vm_type_string = (BYTE *)&VTPM_TYPE_PVM_STRING;
+    else
+      vm_type_string = (BYTE *)&VTPM_TYPE_HVM_STRING;
+
+    // Launch DMI
+    sprintf(dmi_id_str, "%d", (int) dmi_res->dmi_id);
+#ifdef MANUAL_DM_LAUNCH
+    vtpmlogerror(VTPM_LOG_VTPM, "Manually start VTPM with dmi=%s
now.\n", dmi_id_str);
+    dmi_res->dmi_pid = 0;
+#else
+    pid_t pid = fork();
+
+    if (pid == -1) {
+      vtpmlogerror(VTPM_LOG_VTPM, "Could not fork to launch vtpm\n");
+      status = TPM_RESOURCES;
+      goto abort_egress;
+    } else if (pid == 0) {
+      switch (startup_mode) {
+      case TPM_ST_CLEAR:
+        execl (TPM_EMULATOR_PATH, "vtpmd", "clear", vm_type_string,
dmi_id_str, NULL);
+        break;
+      case TPM_ST_STATE:
+        execl (TPM_EMULATOR_PATH, "vtpmd", "save", vm_type_string,
dmi_id_str, NULL);
+        break;
+      case TPM_ST_DEACTIVATED:
+        execl (TPM_EMULATOR_PATH, "vtpmd", "deactivated",
vm_type_string, dmi_id_str, NULL);
+        break;
+      default:
+        status = TPM_BAD_PARAMETER;
+        goto abort_egress;
+      }
+
+      // Returning from these at all is an error.
+      vtpmlogerror(VTPM_LOG_VTPM, "Could not exec to launch vtpm\n");
+    } else {
+      dmi_res->dmi_pid = pid;
+      vtpmloginfo(VTPM_LOG_VTPM, "Launching DMI on PID = %d\n", pid);
+    }
+#endif // MANUAL_DM_LAUNCH
+
+  } // If DMI = VTPM_CTL_DM
+    status = TPM_SUCCESS;
+#endif
+
+abort_egress:
+    //FIXME: Everything should be freed here
+  return (status);
+}
+
+TPM_RESULT VTPM_Close_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res) {
+  TPM_RESULT status = TPM_SUCCESS;
+
+#ifndef VTPM_STUBDOM
+  if (vtpm_globals->connected_dmis == 0) {
+    // No more DMI's connected. Close fifo to prevent a broken pipe.
+    // This is hackish. Need to think of another way.
+    vtpm_ipc_close(g_rx_tpm_ipc_h);
+  }
+
+
+  if (dmi_res->dmi_id != VTPM_CTL_DM) {
+    vtpm_ipc_close(dmi_res->tx_tpm_ipc_h);
+    vtpm_ipc_close(dmi_res->tx_vtpm_ipc_h);
+
+    free(dmi_res->tx_tpm_ipc_h->name);
+    free(dmi_res->tx_vtpm_ipc_h->name);
+    free(dmi_res->tx_tpm_ipc_h);
+    free(dmi_res->tx_vtpm_ipc_h);
+
+#ifndef MANUAL_DM_LAUNCH
+    if (dmi_res->dmi_id != VTPM_CTL_DM) {
+      if (dmi_res->dmi_pid != 0) {
+        vtpmloginfo(VTPM_LOG_VTPM, "Killing dmi on pid %d.\n",
dmi_res->dmi_pid);
+        if (kill(dmi_res->dmi_pid, SIGKILL) !=0) {
+          vtpmloginfo(VTPM_LOG_VTPM, "DMI on pid %d is already
dead.\n", dmi_res->dmi_pid);
+        } else if (waitpid(dmi_res->dmi_pid, NULL, 0) !=
dmi_res->dmi_pid) {
+          vtpmlogerror(VTPM_LOG_VTPM, "DMI on pid %d failed to
stop.\n", dmi_res->dmi_pid);
+          status = TPM_FAIL;
+        }
+      } else {
+        vtpmlogerror(VTPM_LOG_VTPM, "Could not kill dmi because it's
pid was 0.\n");
+        status = TPM_FAIL;
+      }
+    }
+#endif
+
+  } //endif ! dom0
+#endif
+  return status;
+}
+
+
+
    
 TPM_RESULT VTPM_Handle_New_DMI(const buffer_t *param_buf) {
  
@@ -254,7 +419,7 @@ TPM_RESULT VTPM_Handle_Delete_DMI( const buffer_t
*param_buf) {
  
   // Close DMI first
   TPMTRYRETURN(close_dmi( dmi_res ));
-  free ( dmi_res );
+  free_dmi(dmi_res);
    
   status=TPM_SUCCESS;   
   goto egress;
diff --git a/tools/vtpm_manager/manager/migration.c
b/tools/vtpm_manager/manager/migration.c
--- a/tools/vtpm_manager/manager/migration.c
+++ b/tools/vtpm_manager/manager/migration.c
@@ -40,6 +40,7 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include "vtpmpriv.h"
 #include "bsg.h"
@@ -263,7 +264,7 @@ TPM_RESULT VTPM_Handle_Get_Migration_key( const
buffer_t *param_buf,
 TPM_RESULT VTPM_Handle_Load_Migration_key( const buffer_t *param_buf,
                                            buffer_t *result_buf) {
 
-  TPM_RESULT status=TPM_FAIL;
+  TPM_RESULT status=TPM_SUCCESS;
   VTPM_MIGKEY_LIST *mig_key;
 
   vtpmloginfo(VTPM_LOG_VTPM, "Loading Migration Public Key.\n");
@@ -303,5 +304,5 @@ TPM_RESULT VTPM_Handle_Load_Migration_key( const
buffer_t *param_buf,
   free(pubkey_exp_pack.data);
   free(pubkey_mod_pack.data);
 
-  return TPM_SUCCESS;
+  return status;
 }
diff --git a/tools/vtpm_manager/manager/securestorage.c
b/tools/vtpm_manager/manager/securestorage.c
--- a/tools/vtpm_manager/manager/securestorage.c
+++ b/tools/vtpm_manager/manager/securestorage.c
@@ -42,7 +42,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <string.h>
-
+#include <stdlib.h>
 #include "tcg.h"
 #include "vtpm_manager.h"
 #include "vtpmpriv.h"
@@ -58,7 +58,7 @@ TPM_RESULT envelope_encrypt(const buffer_t     *inbuf,
                             CRYPTO_INFO        *asymkey,
                             buffer_t           *sealed_data) {
   TPM_RESULT status = TPM_SUCCESS;
-  symkey_t    symkey;
+  symkey_t    *symkey;
   buffer_t    data_cipher = NULL_BUF,
               symkey_cipher = NULL_BUF;
  
@@ -69,14 +69,14 @@ TPM_RESULT envelope_encrypt(const buffer_t     *inbuf,
   for (i=0; i< buffer_len(inbuf); i++)
     vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", inbuf->bytes[i]);
   vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
- 
+
   // Generate a sym key and encrypt state with it
   TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_genkey (&symkey) );
-  TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_encrypt (&symkey, inbuf,
&data_cipher) );
+  TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_encrypt (symkey, inbuf,
&data_cipher) );
  
   // Encrypt symmetric key
   TPMTRYRETURN( VTSP_Bind(    asymkey,
-                  &symkey.key,
+                  Crypto_symkey_getkey(symkey),
                   &symkey_cipher) );
  
   // Create output blob: symkey_size + symkey_cipher +
state_cipher_size + state_cipher
@@ -86,8 +86,9 @@ TPM_RESULT envelope_encrypt(const buffer_t     *inbuf,
  
   data_cipher32.size = buffer_len(&data_cipher);
   data_cipher32.data = data_cipher.bytes;
- 
+
   TPMTRYRETURN( buffer_init(sealed_data, 2 * sizeof(UINT32) +
symkey_cipher32.size + data_cipher32.size, NULL));
+  memset(sealed_data->bytes, 0, sealed_data->size);
  
   BSG_PackList(sealed_data->bytes, 2,
            BSG_TPM_SIZE32_DATA, &symkey_cipher32,
@@ -109,11 +110,37 @@ TPM_RESULT envelope_encrypt(const buffer_t     *inbuf,
  
   buffer_free ( &data_cipher);
   buffer_free ( &symkey_cipher);
-  Crypto_symcrypto_freekey (&symkey);
+  Crypto_symcrypto_freekey (symkey);
  
   return status;
 }
 
+TPM_RESULT symkey_encrypt(const buffer_t     *inbuf,
+                            CRYPTO_INFO        *asymkey,
+                            buffer_t           *sealed_key) {
+  buffer_t symkey_cipher = NULL_BUF;
+  struct pack_constbuf_t symkey_cipher32;
+  TPM_RESULT status = TPM_SUCCESS;
+
+  // Encrypt symmetric key
+  TPMTRYRETURN( VTSP_Bind(    asymkey,
+                  inbuf,
+                  &symkey_cipher));
+
+  symkey_cipher32.size = buffer_len(&symkey_cipher);
+  symkey_cipher32.data = symkey_cipher.bytes;
+
+  TPMTRYRETURN( buffer_init(sealed_key, sizeof(UINT32) +
symkey_cipher32.size, NULL));
+  BSG_PackList(sealed_key->bytes, 1,
+           BSG_TPM_SIZE32_DATA, &symkey_cipher32);
+  goto egress;
+abort_egress:
+egress:
+  buffer_free( &symkey_cipher);
+  return status;
+}
+
+
 TPM_RESULT envelope_decrypt(const buffer_t     *cipher,
                             TCS_CONTEXT_HANDLE TCSContext,
                 TPM_HANDLE         keyHandle,
@@ -121,15 +148,13 @@ TPM_RESULT envelope_decrypt(const buffer_t    
*cipher,
                             buffer_t           *unsealed_data) {
 
   TPM_RESULT status = TPM_SUCCESS;
-  symkey_t    symkey;
+  symkey_t    *symkey;
   buffer_t    data_cipher = NULL_BUF,
               symkey_clear = NULL_BUF,
               symkey_cipher = NULL_BUF;
-  struct pack_buf_t symkey_cipher32, data_cipher32;
+  struct pack_buf_t symkey_cipher32 = NULL_PACK_BUF, data_cipher32 =
NULL_PACK_BUF;
   int i;
 
-  memset(&symkey, 0, sizeof(symkey_t));
-
   vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Envelope Decrypt Input[%d]: 0x",
buffer_len(cipher) );
   for (i=0; i< buffer_len(cipher); i++)
     vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cipher->bytes[i]);
@@ -159,7 +184,7 @@ TPM_RESULT envelope_decrypt(const buffer_t     *cipher,
   Crypto_symcrypto_initkey (&symkey, &symkey_clear);
  
   // Decrypt State
-  TPMTRY(TPM_DECRYPT_ERROR, Crypto_symcrypto_decrypt (&symkey,
&data_cipher, unsealed_data) );
+  TPMTRY(TPM_DECRYPT_ERROR, Crypto_symcrypto_decrypt (symkey,
&data_cipher, unsealed_data) );
 
   vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Envelope Decrypte Output[%d]: 0x",
buffer_len(unsealed_data));
   for (i=0; i< buffer_len(unsealed_data); i++)
@@ -175,26 +200,64 @@ TPM_RESULT envelope_decrypt(const buffer_t    
*cipher,
   buffer_free ( &data_cipher);
   buffer_free ( &symkey_clear);
   buffer_free ( &symkey_cipher);
-  Crypto_symcrypto_freekey (&symkey);
+  BSG_Destroy(BSG_TPM_SIZE32_DATA, &symkey_cipher32);
+  BSG_Destroy(BSG_TPM_SIZE32_DATA, &data_cipher32);
+  Crypto_symcrypto_freekey (symkey);
+
  
   return status;
 }
 
+TPM_RESULT symkey_decrypt(const buffer_t     *cipher,
+                            TCS_CONTEXT_HANDLE TCSContext,
+                TPM_HANDLE         keyHandle,
+                const TPM_AUTHDATA *key_usage_auth,
+                            buffer_t           *symkey_clear) {
+
+  TPM_RESULT status = TPM_SUCCESS;
+  buffer_t    symkey_cipher = NULL_BUF;
+  struct pack_buf_t symkey_cipher32 = NULL_PACK_BUF;
+
+  BSG_UnpackList(cipher->bytes, 1,
+         BSG_TPM_SIZE32_DATA, &symkey_cipher32);
+
+  TPMTRYRETURN( buffer_init_alias_convert (&symkey_cipher,
+                           symkey_cipher32.size,
+                           symkey_cipher32.data) );
+
+  // Decrypt Symmetric Key
+  TPMTRYRETURN( VTSP_Unbind(  TCSContext,
+                  keyHandle,
+                  &symkey_cipher,
+                  key_usage_auth,
+                  symkey_clear,
+                  &(vtpm_globals->keyAuth) ) );
+
+  goto egress;
+ abort_egress:
+  vtpmlogerror(VTPM_LOG_VTPM, "Failed to decrypt symmetric key
status=%d\n.", status);
+
+ egress:
+  BSG_Destroy(BSG_TPM_SIZE32_DATA, &symkey_cipher32);
+  return status;
+}
+
 TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI_RESOURCE *myDMI,
                 const buffer_t *inbuf,
                 buffer_t *outbuf) {
  
   TPM_RESULT status = TPM_SUCCESS;
-  int fh;
+  int fh = -1;
   long bytes_written;
   buffer_t sealed_NVM = NULL_BUF;
- 
-  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Saving %d bytes of NVM.\n",
buffer_len(inbuf));
+  const buffer_t* nvmbuf = inbuf;
 
-  TPMTRYRETURN( envelope_encrypt(inbuf,
+  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Saving %d bytes of NVM.\n",
buffer_len(nvmbuf));
+
+  TPMTRYRETURN( envelope_encrypt(nvmbuf,
                                  &vtpm_globals->storageKey,
                                  &sealed_NVM) );
-                 
+
   // Write sealed blob off disk from NVMLocation
   // TODO: How to properly return from these. Do we care if we return
failure
   //       after writing the file? We can't get the old one back.
@@ -205,7 +268,6 @@ TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI_RESOURCE
*myDMI,
     status = TPM_IOERROR;
     goto abort_egress;
   }
-  close(fh);
  
   Crypto_SHA1Full (sealed_NVM.bytes, buffer_len(&sealed_NVM), (BYTE *)
&myDMI->NVM_measurement);  
  
@@ -215,6 +277,7 @@ TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI_RESOURCE
*myDMI,
   vtpmlogerror(VTPM_LOG_VTPM, "Failed to save NVM\n.");
  
  egress:
+  close(fh);
   buffer_free(&sealed_NVM);
   return status;
 }
@@ -229,7 +292,8 @@ TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI_RESOURCE
*myDMI,
 
   buffer_t sealed_NVM = NULL_BUF;
   long fh_size;
-  int fh, stat_ret, i;
+  int fh = -1;
+  int stat_ret, i;
   struct stat file_stat;
   TPM_DIGEST sealedNVMHash;
   
@@ -241,6 +305,7 @@ TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI_RESOURCE
*myDMI,
  
   //Read sealed blob off disk from NVMLocation
   fh = open(myDMI->NVMLocation, O_RDONLY);
+  printf("Filename: %s\n", myDMI->NVMLocation);
   stat_ret = fstat(fh, &file_stat);
   if (stat_ret == 0)
     fh_size = file_stat.st_size;
@@ -254,7 +319,6 @@ TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI_RESOURCE
*myDMI,
     status = TPM_IOERROR;
     goto abort_egress;
   }
-  close(fh);
  
   vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Load_NVMing[%d],\n",
buffer_len(&sealed_NVM));
  
@@ -289,14 +353,128 @@ TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI_RESOURCE
*myDMI,
  
  egress:
   buffer_free( &sealed_NVM );
+  close(fh);
+
+  return status;
+}
+
+TPM_RESULT VTPM_Handle_Load_HashKey(VTPM_DMI_RESOURCE *myDMI,
+                const buffer_t    *inbuf,
+                buffer_t          *outbuf) {
+
+  TPM_RESULT status = TPM_SUCCESS;
+
+  buffer_t sealed_NVM = NULL_BUF;
+  long fh_size;
+  int fh = -1;
+  int stat_ret, i;
+  struct stat file_stat;
+  TPM_DIGEST sealedNVMHash;
+
+  if (myDMI->NVMLocation == NULL) {
+    vtpmlogerror(VTPM_LOG_VTPM, "Unable to load NVM because the file
name NULL.\n");
+    status = TPM_AUTHFAIL;
+    goto abort_egress;
+  }
+
+  //Read sealed blob off disk from NVMLocation
+  fh = open(myDMI->NVMLocation, O_RDONLY);
+  printf("Filename: %s\n", myDMI->NVMLocation);
+  stat_ret = fstat(fh, &file_stat);
+  if (stat_ret == 0)
+    fh_size = file_stat.st_size;
+  else {
+    status = TPM_IOERROR;
+    goto abort_egress;
+  }
+
+  TPMTRYRETURN( buffer_init( &sealed_NVM, fh_size, NULL) );
+  if (read(fh, sealed_NVM.bytes, buffer_len(&sealed_NVM)) != fh_size) {
+    status = TPM_IOERROR;
+    goto abort_egress;
+  }
+
+  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Loading %d byte encryption key,\n",
buffer_len(&sealed_NVM));
+
+  Crypto_SHA1Full(sealed_NVM.bytes, buffer_len(&sealed_NVM), (BYTE *)
&sealedNVMHash);
+
+  // Verify measurement of sealed blob.
+  if (memcmp(&sealedNVMHash, &myDMI->NVM_measurement,
sizeof(TPM_DIGEST)) ) {
+    vtpmlogerror(VTPM_LOG_VTPM, "VTPM LoadKey NVM measurement check
failed.\n");
+    vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Correct hash: ");
+    for (i=0; i< sizeof(TPM_DIGEST); i++)
+      vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ",
((BYTE*)&myDMI->NVM_measurement)[i]);
+    vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+
+    vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Measured hash: ");
+    for (i=0; i< sizeof(TPM_DIGEST); i++)
+      vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ",
((BYTE*)&sealedNVMHash)[i]);
+    vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+
+    status = TPM_AUTHFAIL;
+    goto abort_egress;
+  }
+
+  //Decrypt the key into the output buffer
+  TPMTRYRETURN( symkey_decrypt(&sealed_NVM,
+                                 myDMI->TCSContext,
+                 vtpm_globals->storageKeyHandle,
+                     (const
TPM_AUTHDATA*)&vtpm_globals->storage_key_usage_auth,
+                                 outbuf) );
+  goto egress;
+
+ abort_egress:
+  vtpmlogerror(VTPM_LOG_VTPM, "Failed to load Key\n.");
+
+ egress:
+  buffer_free( &sealed_NVM );
+  close(fh);
+
+  return status;
+}
+
+TPM_RESULT VTPM_Handle_Save_HashKey(VTPM_DMI_RESOURCE *myDMI,
+                                 const buffer_t    *inbuf,
+                 buffer_t          *outbuf) {
+  TPM_RESULT status = TPM_SUCCESS;
+  int fh = -1;
+  long bytes_written;
+  buffer_t sealed_key = NULL_BUF;
+
+  TPMTRYRETURN( symkey_encrypt(inbuf,
+                                 &vtpm_globals->storageKey,
+                                 &sealed_key) );
+
+  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Saving %d byte Encryption Key.\n",
buffer_len(inbuf));
+
+  // Write sealed blob off disk from NVMLocation
+  // TODO: How to properly return from these. Do we care if we return
failure
+  //       after writing the file? We can't get the old one back.
+  // TODO: Backup old file and try and recover that way.
+  fh = open(myDMI->NVMLocation, O_WRONLY | O_CREAT | O_TRUNC, S_IREAD |
S_IWRITE);
+  if ( (bytes_written = write(fh, sealed_key.bytes,
buffer_len(&sealed_key) ) != (long) buffer_len(&sealed_key))) {
+    vtpmlogerror(VTPM_LOG_VTPM, "We just overwrote a DMI_NVM and failed
to finish. %ld/%ld bytes.\n", bytes_written, (long)buffer_len(&sealed_key));
+    status = TPM_IOERROR;
+    goto abort_egress;
+  }
  
+  Crypto_SHA1Full (sealed_key.bytes, buffer_len(&sealed_key), (BYTE *)
&myDMI->NVM_measurement);
+
+  goto egress;
+
+ abort_egress:
+  vtpmlogerror(VTPM_LOG_VTPM, "Failed to save Key\n.");
+
+ egress:
+  close(fh);
+  buffer_free(&sealed_key);
   return status;
 }
 
 
 TPM_RESULT VTPM_SaveManagerData(void) {
   TPM_RESULT status=TPM_SUCCESS;
-  int fh, dmis=-1;
+  int fh = -1, dmis=-1;
 
   BYTE *flat_boot_key=NULL, *flat_dmis=NULL, *flat_enc=NULL;
   buffer_t clear_flat_global=NULL_BUF, enc_flat_global=NULL_BUF;
@@ -364,6 +542,7 @@ TPM_RESULT VTPM_SaveManagerData(void) {
                                         BSG_TPM_DIGEST,
&dmi_res->DMI_measurement);
 
     } while (hashtable_iterator_advance(dmi_itr));
+    free(dmi_itr);
   }
 
   fh = open(STATE_FILE, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);
@@ -389,6 +568,7 @@ TPM_RESULT VTPM_SaveManagerData(void) {
 
   free(flat_boot_key);
   free(flat_enc);
+  buffer_free(&clear_flat_global);
   buffer_free(&enc_flat_global);
   free(flat_dmis);
   close(fh);
@@ -403,9 +583,10 @@ TPM_RESULT VTPM_LoadManagerData(void) {
   int fh, stat_ret, dmis=0;
   long fh_size = 0, step_size;
   BYTE *flat_table=NULL;
-  buffer_t  unsealed_data, enc_table_abuf;
-  struct pack_buf_t storage_key_pack, boot_key_pack;
-  UINT32 *dmi_id_key, enc_size;
+  buffer_t  unsealed_data = NULL_BUF;
+  buffer_t enc_table_abuf;
+  struct pack_buf_t storage_key_pack = NULL_PACK_BUF, boot_key_pack =
NULL_PACK_BUF;
+  UINT32 enc_size;
   BYTE vtpm_manager_gen;
 
   VTPM_DMI_RESOURCE *dmi_res;
@@ -438,9 +619,9 @@ TPM_RESULT VTPM_LoadManagerData(void) {
                               BSG_TPM_SIZE32_DATA, &boot_key_pack,
                               BSG_TYPE_UINT32, &enc_size);
 
-  TPMTRYRETURN(buffer_init(&vtpm_globals->bootKeyWrap, 0, 0) );
   TPMTRYRETURN(buffer_init_alias_convert(&enc_table_abuf, enc_size,
flat_table + step_size) );
-  TPMTRYRETURN(buffer_append_raw(&vtpm_globals->bootKeyWrap,
boot_key_pack.size, boot_key_pack.data) );
+  TPMTRYRETURN(buffer_init(&vtpm_globals->bootKeyWrap,
boot_key_pack.size, boot_key_pack.data) );
+
 
   //Load Boot Key
   TPMTRYRETURN( VTSP_LoadKey( vtpm_globals->manager_tcs_handle,
@@ -471,8 +652,8 @@ TPM_RESULT VTPM_LoadManagerData(void) {
                   BSG_TPM_SECRET,   &vtpm_globals->storage_key_usage_auth,
                   BSG_TPM_SIZE32_DATA, &storage_key_pack);
 
-  TPMTRYRETURN(buffer_init(&vtpm_globals->storageKeyWrap, 0, 0) );
-  TPMTRYRETURN(buffer_append_raw(&vtpm_globals->storageKeyWrap,
storage_key_pack.size, storage_key_pack.data) );
+  TPMTRYRETURN(buffer_init(&vtpm_globals->storageKeyWrap,
storage_key_pack.size, storage_key_pack.data) );
+
 
   // Per DMI values to be saved
   while ( step_size < fh_size ){
@@ -501,7 +682,10 @@ TPM_RESULT VTPM_LoadManagerData(void) {
  abort_egress:
   vtpmlogerror(VTPM_LOG_VTPM, "Failed to load service data with error =
%s\n", tpm_get_error_name(status));
  egress:
+  BSG_Destroy(BSG_TPM_SIZE32_DATA, &boot_key_pack);
+  BSG_Destroy(BSG_TPM_SIZE32_DATA, &storage_key_pack);
 
+  buffer_free(&unsealed_data);
   free(flat_table);
   close(fh);
 
diff --git a/tools/vtpm_manager/manager/vtpm_ipc.c
b/tools/vtpm_manager/manager/vtpm_ipc.c
--- a/tools/vtpm_manager/manager/vtpm_ipc.c
+++ b/tools/vtpm_manager/manager/vtpm_ipc.c
@@ -36,26 +36,49 @@
 //
 // ===================================================================
 
+#include <sys/types.h>
 #include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/select.h>
 #include "vtpm_ipc.h"
 #include "vtpmpriv.h"
 #include "log.h"
 
-int vtpm_ipc_init(vtpm_ipc_handle_t *ipc_h, char* name, int flags, BOOL
create) {
+volatile sig_atomic_t IPC_QUIT_FLAG = 0;
+
+const static struct timeval TIMEOUT = {
+   .tv_sec = 1,
+   .tv_usec = 0
+};
+
+int vtpm_ipc_init(vtpm_ipc_handle_t *ipc_h, char* name, int flags, BOOL
create, BOOL preopen) {
+  int rc;
+
   ipc_h->name = name;
   ipc_h->flags = flags;
   ipc_h->fh = VTPM_IPC_CLOSED;
 
-  if (create)
-    return(vtpm_ipc_create(ipc_h));
-  else
-    return 0;
+  if (create) {
+    if((rc = vtpm_ipc_create(ipc_h) != 0)) {
+       return rc;
+    }
+  }
+
+  if(preopen) {
+    ipc_h->fh = open(ipc_h->name, ipc_h->flags);
+    if ( ipc_h->fh == VTPM_IPC_CLOSED ) {
+       vtpmlogerror(VTPM_LOG_VTPM, "VTPM ERROR: Can't open %s\n",
ipc_h->name);
+       return -1;
+    }
+  }
+  return 0;
+
 }
 
 // Create the file that needs opening. Used only for FIFOs
 // FYI: This may cause problems in other file IO schemes. We'll see.
 int vtpm_ipc_create(vtpm_ipc_handle_t *ipc_h) {
-  int fh;
   struct stat file_info;
 
   if ((!ipc_h) || (!ipc_h->name))
@@ -68,8 +91,6 @@ int vtpm_ipc_create(vtpm_ipc_handle_t *ipc_h) {
     }
   }
 
-  ipc_h->fh = VTPM_IPC_CLOSED;
-
   return 0;
 }
 
@@ -78,6 +99,8 @@ int vtpm_ipc_create(vtpm_ipc_handle_t *ipc_h) {
 int vtpm_ipc_read(vtpm_ipc_handle_t *ipc_h, vtpm_ipc_handle_t
*alt_ipc_h, BYTE *bytes, UINT32 size){
   vtpm_ipc_handle_t *my_ipc_h;
   int result;
+  fd_set fds;
+  struct timeval timeout;
  
   if (ipc_h) {
     my_ipc_h = ipc_h;
@@ -94,9 +117,19 @@ int vtpm_ipc_read(vtpm_ipc_handle_t *ipc_h,
vtpm_ipc_handle_t *alt_ipc_h, BYTE *
     return -1;
   }
 
+  FD_ZERO(&fds);
+  while(!FD_ISSET( my_ipc_h->fh, &fds )) {
+     timeout = TIMEOUT;
+     if (IPC_QUIT_FLAG) {
+    return -1;
+     }
+     FD_SET(my_ipc_h->fh, &fds);
+     select(my_ipc_h->fh + 1, &fds, NULL, NULL, &timeout);
+  }
+
   result = read(my_ipc_h->fh, bytes, size);
   if (result < 0) {
-    my_ipc_h->fh = VTPM_IPC_CLOSED;
+     my_ipc_h->fh = VTPM_IPC_CLOSED;
   }
 
   return (result);
@@ -106,6 +139,8 @@ int vtpm_ipc_read(vtpm_ipc_handle_t *ipc_h,
vtpm_ipc_handle_t *alt_ipc_h, BYTE *
 int vtpm_ipc_write(vtpm_ipc_handle_t *ipc_h, vtpm_ipc_handle_t
*alt_ipc_h, BYTE *bytes, UINT32 size) {
   vtpm_ipc_handle_t *my_ipc_h;
   int result;
+  fd_set fds;
+  struct timeval timeout;
 
   if (ipc_h) {
     my_ipc_h = ipc_h;
@@ -122,6 +157,16 @@ int vtpm_ipc_write(vtpm_ipc_handle_t *ipc_h,
vtpm_ipc_handle_t *alt_ipc_h, BYTE
     return -1;
   }
 
+  FD_ZERO(&fds);
+  while(!FD_ISSET( my_ipc_h->fh, &fds )) {
+     timeout = TIMEOUT;
+     if (IPC_QUIT_FLAG) {
+    return -1;
+     }
+     FD_SET(my_ipc_h->fh, &fds);
+     select(my_ipc_h->fh + 1, NULL, &fds, NULL, &timeout);
+  }
+
   result = write(my_ipc_h->fh, bytes, size);
   if (result < 0) {
     my_ipc_h->fh = VTPM_IPC_CLOSED;
diff --git a/tools/vtpm_manager/manager/vtpm_ipc.h
b/tools/vtpm_manager/manager/vtpm_ipc.h
--- a/tools/vtpm_manager/manager/vtpm_ipc.h
+++ b/tools/vtpm_manager/manager/vtpm_ipc.h
@@ -39,10 +39,14 @@
 #ifndef __VTPM_IO_H__
 #define __VTPM_IO_H__
 
+#include <signal.h>
+
 #include "tcg.h"
 
 #define VTPM_IPC_CLOSED -1
 
+extern volatile sig_atomic_t IPC_QUIT_FLAG;
+
 // Represents an (somewhat) abstracted io handle.
 typedef struct vtpm_ipc_handle_t {
   int fh;              // IO handle.
@@ -53,7 +57,7 @@ typedef struct vtpm_ipc_handle_t {
 } vtpm_ipc_handle_t;
 
 
-int vtpm_ipc_init(vtpm_ipc_handle_t *ioh, char* name, int flags, BOOL
create);
+int vtpm_ipc_init(vtpm_ipc_handle_t *ioh, char* name, int flags, BOOL
create, BOOL preopen);
 
 // Create the file that needs opening. Used only for FIFOs
 // FYI: This may cause problems in other file IO schemes. We'll see.
diff --git a/tools/vtpm_manager/manager/vtpm_lock.c
b/tools/vtpm_manager/manager/vtpm_lock.c
--- a/tools/vtpm_manager/manager/vtpm_lock.c
+++ b/tools/vtpm_manager/manager/vtpm_lock.c
@@ -40,24 +40,24 @@
 
 static pthread_rwlock_t vtpm_lock;
 
-void vtpm_lock_init() {
+void vtpm_lock_init(void) {
 
   pthread_rwlock_init( &vtpm_lock, NULL);
 }
 
-void vtpm_lock_destroy(){
+void vtpm_lock_destroy(void){
   pthread_rwlock_destroy(&vtpm_lock);
 }
 
-void vtpm_lock_rdlock(){
+void vtpm_lock_rdlock(void){
   pthread_rwlock_rdlock(&vtpm_lock);
 }
 
-void vtpm_lock_wrlock(){
+void vtpm_lock_wrlock(void){
   pthread_rwlock_wrlock(&vtpm_lock);
 }
 
-void vtpm_lock_unlock(){
+void vtpm_lock_unlock(void){
   pthread_rwlock_unlock(&vtpm_lock);
 }
 
diff --git a/tools/vtpm_manager/manager/vtpm_lock.h
b/tools/vtpm_manager/manager/vtpm_lock.h
--- a/tools/vtpm_manager/manager/vtpm_lock.h
+++ b/tools/vtpm_manager/manager/vtpm_lock.h
@@ -38,11 +38,11 @@
 #ifndef __VTPM_LOCK_H__
 #define __VTPM_LOCK_H__
 
-void vtpm_lock_init();
-void vtpm_lock_destroy();
+void vtpm_lock_init(void);
+void vtpm_lock_destroy(void);
 
-void vtpm_lock_rdlock();
-void vtpm_lock_wrlock();
-void vtpm_lock_unlock();
+void vtpm_lock_rdlock(void);
+void vtpm_lock_wrlock(void);
+void vtpm_lock_unlock(void);
 
 #endif
diff --git a/tools/vtpm_manager/manager/vtpm_manager.c
b/tools/vtpm_manager/manager/vtpm_manager.c
--- a/tools/vtpm_manager/manager/vtpm_manager.c
+++ b/tools/vtpm_manager/manager/vtpm_manager.c
@@ -40,10 +40,12 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include "vtpm_manager.h"
 #include "vtpmpriv.h"
 #include "vtsp.h"
+#include "tpmddl.h"
 #include "bsg.h"
 #include "hashtable.h"
 #include "hashtable_itr.h"
@@ -54,8 +56,8 @@
 VTPM_GLOBALS *vtpm_globals=NULL;
 
 // --------------------------- Well Known Auths --------------------------
-const TPM_AUTHDATA SRK_AUTH = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
-                                  0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff};
+const TPM_AUTHDATA SRK_AUTH = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
+                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
 
 #ifdef WELL_KNOWN_OWNER_AUTH
 static BYTE FIXED_OWNER_AUTH[20] =  {0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff,
@@ -74,7 +76,6 @@ static int equals32(void *k1, void *k2) {
 }
 
 // --------------------------- Functions ------------------------------
-
 TPM_RESULT VTPM_Create_Manager(){
  
   TPM_RESULT status = TPM_SUCCESS;
@@ -104,6 +105,7 @@ TPM_RESULT VTPM_Create_Manager(){
     TPMTRYRETURN(VTSP_DisablePubekRead(vtpm_globals->manager_tcs_handle,
                                        (const
TPM_AUTHDATA*)&vtpm_globals->owner_usage_auth, 
                                        &vtpm_globals->keyAuth));    
+    Crypto_RSACryptoInfoFree(&ek_cryptoInfo);
   } else {
     vtpmloginfo(VTPM_LOG_VTPM, "Failed to readEK meaning TPM has an
owner. Creating Keys off existing SRK.\n");
   }
@@ -181,7 +183,7 @@ TPM_RESULT VTPM_Create_Manager(){
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-TPM_RESULT VTPM_Init_Manager() {
+TPM_RESULT VTPM_Init_Manager(void) {
   TPM_RESULT status = TPM_FAIL, serviceStatus;  
   BYTE *randomsead;
   UINT32 randomsize=256;
@@ -203,6 +205,11 @@ TPM_RESULT VTPM_Init_Manager() {
   vtpm_globals->manager_tcs_handle = 0;
 
   TPMTRYRETURN(TCS_create());
+
+  // Blow away all stale handles left in the tpm
+  if(TDDL_FlushAllResources() != TPM_SUCCESS) {
+     vtpmlogerror(VTPM_LOG_VTPM, "VTPM_FlushResources failed,
continuing anyway..\n");
+  }
  
   // Create TCS Context for service
   TPMTRYRETURN( TCS_OpenContext(&vtpm_globals->manager_tcs_handle ) );
@@ -228,7 +235,7 @@ TPM_RESULT VTPM_Init_Manager() {
     TPMTRYRETURN( VTPM_Create_Manager() );   
     TPMTRYRETURN( VTPM_SaveManagerData() );
   } else if (serviceStatus != TPM_SUCCESS) {
-    vtpmlogerror(VTPM_LOG_VTPM, "Failed to read existing manager file");
+    vtpmlogerror(VTPM_LOG_VTPM, "Failed to read existing manager file\n");
     exit(1);
   }
 
@@ -254,7 +261,7 @@ TPM_RESULT VTPM_Init_Manager() {
 }
 
 ///////////////////////////////////////////////////////////////////////////////

-void VTPM_Stop_Manager() {
+void VTPM_Stop_Manager(void) {
   VTPM_DMI_RESOURCE *dmi_res;
   struct hashtable_itr *dmi_itr;
  
@@ -267,7 +274,7 @@ void VTPM_Stop_Manager() {
     close_dmi( dmi_res ); // Not really interested in return code
      
     } while (hashtable_iterator_advance(dmi_itr));
-        free (dmi_itr);
+    free (dmi_itr);
   }
  
   if ( VTPM_SaveManagerData() != TPM_SUCCESS )
@@ -276,7 +283,21 @@ void VTPM_Stop_Manager() {
   TCS_CloseContext(vtpm_globals->manager_tcs_handle);
   TCS_destroy();
  
-  hashtable_destroy(vtpm_globals->dmi_map, 1);
+  if (hashtable_count(vtpm_globals->dmi_map) > 0) {
+    dmi_itr = hashtable_iterator(vtpm_globals->dmi_map);
+    do {
+      dmi_res = (VTPM_DMI_RESOURCE *) hashtable_iterator_value(dmi_itr);
+      free_dmi(dmi_res);
+    } while (hashtable_iterator_advance(dmi_itr));
+    free (dmi_itr);
+  }
+  hashtable_destroy(vtpm_globals->dmi_map, 0);
+
+  /* Cleanup resources */
+  Crypto_RSACryptoInfoFree(&vtpm_globals->bootKey);
+  Crypto_RSACryptoInfoFree(&vtpm_globals->storageKey);
+  buffer_free(&vtpm_globals->bootKeyWrap);
+  buffer_free(&vtpm_globals->storageKeyWrap);
   free(vtpm_globals);
  
   Crypto_Exit();
diff --git a/tools/vtpm_manager/manager/vtpm_manager.h
b/tools/vtpm_manager/manager/vtpm_manager.h
--- a/tools/vtpm_manager/manager/vtpm_manager.h
+++ b/tools/vtpm_manager/manager/vtpm_manager.h
@@ -61,6 +61,8 @@
 #define VTPM_ORD_TPMCOMMAND   (VTPM_ORD_BASE + 3) // DMI issues HW TPM
Command
 #define VTPM_ORD_GET_MIG_KEY  (VTPM_ORD_BASE + 4) // Get manager's
migration key
 #define VTPM_ORD_LOAD_MIG_KEY (VTPM_ORD_BASE + 5) // load dest
migration key
+#define VTPM_ORD_SAVEHASHKEY      (VTPM_ORD_BASE + 7) // DMI requests
encryption key for persistent storage
+#define VTPM_ORD_LOADHASHKEY      (VTPM_ORD_BASE + 8) // DMI requests
symkey to be regenerated
 
 // Priviledged VTPM Commands (From management console)
 #define VTPM_ORD_OPEN         (VTPM_PRIV_BASE + 1) // Creates/reopens DMI
@@ -147,4 +149,23 @@ VTPM_TPMCommand
 
 *********************************************************************/
 
+#ifndef VTPM_STUBDOM
+#define TPM_EMULATOR_PATH "/usr/bin/vtpmd"
+#endif
+
+#define VTPM_BE_FNAME          "/dev/vtpm"
+#define VTPM_DUMMY_TX_BE_FNAME "/var/vtpm/fifos/dummy_out.fifo"
+#define VTPM_DUMMY_RX_BE_FNAME "/var/vtpm/fifos/dummy_in.fifo"
+#ifndef VTPM_STUBDOM
+#define VTPM_TX_TPM_FNAME      "/var/vtpm/fifos/tpm_cmd_to_%d.fifo"
+#define VTPM_RX_TPM_FNAME      "/var/vtpm/fifos/tpm_rsp_from_all.fifo"
+#define VTPM_TX_VTPM_FNAME     "/var/vtpm/fifos/vtpm_rsp_to_%d.fifo"
+#define VTPM_RX_VTPM_FNAME     "/var/vtpm/fifos/vtpm_cmd_from_all.fifo"
+#endif
+#define VTPM_TX_HP_FNAME       "/var/vtpm/fifos/to_console.fifo"
+#define VTPM_RX_HP_FNAME       "/var/vtpm/fifos/from_console.fifo"
+
+#define VTPM_TYPE_PVM_STRING "pvm"
+#define VTPM_TYPE_HVM_STRING "hvm"
+
 #endif //_VTPM_MANAGER_H_
diff --git a/tools/vtpm_manager/manager/vtpm_manager_handler.c
b/tools/vtpm_manager/manager/vtpm_manager_handler.c
--- a/tools/vtpm_manager/manager/vtpm_manager_handler.c
+++ b/tools/vtpm_manager/manager/vtpm_manager_handler.c
@@ -41,6 +41,8 @@
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
 
 #include "vtpm_manager.h"
 #include "vtpmpriv.h"
@@ -50,26 +52,13 @@
 #include "hashtable_itr.h"
 #include "log.h"
 #include "buffer.h"
+#include "vtpm_manager_handler.h"
 
 #define vtpmhandlerloginfo(module,fmt,args...) vtpmloginfo (module,
"[%s]: " fmt, thread_name, ##args );
 #define vtpmhandlerloginfomore(module,fmt,args...) vtpmloginfomore
(module, fmt, ##args );
 #define vtpmhandlerlogerror(module,fmt,args...) vtpmlogerror (module,
"[%s]: " fmt, thread_name, ##args );
 
-// ---------------------- Prototypes -------------------
-TPM_RESULT vtpm_manager_handle_vtpm_cmd(VTPM_DMI_RESOURCE *dmi_res,
-                    TPM_COMMAND_CODE ord,
-                    buffer_t *command_buf,
-                    buffer_t *result_buf,
-                                        BOOL is_priv,
-                                        char *thread_name);
-
-TPM_RESULT vtpm_manager_handle_tpm_cmd(vtpm_ipc_handle_t *tx_ipc_h,
-                                       vtpm_ipc_handle_t *rx_ipc_h,
-                                       VTPM_DMI_RESOURCE *dmi_res,
-                                       BYTE *cmd_header,
-                                       buffer_t *param_buf,
-                                       buffer_t *result_buf,
-                                       char *thread_name);
+volatile sig_atomic_t HANDLER_QUIT_FLAG = 0;
 
 TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t *tx_ipc_h,
                                  vtpm_ipc_handle_t *rx_ipc_h,
@@ -80,12 +69,13 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t
*tx_ipc_h,
                                  char *thread_name) {
   TPM_RESULT      status =  TPM_FAIL; // Should never return
   UINT32          dmi, in_param_size, cmd_size, out_param_size,
out_message_size, reply_size;
-  BYTE            *cmd_header=NULL, *in_param=NULL, *out_message=NULL,
*reply;
+  BYTE            *cmd_header=NULL, *in_param=NULL, *out_header=NULL,
*reply;
   buffer_t        *command_buf=NULL, *result_buf=NULL;
   TPM_TAG         tag;
   TPM_COMMAND_CODE ord;
   VTPM_DMI_RESOURCE *dmi_res;
   int  size_read, size_write, i;
+  int locked;
   BOOL add_header=TRUE; // This indicates to prepend a header on
result_buf before sending
  
   cmd_header = (BYTE *) malloc(VTPM_COMMAND_HEADER_SIZE_SRV);
@@ -93,7 +83,11 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t
*tx_ipc_h,
   result_buf = (buffer_t *) malloc(sizeof(buffer_t));
 
   // ------------------------ Main Loop --------------------------------
-  while(1) {
+  while(!HANDLER_QUIT_FLAG) {
+    locked = 0;
+
+    buffer_init(command_buf, 0, NULL);
+    buffer_init(result_buf, 0, NULL);
    
     vtpmhandlerloginfo(VTPM_LOG_VTPM, "%s waiting for messages.\n",
thread_name);
 
@@ -106,7 +100,9 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t
*tx_ipc_h,
       for (i=0; i<size_read; i++)
     vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cmd_header[i]);
     } else {
-      vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s can't read from ipc.
Errono = %d. Aborting... \n", thread_name, errno);
+      if (!IPC_QUIT_FLAG) {
+    vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s can't read from ipc. Errono
= %d. Aborting... \n", thread_name, errno);
+      }
       goto abort_command;
     }
 
@@ -155,6 +151,7 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t
*tx_ipc_h,
       vtpmhandlerlogerror(VTPM_LOG_VTPM, "Failed to setup buffers.
Aborting...\n");
       goto abort_command;
     }
+    result_buf->is_owner = TRUE;
    
     // -------------- Dispatch Commands to Handlers -----------
     if ((tag == VTPM_TAG_REQ) && (ord & VTPM_PRIV_MASK)) {
@@ -162,6 +159,7 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t
*tx_ipc_h,
     } else {
       vtpm_lock_rdlock();
     }
+    locked = 1;
 
     if ( !(dmi_res = (VTPM_DMI_RESOURCE *)
hashtable_search(vtpm_globals->dmi_map, &dmi)) ||
          (!dmi_res->connected) ) {
@@ -174,10 +172,22 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t
*tx_ipc_h,
     if (tag == VTPM_TAG_REQ) {
    
       status = vtpm_manager_handle_vtpm_cmd(dmi_res, ord, command_buf,
result_buf, is_priv, thread_name);
+      result_buf->is_owner = TRUE;
 
     } else { // This is not a VTPM Command at all.
       if (fw_tpm) {
+#ifdef VTPM_STUBDOM
+    /* In stubdom mode, we allow the vtpm domains to send raw tpm
commands down the pipe
+     * They can also just embed their tpm commands inside VTPM commands
if they wish to*/
+
+    /* Stick the header back onto the raw command (minus the dmiid) */
+    buffer_prepend_raw(command_buf, VTPM_COMMAND_HEADER_SIZE_CLT,
cmd_header + sizeof(UINT32));
+    status = VTPM_Handle_TPM_Command(dmi_res, command_buf, result_buf);
+#else
+    /* In normal mode, this is used for the guest to forward a raw
command to the vtpm process */
         status = vtpm_manager_handle_tpm_cmd(fw_tx_ipc_h, fw_rx_ipc_h,
dmi_res, cmd_header, command_buf, result_buf, thread_name);
+#endif
+        result_buf->is_owner = TRUE;
 
         // This means calling the DMI failed, not that the cmd failed
in the DMI
         // Since the return will be interpretted by a TPM app, all
errors are IO_ERRORs to the app
@@ -207,36 +217,42 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t
*tx_ipc_h,
     // ------------------- Respond to Sender ------------------
 
     // Errors while handling responses jump here to reply with error
messages
-    // NOTE: Currently there are no recoverable errors in multi-VM
mode. If one
-    //       is added to the code, this ifdef should be removed.
-    //       Also note this is NOT referring to errors in commands, but
rather
-    //       this is about I/O errors and such.
-#ifndef VTPM_MULTI_VM
- abort_with_error:
-#endif
+abort_with_error:
   
     if (add_header) {
       // Prepend VTPM header with destination DM stamped
       out_param_size = buffer_len(result_buf);
       out_message_size = VTPM_COMMAND_HEADER_SIZE_CLT + out_param_size;
-      reply_size = VTPM_COMMAND_HEADER_SIZE_SRV + out_param_size;
-      out_message = (BYTE *) malloc (reply_size);
-      reply = out_message;
+      out_header = (BYTE *) malloc (VTPM_COMMAND_HEADER_SIZE_SRV);
    
-      BSG_PackList(out_message, 4,
+      BSG_PackList(out_header, 4,
            BSG_TYPE_UINT32, (BYTE *) &dmi,
            BSG_TPM_TAG, (BYTE *) &tag,
            BSG_TYPE_UINT32, (BYTE *) &out_message_size,
            BSG_TPM_RESULT, (BYTE *) &status);
    
-      if (buffer_len(result_buf) > 0)
-        memcpy(out_message + VTPM_COMMAND_HEADER_SIZE_SRV,
result_buf->bytes, out_param_size);
-      //Note: Send message + dmi_id
+      buffer_prepend_raw(result_buf, VTPM_COMMAND_HEADER_SIZE_SRV,
out_header);
+      free(out_header);
     } else {
-      reply = result_buf->bytes;
-      reply_size = buffer_len(result_buf);
+#ifdef VTPM_STUBDOM
+       //In stubdom mode, we need to always prepend the dmiid so the
raw command can be returned to the right domain
+       out_header = (BYTE*) malloc(sizeof(UINT32));
+       BSG_PackList(out_header, 1,
+         BSG_TYPE_UINT32, (BYTE*) &dmi);
+       buffer_prepend_raw(result_buf, sizeof(UINT32), out_header);
+       free(out_header);
+#endif
     } 
+    reply = result_buf->bytes;
+    reply_size = buffer_len(result_buf);
+#ifndef VTPM_STUBDOM
     size_write = vtpm_ipc_write(tx_ipc_h, (dmi_res ?
dmi_res->tx_vtpm_ipc_h : NULL), reply, reply_size );
+#else
+    if(reply_size >= 4096) {
+       vtpmhandlerlogerror(VTPM_LOG_VTPM, "MESSAGE TOO BIG!!!");
+    }
+    size_write = vtpm_ipc_write(tx_ipc_h, NULL, reply, reply_size );
+#endif
     if (size_write > 0) {
       vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "SENT: 0x");
       for (i=0; i < reply_size; i++)
@@ -247,7 +263,6 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t
*tx_ipc_h,
       vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s had error writing to ipc.
Aborting... \n", thread_name);
       goto abort_command;
     }
-    free(out_message); out_message=NULL;
    
     if (size_write < (int)reply_size) {
       vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s unable to write full
command to ipc (%d/%d)\n", thread_name, size_write, reply_size);
@@ -264,14 +279,22 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t
*tx_ipc_h,
     buffer_free(command_buf);
 
     // If we have a write lock, save the manager table
-    if ((tag == VTPM_TAG_REQ) && (ord & VTPM_PRIV_MASK) &&
+    if (locked && (tag == VTPM_TAG_REQ) && (ord & VTPM_PRIV_MASK) &&
         (VTPM_SaveManagerData() != TPM_SUCCESS) ) {
        vtpmhandlerlogerror(VTPM_LOG_VTPM, "ERROR: Unable to save
manager data.\n");
     }
 
-    vtpm_lock_unlock();
+    if(locked) {
+       vtpm_lock_unlock();
+    }
     add_header = TRUE; // Reset to the default
   } // End while(1)
+
+  free(cmd_header);
+  free(command_buf);
+  free(result_buf);
+
+  vtpmhandlerloginfo(VTPM_LOG_VTPM, "exiting\n", thread_name);
  
 }
 
@@ -313,6 +336,16 @@ TPM_RESULT
vtpm_manager_handle_vtpm_cmd(VTPM_DMI_RESOURCE *dmi_res,
     status = VTPM_Handle_Load_Migration_key(command_buf,
                                            result_buf);
     break;
+  case VTPM_ORD_SAVEHASHKEY:
+    status = VTPM_Handle_Save_HashKey(dmi_res,
+                   command_buf,
+                   result_buf);
+    break;
+  case VTPM_ORD_LOADHASHKEY:
+    status = VTPM_Handle_Load_HashKey(dmi_res,
+                   command_buf,
+                   result_buf);
+    break;
   
   default:
     // Privileged handlers can do maintanance
@@ -350,6 +383,7 @@ TPM_RESULT
vtpm_manager_handle_vtpm_cmd(VTPM_DMI_RESOURCE *dmi_res,
   return(status);
 }
      
+#ifndef VTPM_STUBDOM
 /////////////////////////////////////////////////////////////////////
 TPM_RESULT vtpm_manager_handle_tpm_cmd(vtpm_ipc_handle_t *tx_ipc_h,
                                        vtpm_ipc_handle_t *rx_ipc_h,
@@ -485,4 +519,5 @@ TPM_RESULT
vtpm_manager_handle_tpm_cmd(vtpm_ipc_handle_t *tx_ipc_h,
 
   return status;
 }
+#endif
 
diff --git a/tools/vtpm_manager/manager/vtpm_manager_handler.h
b/tools/vtpm_manager/manager/vtpm_manager_handler.h
--- /dev/null
+++ b/tools/vtpm_manager/manager/vtpm_manager_handler.h
@@ -0,0 +1,21 @@
+#ifndef VTPM_MANAGER_HANDLER_H
+#define VTPM_MANAGER_HANDLER_H
+// ---------------------- Prototypes -------------------
+TPM_RESULT vtpm_manager_handle_vtpm_cmd(VTPM_DMI_RESOURCE *dmi_res,
+                    TPM_COMMAND_CODE ord,
+                    buffer_t *command_buf,
+                    buffer_t *result_buf,
+                                        BOOL is_priv,
+                                        char *thread_name);
+
+#ifndef VTPM_STUBDOM
+TPM_RESULT vtpm_manager_handle_tpm_cmd(vtpm_ipc_handle_t *tx_ipc_h,
+                                       vtpm_ipc_handle_t *rx_ipc_h,
+                                       VTPM_DMI_RESOURCE *dmi_res,
+                                       BYTE *cmd_header,
+                                       buffer_t *param_buf,
+                                       buffer_t *result_buf,
+                                       char *thread_name);
+#endif
+
+#endif
diff --git a/tools/vtpm_manager/manager/vtpmd.c
b/tools/vtpm_manager/manager/vtpmd.c
--- a/tools/vtpm_manager/manager/vtpmd.c
+++ b/tools/vtpm_manager/manager/vtpmd.c
@@ -45,27 +45,13 @@
 #include <signal.h>
 #include <string.h>
 #include <pthread.h>
+#include <stdlib.h>
 #include "vtpm_manager.h"
 #include "vtpmpriv.h"
 #include "tcg.h"
 #include "log.h"
 #include "vtpm_ipc.h"
 
-#define TPM_EMULATOR_PATH "/usr/bin/vtpmd"
-
-#define VTPM_BE_FNAME          "/dev/vtpm"
-#define VTPM_DUMMY_TX_BE_FNAME "/var/vtpm/fifos/dummy_out.fifo"
-#define VTPM_DUMMY_RX_BE_FNAME "/var/vtpm/fifos/dummy_in.fifo"
-#define VTPM_TX_TPM_FNAME      "/var/vtpm/fifos/tpm_cmd_to_%d.fifo"
-#define VTPM_RX_TPM_FNAME      "/var/vtpm/fifos/tpm_rsp_from_all.fifo"
-#define VTPM_TX_VTPM_FNAME     "/var/vtpm/fifos/vtpm_rsp_to_%d.fifo"
-#define VTPM_RX_VTPM_FNAME     "/var/vtpm/fifos/vtpm_cmd_from_all.fifo"
-#define VTPM_TX_HP_FNAME       "/var/vtpm/fifos/to_console.fifo"
-#define VTPM_RX_HP_FNAME       "/var/vtpm/fifos/from_console.fifo"
-
-#define VTPM_TYPE_PVM_STRING "pvm"
-#define VTPM_TYPE_HVM_STRING "hvm"
-
 struct vtpm_thread_params_s {
   vtpm_ipc_handle_t *tx_ipc_h;
   vtpm_ipc_handle_t *rx_ipc_h;
@@ -76,180 +62,46 @@ struct vtpm_thread_params_s {
   char *thread_name;
 };
 
+static pthread_t           master_thread;
+static pthread_t           be_thread;
+static pthread_t           hp_thread;
+#ifndef VTPM_STUBDOM
+static pthread_t           dmi_thread;
+#endif
+
+
+#ifndef VTPM_STUBDOM
 // This is needed to all extra_close_dmi to close this to prevent a
 // broken pipe when no DMIs are left.
-static vtpm_ipc_handle_t *g_rx_tpm_ipc_h;
+extern vtpm_ipc_handle_t *g_rx_tpm_ipc_h;
+#endif
 
 void *vtpm_manager_thread(void *arg_void) {
-  TPM_RESULT *status = (TPM_RESULT *) malloc(sizeof(TPM_RESULT) );
   struct vtpm_thread_params_s *arg = (struct vtpm_thread_params_s *)
arg_void;
 
-  *status = VTPM_Manager_Handler(arg->tx_ipc_h, arg->rx_ipc_h,
+  VTPM_Manager_Handler(arg->tx_ipc_h, arg->rx_ipc_h,
                                  arg->fw_tpm, arg->fw_tx_ipc_h,
arg->fw_rx_ipc_h,
                                  arg->is_priv, arg->thread_name);
 
-  return (status);
+  return NULL;
 }
 
-
-void signal_handler(int reason) {
-  if (pthread_equal(pthread_self(), vtpm_globals->master_pid)) {
-    vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager shutting down for signal
%d.\n", reason);
-  } else {
-    // For old Linux Thread machines, signals are delivered to each
thread. Deal with them.
-    vtpmloginfo(VTPM_LOG_VTPM, "Child shutting down\n");
-    pthread_exit(NULL);
+void signal_handler(int signal) {
+  if (pthread_equal(pthread_self(), master_thread)) {
+    vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager shutting down for signal
%s(%d). Please wait..\n", strsignal(signal), signal);
+    HANDLER_QUIT_FLAG = IPC_QUIT_FLAG = 1;
   }
-
-  VTPM_Stop_Manager();
-  exit(-1);
 }
 
 struct sigaction ctl_c_handler;
 
-TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res, BYTE vm_type,
BYTE startup_mode) {
-
-  TPM_RESULT status = TPM_SUCCESS;
-  int fh;
-  char dmi_id_str[11]; // UINT32s are up to 10 digits + NULL
-  char *tx_vtpm_name, *tx_tpm_name, *vm_type_string;
-  struct stat file_info;
-
-  if (dmi_res->dmi_id == VTPM_CTL_DM) {
-    dmi_res->tx_tpm_ipc_h = NULL;
-    dmi_res->rx_tpm_ipc_h = NULL;
-    dmi_res->tx_vtpm_ipc_h = NULL;
-    dmi_res->rx_vtpm_ipc_h = NULL;
-  } else {
-    // Create a pair of fifo pipes
-    dmi_res->rx_tpm_ipc_h = NULL;
-    dmi_res->rx_vtpm_ipc_h = NULL;
-
-    if ( ((dmi_res->tx_tpm_ipc_h = (vtpm_ipc_handle_t *) malloc
(sizeof(vtpm_ipc_handle_t))) == NULL ) ||
-         ((dmi_res->tx_vtpm_ipc_h =(vtpm_ipc_handle_t *) malloc
(sizeof(vtpm_ipc_handle_t))) == NULL ) ||
-         ((tx_tpm_name = (char *) malloc(11 +
strlen(VTPM_TX_TPM_FNAME))) == NULL ) ||
-         ((tx_vtpm_name =(char *) malloc(11 +
strlen(VTPM_TX_VTPM_FNAME))) == NULL) ) {
-      status =TPM_RESOURCES;
-      goto abort_egress;
-    }
-
-    sprintf(tx_tpm_name, VTPM_TX_TPM_FNAME, (uint32_t) dmi_res->dmi_id);
-    sprintf(tx_vtpm_name, VTPM_TX_VTPM_FNAME, (uint32_t) dmi_res->dmi_id);
-
-    if ( (vtpm_ipc_init(dmi_res->tx_tpm_ipc_h, tx_tpm_name, O_WRONLY |
O_NONBLOCK, TRUE) != 0) ||
-         (vtpm_ipc_init(dmi_res->tx_vtpm_ipc_h, tx_vtpm_name, O_WRONLY,
TRUE) != 0) ) { //FIXME: O_NONBLOCK?
-      status = TPM_IOERROR;
-      goto abort_egress;
-    }
-
-    // Measure DMI
-    // FIXME: This will measure DMI. Until then use a fixed
DMI_Measurement value
-    // Also, this mechanism is specific to 1 VM architecture.
-    /*
-    fh = open(TPM_EMULATOR_PATH, O_RDONLY);
-    stat_ret = fstat(fh, &file_stat);
-    if (stat_ret == 0)
-      dmi_size = file_stat.st_size;
-    else {
-      vtpmlogerror(VTPM_LOG_VTPM, "Could not open vtpmd!!\n");
-      status = TPM_IOERROR;
-      goto abort_egress;
-    }
-    dmi_buffer
-    */
-    memset(&dmi_res->DMI_measurement, 0xcc, sizeof(TPM_DIGEST));
-
-    if (vm_type == VTPM_TYPE_PVM)
-      vm_type_string = (BYTE *)&VTPM_TYPE_PVM_STRING;
-    else
-      vm_type_string = (BYTE *)&VTPM_TYPE_HVM_STRING;
-
-    // Launch DMI
-    sprintf(dmi_id_str, "%d", (int) dmi_res->dmi_id);
-#ifdef MANUAL_DM_LAUNCH
-    vtpmlogerror(VTPM_LOG_VTPM, "Manually start VTPM with dmi=%s
now.\n", dmi_id_str);
-    dmi_res->dmi_pid = 0;
-#else
-    pid_t pid = fork();
-
-    if (pid == -1) {
-      vtpmlogerror(VTPM_LOG_VTPM, "Could not fork to launch vtpm\n");
-      status = TPM_RESOURCES;
-      goto abort_egress;
-    } else if (pid == 0) {
-      switch (startup_mode) {
-      case TPM_ST_CLEAR:
-        execl (TPM_EMULATOR_PATH, "vtpmd", "clear", vm_type_string,
dmi_id_str, NULL);
-        break;
-      case TPM_ST_STATE:
-        execl (TPM_EMULATOR_PATH, "vtpmd", "save", vm_type_string,
dmi_id_str, NULL);
-        break;
-      case TPM_ST_DEACTIVATED:
-        execl (TPM_EMULATOR_PATH, "vtpmd", "deactivated",
vm_type_string, dmi_id_str, NULL);
-        break;
-      default:
-        status = TPM_BAD_PARAMETER;
-        goto abort_egress;
-      }
-
-      // Returning from these at all is an error.
-      vtpmlogerror(VTPM_LOG_VTPM, "Could not exec to launch vtpm\n");
-    } else {
-      dmi_res->dmi_pid = pid;
-      vtpmloginfo(VTPM_LOG_VTPM, "Launching DMI on PID = %d\n", pid);
-    }
-#endif // MANUAL_DM_LAUNCH
-
-  } // If DMI = VTPM_CTL_DM
-    status = TPM_SUCCESS;
-
-abort_egress:
-  return (status);
-}
-
-TPM_RESULT VTPM_Close_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res) {
-  TPM_RESULT status = TPM_SUCCESS;
-
-  if (vtpm_globals->connected_dmis == 0) {
-    // No more DMI's connected. Close fifo to prevent a broken pipe.
-    // This is hackish. Need to think of another way.
-    vtpm_ipc_close(g_rx_tpm_ipc_h);
-  }
-
- 
-  if (dmi_res->dmi_id != VTPM_CTL_DM) {
-    vtpm_ipc_close(dmi_res->tx_tpm_ipc_h);
-    vtpm_ipc_close(dmi_res->tx_vtpm_ipc_h);
-
-    free(dmi_res->tx_tpm_ipc_h->name);
-    free(dmi_res->tx_vtpm_ipc_h->name);
-
-#ifndef MANUAL_DM_LAUNCH
-    if (dmi_res->dmi_id != VTPM_CTL_DM) {
-      if (dmi_res->dmi_pid != 0) {
-        vtpmloginfo(VTPM_LOG_VTPM, "Killing dmi on pid %d.\n",
dmi_res->dmi_pid);
-        if (kill(dmi_res->dmi_pid, SIGKILL) !=0) {
-          vtpmloginfo(VTPM_LOG_VTPM, "DMI on pid %d is already
dead.\n", dmi_res->dmi_pid);
-        } else if (waitpid(dmi_res->dmi_pid, NULL, 0) !=
dmi_res->dmi_pid) {
-          vtpmlogerror(VTPM_LOG_VTPM, "DMI on pid %d failed to
stop.\n", dmi_res->dmi_pid);
-          status = TPM_FAIL;
-        }
-      } else {
-        vtpmlogerror(VTPM_LOG_VTPM, "Could not kill dmi because it's
pid was 0.\n");
-        status = TPM_FAIL;
-      }
-    }
-#endif
-
-  } //endif ! dom0
-  return status;
-}
-
-
 int main(int argc, char **argv) {
-  vtpm_ipc_handle_t *tx_be_ipc_h, *rx_be_ipc_h, rx_tpm_ipc_h,
rx_vtpm_ipc_h, tx_hp_ipc_h, rx_hp_ipc_h;
-  struct vtpm_thread_params_s be_thread_params, dmi_thread_params,
hp_thread_params;
-  pthread_t be_thread, dmi_thread, hp_thread;
+  vtpm_ipc_handle_t *tx_be_ipc_h, *rx_be_ipc_h, tx_hp_ipc_h, rx_hp_ipc_h;
+  struct vtpm_thread_params_s be_thread_params, hp_thread_params;
+#ifndef VTPM_STUBDOM
+  vtpm_ipc_handle_t rx_tpm_ipc_h, rx_vtpm_ipc_h;
+  struct vtpm_thread_params_s dmi_thread_params;
+#endif
 
 #ifdef DUMMY_BACKEND
   vtpm_ipc_handle_t tx_dummy_ipc_h, rx_dummy_ipc_h;
@@ -258,34 +110,28 @@ int main(int argc, char **argv) {
 #endif
 
   vtpmloginfo(VTPM_LOG_VTPM, "Starting VTPM.\n");
-
-  // -------------------- Initialize Manager -----------------
-  if (VTPM_Init_Manager() != TPM_SUCCESS) {
-    vtpmlogerror(VTPM_LOG_VTPM, "Closing vtpmd due to error during
startup.\n");
-    return -1;
-  }
- 
+
   // -------------------- Setup Ctrl+C Handlers --------------
   ctl_c_handler.sa_handler = signal_handler;
   sigemptyset(&ctl_c_handler.sa_mask);
   ctl_c_handler.sa_flags = 0;   
  
-  if (sigaction(SIGINT, &ctl_c_handler, NULL) == -1)
+  if ((sigaction(SIGINT, &ctl_c_handler, NULL) == -1)
+    || (sigaction(SIGQUIT, &ctl_c_handler, NULL) == -1)
+    || (sigaction(SIGHUP, &ctl_c_handler, NULL) == -1) ) // For easier
debugging with gdb
+  {
     vtpmlogerror(VTPM_LOG_VTPM, "Could not install SIGINT handler.
Ctl+break will not stop manager gently.\n");
+  }
  
-  // For easier debuggin with gdb
-  if (sigaction(SIGHUP, &ctl_c_handler, NULL) == -1)
-    vtpmlogerror(VTPM_LOG_VTPM, "Could not install SIGHUP handler.
Ctl+break will not stop manager gently.\n");   
- 
+  //Block all signals for child threads
   sigset_t sig_mask;
-  sigemptyset(&sig_mask);
-  sigaddset(&sig_mask, SIGPIPE);
-  sigprocmask(SIG_BLOCK, &sig_mask, NULL);
+  sigfillset(&sig_mask);
+  pthread_sigmask(SIG_SETMASK, &sig_mask, NULL);
  
   // ------------------- Set up file ipc structures ----------
 #ifdef DUMMY_BACKEND
-  if ( (vtpm_ipc_init(&tx_dummy_ipc_h, VTPM_DUMMY_TX_BE_FNAME, O_RDWR,
TRUE) != 0) ||
-       (vtpm_ipc_init(&rx_dummy_ipc_h, VTPM_DUMMY_RX_BE_FNAME, O_RDWR,
TRUE) != 0) ) {
+  if ( (vtpm_ipc_init(&tx_dummy_ipc_h, VTPM_DUMMY_TX_BE_FNAME, O_RDWR,
TRUE, FALSE) != 0) ||
+       (vtpm_ipc_init(&rx_dummy_ipc_h, VTPM_DUMMY_RX_BE_FNAME, O_RDWR,
TRUE, FALSE) != 0) ) {
 
     vtpmlogerror(VTPM_LOG_VTPM, "Unable to create Dummy BE FIFOs.\n");
     exit(-1);
@@ -294,21 +140,29 @@ int main(int argc, char **argv) {
   tx_be_ipc_h = &tx_dummy_ipc_h;
   rx_be_ipc_h = &rx_dummy_ipc_h;
 #else
-  vtpm_ipc_init(&real_be_ipc_h, VTPM_BE_FNAME, O_RDWR, FALSE);
+  if(vtpm_ipc_init(&real_be_ipc_h, VTPM_BE_FNAME, O_RDWR, FALSE, TRUE)
!= 0) {
+     vtpmlogerror(VTPM_LOG_VTPM, "Unable to open backend device "
VTPM_BE_FNAME "\n");
+     exit(-1);
+  }
 
   tx_be_ipc_h = &real_be_ipc_h;
   rx_be_ipc_h = &real_be_ipc_h;
 #endif
 
-  if ( (vtpm_ipc_init(&rx_tpm_ipc_h, VTPM_RX_TPM_FNAME, O_RDONLY, TRUE)
!= 0) ||
-       (vtpm_ipc_init(&rx_vtpm_ipc_h, VTPM_RX_VTPM_FNAME, O_RDWR, TRUE)
!= 0) || //FIXME: O_RDONLY?
-       (vtpm_ipc_init(&tx_hp_ipc_h,  VTPM_TX_HP_FNAME, O_RDWR, TRUE) !=
0)    ||
-       (vtpm_ipc_init(&rx_hp_ipc_h,  VTPM_RX_HP_FNAME, O_RDWR, TRUE) !=
0) ) {
+  if (
+#ifndef VTPM_STUBDOM
+       (vtpm_ipc_init(&rx_tpm_ipc_h, VTPM_RX_TPM_FNAME, O_RDONLY, TRUE,
FALSE) != 0) ||
+       (vtpm_ipc_init(&rx_vtpm_ipc_h, VTPM_RX_VTPM_FNAME, O_RDWR, TRUE,
FALSE) != 0) || //FIXME: O_RDONLY?
+#endif
+       (vtpm_ipc_init(&tx_hp_ipc_h,  VTPM_TX_HP_FNAME, O_RDWR, TRUE,
TRUE) != 0)    ||
+       (vtpm_ipc_init(&rx_hp_ipc_h,  VTPM_RX_HP_FNAME, O_RDWR, TRUE,
TRUE) != 0) ) {
     vtpmlogerror(VTPM_LOG_VTPM, "Unable to create initial FIFOs.\n");
     exit(-1);
   }
 
+#ifndef VTPM_STUBDOM
   g_rx_tpm_ipc_h = &rx_tpm_ipc_h;
+#endif
 
   // -------------------- Set up thread params -------------
 
@@ -316,10 +170,15 @@ int main(int argc, char **argv) {
   be_thread_params.rx_ipc_h = rx_be_ipc_h;
   be_thread_params.fw_tpm = TRUE;
   be_thread_params.fw_tx_ipc_h = NULL;
+#ifndef VTPM_STUBDOM
   be_thread_params.fw_rx_ipc_h = &rx_tpm_ipc_h;
+#else
+  be_thread_params.fw_rx_ipc_h = NULL;
+#endif
   be_thread_params.is_priv = FALSE;
   be_thread_params.thread_name = "Backend Listener";
 
+#ifndef VTPM_STUBDOM
   dmi_thread_params.tx_ipc_h = NULL;
   dmi_thread_params.rx_ipc_h = &rx_vtpm_ipc_h;
   dmi_thread_params.fw_tpm = FALSE;
@@ -327,6 +186,7 @@ int main(int argc, char **argv) {
   dmi_thread_params.fw_rx_ipc_h = NULL;
   dmi_thread_params.is_priv = FALSE;
   dmi_thread_params.thread_name = "VTPM Listener";
+#endif
 
   hp_thread_params.tx_ipc_h = &tx_hp_ipc_h;
   hp_thread_params.rx_ipc_h = &rx_hp_ipc_h;
@@ -336,34 +196,50 @@ int main(int argc, char **argv) {
   hp_thread_params.is_priv = TRUE;
   hp_thread_params.thread_name = "Hotplug Listener";
 
+  // -------------------- Initialize Manager -----------------
+  if (VTPM_Init_Manager() != TPM_SUCCESS) {
+    vtpmlogerror(VTPM_LOG_VTPM, "Closing vtpmd due to error during
startup.\n");
+    return -1;
+  }
+
+
   // --------------------- Launch Threads -----------------
 
   vtpm_lock_init();
 
-  vtpm_globals->master_pid = pthread_self();
+  master_thread = pthread_self();
+
  
   if (pthread_create(&be_thread, NULL, vtpm_manager_thread,
&be_thread_params) != 0) {
     vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch BE Thread.\n");
     exit(-1);
   }
  
+#ifndef VTPM_STUBDOM
   if (pthread_create(&dmi_thread, NULL, vtpm_manager_thread,
&dmi_thread_params) != 0) {
     vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch DMI Thread.\n");
     exit(-1);
   }
-
+#endif
 
   if (pthread_create(&hp_thread, NULL, vtpm_manager_thread,
&hp_thread_params) != 0) {
     vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch HP Thread.\n");
     exit(-1);
   }
 
+  //Turn signals back on for the master thread only
+  sigemptyset(&sig_mask);
+  sigaddset(&sig_mask, SIGPIPE);
+  pthread_sigmask(SIG_SETMASK, &sig_mask, NULL);
+
   //Join the other threads until exit time.
   pthread_join(be_thread, NULL);
+#ifndef VTPM_STUBDOM
   pthread_join(dmi_thread, NULL);
+#endif
   pthread_join(hp_thread, NULL);
 
-  vtpmlogerror(VTPM_LOG_VTPM, "VTPM Manager shut down unexpectedly.\n");
+  vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager shutting down...\n");
 
   VTPM_Stop_Manager();
   vtpm_lock_destroy();
diff --git a/tools/vtpm_manager/manager/vtpmpriv.h
b/tools/vtpm_manager/manager/vtpmpriv.h
--- a/tools/vtpm_manager/manager/vtpmpriv.h
+++ b/tools/vtpm_manager/manager/vtpmpriv.h
@@ -40,6 +40,8 @@
 #ifndef __VTPMPRIV_H__
 #define __VTPMPRIV_H__
 
+#include <signal.h>
+
 #include "vtpm_manager.h"
 #include "tcg.h"
 #include "tcs.h"
@@ -54,16 +56,19 @@
 #define DMI_NVM_FILE       "/var/vtpm/vtpm_dm_%d.data"
 #define VTPM_CTL_DM        0
 
+extern volatile sig_atomic_t HANDLER_QUIT_FLAG;
+
 // ------------------------ Private Structures -----------------------
 typedef struct VTPM_DMI_RESOURCE_T {
+#ifndef VTPM_STUBDOM
   // I/O info for Manager to talk to DMI's and controllers
   vtpm_ipc_handle_t      *tx_vtpm_ipc_h;    // TX VTPM Results to DMI
   vtpm_ipc_handle_t      *rx_vtpm_ipc_h;    // RX VTPM Commands from DMI
   vtpm_ipc_handle_t      *tx_tpm_ipc_h;     // TX TPM Commands to DMI
   vtpm_ipc_handle_t      *rx_tpm_ipc_h;     // RX TPM Results from DMI
+
+  pid_t                  dmi_pid;
 
-#ifndef VTPM_MULTI_VM
-  pid_t                 dmi_pid;
 #endif
 
   // Non-persistent Information
@@ -77,6 +82,9 @@ typedef struct VTPM_DMI_RESOURCE_T {
   BYTE                  dmi_type;
   TPM_DIGEST            NVM_measurement;  // Equal to the SHA1 of the blob
   TPM_DIGEST            DMI_measurement;  // Correct measurement of the
owning DMI
+
+  char* uuid;
+
 } VTPM_DMI_RESOURCE;
 
 typedef struct tdVTPM_MIGKEY_LIST {
@@ -89,10 +97,6 @@ typedef struct tdVTPM_MIGKEY_LIST {
 
 typedef struct tdVTPM_GLOBALS {
   // Non-persistent data
-#ifndef VTPM_MULTI_VM
-  pid_t               master_pid;
-#endif
-
   int                 connected_dmis;     // To close guest_rx when no
dmis are connected
 
   struct hashtable    *dmi_map;               // Table of all DMI's
known indexed by persistent instance #
@@ -123,8 +127,8 @@ extern VTPM_GLOBALS *vtpm_globals;   // Key info and
DMI states
 extern const TPM_AUTHDATA SRK_AUTH;  // SRK Well Known Auth Value
 
 // ********************** VTPM Functions *************************
-TPM_RESULT VTPM_Init_Manager(); // Start VTPM Service
-void VTPM_Stop_Manager();  // Stop VTPM Service
+TPM_RESULT VTPM_Init_Manager(void); // Start VTPM Service
+void VTPM_Stop_Manager(void);  // Stop VTPM Service
 TPM_RESULT VTPM_Manager_Handler(vtpm_ipc_handle_t *tx_ipc_h,
                                 vtpm_ipc_handle_t *rx_ipc_h,
                                 BOOL fw_tpm,   // Should forward TPM cmds
@@ -143,6 +147,11 @@ TPM_RESULT VTPM_Handle_Save_NVM(      
VTPM_DMI_RESOURCE *myDMI,
                                         const buffer_t *inbuf,
                                         buffer_t *outbuf);
 
+TPM_RESULT VTPM_Handle_Get_NVM_Size(   VTPM_DMI_RESOURCE *myDMI,
+                                        const buffer_t *inbuf,
+                                        buffer_t *outbuf);
+
+
 TPM_RESULT VTPM_Handle_TPM_Command(    VTPM_DMI_RESOURCE *dmi,
                                         buffer_t *inbuf,
                                         buffer_t *outbuf);
@@ -173,6 +182,9 @@ TPM_RESULT VTPM_Close_DMI_Extra(VTPM_DMI_RESOURCE
*dmi_res);
 TPM_RESULT close_dmi(VTPM_DMI_RESOURCE *dmi_res);
 TPM_RESULT init_dmi(UINT32 dmi_id, BYTE type,  VTPM_DMI_RESOURCE
**dmi_res);
 
+/* Free's dmi_res and all of it's resources */
+void free_dmi(VTPM_DMI_RESOURCE *dmi_res);
+
 TPM_RESULT envelope_encrypt(const buffer_t     *inbuf,
                              CRYPTO_INFO        *asymkey,
                              buffer_t           *sealed_data);
@@ -183,4 +195,14 @@ TPM_RESULT envelope_decrypt(const buffer_t     *cipher,
                             const TPM_AUTHDATA *key_usage_auth,
                             buffer_t           *unsealed_data);
 
+TPM_RESULT symkey_encrypt(const buffer_t     *inbuf,
+                            CRYPTO_INFO        *asymkey,
+                            buffer_t           *sealed_key);
+
+TPM_RESULT symkey_decrypt(const buffer_t     *cipher,
+                            TCS_CONTEXT_HANDLE TCSContext,
+                TPM_HANDLE         keyHandle,
+                const TPM_AUTHDATA *key_usage_auth,
+                            buffer_t           *symkey_clear);
+
 #endif // __VTPMPRIV_H__
diff --git a/tools/vtpm_manager/manager/vtsp.c
b/tools/vtpm_manager/manager/vtsp.c
--- a/tools/vtpm_manager/manager/vtsp.c
+++ b/tools/vtpm_manager/manager/vtsp.c
@@ -38,6 +38,7 @@
 // ==================================================================
 
 #include <string.h>
+#include <stdlib.h>
 #include "tcg.h"
 #include "tcs.h"
 #include "bsg.h"
@@ -312,7 +313,7 @@ TPM_RESULT VTSP_TakeOwnership(   const
TCS_CONTEXT_HANDLE hContext,
   TPM_PROTOCOL_ID proto_id = TPM_PID_OWNER;
   BYTE *new_srk;
  
-  BYTE *paramText;        // Digest to make Auth.
+  BYTE *paramText = NULL;        // Digest to make Auth.
   UINT32 paramTextSize;
  
   // vars for srkpubkey parameter
@@ -458,7 +459,7 @@ TPM_RESULT VTSP_CreateWrapKey(  const
TCS_CONTEXT_HANDLE hContext,
   vtpmloginfo(VTPM_LOG_VTSP, "Creating new key of type %d.\n", usage);
  
   // vars for Calculate encUsageAuth
-  BYTE *paramText;     
+  BYTE *paramText = NULL;
   UINT32 paramTextSize;
  
   // vars for Calculate encUsageAuth
@@ -567,8 +568,7 @@ TPM_RESULT VTSP_CreateWrapKey(  const
TCS_CONTEXT_HANDLE hContext,
                 osapSharedSecret, auth, 0) );
  
   // Unpack/return key structure
-  TPMTRYRETURN(buffer_init(pubKeyBuf, 0, 0) );
-  TPMTRYRETURN(buffer_append_raw(pubKeyBuf, newKeyText.size,
newKeyText.data) );
+  TPMTRYRETURN(buffer_init(pubKeyBuf, newKeyText.size, newKeyText.data) );
  
   goto egress;
  
@@ -664,6 +664,7 @@ TPM_RESULT VTSP_LoadKey(const TCS_CONTEXT_HANDLE   
hContext,
    
     // Destroy rsaKeyParms
     BSG_Destroy(BSG_TPM_RSA_KEY_PARMS, &rsaKeyParms);
+    BSG_Destroy(BSG_TPM_KEY, &newKey);
    
     // Set encryption scheme
     cryptoinfo->encScheme = CRYPTO_ES_RSAESOAEP_SHA1_MGF1;
@@ -733,8 +734,7 @@ TPM_RESULT VTSP_Unbind( const TCS_CONTEXT_HANDLE   
hContext,
                 hContext) );
  
   // Unpack/return key structure
-  TPMTRYRETURN(buffer_init(clear_data, 0, 0));
-  TPMTRYRETURN(buffer_append_raw (clear_data, clear_data_size,
clear_data_text) );
+  TPMTRYRETURN(buffer_init(clear_data, clear_data_size, clear_data_text) );
  
   goto egress;
  
@@ -793,8 +793,7 @@ TPM_RESULT VTSP_Bind(   CRYPTO_INFO *cryptoInfo,
     vtpmlogerror(VTPM_LOG_VTSP, "Enc buffer just overflowed.\n");
   }
  
-  buffer_init(outData, 0, NULL);
-  buffer_append_raw(outData, out_tmp_size, out_tmp);
+  buffer_init(outData, out_tmp_size, out_tmp);
  
   vtpmloginfo(VTPM_LOG_TXDATA, "Bind Generated[%d] = 0x", out_tmp_size);
   for(i = 0 ; i < out_tmp_size ; i++) {
@@ -1005,8 +1004,6 @@ TPM_RESULT VTSP_SaveState( const
TCS_CONTEXT_HANDLE    hContext) {
 
   vtpmloginfo(VTPM_LOG_VTSP, "Calling TPM_SaveState.\n");
 
-  TPM_RESULT status = TPM_SUCCESS;
-
   // Call TCS
   return ( TCSP_SaveState ( hContext ) );
 
diff --git a/tools/vtpm_manager/manager/vtsp.h
b/tools/vtpm_manager/manager/vtsp.h
--- a/tools/vtpm_manager/manager/vtsp.h
+++ b/tools/vtpm_manager/manager/vtsp.h
@@ -42,6 +42,7 @@
 
 #include "tcg.h"
 #include "tcs.h"
+#include "crypto.h"
 
 #define KEY_BUFFER_SIZE 2048
 
diff --git a/tools/vtpm_manager/migration/Makefile
b/tools/vtpm_manager/migration/Makefile
--- a/tools/vtpm_manager/migration/Makefile
+++ b/tools/vtpm_manager/migration/Makefile
@@ -1,5 +1,11 @@
-XEN_ROOT = $(CURDIR)/../../..
-include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+XEN_ROOT = $(realpath ../../..)
+include ../Rules.mk
+
+CFLAGS += -I../crypto
+CFLAGS += -I../util
+CFLAGS += -I../tcs
+CFLAGS += -I../manager
+
 
 VPATH = ../manager
 
@@ -33,10 +39,10 @@ mrproper: clean
     rm -f *~
 
 $(BIND): $(OBJSD)
-    $(CC) $(LDFLAGS) $^ $(LIBS) -o $@
+    $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LIBS) -o $@
 
 $(BINC): $(OBJSC)
-    $(CC) $(LDFLAGS) $^ $(LIBS) -o $@
+    $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LIBS) -o $@
 
 # libraries
 LIBS += ../util/libTCGUtils.a
diff --git a/tools/vtpm_manager/migration/vtpm_manager_if.c
b/tools/vtpm_manager/migration/vtpm_manager_if.c
--- a/tools/vtpm_manager/migration/vtpm_manager_if.c
+++ b/tools/vtpm_manager/migration/vtpm_manager_if.c
@@ -50,15 +50,12 @@
 #include "vtpm_migrator.h"
 #include "vtpm_manager.h"
 
-#define VTPM_TX_HP_FNAME       "/var/vtpm/fifos/from_console.fifo"
-#define VTPM_RX_HP_FNAME       "/var/vtpm/fifos/to_console.fifo"
-
 static vtpm_ipc_handle_t tx_ipc_h, rx_ipc_h;
 
 TPM_RESULT vtpm_manager_open(){
 
-  if ( (vtpm_ipc_init(&tx_ipc_h,  VTPM_TX_HP_FNAME, O_RDWR, TRUE) != 0)
||  //FIXME: wronly
-       (vtpm_ipc_init(&rx_ipc_h,  VTPM_RX_HP_FNAME, O_RDWR, TRUE) != 0)
) { //FIXME: rdonly
+  if ( (vtpm_ipc_init(&tx_ipc_h,  VTPM_TX_HP_FNAME, O_RDWR, TRUE, TRUE)
!= 0) ||  //FIXME: wronly
+       (vtpm_ipc_init(&rx_ipc_h,  VTPM_RX_HP_FNAME, O_RDWR, TRUE, TRUE)
!= 0) ) { //FIXME: rdonly
     vtpmlogerror(VTPM_LOG_VTPM, "Unable to connect to vtpm_manager.\n");
     return TPM_IOERROR;
   }
diff --git a/tools/vtpm_manager/tcs/Makefile
b/tools/vtpm_manager/tcs/Makefile
--- a/tools/vtpm_manager/tcs/Makefile
+++ b/tools/vtpm_manager/tcs/Makefile
@@ -1,5 +1,10 @@
-XEN_ROOT = $(CURDIR)/../../..
-include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+XEN_ROOT = $(realpath ../../..)
+include ../Rules.mk
+
+CFLAGS += -I../crypto
+CFLAGS += -I../util
+CFLAGS += -I../manager
+
 
 BIN        = libTCS.a
 
diff --git a/tools/vtpm_manager/tcs/contextmgr.c
b/tools/vtpm_manager/tcs/contextmgr.c
--- a/tools/vtpm_manager/tcs/contextmgr.c
+++ b/tools/vtpm_manager/tcs/contextmgr.c
@@ -195,6 +195,7 @@ BOOL DeleteHandleFromList(   TCS_CONTEXT_HANDLE
hContext, // in
 
 BOOL FreeHandleList(    CONTEXT_HANDLE*     pContextHandle) { // in
   HANDLE_LIST* pCurrentHandle;
+  HANDLE_LIST* pNext;
   BOOL returncode = TRUE;
  
   vtpmloginfo(VTPM_LOG_TCS_DEEP, "Freeing all handles for context\n");
@@ -205,6 +206,7 @@ BOOL FreeHandleList(    CONTEXT_HANDLE*    
pContextHandle) { // in
   pCurrentHandle = pContextHandle->pHandleList;
   while (pCurrentHandle != NULL) {
    
+    pNext = pCurrentHandle->pNextHandle;
     switch (pCurrentHandle->type) {
     case TPM_RT_KEY:
       returncode = returncode && !TCSP_EvictKey(pContextHandle->handle,
pCurrentHandle->handle);
@@ -216,7 +218,7 @@ BOOL FreeHandleList(    CONTEXT_HANDLE*    
pContextHandle) { // in
       returncode = FALSE;
     }
    
-    pCurrentHandle = pCurrentHandle->pNextHandle;
+    pCurrentHandle = pNext;
    
   }
  
diff --git a/tools/vtpm_manager/tcs/tcs.c b/tools/vtpm_manager/tcs/tcs.c
--- a/tools/vtpm_manager/tcs/tcs.c
+++ b/tools/vtpm_manager/tcs/tcs.c
@@ -77,7 +77,7 @@ CONTEXT_HANDLE *LookupContext( TCS_CONTEXT_HANDLE 
hContext) {
 //
---------------------------------------------------------------------------------
 // Initialization/Uninitialization SubComponent API
 //
---------------------------------------------------------------------------------
-TPM_RESULT TCS_create() {
+TPM_RESULT TCS_create(void) {
   TDDL_RESULT hRes = TDDL_E_FAIL;
   TPM_RESULT result = TPM_FAIL;
  
@@ -101,7 +101,7 @@ TPM_RESULT TCS_create() {
 }
 
 
-void TCS_destroy()
+void TCS_destroy(void)
 {
   TCS_m_nCount--;
  
@@ -113,14 +113,13 @@ void TCS_destroy()
     TCS_CONTEXT_HANDLE  *hContext;
    
     // Close all the TCS contexts. TCS should evict keys based on this
-    if (hashtable_count(context_ht) > 0) {
+    while (hashtable_count(context_ht) > 0) {
       context_itr = hashtable_iterator(context_ht);
-      do {
-        hContext = (TCS_CONTEXT_HANDLE *)
hashtable_iterator_key(context_itr);
-    if (TCS_CloseContext(*hContext) != TPM_SUCCESS)
-        vtpmlogerror(VTPM_LOG_TCS, "Failed to close context %d
properly.\n", *hContext);
+
+      hContext = (TCS_CONTEXT_HANDLE *)
hashtable_iterator_key(context_itr);
+      if (TCS_CloseContext(*hContext) != TPM_SUCCESS)
+        vtpmlogerror(VTPM_LOG_TCS, "Failed to close context %d
properly.\n", *hContext);
      
-      } while (hashtable_iterator_advance(context_itr));
       free(context_itr);
     }
     hashtable_destroy(context_ht, 1);
@@ -534,6 +533,10 @@ TPM_RESULT TCSP_TerminateHandle(TCS_CONTEXT_HANDLE
hContext, // in
               BSG_TYPE_UINT32, &handle);
   // fill paramSize again as we now have the correct size
   BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
+
+  if (!DeleteHandleFromList(hContext, handle)) {
+    vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n");
+  }
  
   // call the TPM driver
   if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
@@ -545,9 +548,6 @@ TPM_RESULT TCSP_TerminateHandle(TCS_CONTEXT_HANDLE
hContext, // in
                BSG_TYPE_UINT32, &paramSize,
                BSG_TPM_COMMAND_CODE, &returnCode);
    
-    if (!DeleteHandleFromList(hContext, handle))
-      vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n");
-      
    
     if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
       // Print debug info
@@ -882,6 +882,7 @@ TPM_RESULT TCSP_CreateWrapKey(TCS_CONTEXT_HANDLE
hContext,   // in
      
       memcpy(*prgbKey, tempBuf, *pcKeySize);
      
+      BSG_Destroy(BSG_TPM_KEY, &wrappedKey);
       vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n",
paramSize);
     } else
       vtpmlogerror(VTPM_LOG_TCS, "TCSP_CreateWrapKey Failed with return
code %s\n", tpm_get_error_name(returnCode));
@@ -980,6 +981,10 @@ TPM_RESULT TCSP_EvictKey(TCS_CONTEXT_HANDLE
hContext, // in
   BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2);
  
   vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength);
+
+  if (!DeleteHandleFromList(hContext, hKey)) {
+    vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n");
+  }
  
   // call the TPM driver
   if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength))
== TDDL_SUCCESS) {
@@ -989,10 +994,6 @@ TPM_RESULT TCSP_EvictKey(TCS_CONTEXT_HANDLE
hContext, // in
                BSG_TYPE_UINT32, &paramSize,
                BSG_TPM_COMMAND_CODE, &returnCode);
    
-    if (!DeleteHandleFromList(hContext, hKey)) {
-      vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n");
-    }     
-   
     if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) {
       vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n",
paramSize);
     } else {
@@ -1019,7 +1020,7 @@ TPM_RESULT TCSP_GetRandom(TCS_CONTEXT_HANDLE
hContext,  // in
   TDDL_UINT32  OutLength = TCPA_MAX_BUFFER_LENGTH;
  
   // check input params
-  if (bytesRequested == NULL || *randomBytes == NULL){
+  if (bytesRequested == NULL || randomBytes == NULL){
     return TPM_BAD_PARAMETER;
   }
  
diff --git a/tools/vtpm_manager/tcs/tcs.h b/tools/vtpm_manager/tcs/tcs.h
--- a/tools/vtpm_manager/tcs/tcs.h
+++ b/tools/vtpm_manager/tcs/tcs.h
@@ -50,8 +50,8 @@
 // Exposed API
 // ------------------------------------------------------------------
 
-TPM_RESULT TCS_create();
-void TCS_destroy();
+TPM_RESULT TCS_create(void);
+void TCS_destroy(void);
 
 TPM_RESULT TCS_OpenContext( /* OUT */ TCS_CONTEXT_HANDLE* hContext );
 
diff --git a/tools/vtpm_manager/tcs/tpmddl.c
b/tools/vtpm_manager/tcs/tpmddl.c
--- /dev/null
+++ b/tools/vtpm_manager/tcs/tpmddl.c
@@ -0,0 +1,167 @@
+/*
+ * 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 <string.h>
+#include "tpmddl.h"
+#include "tcs.h"
+#include "bsg.h"
+#include "log.h"
+
+#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+
+TDDL_RESULT TDDL_GetCapability( TDDL_UINT32 cap,
+      TDDL_UINT32 sub,
+      TDDL_BYTE* buffer,
+      TDDL_UINT32* size)
+{
+   TDDL_RESULT status;
+
+   TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+   UINT32 paramsize = 22;
+   UINT32 outsize;
+   TPM_COMMAND_CODE ord = TPM_ORD_GetCapability;
+   UINT32 subcapsize = 4;
+
+   BYTE inbuf[TCPA_MAX_BUFFER_LENGTH];
+   BYTE outbuf[TCPA_MAX_BUFFER_LENGTH];
+
+   int offset;
+
+   BSG_PackList(inbuf, 6,
+     BSG_TPM_TAG, &(tag),
+     BSG_TYPE_UINT32, &(paramsize),
+     BSG_TPM_COMMAND_CODE, &(ord),
+     BSG_TYPE_UINT32, &(cap),
+     BSG_TYPE_UINT32, &(subcapsize),
+     BSG_TYPE_UINT32, &(sub)
+     );
+
+   //Send the command, get the response
+   TPMTRYRETURN(TDDL_TransmitData( inbuf, paramsize, outbuf, &outsize));
+
+   offset = BSG_UnpackList(outbuf, 4,
+     BSG_TPM_TAG, &(tag),
+     BSG_TYPE_UINT32, &(paramsize),
+     BSG_TPM_RESULT, &(status),
+     BSG_TYPE_UINT32, size
+     );
+   if (status != TPM_SUCCESS || tag != TPM_TAG_RSP_COMMAND) {
+      return status;
+   }
+   if(*size >= TCPA_MAX_BUFFER_LENGTH - offset) {
+      return TPM_FAIL;
+   }
+   memcpy(buffer, outbuf + offset, *size);
+
+abort_egress:
+   return status;
+}
+
+TDDL_RESULT TDDL_FlushSpecific(TDDL_UINT32 handle, TDDL_UINT32 res) {
+    /* FIXME: Add code here to check if TPM_FlushSpecific is not
supported (on 1.1 only TPMS?)
+    * If this is the case then we need to use TPM_EvictKey for key handles
+    * and TPM_Terminate_Handle/TPM_Reset for auth handles */
+   TDDL_RESULT status;
+
+   TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+   UINT32 paramsize = 18;
+   TPM_COMMAND_CODE ord = TPM_ORD_FlushSpecific;
+
+   BYTE inbuf[TCPA_MAX_BUFFER_LENGTH];
+   BYTE outbuf[TCPA_MAX_BUFFER_LENGTH];
+   UINT32 outsize;
+
+   int offset;
+
+   BSG_PackList(inbuf, 5,
+     BSG_TPM_TAG, &(tag),
+     BSG_TYPE_UINT32, &(paramsize),
+     BSG_TPM_COMMAND_CODE, &(ord),
+     BSG_TPM_HANDLE, &(handle),
+     BSG_TPM_RESOURCE_TYPE, &(res)
+     );
+
+   //Send command
+   TPMTRYRETURN(TDDL_TransmitData( inbuf, paramsize, outbuf, &outsize ));
+
+   offset = BSG_UnpackList(outbuf, 4,
+     BSG_TPM_TAG, &(tag),
+     BSG_TYPE_UINT32, &(paramsize),
+     BSG_TPM_RESULT, &(status)
+     );
+
+abort_egress:
+   return status;
+
+}
+
+TDDL_RESULT TDDL_FlushAllResources(void) {
+  TDDL_RESULT status = TPM_SUCCESS;
+
+  TDDL_BYTE buf[TCPA_MAX_BUFFER_LENGTH];
+  TDDL_UINT32 bufsiz;
+
+  UINT16 packedsz;
+  int size;
+  UINT32 handle;
+  BYTE* ptr;
+
+  int i, j;
+
+#define RLISTSZ 6
+  TPM_RESOURCE_TYPE reslist[RLISTSZ] = { TPM_RT_KEY, TPM_RT_AUTH,
TPM_RT_TRANS, TPM_RT_COUNTER, TPM_RT_DAA_TPM, TPM_RT_CONTEXT };
+
+  //Iterate through each resource type and flush all handles
+  for(i = 0; i < RLISTSZ; ++i) {
+     TPM_RESOURCE_TYPE res = reslist[i];
+     // Get list of current key handles
+     if((status = TDDL_GetCapability( TPM_CAP_HANDLE, res, buf,
&bufsiz)) != TPM_SUCCESS) {
+    //This can happen if the resource type is not supported
+    //If this happens just silently skip the resource type
+    if(status == TPM_BAD_MODE) {
+       status = TPM_SUCCESS;
+       continue;
+    //Otherwise we just fail
+    } else {
+       TPMTRYRETURN(status);
+    }
+     }
+
+#if 0
+     //DEBUG PRINTOUTS
+     printf("TPM_GetCapability(TPM_CAP_HANDLE, %lu)\n", (unsigned long)
res);
+     for(j = 0; j < bufsiz; ++j) {
+    printf("%02X ", buf[j]);
+     }
+     printf("\n");
+#endif
+
+     ptr = buf;
+     ptr += BSG_Unpack(BSG_TYPE_UINT16, ptr, &(packedsz));
+     size = packedsz;
+
+     //Flush each handle
+     if(size) {
+    vtpmloginfo(VTPM_LOG_VTPM, "Flushing %u handle(s) of type %lu\n",
size, (unsigned long) res);
+    for(j = 0; j < size; ++j) {
+       ptr += BSG_Unpack(BSG_TPM_HANDLE, ptr, &(handle));
+       TPMTRYRETURN(TDDL_FlushSpecific(handle, res));
+    }
+     }
+
+  }
+
+  goto egress;
+abort_egress:
+egress:
+  return status;
+}
diff --git a/tools/vtpm_manager/tcs/tpmddl.h
b/tools/vtpm_manager/tcs/tpmddl.h
--- a/tools/vtpm_manager/tcs/tpmddl.h
+++ b/tools/vtpm_manager/tcs/tpmddl.h
@@ -50,13 +50,14 @@ typedef unsigned int TDDL_UINT32;
 typedef TDDL_UINT32 TDDL_RESULT;
 typedef unsigned char TDDL_BYTE;
 
-TDDL_RESULT TDDL_Open();
-void TDDL_Close();
+TDDL_RESULT TDDL_Open(void);
+TDDL_RESULT TDDL_Open_use_fd(int fd);
+void TDDL_Close(void);
 TDDL_RESULT TDDL_TransmitData( TDDL_BYTE* in,
                    TDDL_UINT32 insize,
                    TDDL_BYTE* out,
                    TDDL_UINT32* outsize);
-TDDL_RESULT TDDL_GetStatus();
+TDDL_RESULT TDDL_GetStatus(void);
 TDDL_RESULT TDDL_GetCapability( TDDL_UINT32 cap,
                 TDDL_UINT32 sub,
                 TDDL_BYTE* buffer,
@@ -66,4 +67,10 @@ TDDL_RESULT TDDL_SetCapability( TDDL_UINT32 cap,
                 TDDL_BYTE* buffer,
                 TDDL_UINT32* size);
 
+TDDL_RESULT TDDL_FlushSpecific(TDDL_UINT32 handle,
+                TDDL_UINT32 res);
+
+TDDL_RESULT TDDL_FlushAllResources(void);
+
+
 #endif // __TPMDDL_H__
diff --git a/tools/vtpm_manager/tcs/transmit.c
b/tools/vtpm_manager/tcs/transmit.c
--- a/tools/vtpm_manager/tcs/transmit.c
+++ b/tools/vtpm_manager/tcs/transmit.c
@@ -104,12 +104,13 @@ TDDL_TransmitData( TDDL_BYTE* in,
   return status;
 }
 
-TPM_RESULT TDDL_Open() {
+TDDL_RESULT TDDL_Open(void) {
  
   TDDL_RESULT status = TDDL_SUCCESS;
  
+  /* If tpm device is already open just silently return success */
   if (g_TDDL_open)
-    return TPM_FAIL;
+    return TPM_SUCCESS;
 
 #ifdef DUMMY_TPM 
   *g_rx_fdp = open (TPM_RX_FNAME, O_RDWR);
@@ -117,7 +118,7 @@ TPM_RESULT TDDL_Open() {
 
   g_tx_fd = open (TPM_TX_FNAME, O_RDWR);
   if (g_tx_fd < 0) {
-    vtpmlogerror(VTPM_LOG_TXDATA, "TPM open failed");
+    vtpmlogerror(VTPM_LOG_TXDATA, "TPM open failed\n");
     return TPM_IOERROR;
   }
  
@@ -126,7 +127,20 @@ TPM_RESULT TDDL_Open() {
   return status;
 }
 
-void TDDL_Close() {
+TDDL_RESULT TDDL_Open_use_fd(int fd) {
+   TDDL_RESULT status = TDDL_SUCCESS;
+
+   if(g_TDDL_open)
+      return TPM_FAIL;
+
+   g_tx_fd = fd;
+
+   g_TDDL_open = 1;
+
+   return status;
+}
+
+void TDDL_Close(void) {
   if (! g_TDDL_open)
         return;
 
diff --git a/tools/vtpm_manager/util/Makefile
b/tools/vtpm_manager/util/Makefile
--- a/tools/vtpm_manager/util/Makefile
+++ b/tools/vtpm_manager/util/Makefile
@@ -1,5 +1,10 @@
-XEN_ROOT = $(CURDIR)/../../..
-include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk
+XEN_ROOT = $(realpath ../../..)
+include ../Rules.mk
+
+CFLAGS += -I../crypto
+CFLAGS += -I../tcs
+CFLAGS += -I../manager
+
 
 BIN        = libTCGUtils.a
 
diff --git a/tools/vtpm_manager/util/bsg.c b/tools/vtpm_manager/util/bsg.c
--- a/tools/vtpm_manager/util/bsg.c
+++ b/tools/vtpm_manager/util/bsg.c
@@ -41,6 +41,7 @@
 #include <string.h>
 #include <stdarg.h>
 #include <malloc.h>
+#include <stdlib.h>
 #include "tcg.h"
 #include "crypto.h"
 #include "bsg.h"
@@ -317,7 +318,7 @@ static const BSG_Format* find_format (BSG_Type t) {
 // FIXME: should have a function be passed in here which is called if
the test
 // fails. Then the caller can decide what to do: abort, notify, whatever
 //
-BOOL BSG_static_selfcheck ()
+BOOL BSG_static_selfcheck (void)
 {
   int i;
 
diff --git a/tools/vtpm_manager/util/bsg.h b/tools/vtpm_manager/util/bsg.h
--- a/tools/vtpm_manager/util/bsg.h
+++ b/tools/vtpm_manager/util/bsg.h
@@ -161,6 +161,6 @@ TPM_RESULT BSG_DestroyTuple (int numParams,
pack_tuple_t params[]);
 void BSG_PackConst(BSG_UINT32 val, int size, BSG_BYTE* dst);
 BSG_UINT32 BSG_UnpackConst(const BSG_BYTE* src, int size);
 
-BOOL BSG_static_selfcheck ();
+BOOL BSG_static_selfcheck (void);
 
 #endif
diff --git a/tools/vtpm_manager/util/buffer.c
b/tools/vtpm_manager/util/buffer.c
--- a/tools/vtpm_manager/util/buffer.c
+++ b/tools/vtpm_manager/util/buffer.c
@@ -40,6 +40,7 @@
 
 #include "tcg.h"
 #include "bsg.h"
+#include "log.h"
 #include "buffer.h"
 
 static TPM_RESULT buffer_priv_realloc (buffer_t * buf, tpm_size_t newsize);
@@ -51,6 +52,7 @@ static TPM_RESULT buffer_priv_realloc (buffer_t * buf,
tpm_size_t newsize);
 TPM_RESULT buffer_init (buffer_t * buf, tpm_size_t initsize, const
BYTE* initval) {
   if (initsize == 0) {
     memset(buf, 0, sizeof(*buf));
+    buf->bytes = NULL;
     return TPM_SUCCESS;
   }
  
@@ -62,8 +64,11 @@ TPM_RESULT buffer_init (buffer_t * buf, tpm_size_t
initsize, const BYTE* initval
   buf->size = initsize;
   buf->alloc_size = initsize;
  
-  if (initval)
+  if (initval) {
     memcpy (buf->bytes, initval, initsize);
+  } else {
+     memset(buf->bytes, 0, initsize);
+  }
  
   buf->is_owner = TRUE;
  
@@ -190,6 +195,29 @@ TPM_RESULT buffer_append_raw (buffer_t * buf,
tpm_size_t len, const BYTE* bytes)
   return status;
 }
 
+TPM_RESULT buffer_prepend_raw(buffer_t * buf, tpm_size_t len, const
BYTE* bytes) {
+  TPM_RESULT status = TPM_SUCCESS;
+
+  if (buf->alloc_size < buf->size + len) {
+    TPMTRYRETURN( buffer_priv_realloc (buf, buf->size + len) );
+  }
+
+  if(buf->size > 0) {
+    memmove(buf->bytes + len, buf->bytes, buf->size);
+  }
+  memcpy(buf->bytes, bytes, len);
+
+  buf->size += len;
+
+  goto egress;
+
+ abort_egress:
+
+ egress:
+
+  return status;
+}
+
 tpm_size_t buffer_len (const buffer_t* buf) {
   return buf->size;
 }
@@ -199,7 +227,6 @@ TPM_RESULT buffer_free (buffer_t * buf) {
     free (buf->bytes);
     buf->bytes = NULL;
     buf->size = buf->alloc_size = 0;
-  
   }
  
   return TPM_SUCCESS;
@@ -224,3 +251,13 @@ TPM_RESULT buffer_priv_realloc (buffer_t * buf,
tpm_size_t newsize) {
  
   return TPM_SUCCESS;
 }
+
+TPM_RESULT buffer_truncate(buffer_t* buf, tpm_size_t len)
+{
+   if(len <= buf->size) {
+      buf->size = len;
+      return TPM_SUCCESS;
+   }
+
+   return TPM_FAIL;
+}
diff --git a/tools/vtpm_manager/util/buffer.h
b/tools/vtpm_manager/util/buffer.h
--- a/tools/vtpm_manager/util/buffer.h
+++ b/tools/vtpm_manager/util/buffer.h
@@ -92,4 +92,9 @@ TPM_RESULT buffer_free (buffer_t * buf);
 
 TPM_RESULT buffer_append_raw (buffer_t * buf, tpm_size_t len, const
BYTE* bytes);
 
+TPM_RESULT buffer_prepend_raw(buffer_t * buf, tpm_size_t len, const
BYTE* bytes);
+
+//Reduce the size of the buffer, if len > buffer size returns an error
+TPM_RESULT buffer_truncate(buffer_t* buf, tpm_size_t len);
+
 #endif // _TOOLS_H_
diff --git a/tools/vtpm_manager/util/hashtable.c
b/tools/vtpm_manager/util/hashtable.c
--- a/tools/vtpm_manager/util/hashtable.c
+++ b/tools/vtpm_manager/util/hashtable.c
@@ -32,12 +32,6 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-/*
- * There are duplicates of this code in:
- *  - tools/xenstore/hashtable.c
- *  - tools/blktap2/drivers/hashtable.c
- */
-
 #include "hashtable.h"
 #include "hashtable_private.h"
 #include <stdlib.h>
diff --git a/tools/vtpm_manager/util/hashtable.h
b/tools/vtpm_manager/util/hashtable.h
--- a/tools/vtpm_manager/util/hashtable.h
+++ b/tools/vtpm_manager/util/hashtable.h
@@ -32,11 +32,6 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-/*
- * There are duplicates of this code in:
- *  - tools/xenstore/hashtable.h
- *  - tools/blktap2/drivers/hashtable.h
- */
 
 #ifndef __HASHTABLE_CWC22_H__
 #define __HASHTABLE_CWC22_H__
diff --git a/tools/vtpm_manager/util/hashtable_itr.c
b/tools/vtpm_manager/util/hashtable_itr.c
--- a/tools/vtpm_manager/util/hashtable_itr.c
+++ b/tools/vtpm_manager/util/hashtable_itr.c
@@ -32,11 +32,6 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-/*
- * There are duplicates of this code in:
- *  - tools/blktap2/drivers/hashtable_itr.c
- */
-
 #include "hashtable.h"
 #include "hashtable_private.h"
 #include "hashtable_itr.h"
diff --git a/tools/vtpm_manager/util/hashtable_itr.h
b/tools/vtpm_manager/util/hashtable_itr.h
--- a/tools/vtpm_manager/util/hashtable_itr.h
+++ b/tools/vtpm_manager/util/hashtable_itr.h
@@ -32,11 +32,6 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-/*
- * There are duplicates of this code in:
- *  - tools/blktap2/drivers/hashtable_itr.h
- */
-
 
 #ifndef __HASHTABLE_ITR_CWC22__
 #define __HASHTABLE_ITR_CWC22__
diff --git a/tools/vtpm_manager/util/hashtable_private.h
b/tools/vtpm_manager/util/hashtable_private.h
--- a/tools/vtpm_manager/util/hashtable_private.h
+++ b/tools/vtpm_manager/util/hashtable_private.h
@@ -32,12 +32,6 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-/*
- * There are duplicates of this code in:
- *  - tools/xenstore/hashtable_private.h
- *  - tools/blktap2/drivers/hashtable_private.h
- */
-
 #ifndef __HASHTABLE_PRIVATE_CWC22_H__
 #define __HASHTABLE_PRIVATE_CWC22_H__
 
diff --git a/tools/vtpm_manager/util/log.c b/tools/vtpm_manager/util/log.c
--- a/tools/vtpm_manager/util/log.c
+++ b/tools/vtpm_manager/util/log.c
@@ -38,6 +38,17 @@
 #include "buffer.h"
 #include "tcg.h"
 
+char *module_names[] = { "",
+                                "CRYPTO",
+                                "BSG",
+                                "TXDATA",
+                                "TCS",
+                                "TCS",
+                                "VTSP",
+                                "VTPM",
+                                "VTPM",
+                                "VTSP"
+                              };
 // Helper code for the consts, eg. to produce messages for error codes.
 
 typedef struct error_code_entry_t {
diff --git a/tools/vtpm_manager/util/log.h b/tools/vtpm_manager/util/log.h
--- a/tools/vtpm_manager/util/log.h
+++ b/tools/vtpm_manager/util/log.h
@@ -36,6 +36,8 @@
 
 #include <stdint.h>             // for uint32_t
 #include <stddef.h>             // for pointer NULL
+#include <stdio.h>
+#include <tcg.h>
 
 // =========================== LOGGING ==============================
 
@@ -50,17 +52,7 @@
 #define VTPM_LOG_VTPM_DEEP   8
 #define VTPM_LOG_VTSP_DEEP   9
 
-static char *module_names[] = { "",
-                                "CRYPTO",
-                                "BSG",
-                                "TXDATA",
-                                "TCS",
-                                "TCS",
-                                "VTSP",
-                                "VTPM",
-                                "VTPM",
-                                "VTSP"
-                              };
+extern char *module_names[];
 
 // Default to standard logging
 #ifndef LOGGING_MODULES
diff --git a/tools/vtpm_manager/util/tcg.h b/tools/vtpm_manager/util/tcg.h
--- a/tools/vtpm_manager/util/tcg.h
+++ b/tools/vtpm_manager/util/tcg.h
@@ -197,6 +197,7 @@ typedef struct pack_buf_t {
   UINT32 size;
   BYTE * data;
 } pack_buf_t;
+#define NULL_PACK_BUF {0,0}
 
 typedef struct pack_constbuf_t {
   UINT32 size;
@@ -295,6 +296,35 @@ typedef struct pack_constbuf_t {
 #define TPM_ORD_LoadKeyContext           (181UL + TPM_PROTECTED_ORDINAL)
 #define TPM_ORD_SaveAuthContext          (182UL + TPM_PROTECTED_ORDINAL)
 #define TPM_ORD_LoadAuthContext          (183UL + TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_SaveContext                      (184UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_LoadContext                      (185UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_FlushSpecific                    (186UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_PCR_Reset                        (200UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_NV_DefineSpace                   (204UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_NV_WriteValue                    (205UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_NV_WriteValueAuth                (206UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_NV_ReadValue                     (207UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_NV_ReadValueAuth                 (208UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Delegate_UpdateVerification      (209UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Delegate_Manage                  (210UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Delegate_CreateKeyDelegation     (212UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Delegate_CreateOwnerDelegation   (213UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Delegate_VerifyDelegation        (214UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Delegate_LoadOwnerDelegation     (216UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Delegate_ReadAuth                (217UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_Delegate_ReadTable               (219UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_CreateCounter                    (220UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_IncrementCounter                 (221UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ReadCounter                      (222UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ReleaseCounter                   (223UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ReleaseCounterOwner              (224UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_EstablishTransport               (230UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ExecuteTransport                 (231UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_ReleaseTransportSigned           (232UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_GetTicks                         (241UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_TickStampBlob                    (242UL +
TPM_PROTECTED_ORDINAL)
+#define TPM_ORD_MAX                              (256UL +
TPM_PROTECTED_ORDINAL)
+
 #define TSC_ORD_PhysicalPresence         (10UL + TPM_CONNECTION_ORDINAL)
 
 
@@ -419,8 +449,16 @@ typedef struct pack_constbuf_t {
 /// TPM_ResourceTypes
 #define TPM_RT_KEY      0x00000001
 #define TPM_RT_AUTH     0x00000002
+#define TPM_RT_HASH     0x00000003
 #define TPM_RT_TRANS    0x00000004
 #define TPM_RT_CONTEXT  0x00000005
+#define TPM_RT_COUNTER  0x00000006
+#define TPM_RT_DELEGATE 0x00000007
+#define TPM_RT_DAA_TPM  0x00000008
+#define TPM_RT_DAA_V0   0x00000009
+#define TPM_RT_DAA_V1   0x0000000A
+
+
 
 // TPM_PROTOCOL_ID values
 #define TPM_PID_OIAP 0x0001
@@ -447,6 +485,64 @@ typedef struct pack_constbuf_t {
 #define TPM_SS_RSASSAPKCS1v15_SHA1 0x0002
 #define TPM_SS_RSASSAPKCS1v15_DER 0x0003
 
+/*
+ * TPM_CAPABILITY_AREA Values for TPM_GetCapability ([TPM_Part2],
Section 21.1)
+ */
+#define TPM_CAP_ORD                     0x00000001
+#define TPM_CAP_ALG                     0x00000002
+#define TPM_CAP_PID                     0x00000003
+#define TPM_CAP_FLAG                    0x00000004
+#define TPM_CAP_PROPERTY                0x00000005
+#define TPM_CAP_VERSION                 0x00000006
+#define TPM_CAP_KEY_HANDLE              0x00000007
+#define TPM_CAP_CHECK_LOADED            0x00000008
+#define TPM_CAP_SYM_MODE                0x00000009
+#define TPM_CAP_KEY_STATUS              0x0000000C
+#define TPM_CAP_NV_LIST                 0x0000000D
+#define TPM_CAP_MFR                     0x00000010
+#define TPM_CAP_NV_INDEX                0x00000011
+#define TPM_CAP_TRANS_ALG               0x00000012
+#define TPM_CAP_HANDLE                  0x00000014
+#define TPM_CAP_TRANS_ES                0x00000015
+#define TPM_CAP_AUTH_ENCRYPT            0x00000017
+#define TPM_CAP_SELECT_SIZE             0x00000018
+#define TPM_CAP_DA_LOGIC                0x00000019
+#define TPM_CAP_VERSION_VAL             0x0000001A
+
+/* subCap definitions ([TPM_Part2], Section 21.2) */
+#define TPM_CAP_PROP_PCR                0x00000101
+#define TPM_CAP_PROP_DIR                0x00000102
+#define TPM_CAP_PROP_MANUFACTURER       0x00000103
+#define TPM_CAP_PROP_KEYS               0x00000104
+#define TPM_CAP_PROP_MIN_COUNTER        0x00000107
+#define TPM_CAP_FLAG_PERMANENT          0x00000108
+#define TPM_CAP_FLAG_VOLATILE           0x00000109
+#define TPM_CAP_PROP_AUTHSESS           0x0000010A
+#define TPM_CAP_PROP_TRANSESS           0x0000010B
+#define TPM_CAP_PROP_COUNTERS           0x0000010C
+#define TPM_CAP_PROP_MAX_AUTHSESS       0x0000010D
+#define TPM_CAP_PROP_MAX_TRANSESS       0x0000010E
+#define TPM_CAP_PROP_MAX_COUNTERS       0x0000010F
+#define TPM_CAP_PROP_MAX_KEYS           0x00000110
+#define TPM_CAP_PROP_OWNER              0x00000111
+#define TPM_CAP_PROP_CONTEXT            0x00000112
+#define TPM_CAP_PROP_MAX_CONTEXT        0x00000113
+#define TPM_CAP_PROP_FAMILYROWS         0x00000114
+#define TPM_CAP_PROP_TIS_TIMEOUT        0x00000115
+#define TPM_CAP_PROP_STARTUP_EFFECT     0x00000116
+#define TPM_CAP_PROP_DELEGATE_ROW       0x00000117
+#define TPM_CAP_PROP_MAX_DAASESS        0x00000119
+#define TPM_CAP_PROP_DAASESS            0x0000011A
+#define TPM_CAP_PROP_CONTEXT_DIST       0x0000011B
+#define TPM_CAP_PROP_DAA_INTERRUPT      0x0000011C
+#define TPM_CAP_PROP_SESSIONS           0x0000011D
+#define TPM_CAP_PROP_MAX_SESSIONS       0x0000011E
+#define TPM_CAP_PROP_CMK_RESTRICTION    0x0000011F
+#define TPM_CAP_PROP_DURATION           0x00000120
+#define TPM_CAP_PROP_ACTIVE_COUNTER     0x00000122
+#define TPM_CAP_PROP_MAX_NV_AVAILABLE   0x00000123
+#define TPM_CAP_PROP_INPUT_BUFFER       0x00000124
+
 // TPM_KEY_USAGE values
 #define TPM_KEY_EK 0x0000
 #define TPM_KEY_SIGNING 0x0010
diff --git a/tools/vtpm_manager/vtpmconnd/Makefile
b/tools/vtpm_manager/vtpmconnd/Makefile
--- /dev/null
+++ b/tools/vtpm_manager/vtpmconnd/Makefile
@@ -0,0 +1,30 @@
+# 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 = $(realpath ../../..)
+include ../Rules.mk
+
+BIN=vtpmconnd
+OBJS=vtpmconnd.o
+CFLAGS=-O2 -Wall
+
+all: ${BIN}
+
+${BIN}: ${OBJS}
+    gcc -o $@ $<
+
+install: ${BIN}
+    install -m 0755 ${BIN} $(DESTDIR)$(BINDIR)/$(BIN)
+
+.PHONY: mrproper
+mrproper: clean
+clean:
+    -rm ${BIN} ${OBJS}
diff --git a/tools/vtpm_manager/vtpmconnd/vtpmconnd.c
b/tools/vtpm_manager/vtpmconnd/vtpmconnd.c
--- /dev/null
+++ b/tools/vtpm_manager/vtpmconnd/vtpmconnd.c
@@ -0,0 +1,253 @@
+/*
+ * 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 <string.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <ctype.h>
+#include "../manager/vtpm_manager.h"
+
+#define VTPM_BE "/dev/vtpm"
+#define TPM_DEV "/dev/tpm0"
+#define MAX_CMD 4096
+#define DEVNULL "/dev/null"
+#define TPM_SUCCESS_RESP "\x00\x00\x00\x00" "\x01\xC1"
"\x00\x00\x00\x00" "\x00\x00\x00\x00"
+#define TPM_SUCCESS_RESPLEN 14
+
+static int quit = 0;
+
+struct Opts {
+   const char* vtpmbe;
+   const char* tpmdev;
+   int verbosity;
+   int daemon;
+};
+
+struct Opts opts = {
+   .vtpmbe = VTPM_BE,
+   .tpmdev = TPM_DEV,
+   .verbosity = 0,
+   .daemon = 1,
+};
+
+void usage(char* argv0) {
+fprintf(stderr, "Usage:\n \
+\t%s [options] [tpm device node]\n\
+\n\
+-h\t\tdisplay usage message\n\
+-v\t\tturn up verbosity level\n\
+-t <FILE>\tuse FILE for tpm device (default " TPM_DEV ")\n\
+-b <FILE>\tset vtpm backend device to FILE (default: " VTPM_BE ")\n\
+-f\t\trun in the foreground\n",
+argv0
+);
+}
+
+void sighandler(int signum) {
+   quit = 1;
+}
+
+int main_loop(int vbefd, int tpmfd) {
+   uint8_t buf[MAX_CMD];
+   ssize_t size, wrote;
+   int i;
+
+   while(!quit) {
+      /* Wait for cmd from vtpm_manager */
+      if((size = read(vbefd, buf, MAX_CMD)) < 0) {
+     if(errno == EFAULT) {
+        if(opts.verbosity > 0) {
+           fprintf(stderr, "read() failed with error: %s, non-fatal\n",
strerror(errno));
+        }
+        continue;
+     }
+     fprintf(stderr,"Error reading from %s, (%s)\n", opts.vtpmbe,
strerror(errno));
+     return 1;
+      }
+      if(opts.verbosity > 0) {
+     printf("\nvtpm_manager req(%ld):", (long) size);
+     for(i = 0; i < size; ++i) {
+        printf(" %02X", buf[i]);
+     }
+     printf("\n");
+      }
+
+      if(quit) {
+     break;
+      }
+
+      /* Forward the cmd to the tpm, exclude the dmi id */
+      if((wrote = write(tpmfd, buf + 4, size - 4)) != size - 4) {
+     fprintf(stderr,"Error writing to %s, (%s)\n", opts.tpmdev,
strerror(errno));
+     return 1;
+      }
+
+      if(quit) {
+     break;
+      }
+
+      /* Wait for response from tpm */
+      if((size = read(tpmfd, buf + 4, MAX_CMD - 4)) < 0) {
+     fprintf(stderr,"Error reading from %s, (%s)\n", opts.tpmdev,
strerror(errno));
+     return 1;
+      }
+      if(opts.verbosity > 0) {
+     printf("tpm resp(%ld):", (long) size);
+     for(i = 0; i < size + 4; ++i) {
+        printf(" %02X", buf[i]);
+     }
+     printf("\n");
+      }
+
+      if(quit) {
+     break;
+      }
+
+      /* Send response back to vtpm_manager */
+      if((wrote = write(vbefd, buf, size + 4)) != size + 4) {
+     fprintf(stderr, "Error writing to %s, (%s)\n", opts.vtpmbe,
strerror(errno));
+     return 1;
+      }
+   }
+
+   return 0;
+
+}
+
+int main(int argc, char** argv)
+{
+   int rc;
+   int vbefd, tpmfd;
+   int c;
+   int fd = -1;
+   struct sigaction sig;
+   pid_t pid;
+
+   /* Do cmdline opts */
+   opterr = 0;
+
+   while ((c = getopt (argc, argv, "hfvb:t:")) != -1)
+   {
+      switch (c)
+      {
+     case 'h':
+        usage(argv[0]);
+        return 0;
+     case 'f':
+        opts.daemon = 0;
+        break;
+     case 'v':
+        ++opts.verbosity;
+        break;
+     case 'b':
+        opts.vtpmbe = optarg;
+        break;
+     case 't':
+        opts.tpmdev = optarg;
+        break;
+     case '?':
+        if (optopt == 'c')
+           fprintf (stderr, "Option -%c requires an argument.\n", optopt);
+        else if (isprint (optopt))
+           fprintf (stderr, "Unknown option `-%c'.\n", optopt);
+        else
+           fprintf (stderr,
+             "Unknown option character `\\x%x'.\n",
+             optopt);
+            usage(argv[0]);
+        return 1;
+     default:
+        return 1;
+      }
+   }
+
+   /* DAEMONIZE */
+   if(opts.daemon) {
+      pid = fork();
+      if(pid < 0) {
+     fprintf(stderr, "failed to daemonize! fork() failed : %s\n",
strerror(errno));
+     return 1;
+      }
+
+      if (pid > 0) {
+     return 0;
+      }
+   }
+
+
+   /* SIGNAL HANDLING */
+   sig.sa_handler = sighandler;
+   sigemptyset(&sig.sa_mask);
+   sig.sa_flags = 0;
+
+   sigaction(SIGINT, &sig, NULL);
+   sigaction(SIGQUIT, &sig, NULL);
+   sigaction(SIGTERM, &sig, NULL);
+
+   /* FAKE OUT THE HOTPLUG SYSTEM */
+   /* Whenever hotplug writes a message let it go to dev null */
+   if(remove(VTPM_RX_HP_FNAME) != 0 && errno != ENOENT) {
+      fprintf(stderr, "Unable to remove %s : %s\n", VTPM_RX_HP_FNAME,
strerror(errno));
+      return -1;
+   }
+   if(symlink(DEVNULL, VTPM_RX_HP_FNAME) != 0) {
+      fprintf(stderr, "Unable to create symlink %s -> %s : %s\n",
VTPM_RX_HP_FNAME, DEVNULL, strerror(errno));
+   }
+
+   /* Whenever hotplug tries to read a response, always return success */
+   if(remove(VTPM_TX_HP_FNAME) != 0 && errno != ENOENT) {
+      fprintf(stderr, "Unable to remove %s : %s\n", VTPM_TX_HP_FNAME,
strerror(errno));
+      return -1;
+   }
+   if((fd = open(VTPM_TX_HP_FNAME, O_CREAT | O_WRONLY, S_IRUSR |
S_IWUSR)) < 0) {
+      fprintf(stderr, "Unable to open %s for writing : %s\n",
VTPM_TX_HP_FNAME, strerror(errno));
+      return -1;
+   }
+   if(write(fd, TPM_SUCCESS_RESP, TPM_SUCCESS_RESPLEN) !=
TPM_SUCCESS_RESPLEN) {
+      fprintf(stderr, "Unable to write to %s : %s\n", VTPM_TX_HP_FNAME,
strerror(errno));
+      return -1;
+   }
+   close(fd);
+   /* HOTPLUG FAKE OUT DONE */
+
+   /* Open the backend and tpm device */
+   if((vbefd = open(opts.vtpmbe, O_RDWR)) < 0) {
+      fprintf(stderr, "Unable to open `%s', (%s)\n", opts.vtpmbe,
strerror(errno));
+      return 1;
+   }
+   if((tpmfd = open(opts.tpmdev, O_RDWR)) < 0) {
+      fprintf(stderr, "Unable to open `%s', (%s)\n", opts.tpmdev,
strerror(errno));
+      return 1;
+   }
+   if(opts.verbosity > 0) {
+      fprintf(stderr, "Connected to vtpm backend: %s\n", opts.vtpmbe);
+      fprintf(stderr, "Connected to tpm: %s\n", opts.tpmdev);
+   }
+
+   rc = main_loop(vbefd, tpmfd);
+
+   close(vbefd);
+   close(tpmfd);
+
+   remove(VTPM_RX_HP_FNAME);
+   remove(VTPM_TX_HP_FNAME);
+
+
+   return rc;
+
+
+}
diff --git a/tools/vtpm_manager/vtpmmgrtalk/Makefile
b/tools/vtpm_manager/vtpmmgrtalk/Makefile
--- /dev/null
+++ b/tools/vtpm_manager/vtpmmgrtalk/Makefile
@@ -0,0 +1,35 @@
+# 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 = $(realpath ../../..)
+include ../Rules.mk
+
+BIN=vtpmmgrtalk
+OBJS=vtpmmgrtalk.o
+CFLAGS=-Wall -O2 -g
+CFLAGS += -I../crypto
+CFLAGS += -I../util
+CFLAGS += -I../tcs
+CFLAGS += -I../manager
+
+
+all: ${BIN}
+
+${BIN}: ${OBJS}
+    gcc -o $@ $<
+
+install: all
+    install -m 0755 ${BIN} $(DESTDIR)$(BINDIR)/$(BIN)
+
+.PHONY: mrproper
+mrproper: clean
+clean:
+    rm -f ${BIN} ${OBJS}
diff --git a/tools/vtpm_manager/vtpmmgrtalk/vtpmmgrtalk.c
b/tools/vtpm_manager/vtpmmgrtalk/vtpmmgrtalk.c
--- /dev/null
+++ b/tools/vtpm_manager/vtpmmgrtalk/vtpmmgrtalk.c
@@ -0,0 +1,105 @@
+/*
+ * 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 <unistd.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../manager/vtpm_manager.h"
+
+int main(int argc, char** argv) {
+   int wfd, rfd;
+   uint8_t buf[COMMAND_BUFFER_SIZE];
+   ssize_t size;
+   int i, c;
+   int rc = 0;
+
+   const char* wfile = VTPM_RX_HP_FNAME;
+   const char* rfile = VTPM_TX_HP_FNAME;
+
+   /* Open for writing in non-blocking mode and exit if
+    * the manager is not waiting on the other side */
+   if((wfd = open(wfile, O_WRONLY | O_NONBLOCK)) < 0) {
+      fprintf(stderr, "Error opening %s for writing : %s\n",
wfile,strerror(errno));
+      return 1;
+   }
+   /* Set the pipe back to blocking mode */
+   fcntl(wfd, F_SETFL, 0);
+
+   /* Open the read pipe */
+   if((rfd = open(rfile, O_RDONLY)) < 0) {
+      close(wfd);
+      fprintf(stderr, "Error opening %s for reading : %s\n",
rfile,strerror(errno));
+      return 1;
+   }
+
+   /*Grab the ASCII hex input from stdin and convert to binary */
+   for(i = 0; i < COMMAND_BUFFER_SIZE; ++i) {
+      c = scanf("%02hhX", buf + i);
+      if(c == EOF) {
+     break;
+      } else if ( c != 1) {
+     fprintf(stderr, "Malformed Input! Use ASCII hex!\n");
+     rc = 1;
+     goto quit;
+      }
+   }
+   size = i;
+
+   /* Send request to the manager only if a request was actually given */
+   if(size > 0) {
+      /* Lock the pipes for reading/writing */
+      if(flock(wfd, LOCK_EX)) {
+     fprintf(stderr, "Unable to lock %s : %s\n", wfile, strerror(errno));
+     rc = 1;
+     goto quit;
+      }
+      if(flock(rfd, LOCK_EX)) {
+     fprintf(stderr, "Unable to lock %s : %s\n", wfile, strerror(errno));
+     rc = 1;
+     goto quit;
+      }
+
+      /* Write the binary data to the pipe */
+      if(write(wfd, buf, size) != size) {
+     fprintf(stderr, "Error writing to %s : %s\n", wfile, strerror(errno));
+     rc = 1;
+     goto quit;
+      }
+
+      /* Read the response from the manager */
+      size = read(rfd, buf, COMMAND_BUFFER_SIZE);
+      if(size < 0) {
+     fprintf(stderr, "Error reading %s : %s\n", rfile, strerror(errno));
+     rc = 1;
+     goto quit;
+      }
+      /* Output the hex */
+      for(i = 0; i < size; ++i) {
+     printf("%02X", buf[i]);
+      }
+      fprintf(stderr,"\n");
+
+      /* Unlock the pipes */
+      flock(rfd, LOCK_UN);
+      flock(wfd, LOCK_UN);
+   }
+
+   rc = 0;
+quit:
+   close(rfd);
+   close(wfd);
+   return rc;
+}


Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

_______________________________________________
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®.