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=: Control the verbosity of the output to the console. Valid +values for 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=: Specify where the vTPM will get entropy. The valid values +for 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 +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 + +/* + * 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 , + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#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 +#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 +#include +#include +#include +#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 +#include + +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 $