All of lore.kernel.org
 help / color / mirror / Atom feed
* Several vtpm patches and workarounds: persistence, stability, tpm_emulator-0.5.1
@ 2009-08-21 16:02 Matt Fioravante
  2009-08-21 16:33 ` Keir Fraser
  0 siblings, 1 reply; 3+ messages in thread
From: Matt Fioravante @ 2009-08-21 16:02 UTC (permalink / raw)
  To: xen-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 7390 bytes --]

We are using xen and vtpm at JHU APL for a project and ran into many
problems. I've had to develop several patches and workarounds and wanted
to contribute them back to the xen community.

Here are a few patches that will make the xen vtpm system more stable
and allow you to have persistent vtpms. In other words you can reboot a
domU and it will come back up with the same vtpm instance and retain all
the keys and data you stored in it.

Also included is a patch that ports vtpm to tpm_emulator-0.5.1. The new
emulator has a lot of bug fixes over the old 0.4 and is recommended if
you want a working vtpm implementation. This port is incomplete, so
please see the details on that patch before applying it.

Some of these are actual bug fixes while others are hacks/workarounds.
Becuase of this, they have been broken into several patches to assist
the developers in choosing which they want to integrate. With these
patches we have been successfully able to use persistent vtpms for
signing certificates.

All of these patches can be applied on top of each other in any order.
$ patch -p1 < patchfile


Finally, there are also some bugs in the xen hotplug system and the
vtpm_manager. Sometimes the manager can get into a corrupted state and
it will cease to work properly. Workarounds for some of the problems are
included at the end of this email.


==============================
vtpm_manager-hash_error.patch
==============================
There is a bug in the vtpm_manager that has to do with hashing and
saving the NVM memory files (vtpm_dm_%d.data). The file is not truncated
when it is written and this results in the hash becoming invalid because
of the extra bits at the end of the file.

This patch adds O_TRUNC to the flags when opening the file.

More details on this issue are in the bug report on bugzilla 
http://bugzilla.xensource.com/bugzilla/show_bug.cgi?id=1488

==============================
vtpm-uuid.patch
==============================
Right now xen will create a new vtpm instance everytime you start up a
domU, even if you specify the instance parameter in your config file.
Each vtpm instance is then given a uuid and the vtpm.db file maps
instance numbers to uuid numbers.

This patch is a hack that lets you explicitly set the uuid of your vtpm
instance. Everytime you boot up your domU now the vtpm will get that
uuid and thus it will always get the same vtpm instance number instead
of being generated a new one.

So for example, in your config file you would do something like this
vtpm = [ 'backend=0,uuid=dcdb124b-9fed-4040-b149-dd2dfd8d094c' ]

If you are using this patch then be sure to also use the hash_error
patch, otherwise you may see checksum failed messages when booting
your domain and the vtpm tries to read the NVM file. These 2 patches
were made separate because the first is a bug fix and this one is more
of a hack.

==============================
vtpm-0.4-persistence.patch
==============================
This patch is only needed if you want to continue using
tpm_emulator-0.4. It is not necessary if you are going to use the
tpm_emulator-0.5.1 patch.

This patch will add
#define TPM_STRONG_PERSISTENCE
which will make the tpm_emulator send a TPM_SaveState command after
every tpm command it executes. This is needed because some commands like
TPM_TakeOwnership do not send the TPM_SaveState command on their own.
The tpm_emulator will only request the manager to save its state when
this TPM command is sent.

So in short without this patch, if you took ownership of your vtpm and
then rebooted the domU, the the change in state would not be saved and
your vtpm would come back unowned again. 

I imagine several other tpm commands would have this problem as well.

==============================
vtpm-0.5.1.patch
==============================
This patch will port vtpm to use tpm_emulator-0.5.1
The newer version of the emulator contains several bug fixes, one that
we were seeing in our use of vtpm.

This patch also defines TPM_STRONG_PERSISTENCE for the new emulator.

A couple of important notes about this patch:
-This has only been tested on PVM domU's. In theory it should work for
HVM but I have not tried it at all and can guarantee nothing.
-All the relevant changes in tools/vtpm/vtpm.patch have been ported to 
tpm_emulator-0.5.1. 
-None of the changes in tpm_emulator.patch have been ported. In
particular this means the BUILD_EMULATOR option, which as I understand
lets you use the tpm_emulator in dom0 for a machine that does
not have a real hardware TPM does not work. This functionality should be
easy to add though because the new emulator already comes with a kernel
module interface.
-No considerations were made for the VTPM_MULTI_VM feature (which is
supposedly unfinished). This patch may or may not break any progress
made on that feature.

============================
vtpm_manager and xen hotplug workarounds
============================
Here are some issues I've run into when trying to use vtpm. Note that in
my test cases we were only using vtpms in PVM domains.

It might make sense to add these to a readme or something somewhere
until the hotplug issues are fixed.

1-Q) When I boot my domU with a vtpm for the first time I get 
the following error message in the vtpm_managerd output
Loading NVM.
        Sending LoadNVM command
ERROR[VTPM]: Failed to load NVM
.INFO[VTPM]: [VTPM Listener]: VTPM Listener waiting for messages.
        Reading LoadNVM header
1-A) This is ok. This message comes up when the vtpm non-volatile memory
file does not exist, which is normal when xen creates a new vtpm
instance.

2-Q) When I start vtpm_managerd it starts spamming output to the console
forever and gives the following error:
ERROR[VTPM]: [Hotplug Listener]: Hotplug Listener can't read from ipc.
Errono = 0. Aborting... 
2-A) Sometimes the hotplug scripts and the fifos they use to
communicate 
get in a corrupted state. We need to clear all the fifos. 
1) First, stop all of the vms that have vtpms.
2) Kill the vtpm_managerd
3) Search for vtpm processes.
#ps -ef | grep vtpm
You may see processes that look like the following. If you do
not see any then skip ahead to the next step.
/bin/bash /etc/xen/scripts/vtpm add
dd skip=10 bs=1 count=4 if=/var/vtpm/fifos/to_console.fifo
/usr/bin/vtpmd
First, kill any of the dd processes, and then run ps again. Most if
not all  of the /etx/xen/scripts/vtpm processes should have quit.
Kill any of the remaining scripts/vtpm and vtpmd processes.
Note that after killing some of of the "vtpm add" processes
new "vtpm remove" processes may get spawned which you will
also need to kill.
4) Delete all of the fifos and socks
#rm /var/vtpm/fifos/*
#rm /var/vtpm/socks/*
5) Remove the lock files if they exist
# rm -rf /var/run/xen-hotplug/vtpm*
6) Now start up the vtpm_managerd again, it should start without errors.
7) Finally, you should be able to boot up the vms again without any
problems.

3-Q) When I start a domU that has a vtpm it hangs in the
pause state and will not boot. If I wait long enough it will quit and
tell me that the Hotplug scripts are not working.
3-A) This occurs when we have stale lock files that did not get removed
properly. 
Perform the same set of steps in 2-A.


[-- Attachment #1.1.2: vtpm_manager-hash_error.patch --]
[-- Type: text/x-patch, Size: 1033 bytes --]

diff -Naur xen-unstable.hg.pristine/tools/vtpm_manager/manager/securestorage.c xen-unstable.hg/tools/vtpm_manager/manager/securestorage.c
--- xen-unstable.hg.pristine/tools/vtpm_manager/manager/securestorage.c	2009-08-07 10:19:48.000000000 -0400
+++ xen-unstable.hg/tools/vtpm_manager/manager/securestorage.c	2009-08-07 10:21:43.000000000 -0400
@@ -199,7 +199,7 @@
   // 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, S_IREAD | S_IWRITE);
+  fh = open(myDMI->NVMLocation, O_WRONLY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
   if ( (bytes_written = write(fh, sealed_NVM.bytes, buffer_len(&sealed_NVM) ) != (long) buffer_len(&sealed_NVM))) {
     vtpmlogerror(VTPM_LOG_VTPM, "We just overwrote a DMI_NVM and failed to finish. %ld/%ld bytes.\n", bytes_written, (long)buffer_len(&sealed_NVM));
     status = TPM_IOERROR;

[-- Attachment #1.1.3: vtpm-uuid.patch --]
[-- Type: text/x-patch, Size: 1118 bytes --]

diff -Naur xen-unstable.hg.pristine/tools/python/xen/xm/create.py xen-unstable.hg/tools/python/xen/xm/create.py
--- xen-unstable.hg.pristine/tools/python/xen/xm/create.py	2009-08-07 10:19:48.000000000 -0400
+++ xen-unstable.hg/tools/python/xen/xm/create.py	2009-08-07 10:41:31.000000000 -0400
@@ -890,6 +890,7 @@
     if len(vtpm) > 0:
         d = vtpm[0]
         instance = d.get('instance')
+	uuid = d.get('uuid')
         if instance == "VTPMD":
             instance = "0"
         else:
@@ -908,6 +909,8 @@
             config_vtpm.append(['backend', backend])
         if typ:
             config_vtpm.append(['type', type])
+        if uuid:
+            config_vtpm.append(['uuid', type])
         config_devs.append(['device', config_vtpm])
 
 
@@ -1147,7 +1150,7 @@
             (k, v) = b.strip().split('=', 1)
             k = k.strip()
             v = v.strip()
-            if k not in ['backend', 'instance']:
+            if k not in ['backend', 'instance', 'uuid']:
                 err('Invalid vtpm specifier: ' + vtpm)
             d[k] = v
         vtpms.append(d)

[-- Attachment #1.1.4: vtpm-0.4-persistence.patch --]
[-- Type: text/x-patch, Size: 590 bytes --]

diff -Naur xen-unstable.hg.pristine/tools/vtpm/tpm_emulator.patch xen-unstable.hg/tools/vtpm/tpm_emulator.patch
--- xen-unstable.hg.pristine/tools/vtpm/tpm_emulator.patch	2009-08-07 10:19:48.000000000 -0400
+++ xen-unstable.hg/tools/vtpm/tpm_emulator.patch	2009-08-07 11:02:47.000000000 -0400
@@ -1045,7 +1045,8 @@
 @@ -22,7 +23,8 @@
  /* TPM configuration */
  #define TPM_STORE_TO_FILE       1
- #undef  TPM_STRONG_PERSISTENCE
+-#undef  TPM_STRONG_PERSISTENCE
++#define  TPM_STRONG_PERSISTENCE
 -#undef  TPM_GENERATE_EK
 +//#undef  TPM_GENERATE_EK
 +#define  TPM_GENERATE_EK

[-- Attachment #1.1.5: vtpm-0.5.1.patch --]
[-- Type: text/x-patch, Size: 28219 bytes --]

diff -Naur xen-unstable.hg.pristine/tools/vtpm/Makefile xen-unstable.hg/tools/vtpm/Makefile
--- xen-unstable.hg.pristine/tools/vtpm/Makefile	2009-08-07 10:19:48.000000000 -0400
+++ xen-unstable.hg/tools/vtpm/Makefile	2009-08-07 11:18:51.000000000 -0400
@@ -10,7 +10,7 @@
 ORIG_DIR = orig
 
 # Emulator tarball name
-TPM_EMULATOR_NAME = tpm_emulator-0.4
+TPM_EMULATOR_NAME = tpm_emulator-0.5.1
 TPM_EMULATOR_TARFILE = $(TPM_EMULATOR_NAME).tar.gz
 
 GMP_HEADER = /usr/include/gmp.h
@@ -19,13 +19,10 @@
 all: build
 
 .PHONY: build
-build: $(VTPM_DIR) $(TPM_EMULATOR_DIR) build_sub
+build: build_sub
 
 .PHONY: install
 install: build
-	if [ "$(BUILD_EMULATOR)" = "y" ]; then \
-		$(MAKE) -C $(TPM_EMULATOR_DIR) $@ ;\
-	fi 
 	$(MAKE) -C $(VTPM_DIR) $@
 
 .PHONY: clean
@@ -46,25 +43,14 @@
 $(TPM_EMULATOR_TARFILE):
 	wget http://download.berlios.de/tpm-emulator/$(TPM_EMULATOR_TARFILE)
 
-# Create vtpm and TPM emulator dirs
-# apply patches for 1) used as dom0 tpm driver 2) used as vtpm device instance
-$(TPM_EMULATOR_DIR): $(TPM_EMULATOR_TARFILE) tpm_emulator.patch 
-	set -e; if [ "$(BUILD_EMULATOR)" = "y" ]; then \
-		rm -rf $(TPM_EMULATOR_DIR); \
-		tar -xzf $(TPM_EMULATOR_TARFILE); \
-		mv $(TPM_EMULATOR_NAME) $(TPM_EMULATOR_DIR); \
-		cd $(TPM_EMULATOR_DIR); \
-		patch -p1 <../tpm_emulator.patch; \
-	fi
-
-$(VTPM_DIR): $(TPM_EMULATOR_TARFILE) vtpm.patch
+# Create vtpm dirs
+$(VTPM_DIR)/tpmd/tpmd: $(TPM_EMULATOR_TARFILE) vtpm-0.5.1.patch
 	rm -rf $(VTPM_DIR)
 	tar -xzf $(TPM_EMULATOR_TARFILE)
 	mv $(TPM_EMULATOR_NAME) $(VTPM_DIR)
 
 	set -e; cd $(VTPM_DIR); \
-	patch -p1 < ../tpm_emulator.patch; \
-	patch -p1 < ../vtpm.patch
+	patch -p1 < ../vtpm-0.5.1.patch
 
 orig: $(TPM_EMULATOR_TARFILE)
 	mkdir $(ORIG_DIR);
@@ -72,22 +58,14 @@
 	tar -xzf ../$(TPM_EMULATOR_TARFILE);
 
 updatepatches: clean orig
-	set -e; if [ "$(BUILD_EMULATOR)" = "y" ]; then \
-		find $(TPM_EMULATOR_DIR) -name "*.orig" -print | xargs rm -f; \
-		mv tpm_emulator.patch tpm_emulator.patch.old; \
-		diff -uprN orig/$(TPM_EMULATOR_NAME) $(TPM_EMULATOR_DIR) > tpm_emulator.patch || true; \
-        fi; 
 	find $(VTPM_DIR) -name "*.orig" -print | xargs rm -f; 
 	mv vtpm.patch vtpm.patch.old; 
 	diff -uprN $(TPM_EMULATOR_DIR) $(VTPM_DIR) > vtpm.patch || true;
 
 .PHONY: build_sub
-build_sub:
+build_sub: $(VTPM_DIR)/tpmd/tpmd
 	set -e; if [ -e $(GMP_HEADER) ]; then \
 		$(MAKE) -C $(VTPM_DIR); \
-		if [ "$(BUILD_EMULATOR)" = "y" ]; then \
-			$(MAKE) -C $(TPM_EMULATOR_DIR); \
-		fi \
 	else \
 		echo "=== Unable to build VTPMs. libgmp could not be found."; \
 	fi
diff -Naur xen-unstable.hg.pristine/tools/vtpm/vtpm-0.5.1.patch xen-unstable.hg/tools/vtpm/vtpm-0.5.1.patch
--- xen-unstable.hg.pristine/tools/vtpm/vtpm-0.5.1.patch	1969-12-31 19:00:00.000000000 -0500
+++ xen-unstable.hg/tools/vtpm/vtpm-0.5.1.patch	2009-08-07 11:16:17.000000000 -0400
@@ -0,0 +1,766 @@
+diff -Naurp tpm_emulator-0.5.1/Makefile tpm5-test/Makefile
+--- tpm_emulator-0.5.1/Makefile	2008-02-14 03:22:48.000000000 -0500
++++ tpm5-test/Makefile	2009-07-15 09:45:28.000000000 -0400
+@@ -10,7 +10,7 @@ VERSION_MINOR  := 5
+ VERSION_BUILD  := $(shell date +"%s")
+ VERSION_SUFFIX := .1
+ 
+-SUBDIRS := tpmd tpmd_dev tddl
++SUBDIRS := tpmd 
+ 
+ all: version all-recursive
+ 
+@@ -48,12 +48,12 @@ user_install: user
+ modules_install: modules
+ 	@$(MAKE) -C tpmd_dev install || exit -1
+ 
+-DIRS    := . tpm crypto tpmd tpmd_dev tddl tpmd_dev_openbsd
++DIRS    := . tpm crypto tpmd 
+ DISTSRC := $(foreach dir, $(DIRS), $(wildcard $(dir)/*.c))
+ DISTSRC += $(foreach dir, $(DIRS), $(wildcard $(dir)/*.h))
+-DIRS    := . tpmd tpmd_dev tddl tpmd_dev_openbsd
++DIRS    := . tpmd 
+ DISTSRC += $(foreach dir, $(DIRS), $(dir)/Makefile)
+-DISTSRC += ./README ./AUTHORS ./ChangeLog tpmd_dev/tpmd_dev.rules.in
++DISTSRC += ./README ./AUTHORS ./ChangeLog 
+ DISTDIR := tpm_emulator-$(VERSION_MAJOR).$(VERSION_MINOR)$(VERSION_SUFFIX)
+ 
+ dist: $(DISTSRC)
+diff -Naurp tpm_emulator-0.5.1/tpm/tpm_capability.c tpm5-test/tpm/tpm_capability.c
+--- tpm_emulator-0.5.1/tpm/tpm_capability.c	2008-02-14 03:22:48.000000000 -0500
++++ tpm5-test/tpm/tpm_capability.c	2009-07-16 12:04:20.000000000 -0400
+@@ -136,8 +136,19 @@ static TPM_RESULT cap_property(UINT32 su
+ 
+     case TPM_CAP_PROP_TIS_TIMEOUT:
+       debug("[TPM_CAP_PROP_TIS_TIMEOUT]");
+-      /* TODO: TPM_CAP_PROP_TIS_TIMEOUT */
+-      return TPM_FAIL;
++      /* TODO: TPM_CAP_PROP_TIS_TIMEOUT: Measure these values and determine correct ones */
++      UINT32 len = *respSize = 16;
++      BYTE *ptr = *resp = tpm_malloc(*respSize);
++      if (ptr == NULL || 
++          tpm_marshal_UINT32(&ptr, &len, 200000) ||
++          tpm_marshal_UINT32(&ptr, &len, 200000) ||
++          tpm_marshal_UINT32(&ptr, &len, 200000) ||
++          tpm_marshal_UINT32(&ptr, &len, 200000)) {
++        tpm_free(*resp);
++        return TPM_FAIL;
++      }
++      return TPM_SUCCESS;
++
+ 
+     case TPM_CAP_PROP_STARTUP_EFFECT:
+       debug("[TPM_CAP_PROP_STARTUP_EFFECT]");
+@@ -189,8 +200,12 @@ static TPM_RESULT cap_property(UINT32 su
+ 
+     case TPM_CAP_PROP_DURATION:
+       debug("[TPM_CAP_PROP_DURATION]");
+-      /* TODO: TPM_CAP_PROP_DURATION */
+-      return TPM_FAIL;
++      /* TODO: TPM_CAP_PROP_DURATION: Measure these values and return accurate ones */
++      BYTE dur[]= {0x0,0x0,0x0,0xc,0x0,0x7,0xa1,0x20,0x0,0x1e,0x84,0x80,0x11,0xe1,0xa3,0x0}; 
++      *respSize = 16;
++      *resp = tpm_malloc(*respSize);
++      memcpy(*resp,dur,16); 
++
+ 
+     case TPM_CAP_PROP_ACTIVE_COUNTER:
+       debug("[TPM_CAP_PROP_ACTIVE_COUNTER]");
+diff -Naurp tpm_emulator-0.5.1/tpmd/Makefile tpm5-test/tpmd/Makefile
+--- tpm_emulator-0.5.1/tpmd/Makefile	2008-02-14 03:22:48.000000000 -0500
++++ tpm5-test/tpmd/Makefile	2009-07-16 12:08:26.000000000 -0400
+@@ -8,9 +8,10 @@ WFLAGS  := -Wall -Wno-unused -Wpointer-a
+            -Wwrite-strings -Wsign-compare -Wno-multichar
+            #WFLAGS  += -Wextra -Wcast-qual -Wmissing-prototypes -Wmissing-declarations -Wstrict-aliasing
+ CFLAGS  += $(WFLAGS) -g -I.. -I. -O2 -fno-strict-aliasing
++CFLAGS  += -I../../../../tools/vtpm_manager/manager
+ LDFLAGS += -lgmp
+ 
+-BINDIR  := /usr/sbin/
++BINDIR  := /usr/bin/
+ 
+ TPMD    := tpmd
+ DIRS    := ../tpm ../crypto
+@@ -18,6 +19,8 @@ SRCS    := $(foreach dir, $(DIRS), $(wil
+ OBJS    := $(patsubst %.c, %.o, $(SRCS))
+ OBJS    := $(foreach dir, $(DIRS), $(patsubst $(dir)/%.o, %.o, $(filter $(dir)/%.o, $(OBJS))))
+ 
++VTPM_BIN := vtpmd
++
+ vpath %.c $(strip $(DIRS))
+ 
+ all: $(TPMD)
+@@ -32,10 +35,8 @@ TPMD_GROUP ?= tss
+ INSTALL    ?= install
+ 
+ install: $(TPMD)
+-	$(INSTALL) -m 755 -o $(TPMD_USER) -g $(TPMD_GROUP) -d $(DESTDIR)/var/lib/tpm
+-	$(INSTALL) -m 755 -o $(TPMD_USER) -g $(TPMD_GROUP) -d $(DESTDIR)/var/run/tpm
+ 	$(INSTALL) -D -d $(DESTDIR)/$(BINDIR)
+-	$(INSTALL) -m 755 $(TPMD) $(DESTDIR)/$(BINDIR)
++	$(INSTALL) -m 755 $(TPMD) $(DESTDIR)/$(BINDIR)/$(VTPM_BIN)
+ 
+ .PHONY: all clean install
+ 
+diff -Naurp tpm_emulator-0.5.1/tpmd/tpmd.c tpm5-test/tpmd/tpmd.c
+--- tpm_emulator-0.5.1/tpmd/tpmd.c	2008-02-14 03:22:48.000000000 -0500
++++ tpm5-test/tpmd/tpmd.c	2009-07-16 11:19:05.000000000 -0400
+@@ -32,6 +32,9 @@
+ #include <grp.h>
+ #include "tpm_emulator_config.h"
+ #include "tpm/tpm_emulator.h"
++#include "tpm/tpm_structures.h"
++#include "tpm/tpm_marshalling.h"
++#include "vtpm_manager.h"
+ 
+ #define TPM_DAEMON_NAME     "tpmd"
+ #define TPM_CMD_BUF_SIZE    4096
+@@ -39,6 +42,24 @@
+ #define TPM_RANDOM_DEVICE   "/dev/urandom"
+ #undef  TPM_MKDIRS
+ 
++#ifdef VTPM_MULTI_VM
++ #define DEV_BE "/dev/vtpm"
++ #define DEV_FE "/dev/tpm"
++#else
++ #define PVM_RX_FIFO_D "/var/vtpm/fifos/tpm_cmd_to_%d.fifo"
++ #define PVM_TX_FIFO "/var/vtpm/fifos/tpm_rsp_from_all.fifo"
++ #define HVM_RX_FIFO_D "/var/vtpm/socks/%d.socket"
++
++ #define VTPM_RX_FIFO_D "/var/vtpm/fifos/vtpm_rsp_to_%d.fifo"
++ #define VTPM_TX_FIFO "/var/vtpm/fifos/vtpm_cmd_from_all.fifo"
++
++ static char *vtpm_rx_name=NULL;
++#endif
++
++ static int vtpm_tx_fh=-1, vtpm_rx_fh=-1;
++
++#define BUFFER_SIZE 2048
++
+ static volatile int stopflag = 0;
+ static int is_daemon = 0;
+ static int opt_debug = 0;
+@@ -49,6 +70,8 @@ static const char *opt_storage_file = "/
+ static uid_t opt_uid = 0;
+ static gid_t opt_gid = 0;
+ static int tpm_startup = 2;
++static int vtpm_type = VTPM_TYPE_PVM;
++int dmi_id = 0;
+ static int rand_fh;
+ 
+ void tpm_log(int priority, const char *fmt, ...)
+@@ -90,56 +113,241 @@ uint64_t tpm_get_ticks(void)
+ 
+ int tpm_write_to_file(uint8_t *data, size_t data_length)
+ {
+-    int fh;
+-    ssize_t res;
+-    fh = open(opt_storage_file, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
+-    if (fh < 0) return -1;
+-    while (data_length > 0) {
+-        res = write(fh, data, data_length);
+-	if (res < 0) {
+-	    close(fh);
+-	    return -1;
+-	}
+-	data_length -= res; 
+-	data += res;
++  int res, out_data_size, in_header_size;
++  BYTE *ptr, *out_data, *in_header;
++  UINT32 result, len, in_rsp_size;
++  UINT16 tag = VTPM_TAG_REQ;
++	
++  printf("Saving NVM\n");
++  if (vtpm_tx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++    vtpm_tx_fh = open(DEV_FE, O_RDWR);
++#else
++	vtpm_tx_fh = open(VTPM_TX_FIFO, O_WRONLY);
++#endif
++  }
++
++  if (vtpm_tx_fh < 0) {
++		return -1;
++  }
++ 
++  // Send request to VTPM Manager to encrypt data
++#ifdef VTPM_MUTLI_VM
++  out_data_size = len = VTPM_COMMAND_HEADER_SIZE_CLT + data_length;
++#else
++  out_data_size = len = VTPM_COMMAND_HEADER_SIZE_SRV + data_length;
++#endif
++  
++  out_data = ptr = (BYTE *) malloc(len);
++
++  if (ptr == NULL
++#ifndef VTPM_MUTLI_VM
++      || tpm_marshal_UINT32(&ptr, &len, dmi_id)
++#endif
++	  || tpm_marshal_UINT16(&ptr, &len, tag)
++#ifdef VTPM_MUTLI_VM
++	  || tpm_marshal_UINT32(&ptr, &len, out_data_size)
++#else
++	  || tpm_marshal_UINT32(&ptr, &len, out_data_size - sizeof(uint32_t))
++#endif  
++	  || tpm_marshal_UINT32(&ptr, &len, VTPM_ORD_SAVENVM)
++	  || tpm_marshal_BYTE_ARRAY(&ptr, &len, data, data_length)) {
++	free(out_data);
++	return -1;
++  }
++  
++  printf("\tSending SaveNVM Command.\n");
++  res = write(vtpm_tx_fh, out_data, out_data_size);
++  free(out_data);
++  if (res != out_data_size) return -1;
++
++  if (vtpm_rx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++    vtpm_rx_fh = vtpm_tx_fh
++#else
++    if (vtpm_rx_name == NULL) {
++      vtpm_rx_name = malloc(10 + strlen(VTPM_RX_FIFO_D));
++      sprintf(vtpm_rx_name, VTPM_RX_FIFO_D, (uint32_t) dmi_id);
+     }
+-    close(fh);
+-    return 0;
++	vtpm_rx_fh = open(vtpm_rx_name, O_RDONLY);
++#endif
++  }
++
++  if (vtpm_rx_fh < 0) {
++		return -1;
++  }
++  
++  // Read Header of response so we can get the size & status
++#ifdef VTPM_MUTLI_VM
++  in_header_size = len = VTPM_COMMAND_HEADER_SIZE_CLT;
++#else
++  in_header_size = len = VTPM_COMMAND_HEADER_SIZE_SRV;
++#endif
++  in_header = ptr = malloc(in_header_size);
++  
++  printf("\tReading SaveNVM header.\n");
++  res = read(vtpm_rx_fh, in_header, in_header_size);
++
++  if ( (res != in_header_size)
++#ifndef VTPM_MUTLI_VM
++       || tpm_unmarshal_UINT32(&ptr, &len, (UINT32*)&dmi_id)
++#endif
++	   || tpm_unmarshal_UINT16(&ptr, &len, &tag)
++	   || tpm_unmarshal_UINT32(&ptr, &len, &in_rsp_size)
++	   || tpm_unmarshal_UINT32(&ptr, &len, &result) ) {
++	  free(in_header);
++	  return -1;
++  }
++  free(in_header);
++  
++  if (result != VTPM_SUCCESS) {
++      return -1;  
++  }
++
++#ifdef VTPM_MUTLI_VM
++  close(vtpm_tx_fh); close(vtpm_rx_fh);
++#endif
++	  
++  printf("\tFinishing up SaveNVM\n");
++  return (0);
+ }
+ 
+ int tpm_read_from_file(uint8_t **data, size_t *data_length)
+ {
+-    int fh;
+-    ssize_t res;
+-    size_t total_length;
+-    fh = open(opt_storage_file, O_RDONLY);
+-    if (fh < 0) return -1;
+-    total_length = lseek(fh, 0, SEEK_END);
+-    lseek(fh, 0, SEEK_SET);
+-    *data = tpm_malloc(total_length);
+-    if (*data == NULL) {
+-        close(fh);
+-        return -1;
+-    }
+-    *data_length = 0;
+-    while (total_length > 0) {
+-        res = read(fh, &(*data)[*data_length], total_length);
+-	if (res < 0) {
+-	    close(fh);
+-	    tpm_free(*data);
+-	    return -1;
+-	}
+-        *data_length += res;
+-	total_length -= res;
++  int res, out_data_size, in_header_size;
++  uint8_t *ptr, *out_data, *in_header;
++  UINT16 tag = VTPM_TAG_REQ;
++  UINT32 len, in_rsp_size, result;
++#ifdef VTPM_MUTLI_VM
++	int vtpm_rx_fh, vtpm_tx_fh;
++#endif
++	
++  printf("Loading NVM.\n");
++  if (vtpm_tx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++    vtpm_tx_fh = open(DEV_FE, O_RDWR);
++#else
++	vtpm_tx_fh = open(VTPM_TX_FIFO, O_WRONLY);
++#endif
++  }
++
++  if (vtpm_tx_fh < 0) {
++	printf("Error in read_from_file:301\n");
++		return -1;
++  }
++ 
++  // Send request to VTPM Manager to encrypt data
++#ifdef VTPM_MUTLI_VM
++  out_data_size = len = VTPM_COMMAND_HEADER_SIZE_CLT;
++#else
++  out_data_size = len = VTPM_COMMAND_HEADER_SIZE_SRV;
++#endif
++  out_data = ptr = (BYTE *) malloc(len);
++
++  if (ptr == NULL
++#ifndef VTPM_MUTLI_VM
++      || tpm_marshal_UINT32(&ptr, &len, dmi_id)
++#endif  
++      || tpm_marshal_UINT16(&ptr, &len, tag)
++#ifdef VTPM_MUTLI_VM
++      || tpm_marshal_UINT32(&ptr, &len, out_data_size)
++#else
++      || tpm_marshal_UINT32(&ptr, &len, out_data_size - sizeof(uint32_t))
++#endif
++      || tpm_marshal_UINT32(&ptr, &len, VTPM_ORD_LOADNVM)) {
++    free(out_data);
++    printf("Error in read_from_file:325\n");
++
++    return -1;
++  }
++
++  printf("\tSending LoadNVM command\n");
++  res = write(vtpm_tx_fh, out_data, out_data_size);
++  free(out_data);
++  if (res != out_data_size) 
++    {
++	printf("Error in read_from_file:335\n");
++	return -1;
++    }
++
++    if (vtpm_rx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++    vtpm_rx_fh = vtpm_tx_fh;
++#else
++    if (vtpm_rx_name == NULL) {
++      vtpm_rx_name = malloc(10 + strlen(VTPM_RX_FIFO_D));
++      sprintf(vtpm_rx_name, VTPM_RX_FIFO_D, (uint32_t) dmi_id);
+     }
+-    close(fh);
+-    return 0;
++	vtpm_rx_fh = open(vtpm_rx_name, O_RDONLY);
++#endif
++  }
++
++  if (vtpm_rx_fh < 0) {
++	printf("Error in read_from_file:352\n");	
++	return -1;
++  }
++  
++  // Read Header of response so we can get the size & status
++#ifdef VTPM_MUTLI_VM
++  in_header_size = len = VTPM_COMMAND_HEADER_SIZE_CLT;
++#else
++  in_header_size = len = VTPM_COMMAND_HEADER_SIZE_SRV;
++#endif
++  in_header = ptr = malloc(in_header_size);
++  
++  printf("\tReading LoadNVM header\n");
++  res = read(vtpm_rx_fh, in_header, in_header_size);
++
++  if ( (res != in_header_size)
++#ifndef VTPM_MUTLI_VM
++       || tpm_unmarshal_UINT32(&ptr, &len, (UINT32*)&dmi_id)
++#endif
++       || tpm_unmarshal_UINT16(&ptr, &len, &tag)
++       || tpm_unmarshal_UINT32(&ptr, &len, &in_rsp_size)
++       || tpm_unmarshal_UINT32(&ptr, &len, &result) ) {
++      free(in_header);
++      printf("Error in read_from_file:375\n");     
++      return -1;
++  }
++  free(in_header);
++  
++  if (result != VTPM_SUCCESS) {
++    printf("Error in read_from_file:381\n");
++    return -1;  
++  }
++
++  // Read Encrypted data from VTPM Manager
++  *data_length = in_rsp_size - VTPM_COMMAND_HEADER_SIZE_CLT;
++  *data = (uint8_t *) malloc(*data_length);
++
++  printf("\tReading clear data from LoadNVM.\n");
++  res = read(vtpm_rx_fh, *data, *data_length);
++#ifdef VTPM_MUTLI_VM
++  close(vtpm_rx_fh);close(vtpm_tx_fh);
++#endif 
++	
++  printf("\tReturing from loading NVM\n");
++  if (res != (int)*data_length) {
++      free(*data);
++      printf("Error in read_from_file:398\n");
++      return -1;
++  } else {
++      return 0;
++  }
++
++
++    
+ }
+ 
+ static void print_usage(char *name)
+ {
+     printf("usage: %s [-d] [-f] [-s storage file] [-u unix socket name] "
+-           "[-o user name] [-g group name] [-h] [startup mode]\n", name);
++           "[-o user name] [-g group name] [-h]"
++#ifdef VTPM_MULTI_VM
++	   "clear|save|deactivated\n", name);
++#else
++	   "clear|save|deactivated pvm|hvm vtpmid\n", name);
++#endif
+     printf("  d : enable debug mode\n");
+     printf("  f : forces the application to run in the foreground\n");
+     printf("  s : storage file to use (default: %s)\n", opt_storage_file);
+@@ -205,7 +413,13 @@ static void parse_options(int argc, char
+                 exit(EXIT_SUCCESS);
+         }
+     }
+-    if (optind < argc) {
++    /*Make sure we have all required options*/
++#ifdef VTPM_MULTI_VM
++#define EXTRA_OPTS 0
++#else
++#define EXTRA_OPTS 2
++#endif
++    if (optind < argc - EXTRA_OPTS ) {
+         debug("startup mode = '%s'", argv[optind]);
+         if (!strcmp(argv[optind], "clear")) {
+             tpm_startup = 1;
+@@ -219,6 +433,25 @@ static void parse_options(int argc, char
+             print_usage(argv[0]);
+             exit(EXIT_SUCCESS);
+         }
++#ifndef VTPM_MULTI_VM
++        ++optind;
++	if(!strcmp(argv[optind], "pvm")) {
++		vtpm_type = VTPM_TYPE_PVM;	// Get commands from vTPM Manager through fifo
++	} else if (!strcmp(argv[optind], "hvm")) {
++		vtpm_type = VTPM_TYPE_HVM;	// Get commands from qemu via socket
++        } else {
++		error("Invalid vm mode '%s'; must be 'pvm', "
++			"or 'hvm' ", argv[optind]);
++		print_usage(argv[0]);
++		exit(EXIT_SUCCESS);
++	}
++        ++optind;
++	dmi_id = atoi(argv[optind]);
++#endif
++    } else {
++	error("Invalid number of arguments");
++	print_usage(argv[0]);
++	exit(EXIT_SUCCESS);
+     }
+ }
+ 
+@@ -348,93 +581,180 @@ static int init_socket(const char *name)
+ 
+ static void main_loop(void)
+ {
+-    int sock, fh, res;
+-    int32_t in_len;
++    int32_t in_len, written;
+     uint32_t out_len;
+-    uint8_t in[TPM_CMD_BUF_SIZE], *out;
++    uint8_t in[TPM_CMD_BUF_SIZE], *out, *addressed_out;
++    int guest_id=-1;
++    int i;
++    char *vtpm_rx_file=NULL;
++    int res;
++
++#ifndef VTPM_MULTI_VM
++    int sockfd = -1;
+     struct sockaddr_un addr;
+-    socklen_t addr_len;
+-    fd_set rfds;
+-    struct timeval tv;
++    struct sockaddr_un client_addr;
++    unsigned int client_length;
++#endif
++
++    int vtpm_tx_fh=-1, vtpm_rx_fh=-1;
++
++#ifndef VTPM_MULTI_VM
++  if (vtpm_type == VTPM_TYPE_PVM) {
++    vtpm_rx_file = malloc(10 + strlen(PVM_RX_FIFO_D));
++    sprintf(vtpm_rx_file, PVM_RX_FIFO_D, (uint32_t) dmi_id);
++  } else {
++    vtpm_rx_file = malloc(10 + strlen(HVM_RX_FIFO_D));
++    sprintf(vtpm_rx_file, HVM_RX_FIFO_D, (uint32_t) dmi_id);
++
++    if ( (sockfd = socket(PF_UNIX,SOCK_STREAM,0)) < 0) {
++          error("Unable to create socket. errno = %d\n", errno);
++      exit (-1);
++    }
++
++    memset(&addr, 0, sizeof(addr));
++    addr.sun_family = AF_UNIX;
++    strcpy(addr.sun_path,vtpm_rx_file );
++    unlink(addr.sun_path);
++  }
++#endif
+ 
+     info("staring main loop");
+-    /* open UNIX socket */
+-    sock = init_socket(opt_socket_name);
+-    if (sock < 0) exit(EXIT_FAILURE);
+     /* init tpm emulator */
+-    debug("initializing TPM emulator: %d", tpm_startup);
++#ifdef VTPM_MULTI_VM
++    debug("initializing TPM emulator: state=%d", tpm_startup);
++#else
++    debug("initializing TPM emulator: state=%d, type=%d, id=%d", tpm_startup, vtpm_type, dmi_id);
++#endif
+     tpm_emulator_init(tpm_startup);
+     /* start command processing */
+     while (!stopflag) {
+         /* wait for incomming connections */
+         debug("waiting for connections...");
+-        FD_ZERO(&rfds);
+-        FD_SET(sock, &rfds);
+-        tv.tv_sec = 10;
+-        tv.tv_usec = 0;
+-        res = select(sock + 1, &rfds, NULL, NULL, &tv);
+-        if (res < 0) {
+-            error("select(sock) failed: %s", strerror(errno));
+-            break;
+-        } else if (res == 0) {
+-            continue;
+-        }
+-        addr_len = sizeof(addr);
+-        fh = accept(sock, (struct sockaddr*)&addr, &addr_len);
+-        if (fh < 0) {
+-            error("accept() failed: %s", strerror(errno));
+-            continue;
+-        }
++	if (vtpm_rx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++	    vtpm_rx_fh = open(DEV_BE, O_RDWR);
++#else
++	    if (vtpm_type == VTPM_TYPE_PVM)
++	    {
++		vtpm_rx_fh = open(vtpm_rx_file, O_RDONLY);
++	    } else {
++		if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
++		    error("Unable to bind(). errno = %d\n", errno);
++		    exit (-1);
++		}
++
++		if (listen(sockfd, 10) <0) {
++		    error("Unable to listen(). errno = %d\n", errno);
++		    exit (-1);
++		} 
++
++		 memset(&client_addr, 0, sizeof(client_addr));
++		 client_length = sizeof(client_addr);
++
++		 vtpm_rx_fh = vtpm_tx_fh = accept(sockfd, (struct sockaddr *)&client_addr, &client_length);
++	    }
++#endif
++	}
++	
++	/*Error Checking*/
++	if (vtpm_rx_fh < 0) {
++	  error("Failed to open devices to listen to guest.\n");
++	  exit(-1);
++	}
++
+         /* receive and handle commands */
+         in_len = 0;
+         do {
+             debug("waiting for commands...");
+-            FD_ZERO(&rfds);
+-            FD_SET(fh, &rfds);
+-            tv.tv_sec = TPM_COMMAND_TIMEOUT;
+-            tv.tv_usec = 0;
+-            res = select(fh + 1, &rfds, NULL, NULL, &tv);
+-            if (res < 0) {
+-                error("select(fh) failed: %s", strerror(errno));
+-                close(fh);
+-                break;
+-            } else if (res == 0) {
+-#ifdef TPMD_DISCONNECT_IDLE_CLIENTS	    
+-                info("connection closed due to inactivity");
+-                close(fh);
+-                break;
+-#else		
+-                continue;
+-#endif		
+-            }
+-            in_len = read(fh, in, sizeof(in));
+-            if (in_len > 0) {
++
++            in_len = read(vtpm_rx_fh, in, sizeof(in));
++	    /*Magic size of minimum TPM command is 6*/
++		//FIXME Magic size check may not be required anymore
++            if (in_len < 6) {
++		info("Recv incomplete command of %d bytes.", in_len);
++		if (in_len <= 0) {
++		    close(vtpm_rx_fh);
++		    vtpm_rx_fh = -1;
++		    continue;
++                 }
++	    } else {
++		/*Debug Printouts*/
+                 debug("received %d bytes", in_len);
++		debug_nostop("Recv[%d]: 0x", in_len);
++		for (i=0; i< in_len; i++) 
++		    debug_more("%x ", in[i]);
++		debug_more("\n");
++		/*Multiple Guest check*/
++		if (guest_id == -1) {
++		    guest_id = *((int32_t *) in);
++		} else {
++		    if (guest_id != *((int32_t *) in) ) {
++			error("WARNING: More than one guest attached\n");
++		    }
++		}
++
++		/*Open tx handle now*/
++		if (vtpm_tx_fh < 0) {
++#ifdef VTPM_MUTLI_VM
++		    vtpm_tx_fh = open(DEV_BE, O_RDWR);
++		    vtpm_rx_fh = vtpm_tx_fh;
++#else
++		    if (vtpm_type == VTPM_TYPE_PVM) {
++			vtpm_tx_fh = open(PVM_TX_FIFO, O_WRONLY);
++     		    } // No need to open the other direction for HVM
++#endif
++		}
++		if (vtpm_tx_fh < 0) {
++		  error("Failed to open devices to respond to guest.\n");
++		  exit(-1);
++		}
++
++		/*Handle the TPM command now*/
+                 out = NULL;
+-                res = tpm_handle_command(in, in_len, &out, &out_len);
++                res = tpm_handle_command(in + sizeof(uint32_t), in_len - sizeof(uint32_t), &out, &out_len);
+                 if (res < 0) {
+                     error("tpm_handle_command() failed");
+                 } else {
+                     debug("sending %d bytes", out_len);
++		    //FIXME this prepending may or may not be needed
++		    /*Prepend the first 4 bytes of the in buffer.. why?*/
++		    addressed_out = (uint8_t *) tpm_malloc(sizeof(uint32_t) + out_len);
++		    *(uint32_t *) addressed_out = *(uint32_t *) in;
++		    memcpy(addressed_out + sizeof(uint32_t), out, out_len);
++		    out_len += sizeof(uint32_t);
++		    /*End Prepend*/
++
++		    /*Perform write operation now*/
+                     while (out_len > 0) {
+-                        res = write(fh, out, out_len);
++                        res = write(vtpm_tx_fh, addressed_out, out_len);
++
+                         if (res < 0) {
+                             error("write(%d) failed: %s", out_len, strerror(errno));
+                             break;
+-                        }
++                        } else {
++			  debug_nostop("Sent[%Zu]: ", out_len);
++			  for (i=0; (unsigned int)i< out_len; i++)
++			    debug_more("%x ", addressed_out[i]);
++			  debug_more("\n");
++			}
+                         out_len	-= res;
+                     }
+                     tpm_free(out);
++		    tpm_free(addressed_out);
+                 }
+             }
+         } while (in_len > 0);
+-        close(fh);
++        //close(fh);
+     }
++    
+     /* shutdown tpm emulator */
+     tpm_emulator_shutdown();
+-    /* close socket */
+-    close(sock);
+-    unlink(opt_socket_name);
++    /* Close handles */
++    close(vtpm_tx_fh);
++#ifndef VTPM_MULTI_VM
++    close(vtpm_rx_fh);
++    free(vtpm_rx_file);
++#endif
+     info("main loop stopped");
+ }
+ 
+@@ -450,12 +770,13 @@ int main(int argc, char **argv)
+     /* open random device */
+     init_random();
+     /* init signal handlers */
+-    init_signal_handler();
++    //init_signal_handler();
+     /* unless requested otherwiese, fork and daemonize process */
+-    if (!opt_foreground) daemonize();
++    //if (!opt_foreground) daemonize();
+     /* start main processing loop */
+     main_loop();
+     info("stopping TPM Emulator daemon");
+     closelog();
+     return 0;
+ }
++
+diff -Naurp tpm_emulator-0.5.1/tpmd/tpm_emulator_config.h tpm5-test/tpmd/tpm_emulator_config.h
+--- tpm_emulator-0.5.1/tpmd/tpm_emulator_config.h	2008-02-14 03:22:48.000000000 -0500
++++ tpm5-test/tpmd/tpm_emulator_config.h	2009-07-16 11:25:26.000000000 -0400
+@@ -29,23 +29,28 @@
+ 
+ /* TPM emulator configuration */
+ 
+-#undef  TPM_STRONG_PERSISTENCE
+-#undef  TPM_GENERATE_EK
++#define  TPM_STRONG_PERSISTENCE
++#define  TPM_GENERATE_EK
+ #undef  TPM_GENERATE_SEED_DAA
+ #undef  TPM_MEMORY_ALIGNMENT_MANDATORY
+ 
++extern int dmi_id;
++
+ /* log macros */
+ 
+ void tpm_log(int priority, const char *fmt, ...);
+ 
+-#define debug(fmt, ...) tpm_log(LOG_DEBUG, "%s:%d: Debug: " fmt "\n", \
+-                                __FILE__, __LINE__, ## __VA_ARGS__)
+-#define info(fmt, ...)  tpm_log(LOG_INFO, "%s:%d: Info: " fmt "\n", \
+-                                __FILE__, __LINE__, ## __VA_ARGS__)
+-#define error(fmt, ...) tpm_log(LOG_ERR, "%s:%d: Error: " fmt "\n", \
+-                                __FILE__, __LINE__, ## __VA_ARGS__)
+-#define alert(fmt, ...) tpm_log(LOG_ALERT, "%s:%d: Alert: " fmt "\n", \
+-                                __FILE__, __LINE__, ## __VA_ARGS__)
++#define debug(fmt, ...) tpm_log(LOG_DEBUG, "VTPMD[%d]: %s:%d: Debug: " fmt "\n", \
++                                dmi_id, __FILE__, __LINE__, ## __VA_ARGS__)
++#define info(fmt, ...)  tpm_log(LOG_INFO, "VTPMD[%d]: %s:%d: Info: " fmt "\n", \
++                                dmi_id, __FILE__, __LINE__, ## __VA_ARGS__)
++#define error(fmt, ...) tpm_log(LOG_ERR, "VTPMD[%d]: %s:%d: Error: " fmt "\n", \
++                                dmi_id, __FILE__, __LINE__, ## __VA_ARGS__)
++#define alert(fmt, ...) tpm_log(LOG_ALERT, "VTPMD[%d]: %s:%d: Alert: " fmt "\n", \
++                                dmi_id, __FILE__, __LINE__, ## __VA_ARGS__)
++#define debug_nostop(fmt, ...) tpm_log(LOG_DEBUG, "VTPMD[%d]: %s:%d: Debug: " fmt, \
++                                dmi_id, __FILE__, __LINE__, ## __VA_ARGS__)
++#define debug_more(fmt, ...) tpm_log(LOG_DEBUG, fmt, ## __VA_ARGS__)
+ 
+ /*  min/max macros that also do strict type-checking */
+ 

[-- Attachment #1.2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 2420 bytes --]

[-- Attachment #2: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Several vtpm patches and workarounds: persistence, stability, tpm_emulator-0.5.1
  2009-08-21 16:02 Several vtpm patches and workarounds: persistence, stability, tpm_emulator-0.5.1 Matt Fioravante
@ 2009-08-21 16:33 ` Keir Fraser
  2009-08-21 19:46   ` Matt Fioravante
  0 siblings, 1 reply; 3+ messages in thread
From: Keir Fraser @ 2009-08-21 16:33 UTC (permalink / raw)
  To: Matt Fioravante, xen-devel

Thanks. Can you provide a signed-off-by line for these patches? Then at
least some of them can go into the Xen repository.

 -- Keir

On 21/08/2009 17:02, "Matt Fioravante" <Matthew.Fioravante@jhuapl.edu>
wrote:

> We are using xen and vtpm at JHU APL for a project and ran into many
> problems. I've had to develop several patches and workarounds and wanted
> to contribute them back to the xen community.
> 
> Here are a few patches that will make the xen vtpm system more stable
> and allow you to have persistent vtpms. In other words you can reboot a
> domU and it will come back up with the same vtpm instance and retain all
> the keys and data you stored in it.
> 
> Also included is a patch that ports vtpm to tpm_emulator-0.5.1. The new
> emulator has a lot of bug fixes over the old 0.4 and is recommended if
> you want a working vtpm implementation. This port is incomplete, so
> please see the details on that patch before applying it.
> 
> Some of these are actual bug fixes while others are hacks/workarounds.
> Becuase of this, they have been broken into several patches to assist
> the developers in choosing which they want to integrate. With these
> patches we have been successfully able to use persistent vtpms for
> signing certificates.
> 
> All of these patches can be applied on top of each other in any order.
> $ patch -p1 < patchfile
> 
> 
> Finally, there are also some bugs in the xen hotplug system and the
> vtpm_manager. Sometimes the manager can get into a corrupted state and
> it will cease to work properly. Workarounds for some of the problems are
> included at the end of this email.
> 
> 
> ==============================
> vtpm_manager-hash_error.patch
> ==============================
> There is a bug in the vtpm_manager that has to do with hashing and
> saving the NVM memory files (vtpm_dm_%d.data). The file is not truncated
> when it is written and this results in the hash becoming invalid because
> of the extra bits at the end of the file.
> 
> This patch adds O_TRUNC to the flags when opening the file.
> 
> More details on this issue are in the bug report on bugzilla
> http://bugzilla.xensource.com/bugzilla/show_bug.cgi?id=1488
> 
> ==============================
> vtpm-uuid.patch
> ==============================
> Right now xen will create a new vtpm instance everytime you start up a
> domU, even if you specify the instance parameter in your config file.
> Each vtpm instance is then given a uuid and the vtpm.db file maps
> instance numbers to uuid numbers.
> 
> This patch is a hack that lets you explicitly set the uuid of your vtpm
> instance. Everytime you boot up your domU now the vtpm will get that
> uuid and thus it will always get the same vtpm instance number instead
> of being generated a new one.
> 
> So for example, in your config file you would do something like this
> vtpm = [ 'backend=0,uuid=dcdb124b-9fed-4040-b149-dd2dfd8d094c' ]
> 
> If you are using this patch then be sure to also use the hash_error
> patch, otherwise you may see checksum failed messages when booting
> your domain and the vtpm tries to read the NVM file. These 2 patches
> were made separate because the first is a bug fix and this one is more
> of a hack.
> 
> ==============================
> vtpm-0.4-persistence.patch
> ==============================
> This patch is only needed if you want to continue using
> tpm_emulator-0.4. It is not necessary if you are going to use the
> tpm_emulator-0.5.1 patch.
> 
> This patch will add
> #define TPM_STRONG_PERSISTENCE
> which will make the tpm_emulator send a TPM_SaveState command after
> every tpm command it executes. This is needed because some commands like
> TPM_TakeOwnership do not send the TPM_SaveState command on their own.
> The tpm_emulator will only request the manager to save its state when
> this TPM command is sent.
> 
> So in short without this patch, if you took ownership of your vtpm and
> then rebooted the domU, the the change in state would not be saved and
> your vtpm would come back unowned again.
> 
> I imagine several other tpm commands would have this problem as well.
> 
> ==============================
> vtpm-0.5.1.patch
> ==============================
> This patch will port vtpm to use tpm_emulator-0.5.1
> The newer version of the emulator contains several bug fixes, one that
> we were seeing in our use of vtpm.
> 
> This patch also defines TPM_STRONG_PERSISTENCE for the new emulator.
> 
> A couple of important notes about this patch:
> -This has only been tested on PVM domU's. In theory it should work for
> HVM but I have not tried it at all and can guarantee nothing.
> -All the relevant changes in tools/vtpm/vtpm.patch have been ported to
> tpm_emulator-0.5.1.
> -None of the changes in tpm_emulator.patch have been ported. In
> particular this means the BUILD_EMULATOR option, which as I understand
> lets you use the tpm_emulator in dom0 for a machine that does
> not have a real hardware TPM does not work. This functionality should be
> easy to add though because the new emulator already comes with a kernel
> module interface.
> -No considerations were made for the VTPM_MULTI_VM feature (which is
> supposedly unfinished). This patch may or may not break any progress
> made on that feature.
> 
> ============================
> vtpm_manager and xen hotplug workarounds
> ============================
> Here are some issues I've run into when trying to use vtpm. Note that in
> my test cases we were only using vtpms in PVM domains.
> 
> It might make sense to add these to a readme or something somewhere
> until the hotplug issues are fixed.
> 
> 1-Q) When I boot my domU with a vtpm for the first time I get
> the following error message in the vtpm_managerd output
> Loading NVM.
>         Sending LoadNVM command
> ERROR[VTPM]: Failed to load NVM
> .INFO[VTPM]: [VTPM Listener]: VTPM Listener waiting for messages.
>         Reading LoadNVM header
> 1-A) This is ok. This message comes up when the vtpm non-volatile memory
> file does not exist, which is normal when xen creates a new vtpm
> instance.
> 
> 2-Q) When I start vtpm_managerd it starts spamming output to the console
> forever and gives the following error:
> ERROR[VTPM]: [Hotplug Listener]: Hotplug Listener can't read from ipc.
> Errono = 0. Aborting...
> 2-A) Sometimes the hotplug scripts and the fifos they use to
> communicate 
> get in a corrupted state. We need to clear all the fifos.
> 1) First, stop all of the vms that have vtpms.
> 2) Kill the vtpm_managerd
> 3) Search for vtpm processes.
> #ps -ef | grep vtpm
> You may see processes that look like the following. If you do
> not see any then skip ahead to the next step.
> /bin/bash /etc/xen/scripts/vtpm add
> dd skip=10 bs=1 count=4 if=/var/vtpm/fifos/to_console.fifo
> /usr/bin/vtpmd
> First, kill any of the dd processes, and then run ps again. Most if
> not all  of the /etx/xen/scripts/vtpm processes should have quit.
> Kill any of the remaining scripts/vtpm and vtpmd processes.
> Note that after killing some of of the "vtpm add" processes
> new "vtpm remove" processes may get spawned which you will
> also need to kill.
> 4) Delete all of the fifos and socks
> #rm /var/vtpm/fifos/*
> #rm /var/vtpm/socks/*
> 5) Remove the lock files if they exist
> # rm -rf /var/run/xen-hotplug/vtpm*
> 6) Now start up the vtpm_managerd again, it should start without errors.
> 7) Finally, you should be able to boot up the vms again without any
> problems.
> 
> 3-Q) When I start a domU that has a vtpm it hangs in the
> pause state and will not boot. If I wait long enough it will quit and
> tell me that the Hotplug scripts are not working.
> 3-A) This occurs when we have stale lock files that did not get removed
> properly. 
> Perform the same set of steps in 2-A.
> 

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Several vtpm patches and workarounds: persistence, stability, tpm_emulator-0.5.1
  2009-08-21 16:33 ` Keir Fraser
