* [PATCH 5/7] vtpm Mini-Os domain: hotplug fixes
@ 2010-08-25 15:24 Matthew Fioravante
0 siblings, 0 replies; only message in thread
From: Matthew Fioravante @ 2010-08-25 15:24 UTC (permalink / raw)
To: xen-devel@lists.xensource.com
[-- Attachment #1.1.1: Type: text/plain, Size: 839 bytes --]
Signed-off-by: Matthew Fioravante <matthew.fioravante@jhuapl.edu>
This patch adds the actual vtpm-stubdom domain itself to the stubdom
directory makefile heirarchy. To build vtpm-stubdom and all of its
dependent libraries simply do:
cd stubdom; make vtpm-stubdom
libgmp was ported to mini-os as it is needed by the tpm_emulator. To
build it:
$ cd stubdom; make cross-gmp
polarssl was ported to mini-os because the vtpm needs an AES
implementation to encrypt its persistent state for storage on disk. To
build it:
$ cd stubdom; make cross-polarssl
Finally the berlios tpm_emulator version 0.6.1 was ported to mini-os as
it is the core engine of the vtpm. To build it separately do:
$ cd stubdom; make cross-tpmemu
Documentation on the architecture and how to use the domain is in
stubdom/vtpm/README
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.1.2: 5-vtpm-stubdom.patch --]
[-- Type: text/x-patch; name="5-vtpm-stubdom.patch", Size: 51351 bytes --]
diff -r bb97efd3e952 -r 9737432b5f8f stubdom/gmp.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/gmp.patch Tue Jul 20 17:12:35 2010 -0400
@@ -0,0 +1,72 @@
+--- configure.orig 2009-12-10 11:33:08.000000000 -0500
++++ configure 2009-12-10 11:31:25.000000000 -0500
+@@ -25999,60 +25999,7 @@
+ fi
+ echo "$as_me:$LINENO: checking for quad_t" >&5
+ echo $ECHO_N "checking for quad_t... $ECHO_C" >&6
+-if test "${ac_cv_type_quad_t+set}" = set; then
+- echo $ECHO_N "(cached) $ECHO_C" >&6
+-else
+- cat >conftest.$ac_ext <<_ACEOF
+-/* confdefs.h. */
+-_ACEOF
+-cat confdefs.h >>conftest.$ac_ext
+-cat >>conftest.$ac_ext <<_ACEOF
+-/* end confdefs.h. */
+-$ac_includes_default
+-int
+-main ()
+-{
+-if ((quad_t *) 0)
+- return 0;
+-if (sizeof (quad_t))
+- return 0;
+- ;
+- return 0;
+-}
+-_ACEOF
+-rm -f conftest.$ac_objext
+-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+- (eval $ac_compile) 2>conftest.er1
+- ac_status=$?
+- grep -v '^ *+' conftest.er1 >conftest.err
+- rm -f conftest.er1
+- cat conftest.err >&5
+- echo "$as_me:$LINENO: \$? = $ac_status" >&5
+- (exit $ac_status); } &&
+- { ac_try='test -z "$ac_c_werror_flag"
+- || test ! -s conftest.err'
+- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+- (eval $ac_try) 2>&5
+- ac_status=$?
+- echo "$as_me:$LINENO: \$? = $ac_status" >&5
+- (exit $ac_status); }; } &&
+- { ac_try='test -s conftest.$ac_objext'
+- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+- (eval $ac_try) 2>&5
+- ac_status=$?
+- echo "$as_me:$LINENO: \$? = $ac_status" >&5
+- (exit $ac_status); }; }; then
+- ac_cv_type_quad_t=yes
+-else
+- echo "$as_me: failed program was:" >&5
+-sed 's/^/| /' conftest.$ac_ext >&5
+-
+ ac_cv_type_quad_t=no
+-fi
+-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+-fi
+-echo "$as_me:$LINENO: result: $ac_cv_type_quad_t" >&5
+-echo "${ECHO_T}$ac_cv_type_quad_t" >&6
+ if test $ac_cv_type_quad_t = yes; then
+
+ cat >>confdefs.h <<_ACEOF
+@@ -27770,7 +27717,7 @@
+
+
+
+-for ac_func in alarm attr_get clock clock_gettime cputime getpagesize getrusage gettimeofday getsysinfo localeconv memset mmap mprotect nl_langinfo obstack_vprintf popen processor_info pstat_getprocessor raise read_real_time sigaction sigaltstack sigstack syssgi strchr strerror strnlen strtol strtoul sysconf sysctl sysctlbyname times
++for ac_func in alarm attr_get clock clock_gettime cputime getpagesize getrusage gettimeofday getsysinfo localeconv memset mmap mprotect nl_langinfo popen processor_info pstat_getprocessor raise read_real_time sigaction sigaltstack sigstack syssgi strchr strerror strnlen strtol strtoul sysconf sysctl sysctlbyname times
+ do
+ as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ echo "$as_me:$LINENO: checking for $ac_func" >&5
diff -r bb97efd3e952 -r 9737432b5f8f stubdom/polarssl.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/polarssl.patch Tue Jul 20 17:12:35 2010 -0400
@@ -0,0 +1,12 @@
+diff -Naur polarssl-0.12.1.orig/include/polarssl/config.h polarssl-0.12.1/include/polarssl/config.h
+--- polarssl-0.12.1.orig/include/polarssl/config.h 2010-04-15 16:33:20.000000000 -0400
++++ polarssl-0.12.1/include/polarssl/config.h 2010-04-15 16:34:08.000000000 -0400
+@@ -221,7 +221,7 @@
+ *
+ * This module provides TCP/IP networking routines.
+ */
+-#define POLARSSL_NET_C
++//#define POLARSSL_NET_C
+
+ /*
+ * Module: library/padlock.c
diff -r bb97efd3e952 -r 9737432b5f8f stubdom/tpmemu-0.6.1.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/tpmemu-0.6.1.patch Tue Jul 20 17:12:35 2010 -0400
@@ -0,0 +1,36 @@
+diff -Naur tpm_emulator-0.6.1/tpm/tpm_data.c tpm_emulator-x86_32/tpm/tpm_data.c
+--- tpm_emulator-0.6.1/tpm/tpm_data.c 2009-10-09 05:07:22.000000000 -0400
++++ tpm_emulator-x86_32/tpm/tpm_data.c 2010-02-15 12:53:47.000000000 -0500
+@@ -246,8 +246,7 @@
+ || tpm_unmarshal_TPM_PERMANENT_DATA(&ptr, &len, &tpmData.permanent.data)
+ || tpm_unmarshal_TPM_STCLEAR_FLAGS(&ptr, &len, &tpmData.stclear.flags)
+ || tpm_unmarshal_TPM_STCLEAR_DATA(&ptr, &len, &tpmData.stclear.data)
+- || tpm_unmarshal_TPM_STANY_DATA(&ptr, &len, &tpmData.stany.data)
+- || len > 0) {
++ || tpm_unmarshal_TPM_STANY_DATA(&ptr, &len, &tpmData.stany.data)) {
+ tpm_free(buf);
+ return -1;
+ }
+diff -Naur tpm_emulator-0.6.1/tpmd/Makefile tpm_emulator-x86_32/tpmd/Makefile
+--- tpm_emulator-0.6.1/tpmd/Makefile 2009-10-09 05:07:22.000000000 -0400
++++ tpm_emulator-x86_32/tpmd/Makefile 2010-02-15 12:52:07.000000000 -0500
+@@ -39,3 +39,5 @@
+
+ .PHONY: all clean install
+
++.PHONY: objs
++objs: $(OBJS)
+diff -Naur tpm_emulator-0.6.1/tpmd/tpm_emulator_config.h tpm_emulator-x86_32/tpmd/tpm_emulator_config.h
+--- tpm_emulator-0.6.1/tpmd/tpm_emulator_config.h 2009-10-09 05:07:22.000000000 -0400
++++ tpm_emulator-x86_32/tpmd/tpm_emulator_config.h 2010-02-15 12:52:07.000000000 -0500
+@@ -29,8 +29,8 @@
+
+ /* 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
+ #undef TPM_USE_INTERNAL_PRNG
diff -r bb97efd3e952 -r 9737432b5f8f stubdom/vtpm/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/vtpm/Makefile Tue Jul 20 17:12:35 2010 -0400
@@ -0,0 +1,26 @@
+TPMEMU_DIR=../tpm_emulator-$(XEN_TARGET_ARCH)/tpmd
+TPMEMU_OBJS=$(wildcard $(TPMEMU_DIR)/*.o)
+XEN_ROOT=../..
+MNGR_ROOT=$(XEN_ROOT)/tools/vtpm_manager
+
+PSSL_DIR=../polarssl-$(XEN_TARGET_ARCH)/library
+PSSL_OBJS=aes.o padlock.o
+
+TARGET=vtpm.a
+OBJS=vtpm.o vtpm_cmd.o vtpmblk.o
+
+CPPFLAGS+=-I$(MNGR_ROOT)/manager
+
+$(TARGET): $(OBJS)
+ ar -cr $@ $^ $(TPMEMU_OBJS) $(foreach obj,$(PSSL_OBJS),$(PSSL_DIR)/$(obj))
+
+clean: clean-compat
+ -rm $(TARGET) $(OBJS)
+
+compat:
+ make -C compat
+
+clean-compat:
+ make -C compat clean
+
+.PHONY: compat clean-compat clean
diff -r bb97efd3e952 -r 9737432b5f8f stubdom/vtpm/README
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/vtpm/README Tue Jul 20 17:12:35 2010 -0400
@@ -0,0 +1,133 @@
+vtpm-stubdom
+======================
+
+vtpm-stubdom is an implementation of the berlios tpm emulator running in a
+mini-os domain.
+
+building vtpm-stubdom
+======================
+You can build the vtpm mini-os domain from the stubdom directory
+
+$cd stubdom
+$make vtpm-stubdom
+
+The final image will be located at stubdom/mini-os-${ARCH}-vtpm/mini-os.gz
+
+building vtpm_managerd in stubdom mode
+=====================
+To operate correctly, vtpm_managerd must be built with the macro VTPM_STUBDOM
+defined. To do this edit the file tools/vtpm_manager/Rules.mk and uncomment
+the line that reads:
+CFLAGS += -DVTPM_STUBDOM
+
+Now rebuild and reinstall the manager
+$ cd tools/vtpm_manager
+$ make clean
+$ make
+# make install
+
+
+architecture
+=====================
++-------+ +--------------------+
+| guest | | vtpm-stubdom | +-------------------+
+| [tpm_xenu]-->[tpmback] berlios [tpmfront]-+ | dom0 |
++-------+ +--------------------+ +->[tpmbk] vtpm_managerd |
+ | +-----[tpm_tis]-----+
++-------+ +--------------------+ | |
+| guest | | vtpm-stubdom | | {Physical TPM}
+| [tpm_xenu]-->[tpmback] berlios [tpmfront]-+
++-------+ +--------------------+
+
+In this architecture we have a guest domain that wishes to use a vTPM, a
+vtpm-stubdom domain that implements the vTPM, and finally the vtpm_managerd
+daemon running in dom0 that protects the secrets for each vtpm and
+controls access to the physical tpm.
+
+Each domain communicates using the paravirtualized tpm frontend and backend
+drivers. These are implmented as tpm_xenu (frontend) and tpmbk (backend) in
+linux and tpmfront (frontend) and tpmback (backend) in mini-os. The tpm_xenu
+driver creates a /dev/tpm* device node for the guest just as if it had a real
+tpm.
+
+Whenever the guest sends a TPM request it is sent directly to vtpm-stubdom,
+handled there, and then the response is returned. vtpm-stubdom sends requests
+to the manager when it needs to access the physical TPM for entropy or when it
+needs to save or load its state.
+
+secure storage
+=====================
+vtpm-stubdom uses the mini-os block device driver to save its state. The vtpm
+domain config file must contain a "disk" entry pointing it to its disk image
+file. The device node must be set to hda or the block device driver will fail.
+example: disk = ['file:/tmp/myvtpm.img,hda,w']
+
+the vtpm manager protects the keys used to encrypt the vtpm state using the
+physical TPM. The following outline the set of operations in saving and loading.
+
+vTPM load operation
+1) vtpm: request symkey from manager (VTPM_ORD_LOADKEY)
+2) manager: unseal symkey using TPM and return it
+3) vtpm: read data from block device
+4) vtpm: verify hash (not implemented yet)
+5) vtpm: decrypt state and load into memory
+
+vTPM save operation
+1) vtpm: generate symkey
+2) vtpm: encrypt state
+3) vtpm: generate hash (not implemented yet)
+4) vtpm: write encrypted blob to block device
+5) vtpm: send symkey to manager for storage
+6) manager: seal symkey using TPM
+
+
+domain config files
+=====================
+(see the examples directory)
+
+Both the guest and the vtpm domain need to have domain config files. The guest
+config file must contain a vtpm device entry with its backend pointing to the
+vtpm domain.
+vtpm = ['backend=myvtpm']
+
+The vtpm-studom domain must have a vtpm device entry with its
+backend pointing to dom0 and a unique uuid for persistence.
+vtpm = ['backend=0,uuid=4209a551-9b79-4feb-ad4d-b4ff1c1bc355']
+
+You can create a uuid using the uuidgen program which should be installed
+on your system.
+
+The vtpm also needs a disk image to store its persistent state. You can
+create one using dd and then point your vtpm config file to it.
+
+dd if=/dev/zero of=/tmp/myvtpm.img bs=4M count=1
+
+First boot the vtpm domain and then boot the guest. You should see that the
+tpm emulator start up and that the guest connected in the vtpm domain console.
+
+run time configuration
+=====================
+vtpm-stubdom has a few runtime configuration options. These can be passed to
+the domain using the "extra" parameter.
+example: extra = 'loglevel=info pvm clear'
+
+Valid options are as follows:
+loglevel=<LOG>: Control the verbosity of the output to the console. Valid
+values for <LOG> are: debug, info, error, and alert. (default=info)
+
+pvm: The guest is a pvm domain. (default)
+hvm: The guest is an hvm domain. (Not implemented)
+
+clear: Start the tpm emulator in clear mode. (see: berlios) (Note: this is the
+default and you almost always want this)
+save: Start the tpm emulator in save mode. (see: berlios)
+deactivated: Start the tpm emulator in deactivated mode. (see: berlios)
+
+entropysrc=<ENTSRC>: Specify where the vTPM will get entropy. The valid values
+for <ENTSRC> are:
+ tpm: get entropy from the hardware tpm (default)
+ rand: get entropy by successively calling rand()
+Regardless of which mode is chosen, srand() is given sizeof(unsigned int)
+ bytes of entropy from the physical TPM on boot.
+
+
diff -r bb97efd3e952 -r 9737432b5f8f stubdom/vtpm/compat/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/vtpm/compat/Makefile Tue Jul 20 17:12:35 2010 -0400
@@ -0,0 +1,26 @@
+
+TARGET=asm/byteorder.h
+
+$(TARGET): endian_test
+ mkdir -p `dirname $(TARGET)`
+ echo "#ifndef BYTEORDER_TPM_COMPAT_H" > $(TARGET)
+ echo "#define BYTEORDER_TPM_COMPAT_H" >> $(TARGET)
+ echo "" >> $(TARGET)
+ cat swab.h >> $(TARGET)
+ echo "" >> $(TARGET)
+ if ./endian_test; then \
+ echo "Little Endian Host Cpu detected"; \
+ cat little_endian.h >> $(TARGET); \
+ else \
+ echo "Big Endian Host Cpu detected"; \
+ cat big_endian.h >> $(TARGET); \
+ fi
+ echo "#endif /* BYTEORDER_TPM_COMPAT_H */" >> $(TARGET)
+
+
+endian_test: endian_test.c
+ $(CC) $(CFLAGS) -o $@ $<
+
+clean:
+ -rm $(TARGET)
+ -rm endian_test
diff -r bb97efd3e952 -r 9737432b5f8f stubdom/vtpm/compat/big_endian.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/vtpm/compat/big_endian.h Tue Jul 20 17:12:35 2010 -0400
@@ -0,0 +1,14 @@
+
+#define __cpu_to_le64(x) (__swab64((x)))
+#define __le64_to_cpu(x) (__swab64((uint64_t)(x)))
+#define __cpu_to_le32(x) (__swab32((x)))
+#define __le32_to_cpu(x) (__swab32((uint32_t)(x)))
+#define __cpu_to_le16(x) (__swab16((x)))
+#define __le16_to_cpu(x) (__swab16((uint16_t)(x)))
+#define __cpu_to_be64(x) ((uint64_t)(x))
+#define __be64_to_cpu(x) ((uint64_t)(x))
+#define __cpu_to_be32(x) ((uint32_t)(x))
+#define __be32_to_cpu(x) ((uint32_t)(x))
+#define __cpu_to_be16(x) ((uint16_t)(x))
+#define __be16_to_cpu(x) ((uint16_t)(x))
+
diff -r bb97efd3e952 -r 9737432b5f8f stubdom/vtpm/compat/endian_test.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/vtpm/compat/endian_test.c Tue Jul 20 17:12:35 2010 -0400
@@ -0,0 +1,15 @@
+#include <stdio.h>
+int main(void)
+{
+ union {
+ char c;
+ int i;
+ } u;
+ u.i = 0;
+ u.c = 1;
+
+ if (u.i == 1)
+ return 0; /* Little Endian */
+ else
+ return 1; /* Big Endian */
+}
diff -r bb97efd3e952 -r 9737432b5f8f stubdom/vtpm/compat/little_endian.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/vtpm/compat/little_endian.h Tue Jul 20 17:12:35 2010 -0400
@@ -0,0 +1,14 @@
+
+#define __cpu_to_le64(x) ((uint64_t)(x))
+#define __le64_to_cpu(x) ((uint64_t)(x))
+#define __cpu_to_le32(x) ((uint32_t)(x))
+#define __le32_to_cpu(x) ((uint32_t)(x))
+#define __cpu_to_le16(x) ((uint16_t)(x))
+#define __le16_to_cpu(x) ((uint16_t)(x))
+#define __cpu_to_be64(x) (__swab64((x)))
+#define __be64_to_cpu(x) (__swab64((uint64_t)(x)))
+#define __cpu_to_be32(x) (__swab32((x)))
+#define __be32_to_cpu(x) (__swab32((uint32_t)(x)))
+#define __cpu_to_be16(x) (__swab16((x)))
+#define __be16_to_cpu(x) (__swab16((uint16_t)(x)))
+
diff -r bb97efd3e952 -r 9737432b5f8f stubdom/vtpm/compat/swab.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/vtpm/compat/swab.h Tue Jul 20 17:12:35 2010 -0400
@@ -0,0 +1,26 @@
+#include <stdint.h>
+
+/*
+ * casts are necessary for constants, because we never know how for sure
+ * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way.
+ */
+#define __swab16(x) ((uint16_t)( \
+ (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \
+ (((uint16_t)(x) & (uint16_t)0xff00U) >> 8)))
+
+#define __swab32(x) ((uint32_t)( \
+ (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
+ (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
+ (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
+ (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
+
+#define __swab64(x) ((uint64_t)( \
+ (((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \
+ (((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
+ (((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
+ (((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
+ (((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
+ (((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
+ (((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
+ (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56)))
+
diff -r bb97efd3e952 -r 9737432b5f8f stubdom/vtpm/examples/myguest.cfg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/vtpm/examples/myguest.cfg Tue Jul 20 17:12:35 2010 -0400
@@ -0,0 +1,5 @@
+bootloader = pygrub
+memory = 192
+name = 'myguest'
+disk = ['file:/tmp/myguest.img,hda1,w']
+vtpm = ['backend=myvtpm']
diff -r bb97efd3e952 -r 9737432b5f8f stubdom/vtpm/examples/myvtpm.cfg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/vtpm/examples/myvtpm.cfg Tue Jul 20 17:12:35 2010 -0400
@@ -0,0 +1,8 @@
+kernel = '/boot/vtpm-stubdom.gz'
+memory = '8'
+name = 'vtpm'
+on_shutdown = 'destroy'
+on_crash = 'destroy'
+disk = ['file:/tmp/myvtpm.img,hda,w']
+extra = 'loglevel=info pvm clear'
+vtpm = ['backend=0,uuid=4209a551-9b79-4feb-ad4d-b4ff1c1bc355']
diff -r bb97efd3e952 -r 9737432b5f8f stubdom/vtpm/vtpm.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/vtpm/vtpm.c Tue Jul 20 17:12:35 2010 -0400
@@ -0,0 +1,325 @@
+/* Software-Based Trusted Platform Module (TPM) Emulator for Linux
+ * Copyright (C) 2006 Mario Strasser <mast@gmx.net>,
+ * Swiss Federal Institute of Technology (ETH) Zurich
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * $Id: tpmd.c 337 2009-09-24 08:49:54Z mast $
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <syslog.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <xen/xen.h>
+#include <tpmback.h>
+#include <tpmfront.h>
+
+#include "tpm_emulator_config.h"
+#include "tpm/tpm_emulator.h"
+#include "vtpm.h"
+#include "vtpm_cmd.h"
+#include "vtpmblk.h"
+
+/* Global commandline options - default values */
+struct Opt_args opt_args = {
+ .mode = MODE_PVM,
+ .startup = ST_CLEAR,
+ .loglevel = LOG_INFO,
+ .entropysrc = ENT_TPM,
+};
+
+struct tpmfront_dev* tpmfront_dev;
+
+
+void tpm_log(int priority, const char *fmt, ...)
+{
+ va_list v;
+ va_start(v, fmt);
+ vprintf(fmt, v);
+ va_end(v);
+}
+
+void get_rand_bytes_rand(uint8_t* buf, size_t nbytes)
+{
+ int r, i;
+ while (nbytes > 0) {
+ r = rand();
+ for(i = sizeof(int); i > 0 && nbytes > 0; --i) {
+ --nbytes;
+ buf[nbytes] = ((uint8_t*)&r)[i];
+ }
+ }
+}
+
+void tpm_get_extern_random_bytes(void *buf, size_t nbytes)
+{
+ switch(opt_args.entropysrc) {
+ case ENT_TPM:
+ VTPM_GetRandom(tpmfront_dev, buf, nbytes);
+ break;
+ case ENT_RAND:
+ get_rand_bytes_rand(buf, nbytes);
+ break;
+ default:
+ break;
+ }
+}
+
+uint64_t tpm_get_ticks(void)
+{
+ static uint64_t old_t = 0;
+ uint64_t new_t, res_t;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ new_t = (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec;
+ res_t = (old_t > 0) ? new_t - old_t : 0;
+ old_t = new_t;
+ return res_t;
+}
+
+int tpm_read_from_file(uint8_t **data, size_t *data_length) {
+ return read_vtpmblk(tpmfront_dev, data, data_length);
+}
+
+int tpm_write_to_file(uint8_t *data, size_t data_length) {
+ return write_vtpmblk(tpmfront_dev, data, data_length);
+}
+
+int init_random(void) {
+ int rc;
+ unsigned int seed = 0;
+
+ if((rc = VTPM_GetRandom(tpmfront_dev, (BYTE*)&seed, sizeof(seed)))) {
+ error("VTPM_GetRandom failed with error code %d", rc);
+ return rc;
+ }
+ srand(seed);
+
+ info("Seeded the RNG with %lu bytes of entropy", (unsigned long) sizeof(seed));
+ return 0;
+
+}
+
+static void main_loop(void) {
+ tpmcmd_t* tpmcmd = NULL;
+ domid_t domid; /* Domid of frontend */
+ unsigned long handle; /* handle of frontend */
+ uint8_t* out;
+ uint32_t out_len;
+ int res = -1;
+
+ info("VTPM Initializing\n");
+ /* Initialize the emulator */
+ tpm_emulator_init(opt_args.startup);
+
+ /* Wait for the frontend domain to connect */
+ info("Waiting for frontend domain to connect..");
+ if(tpmback_wait_for_frontend_connect(&domid, &handle) == 0) {
+ info("VTPM attached to Frontend %lu/%u", (unsigned long) domid, (unsigned) handle);
+ } else {
+ error("Unable to attach to a frontend");
+ }
+
+ tpmcmd = tpmback_req(domid, handle);
+ while(tpmcmd) {
+ /* Handle the request */
+ if(tpmcmd->req_len) {
+ out = NULL;
+ out_len = 0;
+ res = tpm_handle_command(tpmcmd->req, tpmcmd->req_len, &out, &out_len);
+ if(res < 0) {
+ error("tpm_handle_command() failed");
+ }
+ else
+ {
+ tpmcmd->resp = out;
+ tpmcmd->resp_len = out_len;
+ }
+ }
+
+ /* Send the response */
+ tpmback_resp(tpmcmd);
+
+ /* Free the out buffer if it was allocated */
+ if(tpmcmd->req_len && res >= 0) {
+ tpm_free(out);
+ }
+
+ /* Wait for the next request */
+ tpmcmd = tpmback_req(domid, handle);
+
+ }
+
+ info("VTPM Shutting down\n");
+
+ tpm_emulator_shutdown();
+}
+
+int parse_cmd_line(int argc, char** argv)
+{
+ int ival;
+ char sval[25];
+ char* logstr = NULL;
+ /* Parse the command strings */
+ for(unsigned int i = 1; i < argc; ++i) {
+ if (sscanf(argv[i], "loglevel=%d", &ival) == 1)
+ opt_args.loglevel = ival;
+ else if (sscanf(argv[i], "loglevel=%25s", sval) == 1){
+ if (!strcmp(sval, "debug"))
+ opt_args.loglevel = LOG_DEBUG;
+ else if (!strcmp(sval, "info"))
+ opt_args.loglevel = LOG_INFO;
+ else if (!strcmp(sval, "error"))
+ opt_args.loglevel = LOG_ERR;
+ else if (!strcmp(sval, "alert"))
+ opt_args.loglevel = LOG_ALERT;
+ }
+ else if (!strcmp(argv[i], "pvm")) {
+ opt_args.mode = MODE_PVM;
+ }
+ else if (!strcmp(argv[i], "hvm")) {
+ opt_args.mode = MODE_HVM;
+ }
+ else if (!strcmp(argv[i], "clear")) {
+ opt_args.startup = ST_CLEAR;
+ }
+ else if (!strcmp(argv[i], "save")) {
+ opt_args.startup = ST_SAVE;
+ }
+ else if (!strcmp(argv[i], "deactivated")) {
+ opt_args.startup = ST_DEACTIVATED;
+ }
+ else if (!strncmp(argv[i], "entropysrc=", 11)) {
+ if (!strcmp(argv[i] + 11, "tpm")) {
+ opt_args.entropysrc = ENT_TPM;
+ }
+ else if (!strcmp(argv[i] + 11, "rand")) {
+ opt_args.entropysrc = ENT_RAND;
+ }
+ }
+ else {
+ error("Invalid command line option `%s'", argv[i]);
+ }
+
+ }
+
+ /* Clamp the log levels */
+ if (opt_args.loglevel <= LOG_ALERT) {
+ opt_args.loglevel = LOG_ALERT;
+ logstr = "alert";
+ } else if(opt_args.loglevel <= LOG_ERR) {
+ opt_args.loglevel = LOG_ERR;
+ logstr = "error";
+ } else if(opt_args.loglevel <= LOG_INFO) {
+ opt_args.loglevel = LOG_INFO;
+ logstr = "info";
+ } else {
+ opt_args.loglevel = LOG_DEBUG;
+ logstr = "debug";
+ }
+
+ /* Check Errors and print results */
+ switch (opt_args.mode) {
+ case MODE_HVM:
+ alert("hvm mode is not currently supported!");
+ return -1;
+ break;
+ case MODE_PVM:
+ info("Running in pvm mode");
+ break;
+ default:
+ alert("Mode not specified! You must specify either pvm or hvm on the command line");
+ return -1;
+ }
+
+ switch(opt_args.startup) {
+ case ST_CLEAR:
+ info("Startup mode is `clear'");
+ break;
+ case ST_SAVE:
+ info("Startup mode is `save'");
+ break;
+ case ST_DEACTIVATED:
+ info("Startup mode is `deactivated'");
+ break;
+ default:
+ error("Invalid startup mode %d", opt_args.startup);
+ return -1;
+ }
+
+ switch(opt_args.entropysrc)
+ {
+ case ENT_TPM:
+ info("Will use Hardware TPM for entropy source");
+ break;
+ case ENT_RAND:
+ info("Will use rand() for entropy source");
+ break;
+ default:
+ error("Invalid entropy source %d", opt_args.entropysrc);
+ return -1;
+ }
+
+ info("Log level set to %s", logstr);
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ //FIXME: initializing blkfront without this sleep causes the domain to crash on boot
+ sleep(2);
+
+ info("starting TPM Emulator (1.2.%s.%s)", TPM_STR(VERSION_MAJOR), TPM_STR(VERSION_MINOR));
+ if(parse_cmd_line(argc, argv)) {
+ error("Error parsing commandline\n");
+ return -1;
+ }
+
+ /* Initialize devices */
+ init_tpmback();
+ if((tpmfront_dev = init_tpmfront(NULL)) == NULL) {
+ error("Unable to initialize tpmfront device");
+ goto abort_posttpmfront;
+ }
+
+ /* Seed the RNG with entropy from hardware TPM */
+ if(init_random()) {
+ error("Unable to initialize RNG");
+ goto abort_postrng;
+ }
+
+ /* Initialize blkfront device */
+ if(init_vtpmblk(tpmfront_dev)) {
+ error("Unable to initialize Blkfront persistent storage");
+ goto abort_postvtpmblk;
+ }
+
+ /* Run main loop */
+ main_loop();
+
+ /* Shutdown blkfront */
+ shutdown_vtpmblk();
+abort_postvtpmblk:
+abort_postrng:
+
+ /* Close devices */
+ shutdown_tpmfront(tpmfront_dev);
+abort_posttpmfront:
+ shutdown_tpmback();
+
+ return 0;
+}
diff -r bb97efd3e952 -r 9737432b5f8f stubdom/vtpm/vtpm.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/vtpm/vtpm.h Tue Jul 20 17:12:35 2010 -0400
@@ -0,0 +1,29 @@
+#ifndef VTPM_H
+#define VTPM_H
+
+/* For testing */
+#define VERS_CMD "\x00\xC1\x00\x00\x00\x16\x00\x00\x00\x65\x00\x00\x00\x05\x00\x00\x00\x04\x00\x00\x01\x03"
+#define VERS_CMD_LEN 22
+
+/* Global commandline options */
+struct Opt_args {
+ enum Mode{
+ MODE_INVALID,
+ MODE_PVM,
+ MODE_HVM
+ } mode;
+ enum StartUp {
+ ST_CLEAR = 1,
+ ST_SAVE = 2,
+ ST_DEACTIVATED = 3
+ } startup;
+ enum EntropySource {
+ ENT_TPM,
+ ENT_RAND
+ } entropysrc;
+ int loglevel;
+};
+extern struct Opt_args opt_args;
+
+#endif
+
diff -r bb97efd3e952 -r 9737432b5f8f stubdom/vtpm/vtpm_cmd.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/vtpm/vtpm_cmd.c Tue Jul 20 17:12:35 2010 -0400
@@ -0,0 +1,182 @@
+#include <types.h>
+#include <xen/xen.h>
+#include <mm.h>
+#include <gnttab.h>
+#include "tpm/tpm_marshalling.h"
+#include "vtpm_manager.h"
+#include "vtpm_cmd.h"
+
+#define TRYFAILGOTO(C) \
+ if((C)) { \
+ status = TPM_FAIL; \
+ goto abort_egress; \
+ }
+#define TRYFAILGOTOMSG(C, msg) \
+ if((C)) { \
+ status = TPM_FAIL; \
+ error(msg); \
+ goto abort_egress; \
+ }
+#define CHECKSTATUSGOTO(ret, fname) \
+ if((ret) != TPM_SUCCESS) { \
+ error("%s failed with error code (%lu)", fname, (unsigned long) ret); \
+ status = ord; \
+ goto abort_egress; \
+ }
+
+#define ERR_MALFORMED "Malformed response from backend"
+#define ERR_TPMFRONT "Error sending command through frontend device"
+
+struct shpage {
+ void* page;
+ grant_ref_t grantref;
+};
+
+typedef struct shpage shpage_t;
+
+static inline int pack_header(uint8_t** bptr, UINT32* len, TPM_TAG tag, UINT32 size, TPM_COMMAND_CODE ord)
+{
+ return *bptr == NULL ||
+ tpm_marshal_UINT16(bptr, len, tag) ||
+ tpm_marshal_UINT32(bptr, len, size) ||
+ tpm_marshal_UINT32(bptr, len, ord);
+}
+
+static inline int unpack_header(uint8_t** bptr, UINT32* len, TPM_TAG* tag, UINT32* size, TPM_COMMAND_CODE* ord)
+{
+ return *bptr == NULL ||
+ tpm_unmarshal_UINT16(bptr, len, tag) ||
+ tpm_unmarshal_UINT32(bptr, len, size) ||
+ tpm_unmarshal_UINT32(bptr, len, ord);
+}
+
+TPM_RESULT VTPM_GetRandom(struct tpmfront_dev* tpmfront_dev, BYTE* bytes, UINT32 numbytes) {
+ TPM_RESULT status = TPM_SUCCESS;
+ uint8_t* cmdbuf, *resp, *bptr;
+ size_t resplen = 0;
+ UINT32 len;
+
+ /*Ask the real tpm for random bytes for the seed */
+ TPM_TAG tag = TPM_TAG_RQU_COMMAND;
+ UINT32 size;
+ TPM_COMMAND_CODE ord = TPM_ORD_GetRandom;
+ len = size = sizeof(TPM_TAG) + sizeof(UINT32) + sizeof(TPM_COMMAND_CODE) + sizeof(UINT32);
+
+ /*Create the raw tpm command */
+ bptr = cmdbuf = malloc(size);
+ TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
+ TRYFAILGOTO(tpm_marshal_UINT32(&bptr, &len, numbytes));
+
+ /* Send cmd, wait for response */
+ TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp, &resplen),
+ ERR_TPMFRONT);
+
+ bptr = resp; len = resplen;
+ TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size, &ord), ERR_MALFORMED);
+
+ //Check return status of command
+ CHECKSTATUSGOTO(ord, "TPM_GetRandom()");
+
+ // Get the number of random bytes in the response
+ TRYFAILGOTOMSG(tpm_unmarshal_UINT32(&bptr, &len, &size), ERR_MALFORMED);
+
+ /* FIXME: Does this ever really happen? */
+ if(size != numbytes) {
+ error("TPM_GetRandom() returned insufficient number of bytes!");
+ status = TPM_FAIL;
+ goto abort_egress;
+ }
+
+ //Get the random bytes out, tpm may give us less bytes than what we wanrt
+ TRYFAILGOTOMSG(tpm_unmarshal_BYTE_ARRAY(&bptr, &len, bytes, numbytes), ERR_MALFORMED);
+
+ goto egress;
+abort_egress:
+egress:
+ free(cmdbuf);
+ return status;
+
+}
+
+TPM_RESULT VTPM_LoadKey(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t* data_length)
+{
+ TPM_RESULT status = TPM_SUCCESS;
+ uint8_t* bptr, *resp;
+ uint8_t* cmdbuf = NULL;
+ size_t resplen = 0;
+ UINT32 len;
+
+ TPM_TAG tag = VTPM_TAG_REQ;
+ UINT32 size;
+ TPM_COMMAND_CODE ord = VTPM_ORD_LOADKEY;
+
+ /*Create the command*/
+ len = size = VTPM_COMMAND_HEADER_SIZE_CLT;
+ bptr = cmdbuf = malloc(size);
+ TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
+
+ /* Send the command to vtpm_managerd */
+ info("Requesting Encryption key from backend");
+ TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp, &resplen), ERR_TPMFRONT);
+
+ /* Unpack response header */
+ bptr = resp;
+ len = resplen;
+ TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size, &ord), ERR_MALFORMED);
+
+ /* Check return code */
+ CHECKSTATUSGOTO(ord, "VTPM_LoadKey()");
+
+ /* Get the size of the key */
+ *data_length = size - VTPM_COMMAND_HEADER_SIZE_CLT;
+
+ /* Copy the key bits */
+ *data = malloc(*data_length);
+ memcpy(*data, bptr, *data_length);
+
+ goto egress;
+abort_egress:
+ error("VTPM_LoadKey failed");
+egress:
+ free(cmdbuf);
+ return status;
+}
+
+TPM_RESULT VTPM_SaveKey(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t data_length)
+{
+ TPM_RESULT status = TPM_SUCCESS;
+ uint8_t* bptr, *resp;
+ uint8_t* cmdbuf = NULL;
+ size_t resplen = 0;
+ UINT32 len;
+
+ TPM_TAG tag = VTPM_TAG_REQ;
+ UINT32 size;
+ TPM_COMMAND_CODE ord = VTPM_ORD_SAVEKEY;
+
+ /*Create the command*/
+ len = size = VTPM_COMMAND_HEADER_SIZE_CLT + data_length;
+ bptr = cmdbuf = malloc(size);
+ TRYFAILGOTO(pack_header(&bptr, &len, tag, size, ord));
+ memcpy(bptr, data, data_length);
+ bptr += data_length;
+
+ /* Send the command to vtpm_managerd */
+ info("Sending encryption key to backend");
+ TRYFAILGOTOMSG(tpmfront_cmd(tpmfront_dev, cmdbuf, size, &resp, &resplen), ERR_TPMFRONT);
+
+ /* Unpack response header */
+ bptr = resp;
+ len = resplen;
+ TRYFAILGOTOMSG(unpack_header(&bptr, &len, &tag, &size, &ord), ERR_MALFORMED);
+
+ /* Check return code */
+ CHECKSTATUSGOTO(ord, "VTPM_SaveKey()");
+
+ goto egress;
+abort_egress:
+ error("VTPM_SaveKey failed");
+egress:
+ free(cmdbuf);
+ return status;
+}
diff -r bb97efd3e952 -r 9737432b5f8f stubdom/vtpm/vtpm_cmd.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/vtpm/vtpm_cmd.h Tue Jul 20 17:12:35 2010 -0400
@@ -0,0 +1,22 @@
+#ifndef MANAGER_H
+#define MANAGER_H
+
+#include <tpmfront.h>
+#include "tpm_emulator_config.h"
+#include "tpm/tpm_emulator.h"
+#include "tpm/tpm_structures.h"
+
+/* Request random bytes from hardware tpm, returns 0 on success */
+TPM_RESULT VTPM_GetRandom(struct tpmfront_dev* tpmfront_dev, BYTE* bytes, UINT32 numbytes);
+/* Send NVM data to manager for secure storage */
+TPM_RESULT VTPM_SaveNVM(struct tpmfront_dev* tpmfront_dev, BYTE *data, size_t data_length);
+/* Retreive NVM data from manager */
+TPM_RESULT VTPM_LoadNVM(struct tpmfront_dev* tpmfront_dev, BYTE **data, size_t *data_length);
+/* Retreive the size of the NVM data */
+TPM_RESULT VTPM_GetNVMSize(struct tpmfront_dev* tpmfront_dev, UINT32* size);
+/* Retreive 256 bit AES encryption key from manager */
+TPM_RESULT VTPM_LoadKey(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t* data_length);
+/* Manager securely saves our 256 bit AES encryption key */
+TPM_RESULT VTPM_SaveKey(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t data_length);
+
+#endif
diff -r bb97efd3e952 -r 9737432b5f8f stubdom/vtpm/vtpmblk.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/vtpm/vtpmblk.c Tue Jul 20 17:12:35 2010 -0400
@@ -0,0 +1,343 @@
+#include <blkfront.h>
+#include <fcntl.h>
+#include <xmalloc.h>
+#include <asm/byteorder.h>
+#include "vtpmblk.h"
+#include "tpm_emulator_config.h"
+#include "tpm/tpm_marshalling.h"
+#include "vtpm_cmd.h"
+#include "polarssl/aes.h"
+
+struct blkfront_dev* blkdev = NULL;
+struct blkfront_info blkinfo;
+struct blkfront_aiocb aiocb;
+unsigned long long disksize = 0;
+#define SECTORS_PER_BLOCK 8
+unsigned int blocksize;
+
+/*Encryption key and block sizes */
+#define BLKSZ 16
+#define KEYSZ 32
+
+int init_vtpmblk(struct tpmfront_dev* tpmfront_dev)
+{
+ info("Initializing persistent NVM storage\n");
+ /* Initialize block device */
+ if((blkdev = init_blkfront(NULL, &blkinfo)) == NULL) {
+ error("Unable to initialize blkfront");
+ return -1;
+ }
+ if (blkinfo.info & VDISK_READONLY || blkinfo.mode != O_RDWR) {
+ error("block device is read only!");
+ goto error;
+ }
+ disksize = blkinfo.sectors * blkinfo.sector_size;
+ blocksize = SECTORS_PER_BLOCK * blkinfo.sector_size;
+ aiocb.aio_dev = blkdev;
+ aiocb.aio_buf = _xmalloc(blocksize, blkinfo.sector_size);
+ aiocb.aio_nbytes = blocksize;
+ aiocb.aio_offset = 0;
+ aiocb.aio_cb = NULL;
+ aiocb.data = NULL;
+
+ return 0;
+error:
+ shutdown_blkfront(blkdev);
+ blkdev = NULL;
+ return -1;
+}
+
+void shutdown_vtpmblk(void)
+{
+ if (blkdev != NULL) {
+ free(aiocb.aio_buf);
+ shutdown_blkfront(blkdev);
+ }
+ blkdev = NULL;
+}
+
+off_t blkoff; /* block offset */
+static void rwop_begin(void)
+{
+ aiocb.aio_offset = 0;
+ blkoff = 0;
+}
+
+static void rwop_finish(int write)
+{
+ /* if we have an unfinished block, write it to disk with padded zeroes at the end */
+ if(write && blkoff) {
+ memset(&aiocb.aio_buf[blkoff], 0, blocksize - blkoff);
+ aiocb.aio_cb = NULL;
+ blkfront_write(&aiocb);
+ aiocb.aio_offset += blocksize;
+ }
+ blkoff = 0;
+ /* Probably redundant */
+ blkfront_sync(blkdev);
+}
+#define write_finish() rwop_finish(1)
+#define read_finish() rwop_finish(0)
+
+static int rw_data(uint8_t* data, size_t len, int write)
+{
+ size_t bytes;
+ if( data == NULL ) {
+ return -1;
+ }
+ while(len > 0) {
+ /* determine how many bytes to read/write from/to the current block buffer */
+ bytes = blkoff + len > blocksize ? blocksize - blkoff : len;
+
+ /* If read op, and were at a new block, then read now */
+ if(!write && blkoff == 0) {
+ aiocb.aio_cb = NULL;
+ blkfront_read(&aiocb);
+ aiocb.aio_offset += blocksize;
+ }
+ /* Memory buffer copying */
+ if (write) {
+ memcpy(&aiocb.aio_buf[blkoff], data, bytes);
+ } else {
+ memcpy(data, &aiocb.aio_buf[blkoff], bytes);
+ }
+ /*Adjust pointers and counters */
+ len -= bytes;
+ data += bytes;
+ blkoff = (blkoff + bytes) % blocksize;
+ //Did we finish writing a block? if so write it to disk
+ if(write && blkoff == 0) {
+ aiocb.aio_cb = NULL;
+ blkfront_write(&aiocb);
+ aiocb.aio_offset += blocksize;
+ }
+ }
+ return 0;
+}
+#define write_data(data, len) rw_data(data, len, 1)
+#define read_data(data, len) rw_data(data, len, 0)
+
+int write_vtpmblk_raw(uint8_t *data, size_t data_length)
+{
+ uint32_t lenbuf;
+ debug("Begin Write data=%p len=%u", data, data_length);
+ if(!blkdev) {
+ error("Tried to write before NVM driver was initialized");
+ return -1;
+ }
+ /* Make sure we have enough space to write (in terms of blocks) */
+ if((data_length % blocksize ? data_length + blocksize - (data_length % blocksize) : data_length) > disksize) {
+ error("NVM Write Operation failed: Not enough space on block device");
+ return -1;
+ }
+ rwop_begin();
+ lenbuf = CPU_TO_BE32((uint32_t)data_length);
+ write_data((uint8_t*)&lenbuf, 4);
+ write_data(data, data_length);
+ write_finish();
+
+ info("Wrote %u bytes to NVM persistent storage", data_length);
+
+ return 0;
+}
+
+int read_vtpmblk_raw(uint8_t **data, size_t *data_length)
+{
+ uint32_t lenbuf;
+ if(!blkdev) {
+ error("Tried to read before NVM driver was initialized");
+ return -1;
+ }
+ rwop_begin();
+ read_data((uint8_t*)&lenbuf, 4);
+ *data_length = (size_t) BE32_TO_CPU(lenbuf);
+ if(*data_length == 0) {
+ return -1;
+ }
+
+ *data = tpm_malloc(*data_length);
+ read_data(*data, *data_length);
+ read_finish();
+
+ info("Read %u bytes from NVM persistent storage", *data_length);
+ return 0;
+}
+
+int encrypt_vtpmblk(uint8_t* clear, size_t clear_len, uint8_t** cipher, size_t* cipher_len, uint8_t** symkey)
+{
+ int rc = 0;
+ uint8_t iv[BLKSZ];
+ aes_context aes_ctx;
+ UINT32 temp;
+ int mod;
+
+ uint8_t* clbuf = NULL;
+
+ uint8_t* ivptr;
+ int ivlen;
+
+ uint8_t* cptr; //Cipher block pointer
+ int clen; //Cipher block length
+
+ /*Create a new 256 bit encryption key */
+ *symkey = malloc(KEYSZ);
+ if(*symkey == NULL) {
+ rc = -1;
+ goto abort_egress;
+ }
+ tpm_get_extern_random_bytes(*symkey, KEYSZ);
+
+ /*Setup initialization vector - random bits and then 4 bytes clear text size at the end*/
+ temp = sizeof(UINT32);
+ ivlen = BLKSZ - temp;
+ tpm_get_extern_random_bytes(iv, ivlen);
+ ivptr = iv + ivlen;
+ tpm_marshal_UINT32(&ivptr, &temp, (UINT32) clear_len);
+
+ /*The clear text needs to be padded out to a multiple of BLKSZ */
+ mod = clear_len % BLKSZ;
+ clen = mod ? clear_len + BLKSZ - mod : clear_len;
+ clbuf = malloc(clen);
+ if (clbuf == NULL) {
+ rc = -1;
+ goto abort_egress;
+ }
+ memcpy(clbuf, clear, clear_len);
+ /* zero out the padding bits - FIXME: better / more secure way to handle these? */
+ if(clen - clear_len) {
+ memset(clbuf + clear_len, 0, clen - clear_len);
+ }
+
+ /* Setup the ciphertext buffer */
+ *cipher_len = BLKSZ + clen; /*iv + ciphertext */
+ cptr = *cipher = malloc(*cipher_len);
+ if (*cipher == NULL) {
+ rc = -1;
+ goto abort_egress;
+ }
+
+ /* Copy the IV to cipher text blob*/
+ memcpy(cptr, iv, BLKSZ);
+ cptr += BLKSZ;
+
+ /* Setup encryption */
+ aes_setkey_enc(&aes_ctx, *symkey, 256);
+
+ /* Do encryption now */
+ aes_crypt_cbc(&aes_ctx, AES_ENCRYPT, clear_len, iv, clbuf, cptr);
+
+ goto egress;
+abort_egress:
+egress:
+ free(clbuf);
+ return rc;
+}
+int decrypt_vtpmblk(uint8_t* cipher, size_t cipher_len, uint8_t** clear, size_t* clear_len, uint8_t* symkey)
+{
+ int rc = 0;
+ uint8_t iv[BLKSZ];
+ uint8_t* ivptr;
+ UINT32 u32, temp;
+ aes_context aes_ctx;
+
+ uint8_t* cptr = cipher; //cipher block pointer
+ int clen = cipher_len; //cipher block length
+
+ /* Pull out the initialization vector */
+ memcpy(iv, cipher, BLKSZ);
+ cptr += BLKSZ;
+ clen -= BLKSZ;
+
+ /* Setup the clear text buffer */
+ if((*clear = malloc(clen)) == NULL) {
+ rc = -1;
+ goto abort_egress;
+ }
+
+ /* Get the length of clear text from last 4 bytes of iv */
+ temp = sizeof(UINT32);
+ ivptr = iv + BLKSZ - temp;
+ tpm_unmarshal_UINT32(&ivptr, &temp, &u32);
+ *clear_len = u32;
+
+ /* Setup decryption */
+ aes_setkey_dec(&aes_ctx, symkey, 256);
+
+ /* Do decryption now */
+ if ((clen % BLKSZ) != 0) {
+ error("Decryption Error: Cipher block size was not a multiple of %u", BLKSZ);
+ rc = -1;
+ goto abort_egress;
+ }
+ aes_crypt_cbc(&aes_ctx, AES_DECRYPT, clen, iv, cptr, *clear);
+
+ /* Chop off extra block padding bits */
+ *clear = realloc(*clear, *clear_len);
+
+ goto egress;
+abort_egress:
+egress:
+ return rc;
+}
+
+int write_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t* data, size_t data_length) {
+ int rc;
+ uint8_t* cipher = NULL;
+ size_t cipher_len = 0;
+ uint8_t* symkey = NULL;
+ size_t keysize = KEYSZ;
+
+ if((rc = encrypt_vtpmblk(data, data_length, &cipher, &cipher_len, &symkey))) {
+ goto abort_egress;
+ }
+ if((rc = write_vtpmblk_raw(cipher, cipher_len))) {
+ goto abort_egress;
+ }
+ if((rc = VTPM_SaveKey(tpmfront_dev, symkey, keysize)) != TPM_SUCCESS) {
+ goto abort_egress;
+ }
+ goto egress;
+abort_egress:
+egress:
+ free(cipher);
+ /* Be needlessly paranoid */
+ if (symkey != NULL) {
+ memset(symkey, 0, keysize);
+ }
+ free(symkey);
+ return rc;
+}
+
+int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t** data, size_t *data_length) {
+ int rc;
+ uint8_t* cipher = NULL;
+ size_t cipher_len = 0;
+ uint8_t* symkey = NULL;
+ size_t keysize = KEYSZ;
+ if((rc = VTPM_LoadKey(tpmfront_dev, &symkey, &keysize)) != TPM_SUCCESS) {
+ goto abort_egress;
+ }
+ if(keysize != 32) {
+ error("Manager returned a key of invalid size! expected %d, actual %d", KEYSZ, keysize);
+ rc = -1;
+ goto abort_egress;
+ }
+ if((rc = read_vtpmblk_raw(&cipher, &cipher_len))) {
+ goto abort_egress;
+ }
+ if((rc = decrypt_vtpmblk(cipher, cipher_len, data, data_length, symkey))) {
+ goto abort_egress;
+ }
+ goto egress;
+abort_egress:
+egress:
+ free(cipher);
+ /* Be needlessly paranoid */
+ if (symkey != NULL) {
+ memset(symkey, 0, keysize);
+ }
+ free(symkey);
+ printf("FOO\n");
+ return rc;
+}
+
diff -r bb97efd3e952 -r 9737432b5f8f stubdom/vtpm/vtpmblk.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/vtpm/vtpmblk.h Tue Jul 20 17:12:35 2010 -0400
@@ -0,0 +1,14 @@
+#ifndef NVM_H
+#define NVM_H
+#include <mini-os/types.h>
+#include <tpmfront.h>
+
+int init_vtpmblk(struct tpmfront_dev* tpmfront_dev);
+void shutdown_vtpmblk(void);
+
+/* Encrypts and writes data to blk device */
+int write_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t *data, size_t data_length);
+/* Reads, Decrypts, and returns data from blk device */
+int read_vtpmblk(struct tpmfront_dev* tpmfront_dev, uint8_t **data, size_t *data_length);
+
+#endif
diff -r c54dd4a9e114 -r c84db039be86 extras/mini-os/Makefile
--- a/extras/mini-os/Makefile Tue Jul 20 15:28:22 2010 -0400
+++ b/extras/mini-os/Makefile Tue Jul 20 15:42:37 2010 -0400
@@ -78,12 +78,22 @@
OBJS := $(filter-out $(OBJ_DIR)/lwip%.o $(LWO), $(OBJS))
+ifeq ($(vtpm),y)
+ APP_LDLIBS += -lgmp
+ LDLIBS += -lc
+ OBJS := $(filter-out $(OBJ_DIR)/fs-front.o, $(OBJS))
+ OBJS := $(filter-out $(OBJ_DIR)/daytime.o, $(OBJS))
+ OBJS := $(filter-out $(OBJ_DIR)/pcifront.o, $(OBJS))
+ OBJS := $(filter-out $(OBJ_DIR)/netfront.o, $(OBJS))
+ OBJS := $(filter-out $(OBJ_DIR)/fbfront.o, $(OBJS))
+endif
+
ifeq ($(libc),y)
-APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxc-$(XEN_TARGET_ARCH) -whole-archive -lxenguest -lxenctrl -no-whole-archive
-APP_LDLIBS += -lpci
-APP_LDLIBS += -lz
-APP_LDLIBS += -lm
-LDLIBS += -lc
+ APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxc-$(XEN_TARGET_ARCH) -whole-archive -lxenguest -lxenctrl -no-whole-archive
+ APP_LDLIBS += -lpci
+ APP_LDLIBS += -lz
+ APP_LDLIBS += -lm
+ LDLIBS += -lc
endif
ifneq ($(APP_OBJS)-$(lwip),-y)
diff -r c54dd4a9e114 -r c84db039be86 extras/mini-os/minios.mk
--- a/extras/mini-os/minios.mk Tue Jul 20 15:28:22 2010 -0400
+++ b/extras/mini-os/minios.mk Tue Jul 20 15:42:37 2010 -0400
@@ -26,6 +26,10 @@
DEF_CFLAGS += -O3
endif
+ifeq ($(vtpm),y)
+DEF_CPPFLAGS += -DNO_LIBXC -DNO_FSFRONT -DNO_PCIFRONT -DNO_NETFRONT -DNO_FBFRONT
+endif
+
# Make the headers define our internal stuff
DEF_CFLAGS += -D__INSIDE_MINIOS__
diff -r 9f49667fec71 stubdom/Makefile
--- a/stubdom/Makefile Fri Jul 30 15:22:39 2010 +0100
+++ b/stubdom/Makefile Mon Aug 02 17:13:19 2010 -0400
@@ -31,6 +31,18 @@
OCAML_URL?=http://caml.inria.fr/pub/distrib/ocaml-3.11
OCAML_VERSION=3.11.0
+#GMP_URL?=$(XEN_EXTFILES_URL)
+GMP_URL?=ftp://ftp.gnu.org/gnu/gmp
+GMP_VERSION=4.3.1
+
+#POLARSSL_URL?=$(XEN_EXTFILES_URL)
+POLARSSL_URL?=http://polarssl.org/code/releases
+POLARSSL_VERSION=0.12.1
+
+#TPMEMU_URL?=$(XEN_EXTFILES_URL)
+TPMEMU_URL?=http://download.berlios.de/tpm-emulator
+TPMEMU_VERSION=0.6.1
+
WGET=wget -c
GNU_TARGET_ARCH:=$(XEN_TARGET_ARCH)
@@ -74,7 +86,7 @@
TARGET_LDFLAGS += -nostdlib -L$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/lib
-TARGETS=ioemu c caml grub
+TARGETS=ioemu c caml grub vtpm
CROSS_MAKE := $(MAKE) DESTDIR=
@@ -177,6 +189,70 @@
touch $@
#############
+# cross-gmp
+#############
+gmp-$(GMP_VERSION).tar.gz:
+ $(WGET) $(GMP_URL)/$@
+
+gmp-$(XEN_TARGET_ARCH): gmp-$(GMP_VERSION).tar.gz
+ tar xzf $<
+ mv gmp-$(GMP_VERSION) $@
+ patch -d $@ -p0 < gmp.patch
+ touch $@
+
+GMP_STAMPFILE=$(CROSS_ROOT)/$(GNU_TARGET_ARCH)-xen-elf/lib/libgmp.a
+.PHONY: cross-gmp
+ifeq ($(XEN_TARGET_ARCH), x86_32)
+ GMPEXT=ABI=32
+endif
+cross-gmp: $(GMP_STAMPFILE)
+$(GMP_STAMPFILE): gmp-$(XEN_TARGET_ARCH) $(NEWLIB_STAMPFILE)
+ ( cd $< && \
+ CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" CC=$(CC) $(GMPEXT) ./configure --disable-shared --enable-static --disable-fft --without-readline --prefix=$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf && \
+ $(CROSS_MAKE) && \
+ $(CROSS_MAKE) install )
+
+#############
+# cross-polarssl
+#############
+polarssl-$(POLARSSL_VERSION)-gpl.tgz:
+ $(WGET) $(POLARSSL_URL)/$@
+
+polarssl-$(XEN_TARGET_ARCH): polarssl-$(POLARSSL_VERSION)-gpl.tgz
+ tar xzf $<
+ mv polarssl-$(POLARSSL_VERSION) $@
+ patch -d $@ -p1 < polarssl.patch
+ touch $@
+
+POLARSSL_STAMPFILE=$(CROSS_ROOT)/$(GNU_TARGET_ARCH)-xen-elf/lib/libpolarssl.a
+cross-polarssl: $(POLARSSL_STAMPFILE)
+$(POLARSSL_STAMPFILE): polarssl-$(XEN_TARGET_ARCH) $(NEWLIB_STAMPFILE)
+ ( cd $</library && \
+ make CC="$(CC) -I/usr/include $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -I$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include/machine -I $(realpath $(MINI_OS)/include)" && \
+ mkdir -p $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include && \
+ cp -r ../include/* $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include && \
+ mkdir -p $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/lib && \
+ $(INSTALL_DATA) libpolarssl.a $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/lib/ )
+
+#############
+# cross-tpmemu
+#############
+tpm_emulator-$(TPMEMU_VERSION).tar.gz:
+ $(WGET) $(TPMEMU_URL)/$@
+
+tpm_emulator-$(XEN_TARGET_ARCH): tpm_emulator-$(TPMEMU_VERSION).tar.gz
+ tar xzf $<
+ mv tpm_emulator-$(TPMEMU_VERSION) $@
+ patch -d $@ -p1 < tpmemu-$(TPMEMU_VERSION).patch
+ touch $@
+.PHONY: cross-tpmemu
+cross-tpmemu: tpm_emulator-$(XEN_TARGET_ARCH) $(GMP_STAMPFILE)
+ make CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" -C $(CURDIR)/vtpm compat
+ ( cd $< && \
+ make version && \
+ make CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -I. -I.. -isystem $(CURDIR)/vtpm/compat -D__linux__" CC=$(CC) -C tpmd objs )
+
+#############
# Cross-ocaml
#############
@@ -306,6 +382,15 @@
CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(CROSS_MAKE) -C $@ LWIPDIR=$(CURDIR)/lwip-$(XEN_TARGET_ARCH)
######
+# VTPM
+######
+
+.PHONY: vtpm
+vtpm: cross-polarssl cross-tpmemu
+ make -C $(MINI_OS) links
+ XEN_TARGET_ARCH="$(XEN_TARGET_ARCH)" CPPFLAGS="$(TARGET_CPPFLAGS) -isystem $(CURDIR)/vtpm/compat -I$(CURDIR)/tpm_emulator-$(XEN_TARGET_ARCH) -I$(CURDIR)/tpm_emulator-$(XEN_TARGET_ARCH)/tpmd -D__linux__" CFLAGS="$(TARGET_CFLAGS)" $(CROSS_MAKE) -C $@
+
+######
# Grub
######
@@ -341,6 +426,10 @@
c-stubdom: mini-os-$(XEN_TARGET_ARCH)-c lwip-$(XEN_TARGET_ARCH) libxc c
DEF_CPPFLAGS="$(TARGET_CPPFLAGS)" DEF_CFLAGS="-DCONFIG_C $(TARGET_CFLAGS)" DEF_LDFLAGS="$(TARGET_LDFLAGS)" $(CROSS_MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip-$(XEN_TARGET_ARCH) APP_OBJS=$(CURDIR)/c/main.a
+.PHONY: vtpm-stubdom
+vtpm-stubdom: mini-os-$(XEN_TARGET_ARCH)-vtpm vtpm
+ DEF_CPPFLAGS="$(TARGET_CPPFLAGS)" DEF_CFLAGS="-DCONFIG_C $(TARGET_CFLAGS)" DEF_LDFLAGS="$(TARGET_LDFLAGS)" vtpm=y $(CROSS_MAKE) -C $(MINI_OS) libc=n OBJ_DIR=$(CURDIR)/$< APP_OBJS="$(CURDIR)/vtpm/vtpm.a"
+
.PHONY: pv-grub
pv-grub: mini-os-$(XEN_TARGET_ARCH)-grub libxc grub
DEF_CPPFLAGS="$(TARGET_CPPFLAGS)" DEF_CFLAGS="-DCONFIG_GRUB $(TARGET_CFLAGS)" DEF_LDFLAGS="$(TARGET_LDFLAGS)" $(CROSS_MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$< APP_OBJS=$(CURDIR)/grub-$(XEN_TARGET_ARCH)/main.a
@@ -380,8 +469,10 @@
rm -fr mini-os-$(XEN_TARGET_ARCH)-c
rm -fr mini-os-$(XEN_TARGET_ARCH)-caml
rm -fr mini-os-$(XEN_TARGET_ARCH)-grub
+ rm -fr mini-os-$(XEN_TARGET_ARCH)-vtpm
$(CROSS_MAKE) -C caml clean
$(CROSS_MAKE) -C c clean
+ $(CROSS_MAKE) -C vtpm clean
rm -fr grub-$(XEN_TARGET_ARCH)
rm -f $(STUBDOMPATH)
[ ! -d libxc-$(XEN_TARGET_ARCH) ] || $(CROSS_MAKE) -C libxc-$(XEN_TARGET_ARCH) clean
@@ -393,6 +484,9 @@
rm -fr $(CROSS_ROOT)
rm -fr newlib-$(XEN_TARGET_ARCH)
rm -fr zlib-$(XEN_TARGET_ARCH) pciutils-$(XEN_TARGET_ARCH)
+ rm -fr gmp-$(XEN_TARGET_ARCH)
+ rm -fr polarssl-$(XEN_TARGET_ARCH)
+ rm -fr tpm_emulator-$(XEN_TARGET_ARCH)
rm -fr libxc-$(XEN_TARGET_ARCH) ioemu
rm -f mk-headers-$(XEN_TARGET_ARCH)
rm -fr ocaml-$(XEN_TARGET_ARCH)
@@ -402,6 +496,9 @@
.PHONY: patchclean
patchclean: crossclean
rm -fr newlib-$(NEWLIB_VERSION)
+ rm -fr gmp-$(XEN_TARGET_ARCH)
+ rm -fr polarssl-$(XEN_TARGET_ARCH)
+ rm -fr tpm_emulator-$(XEN_TARGET_ARCH)
rm -fr lwip-$(XEN_TARGET_ARCH)
rm -fr grub-upstream
@@ -410,10 +507,13 @@
downloadclean: patchclean
rm -f newlib-$(NEWLIB_VERSION).tar.gz
rm -f zlib-$(ZLIB_VERSION).tar.gz
+ rm -f gmp-$(GMP_VERSION).tar.gz
+ rm -f tpm_emulator-$(TPMEMU_VERSION).tar.gz
rm -f pciutils-$(LIBPCI_VERSION).tar.bz2
rm -f grub-$(GRUB_VERSION).tar.gz
rm -f lwip-$(LWIP_VERSION).tar.gz
rm -f ocaml-$(OCAML_VERSION).tar.gz
+ rm -f polarssl-$(POLARSSL_VERSION)-gpl.tgz
.PHONY: distclean
distclean: downloadclean
[-- Attachment #1.2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 2518 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] only message in thread
only message in thread, other threads:[~2010-08-25 15:24 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-08-25 15:24 [PATCH 5/7] vtpm Mini-Os domain: hotplug fixes Matthew Fioravante
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).