@ 2009-08-21 19:46   ` Matt Fioravante
  0 siblings, 0 replies; 3+ messages in thread
From: Matt Fioravante @ 2009-08-21 19:46 UTC (permalink / raw)
  To: xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 8421 bytes --]

Signed-off-by: Matt Fioravante <Matthew.Fioravante@jhuapl.edu>

On Fri, 2009-08-21 at 12:33 -0400, Keir Fraser wrote:
> Thanks. Can you provide a signed-off-by line for these patches? Then at
> least some of them can go into the Xen repository.
> 
>  -- Keir
> 
> On 21/08/2009 17:02, "Matt Fioravante" <Matthew.Fioravante@jhuapl.edu>
> wrote:
> 
> > We are using xen and vtpm at JHU APL for a project and ran into many
> > problems. I've had to develop several patches and workarounds and wanted
> > to contribute them back to the xen community.
> > 
> > Here are a few patches that will make the xen vtpm system more stable
> > and allow you to have persistent vtpms. In other words you can reboot a
> > domU and it will come back up with the same vtpm instance and retain all
> > the keys and data you stored in it.
> > 
> > Also included is a patch that ports vtpm to tpm_emulator-0.5.1. The new
> > emulator has a lot of bug fixes over the old 0.4 and is recommended if
> > you want a working vtpm implementation. This port is incomplete, so
> > please see the details on that patch before applying it.
> > 
> > Some of these are actual bug fixes while others are hacks/workarounds.
> > Becuase of this, they have been broken into several patches to assist
> > the developers in choosing which they want to integrate. With these
> > patches we have been successfully able to use persistent vtpms for
> > signing certificates.
> > 
> > All of these patches can be applied on top of each other in any order.
> > $ patch -p1 < patchfile
> > 
> > 
> > Finally, there are also some bugs in the xen hotplug system and the
> > vtpm_manager. Sometimes the manager can get into a corrupted state and
> > it will cease to work properly. Workarounds for some of the problems are
> > included at the end of this email.
> > 
> > 
> > ==============================
> > vtpm_manager-hash_error.patch
> > ==============================
> > There is a bug in the vtpm_manager that has to do with hashing and
> > saving the NVM memory files (vtpm_dm_%d.data). The file is not truncated
> > when it is written and this results in the hash becoming invalid because
> > of the extra bits at the end of the file.
> > 
> > This patch adds O_TRUNC to the flags when opening the file.
> > 
> > More details on this issue are in the bug report on bugzilla
> > http://bugzilla.xensource.com/bugzilla/show_bug.cgi?id=1488
> > 
> > ==============================
> > vtpm-uuid.patch
> > ==============================
> > Right now xen will create a new vtpm instance everytime you start up a
> > domU, even if you specify the instance parameter in your config file.
> > Each vtpm instance is then given a uuid and the vtpm.db file maps
> > instance numbers to uuid numbers.
> > 
> > This patch is a hack that lets you explicitly set the uuid of your vtpm
> > instance. Everytime you boot up your domU now the vtpm will get that
> > uuid and thus it will always get the same vtpm instance number instead
> > of being generated a new one.
> > 
> > So for example, in your config file you would do something like this
> > vtpm = [ 'backend=0,uuid=dcdb124b-9fed-4040-b149-dd2dfd8d094c' ]
> > 
> > If you are using this patch then be sure to also use the hash_error
> > patch, otherwise you may see checksum failed messages when booting
> > your domain and the vtpm tries to read the NVM file. These 2 patches
> > were made separate because the first is a bug fix and this one is more
> > of a hack.
> > 
> > ==============================
> > vtpm-0.4-persistence.patch
> > ==============================
> > This patch is only needed if you want to continue using
> > tpm_emulator-0.4. It is not necessary if you are going to use the
> > tpm_emulator-0.5.1 patch.
> > 
> > This patch will add
> > #define TPM_STRONG_PERSISTENCE
> > which will make the tpm_emulator send a TPM_SaveState command after
> > every tpm command it executes. This is needed because some commands like
> > TPM_TakeOwnership do not send the TPM_SaveState command on their own.
> > The tpm_emulator will only request the manager to save its state when
> > this TPM command is sent.
> > 
> > So in short without this patch, if you took ownership of your vtpm and
> > then rebooted the domU, the the change in state would not be saved and
> > your vtpm would come back unowned again.
> > 
> > I imagine several other tpm commands would have this problem as well.
> > 
> > ==============================
> > vtpm-0.5.1.patch
> > ==============================
> > This patch will port vtpm to use tpm_emulator-0.5.1
> > The newer version of the emulator contains several bug fixes, one that
> > we were seeing in our use of vtpm.
> > 
> > This patch also defines TPM_STRONG_PERSISTENCE for the new emulator.
> > 
> > A couple of important notes about this patch:
> > -This has only been tested on PVM domU's. In theory it should work for
> > HVM but I have not tried it at all and can guarantee nothing.
> > -All the relevant changes in tools/vtpm/vtpm.patch have been ported to
> > tpm_emulator-0.5.1.
> > -None of the changes in tpm_emulator.patch have been ported. In
> > particular this means the BUILD_EMULATOR option, which as I understand
> > lets you use the tpm_emulator in dom0 for a machine that does
> > not have a real hardware TPM does not work. This functionality should be
> > easy to add though because the new emulator already comes with a kernel
> > module interface.
> > -No considerations were made for the VTPM_MULTI_VM feature (which is
> > supposedly unfinished). This patch may or may not break any progress
> > made on that feature.
> > 
> > ============================
> > vtpm_manager and xen hotplug workarounds
> > ============================
> > Here are some issues I've run into when trying to use vtpm. Note that in
> > my test cases we were only using vtpms in PVM domains.
> > 
> > It might make sense to add these to a readme or something somewhere
> > until the hotplug issues are fixed.
> > 
> > 1-Q) When I boot my domU with a vtpm for the first time I get
> > the following error message in the vtpm_managerd output
> > Loading NVM.
> >         Sending LoadNVM command
> > ERROR[VTPM]: Failed to load NVM
> > .INFO[VTPM]: [VTPM Listener]: VTPM Listener waiting for messages.
> >         Reading LoadNVM header
> > 1-A) This is ok. This message comes up when the vtpm non-volatile memory
> > file does not exist, which is normal when xen creates a new vtpm
> > instance.
> > 
> > 2-Q) When I start vtpm_managerd it starts spamming output to the console
> > forever and gives the following error:
> > ERROR[VTPM]: [Hotplug Listener]: Hotplug Listener can't read from ipc.
> > Errono = 0. Aborting...
> > 2-A) Sometimes the hotplug scripts and the fifos they use to
> > communicate 
> > get in a corrupted state. We need to clear all the fifos.
> > 1) First, stop all of the vms that have vtpms.
> > 2) Kill the vtpm_managerd
> > 3) Search for vtpm processes.
> > #ps -ef | grep vtpm
> > You may see processes that look like the following. If you do
> > not see any then skip ahead to the next step.
> > /bin/bash /etc/xen/scripts/vtpm add
> > dd skip=10 bs=1 count=4 if=/var/vtpm/fifos/to_console.fifo
> > /usr/bin/vtpmd
> > First, kill any of the dd processes, and then run ps again. Most if
> > not all  of the /etx/xen/scripts/vtpm processes should have quit.
> > Kill any of the remaining scripts/vtpm and vtpmd processes.
> > Note that after killing some of of the "vtpm add" processes
> > new "vtpm remove" processes may get spawned which you will
> > also need to kill.
> > 4) Delete all of the fifos and socks
> > #rm /var/vtpm/fifos/*
> > #rm /var/vtpm/socks/*
> > 5) Remove the lock files if they exist
> > # rm -rf /var/run/xen-hotplug/vtpm*
> > 6) Now start up the vtpm_managerd again, it should start without errors.
> > 7) Finally, you should be able to boot up the vms again without any
> > problems.
> > 
> > 3-Q) When I start a domU that has a vtpm it hangs in the
> > pause state and will not boot. If I wait long enough it will quit and
> > tell me that the Hotplug scripts are not working.
> > 3-A) This occurs when we have stale lock files that did not get removed
> > properly. 
> > Perform the same set of steps in 2-A.
> > 
> 
> 

[-- Attachment #1.2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 2420 bytes --]

[-- Attachment #2: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2009-08-21 19:46 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-08-21 16:02 Several vtpm patches and workarounds: persistence, stability, tpm_emulator-0.5.1 Matt Fioravante
2009-08-21 16:33 ` Keir Fraser
2009-08-21 19:46   ` Matt Fioravante

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.