[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH vtpm_manager 1/2] Updates and bug fixes to vtpm_manager
The following patch contains a major set of bug fixes and feature enhancements to vtpm_manager. vtpm_manager was previously riddled with memory leaks, race conditions, IO deadlocks, and other assorted bugs. This patch fixes numerous bugs in vtpm manager and also adds new functionality for supporting vtpm stub domains. It adds a new program (vtpmmgrtalk) that is used by the hotplug script fixes (next patch) to avoid IO deadlocks with pipes. Finally, it also breaks the compilation of vtpm_manager into separate static libraries, which are then used later by the vtpmmgrdom stub domain. Signed of by: Matthew Fioravante matthew.fioravante@xxxxxxxxxx diff --git a/tools/vtpm_manager/Makefile b/tools/vtpm_manager/Makefile --- a/tools/vtpm_manager/Makefile +++ b/tools/vtpm_manager/Makefile @@ -1,9 +1,9 @@ -XEN_ROOT = $(CURDIR)/../.. +XEN_ROOT = $(realpath ../..) # Base definitions and rules -include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk +include Rules.mk -SUBDIRS = crypto tcs util manager migration +SUBDIRS = crypto tcs util manager migration vtpmmgrtalk vtpmconnd OPENSSL_HEADER = /usr/include/openssl/crypto.h .PHONY: all clean install diff --git a/tools/vtpm_manager/README b/tools/vtpm_manager/README --- a/tools/vtpm_manager/README +++ b/tools/vtpm_manager/README @@ -43,9 +43,6 @@ Compile Flags LOGGING_MODULES -> How extensive logging happens see util/log.h for more info -VTPM_MULTI_VM -> Defined: VTPMs run in their own VMs - Not Defined (default): VTPMs are processes - # Debugging flags that may disappear without notice in the future DUMMY_BACKEND -> vtpm_manager listens on /tmp/in.fifo and @@ -59,6 +56,10 @@ WELL_KNOWN_OWNER_AUTH -> Rather than randomly generating the password for lost. However this has no protection from malicious app issuing a TPM_OwnerClear to wipe the TPM +VTPM_STUBDOM -> vtpm_manager runs in vtpm_stubdom mode with + vtpm instances running in mini-os domains + (see: stubdom/vtpm/README for details) + Requirements ============ - xen-unstable diff --git a/tools/vtpm_manager/Rules.mk b/tools/vtpm_manager/Rules.mk --- a/tools/vtpm_manager/Rules.mk +++ b/tools/vtpm_manager/Rules.mk @@ -6,7 +6,7 @@ include $(XEN_ROOT)/tools/Rules.mk # # General compiler flags -CFLAGS = -Werror -g3 +CFLAGS = -Werror -g3 -I. # Generic project files HDRS = $(wildcard *.h) @@ -31,18 +31,18 @@ $(OBJS): $(SRCS) CFLAGS += -D_GNU_SOURCE # Logging Level. See utils/tools.h for usage -CFLAGS += -DLOGGING_MODULES="(BITMASK(VTPM_LOG_TCS)|BITMASK(VTPM_LOG_VTSP)|BITMASK(VTPM_LOG_VTPM))" +#CFLAGS += -DLOGGING_MODULES="(BITMASK(VTPM_LOG_TCS)|BITMASK(VTPM_LOG_VTSP)|BITMASK(VTPM_LOG_VTPM))" # Silent Mode #CFLAGS += -DLOGGING_MODULES=0x0 -#CFLAGS += -DLOGGING_MODULES=0xff - -# Use frontend/backend pairs between manager & DMs? -#CFLAGS += -DVTPM_MULTI_VM +CFLAGS += -DLOGGING_MODULES=0xff # vtpm_manager listens on fifo's rather than backend #CFLAGS += -DDUMMY_BACKEND +# Build for use with vtpm-stubdom +#CFLAGS += -DVTPM_STUBDOM + # TCS talks to fifo's rather than /dev/tpm. TPM Emulator assumed on fifos #CFLAGS += -DDUMMY_TPM @@ -52,8 +52,3 @@ CFLAGS += -DLOGGING_MODULES="(BITMASK(VTPM_LOG_TCS)|BITMASK(VTPM_LOG_VTSP)|BITMA # Fixed OwnerAuth #CFLAGS += -DWELL_KNOWN_OWNER_AUTH -# Include -CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/crypto -CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/util -CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/tcs -CFLAGS += -I$(XEN_ROOT)/tools/vtpm_manager/manager diff --git a/tools/vtpm_manager/crypto/Makefile b/tools/vtpm_manager/crypto/Makefile --- a/tools/vtpm_manager/crypto/Makefile +++ b/tools/vtpm_manager/crypto/Makefile @@ -1,5 +1,9 @@ -XEN_ROOT = $(CURDIR)/../../.. -include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk +XEN_ROOT = $(realpath ../../..) +include ../Rules.mk + +CFLAGS += -I../util +CFLAGS += -I../tcs +CFLAGS += -I../manager BIN = libtcpaCrypto.a diff --git a/tools/vtpm_manager/crypto/crypto.c b/tools/vtpm_manager/crypto/crypto.c --- a/tools/vtpm_manager/crypto/crypto.c +++ b/tools/vtpm_manager/crypto/crypto.c @@ -45,6 +45,8 @@ #include "crypto.h" #include "log.h" +extern const EVP_CIPHER * SYM_CIPHER; + /** * Initialize cryptography library * @rand: random seed @@ -83,6 +85,6 @@ void Crypto_GetRandom(void* data, int size) { result = RAND_pseudo_bytes((BYTE*) data, size); if (result <= 0) - vtpmlogerror (VTPM_LOG_CRYPTO, "RAND_pseudo_bytes failed: %s\n", - ERR_error_string (ERR_get_error(), NULL)); + vtpmlogerror (VTPM_LOG_CRYPTO, "RAND_pseudo_bytes failed: rc=%d errstr=%s\n", + result, ERR_error_string (ERR_get_error(), NULL)); } diff --git a/tools/vtpm_manager/crypto/crypto.h b/tools/vtpm_manager/crypto/crypto.h --- a/tools/vtpm_manager/crypto/crypto.h +++ b/tools/vtpm_manager/crypto/crypto.h @@ -76,7 +76,7 @@ typedef struct CRYPTO_INFO { void Crypto_Init(const BYTE* rand, int size); -void Crypto_Exit(); +void Crypto_Exit(void); void Crypto_GetRandom(void* data, int size); @@ -127,6 +127,8 @@ void Crypto_RSABuildCryptoInfoPublic( /*[IN]*/ UINT32 pubExpSize, /*[IN]*/ BYTE *modulus, CRYPTO_INFO* cryptoInfo); +void Crypto_RSACryptoInfoFree(CRYPTO_INFO* cryptoInfo); + // // symmetric pack and unpack operations // diff --git a/tools/vtpm_manager/crypto/rsa.c b/tools/vtpm_manager/crypto/rsa.c --- a/tools/vtpm_manager/crypto/rsa.c +++ b/tools/vtpm_manager/crypto/rsa.c @@ -149,6 +149,10 @@ void Crypto_RSABuildCryptoInfoPublic( /*[IN]*/ UINT32 pubExpSize, } +void Crypto_RSACryptoInfoFree(CRYPTO_INFO* cryptoInfo) { + RSA_free(cryptoInfo->keyInfo); +} + int Crypto_RSAEnc( CRYPTO_INFO *key, UINT32 inDataSize, BYTE *inData, @@ -161,6 +165,7 @@ int Crypto_RSAEnc( CRYPTO_INFO *key, if (paddedData == NULL) return -1; + memset(paddedData, 0, sizeof(BYTE) * paddedDataSize); *outDataSize = 0; diff --git a/tools/vtpm_manager/crypto/sym_crypto.c b/tools/vtpm_manager/crypto/sym_crypto.c --- a/tools/vtpm_manager/crypto/sym_crypto.c +++ b/tools/vtpm_manager/crypto/sym_crypto.c @@ -41,8 +41,16 @@ #include <openssl/rand.h> #include "tcg.h" +#include "log.h" #include "sym_crypto.h" +struct symkey_t { + buffer_t key; + + EVP_CIPHER_CTX context; + const EVP_CIPHER * cipher; +}; + typedef enum crypt_op_type_t { CRYPT_ENCRYPT, CRYPT_DECRYPT @@ -61,19 +69,22 @@ const EVP_CIPHER * SYM_CIPHER = NULL; const BYTE ZERO_IV[EVP_MAX_IV_LENGTH] = {0}; -TPM_RESULT Crypto_symcrypto_initkey (symkey_t * key, const buffer_t* keybits) { +TPM_RESULT Crypto_symcrypto_initkey (symkey_t ** key, const buffer_t* keybits) { TPM_RESULT status = TPM_SUCCESS; - EVP_CIPHER_CTX_init (&key->context); + *key = malloc(sizeof(symkey_t)); + + EVP_CIPHER_CTX_init (&(*key)->context); - key->cipher = SYM_CIPHER; + (*key)->cipher = SYM_CIPHER; - TPMTRYRETURN( buffer_init_copy (&key->key, keybits)); + TPMTRYRETURN( buffer_init_copy (&(*key)->key, keybits)); goto egress; abort_egress: - EVP_CIPHER_CTX_cleanup (&key->context); + EVP_CIPHER_CTX_cleanup (&(*key)->context); + free(key); egress: @@ -82,19 +93,21 @@ TPM_RESULT Crypto_symcrypto_initkey (symkey_t * key, const buffer_t* keybits) { -TPM_RESULT Crypto_symcrypto_genkey (symkey_t * key) { +TPM_RESULT Crypto_symcrypto_genkey (symkey_t ** key) { int res; TPM_RESULT status = TPM_SUCCESS; + + *key = malloc(sizeof(symkey_t)); // hmm, EVP_CIPHER_CTX_init does not return a value - EVP_CIPHER_CTX_init (&key->context); + EVP_CIPHER_CTX_init (&(*key)->context); - key->cipher = SYM_CIPHER; + (*key)->cipher = SYM_CIPHER; - TPMTRYRETURN( buffer_init (&key->key, EVP_CIPHER_key_length(key->cipher), NULL)) ; + TPMTRYRETURN( buffer_init (&(*key)->key, EVP_CIPHER_key_length((*key)->cipher), NULL)) ; // and generate the key material - res = RAND_pseudo_bytes (key->key.bytes, key->key.size); + res = RAND_pseudo_bytes ((*key)->key.bytes, (*key)->key.size); if (res < 0) ERRORDIE (TPM_SHORTRANDOM); @@ -102,8 +115,9 @@ TPM_RESULT Crypto_symcrypto_genkey (symkey_t * key) { goto egress; abort_egress: - EVP_CIPHER_CTX_cleanup (&key->context); - buffer_free (&key->key); + EVP_CIPHER_CTX_cleanup (&(*key)->context); + buffer_free (&(*key)->key); + free(key); egress: return status; @@ -119,11 +133,11 @@ TPM_RESULT Crypto_symcrypto_encrypt (symkey_t* key, buffer_init_const (&iv, EVP_MAX_IV_LENGTH, ZERO_IV); - buffer_init (o_cipher, - clear->size + - EVP_CIPHER_iv_length(key->cipher) + - EVP_CIPHER_block_size (key->cipher), - 0); + TPMTRYRETURN( buffer_init (o_cipher, + clear->size + + EVP_CIPHER_iv_length(key->cipher) + + EVP_CIPHER_block_size (key->cipher), + 0) ); // copy the IV into the front buffer_copy (o_cipher, &iv); @@ -139,6 +153,7 @@ TPM_RESULT Crypto_symcrypto_encrypt (symkey_t* key, goto egress; abort_egress: + buffer_free(o_cipher); egress: @@ -170,7 +185,7 @@ TPM_RESULT Crypto_symcrypto_decrypt (symkey_t* key, // and decrypt TPMTRYRETURN ( ossl_symcrypto_op (key, &cipher_alias, &iv, o_clear, CRYPT_DECRYPT) ); - + goto egress; abort_egress: @@ -188,6 +203,8 @@ TPM_RESULT Crypto_symcrypto_freekey (symkey_t * key) { buffer_free (&key->key); EVP_CIPHER_CTX_cleanup (&key->context); + + free(key); return TPM_SUCCESS; } @@ -235,3 +252,8 @@ TPM_RESULT ossl_symcrypto_op (symkey_t* key, return status; } + +buffer_t* Crypto_symkey_getkey(symkey_t* key) +{ + return &key->key; +} diff --git a/tools/vtpm_manager/crypto/sym_crypto.h b/tools/vtpm_manager/crypto/sym_crypto.h --- a/tools/vtpm_manager/crypto/sym_crypto.h +++ b/tools/vtpm_manager/crypto/sym_crypto.h @@ -40,21 +40,15 @@ #ifndef _SYM_CRYPTO_H #define _SYM_CRYPTO_H -#include <openssl/evp.h> #include "buffer.h" -typedef struct symkey_t { - buffer_t key; - - EVP_CIPHER_CTX context; - const EVP_CIPHER * cipher; -} symkey_t; +typedef struct symkey_t symkey_t; -extern const EVP_CIPHER * SYM_CIPHER; +//Allocates a symkey with random bits +TPM_RESULT Crypto_symcrypto_genkey (symkey_t ** key); -TPM_RESULT Crypto_symcrypto_genkey (symkey_t * key); - -TPM_RESULT Crypto_symcrypto_initkey (symkey_t * key, const buffer_t* keybits); +//Allocates a symkey with given keybits +TPM_RESULT Crypto_symcrypto_initkey (symkey_t ** key, const buffer_t* keybits); // these functions will allocate their output buffers @@ -66,7 +60,10 @@ TPM_RESULT Crypto_symcrypto_decrypt (symkey_t* key, const buffer_t* cipher, buffer_t* o_clear); -// only free the internal parts, not the 'key' ptr +//Frees the symkey TPM_RESULT Crypto_symcrypto_freekey (symkey_t * key); +//Get the raw key byte buffer +buffer_t* Crypto_symkey_getkey(symkey_t* key); + #endif /* _SYM_CRYPTO_H */ diff --git a/tools/vtpm_manager/manager/Makefile b/tools/vtpm_manager/manager/Makefile --- a/tools/vtpm_manager/manager/Makefile +++ b/tools/vtpm_manager/manager/Makefile @@ -1,7 +1,18 @@ -XEN_ROOT = $(CURDIR)/../../.. -include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk +XEN_ROOT = $(realpath ../../..) +include ../Rules.mk + +CFLAGS += -I../crypto +CFLAGS += -I../util +CFLAGS += -I../tcs + + +MAINS := vtpmd.o +MGRLIB := libvtpmmanager.a +VTSPOBJS := vtsp.o +VTSPLIB := libvtsp.a +BIN := vtpm_managerd +OBJS := $(filter-out $(MAINS) $(VTSPOBJS), $(OBJS)) -BIN = vtpm_managerd .PHONY: all all: build @@ -28,8 +39,14 @@ clean: mrproper: clean rm -f *~ -$(BIN): $(OBJS) - $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ +$(BIN): $(MAINS) $(MGRLIB) $(VTSPLIB) + $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LIBS) -o $@ + +$(VTSPLIB): $(VTSPOBJS) + $(AR) rcs $@ $^ + +$(MGRLIB): $(OBJS) + $(AR) rcs $@ $^ # libraries LIBS += ../tcs/libTCS.a ../util/libTCGUtils.a ../crypto/libtcpaCrypto.a diff --git a/tools/vtpm_manager/manager/dmictl.c b/tools/vtpm_manager/manager/dmictl.c --- a/tools/vtpm_manager/manager/dmictl.c +++ b/tools/vtpm_manager/manager/dmictl.c @@ -40,6 +40,9 @@ #include <stdio.h> #include <unistd.h> #include <string.h> +#include <fcntl.h> +#include <inttypes.h> +#include <stdlib.h> #include "vtpmpriv.h" #include "bsg.h" @@ -51,6 +54,13 @@ #define TPM_EMULATOR_PATH "/usr/bin/vtpmd" +#ifndef VTPM_STUBDOM +// This is needed to all extra_close_dmi to close this to prevent a +// broken pipe when no DMIs are left. +vtpm_ipc_handle_t *g_rx_tpm_ipc_h; +#endif + + // if dmi_res is non-null, then return a pointer to new object. // Also, this does not fill in the measurements. They should be filled by // design dependent code or saveNVM @@ -81,7 +91,7 @@ TPM_RESULT init_dmi(UINT32 dmi_id, BYTE dmi_type, VTPM_DMI_RESOURCE **dmi_res) { // install into map if (!hashtable_insert(vtpm_globals->dmi_map, dmi_id_key, new_dmi)){ - vtpmlogerror(VTPM_LOG_VTPM, "Failed to insert instance into table. Aborting.\n", dmi_id); + vtpmlogerror(VTPM_LOG_VTPM, "Failed to insert instance %" PRIu32 "into table. Aborting.\n", dmi_id); status = TPM_FAIL; goto abort_egress; } @@ -116,6 +126,161 @@ TPM_RESULT close_dmi(VTPM_DMI_RESOURCE *dmi_res) { return (VTPM_Close_DMI_Extra(dmi_res) ); } + +void free_dmi(VTPM_DMI_RESOURCE *dmi_res) { + if(dmi_res != NULL) { + free(dmi_res->NVMLocation); + } + free(dmi_res); +} + +TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res, BYTE vm_type, BYTE startup_mode) { + + TPM_RESULT status = TPM_SUCCESS; +#ifndef VTPM_STUBDOM + int fh; + char dmi_id_str[11]; // UINT32s are up to 10 digits + NULL + char *tx_vtpm_name, *tx_tpm_name, *vm_type_string; + struct stat file_info; + + if (dmi_res->dmi_id == VTPM_CTL_DM) { + dmi_res->tx_tpm_ipc_h = NULL; + dmi_res->rx_tpm_ipc_h = NULL; + dmi_res->tx_vtpm_ipc_h = NULL; + dmi_res->rx_vtpm_ipc_h = NULL; + } else { + // Create a pair of fifo pipes + dmi_res->rx_tpm_ipc_h = NULL; + dmi_res->rx_vtpm_ipc_h = NULL; + + if ( ((dmi_res->tx_tpm_ipc_h = (vtpm_ipc_handle_t *) malloc (sizeof(vtpm_ipc_handle_t))) == NULL ) || + ((dmi_res->tx_vtpm_ipc_h =(vtpm_ipc_handle_t *) malloc (sizeof(vtpm_ipc_handle_t))) == NULL ) || + ((tx_tpm_name = (char *) malloc(11 + strlen(VTPM_TX_TPM_FNAME))) == NULL ) || + ((tx_vtpm_name =(char *) malloc(11 + strlen(VTPM_TX_VTPM_FNAME))) == NULL) ) { + status =TPM_RESOURCES; + goto abort_egress; + } + + sprintf(tx_tpm_name, VTPM_TX_TPM_FNAME, (uint32_t) dmi_res->dmi_id); + sprintf(tx_vtpm_name, VTPM_TX_VTPM_FNAME, (uint32_t) dmi_res->dmi_id); + + if ( (vtpm_ipc_init(dmi_res->tx_tpm_ipc_h, tx_tpm_name, O_WRONLY | O_NONBLOCK, TRUE, FALSE) != 0) || + (vtpm_ipc_init(dmi_res->tx_vtpm_ipc_h, tx_vtpm_name, O_WRONLY, TRUE, FALSE) != 0) ) { //FIXME: O_NONBLOCK? + status = TPM_IOERROR; + goto abort_egress; + } + + // Measure DMI + // FIXME: This will measure DMI. Until then use a fixed DMI_Measurement value + // Also, this mechanism is specific to 1 VM architecture. + /* + fh = open(TPM_EMULATOR_PATH, O_RDONLY); + stat_ret = fstat(fh, &file_stat); + if (stat_ret == 0) + dmi_size = file_stat.st_size; + else { + vtpmlogerror(VTPM_LOG_VTPM, "Could not open vtpmd!!\n"); + status = TPM_IOERROR; + goto abort_egress; + } + dmi_buffer + */ + memset(&dmi_res->DMI_measurement, 0xcc, sizeof(TPM_DIGEST)); + + if (vm_type == VTPM_TYPE_PVM) + vm_type_string = (BYTE *)&VTPM_TYPE_PVM_STRING; + else + vm_type_string = (BYTE *)&VTPM_TYPE_HVM_STRING; + + // Launch DMI + sprintf(dmi_id_str, "%d", (int) dmi_res->dmi_id); +#ifdef MANUAL_DM_LAUNCH + vtpmlogerror(VTPM_LOG_VTPM, "Manually start VTPM with dmi=%s now.\n", dmi_id_str); + dmi_res->dmi_pid = 0; +#else + pid_t pid = fork(); + + if (pid == -1) { + vtpmlogerror(VTPM_LOG_VTPM, "Could not fork to launch vtpm\n"); + status = TPM_RESOURCES; + goto abort_egress; + } else if (pid == 0) { + switch (startup_mode) { + case TPM_ST_CLEAR: + execl (TPM_EMULATOR_PATH, "vtpmd", "clear", vm_type_string, dmi_id_str, NULL); + break; + case TPM_ST_STATE: + execl (TPM_EMULATOR_PATH, "vtpmd", "save", vm_type_string, dmi_id_str, NULL); + break; + case TPM_ST_DEACTIVATED: + execl (TPM_EMULATOR_PATH, "vtpmd", "deactivated", vm_type_string, dmi_id_str, NULL); + break; + default: + status = TPM_BAD_PARAMETER; + goto abort_egress; + } + + // Returning from these at all is an error. + vtpmlogerror(VTPM_LOG_VTPM, "Could not exec to launch vtpm\n"); + } else { + dmi_res->dmi_pid = pid; + vtpmloginfo(VTPM_LOG_VTPM, "Launching DMI on PID = %d\n", pid); + } +#endif // MANUAL_DM_LAUNCH + + } // If DMI = VTPM_CTL_DM + status = TPM_SUCCESS; +#endif + +abort_egress: + //FIXME: Everything should be freed here + return (status); +} + +TPM_RESULT VTPM_Close_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res) { + TPM_RESULT status = TPM_SUCCESS; + +#ifndef VTPM_STUBDOM + if (vtpm_globals->connected_dmis == 0) { + // No more DMI's connected. Close fifo to prevent a broken pipe. + // This is hackish. Need to think of another way. + vtpm_ipc_close(g_rx_tpm_ipc_h); + } + + + if (dmi_res->dmi_id != VTPM_CTL_DM) { + vtpm_ipc_close(dmi_res->tx_tpm_ipc_h); + vtpm_ipc_close(dmi_res->tx_vtpm_ipc_h); + + free(dmi_res->tx_tpm_ipc_h->name); + free(dmi_res->tx_vtpm_ipc_h->name); + free(dmi_res->tx_tpm_ipc_h); + free(dmi_res->tx_vtpm_ipc_h); + +#ifndef MANUAL_DM_LAUNCH + if (dmi_res->dmi_id != VTPM_CTL_DM) { + if (dmi_res->dmi_pid != 0) { + vtpmloginfo(VTPM_LOG_VTPM, "Killing dmi on pid %d.\n", dmi_res->dmi_pid); + if (kill(dmi_res->dmi_pid, SIGKILL) !=0) { + vtpmloginfo(VTPM_LOG_VTPM, "DMI on pid %d is already dead.\n", dmi_res->dmi_pid); + } else if (waitpid(dmi_res->dmi_pid, NULL, 0) != dmi_res->dmi_pid) { + vtpmlogerror(VTPM_LOG_VTPM, "DMI on pid %d failed to stop.\n", dmi_res->dmi_pid); + status = TPM_FAIL; + } + } else { + vtpmlogerror(VTPM_LOG_VTPM, "Could not kill dmi because it's pid was 0.\n"); + status = TPM_FAIL; + } + } +#endif + + } //endif ! dom0 +#endif + return status; +} + + + TPM_RESULT VTPM_Handle_New_DMI(const buffer_t *param_buf) { @@ -254,7 +419,7 @@ TPM_RESULT VTPM_Handle_Delete_DMI( const buffer_t *param_buf) { // Close DMI first TPMTRYRETURN(close_dmi( dmi_res )); - free ( dmi_res ); + free_dmi(dmi_res); status=TPM_SUCCESS; goto egress; diff --git a/tools/vtpm_manager/manager/migration.c b/tools/vtpm_manager/manager/migration.c --- a/tools/vtpm_manager/manager/migration.c +++ b/tools/vtpm_manager/manager/migration.c @@ -40,6 +40,7 @@ #include <stdio.h> #include <unistd.h> #include <string.h> +#include <stdlib.h> #include "vtpmpriv.h" #include "bsg.h" @@ -263,7 +264,7 @@ TPM_RESULT VTPM_Handle_Get_Migration_key( const buffer_t *param_buf, TPM_RESULT VTPM_Handle_Load_Migration_key( const buffer_t *param_buf, buffer_t *result_buf) { - TPM_RESULT status=TPM_FAIL; + TPM_RESULT status=TPM_SUCCESS; VTPM_MIGKEY_LIST *mig_key; vtpmloginfo(VTPM_LOG_VTPM, "Loading Migration Public Key.\n"); @@ -303,5 +304,5 @@ TPM_RESULT VTPM_Handle_Load_Migration_key( const buffer_t *param_buf, free(pubkey_exp_pack.data); free(pubkey_mod_pack.data); - return TPM_SUCCESS; + return status; } diff --git a/tools/vtpm_manager/manager/securestorage.c b/tools/vtpm_manager/manager/securestorage.c --- a/tools/vtpm_manager/manager/securestorage.c +++ b/tools/vtpm_manager/manager/securestorage.c @@ -42,7 +42,7 @@ #include <fcntl.h> #include <unistd.h> #include <string.h> - +#include <stdlib.h> #include "tcg.h" #include "vtpm_manager.h" #include "vtpmpriv.h" @@ -58,7 +58,7 @@ TPM_RESULT envelope_encrypt(const buffer_t *inbuf, CRYPTO_INFO *asymkey, buffer_t *sealed_data) { TPM_RESULT status = TPM_SUCCESS; - symkey_t symkey; + symkey_t *symkey; buffer_t data_cipher = NULL_BUF, symkey_cipher = NULL_BUF; @@ -69,14 +69,14 @@ TPM_RESULT envelope_encrypt(const buffer_t *inbuf, for (i=0; i< buffer_len(inbuf); i++) vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", inbuf->bytes[i]); vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); - + // Generate a sym key and encrypt state with it TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_genkey (&symkey) ); - TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_encrypt (&symkey, inbuf, &data_cipher) ); + TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_encrypt (symkey, inbuf, &data_cipher) ); // Encrypt symmetric key TPMTRYRETURN( VTSP_Bind( asymkey, - &symkey.key, + Crypto_symkey_getkey(symkey), &symkey_cipher) ); // Create output blob: symkey_size + symkey_cipher + state_cipher_size + state_cipher @@ -86,8 +86,9 @@ TPM_RESULT envelope_encrypt(const buffer_t *inbuf, data_cipher32.size = buffer_len(&data_cipher); data_cipher32.data = data_cipher.bytes; - + TPMTRYRETURN( buffer_init(sealed_data, 2 * sizeof(UINT32) + symkey_cipher32.size + data_cipher32.size, NULL)); + memset(sealed_data->bytes, 0, sealed_data->size); BSG_PackList(sealed_data->bytes, 2, BSG_TPM_SIZE32_DATA, &symkey_cipher32, @@ -109,11 +110,37 @@ TPM_RESULT envelope_encrypt(const buffer_t *inbuf, buffer_free ( &data_cipher); buffer_free ( &symkey_cipher); - Crypto_symcrypto_freekey (&symkey); + Crypto_symcrypto_freekey (symkey); return status; } +TPM_RESULT symkey_encrypt(const buffer_t *inbuf, + CRYPTO_INFO *asymkey, + buffer_t *sealed_key) { + buffer_t symkey_cipher = NULL_BUF; + struct pack_constbuf_t symkey_cipher32; + TPM_RESULT status = TPM_SUCCESS; + + // Encrypt symmetric key + TPMTRYRETURN( VTSP_Bind( asymkey, + inbuf, + &symkey_cipher)); + + symkey_cipher32.size = buffer_len(&symkey_cipher); + symkey_cipher32.data = symkey_cipher.bytes; + + TPMTRYRETURN( buffer_init(sealed_key, sizeof(UINT32) + symkey_cipher32.size, NULL)); + BSG_PackList(sealed_key->bytes, 1, + BSG_TPM_SIZE32_DATA, &symkey_cipher32); + goto egress; +abort_egress: +egress: + buffer_free( &symkey_cipher); + return status; +} + + TPM_RESULT envelope_decrypt(const buffer_t *cipher, TCS_CONTEXT_HANDLE TCSContext, TPM_HANDLE keyHandle, @@ -121,15 +148,13 @@ TPM_RESULT envelope_decrypt(const buffer_t *cipher, buffer_t *unsealed_data) { TPM_RESULT status = TPM_SUCCESS; - symkey_t symkey; + symkey_t *symkey; buffer_t data_cipher = NULL_BUF, symkey_clear = NULL_BUF, symkey_cipher = NULL_BUF; - struct pack_buf_t symkey_cipher32, data_cipher32; + struct pack_buf_t symkey_cipher32 = NULL_PACK_BUF, data_cipher32 = NULL_PACK_BUF; int i; - memset(&symkey, 0, sizeof(symkey_t)); - vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Envelope Decrypt Input[%d]: 0x", buffer_len(cipher) ); for (i=0; i< buffer_len(cipher); i++) vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cipher->bytes[i]); @@ -159,7 +184,7 @@ TPM_RESULT envelope_decrypt(const buffer_t *cipher, Crypto_symcrypto_initkey (&symkey, &symkey_clear); // Decrypt State - TPMTRY(TPM_DECRYPT_ERROR, Crypto_symcrypto_decrypt (&symkey, &data_cipher, unsealed_data) ); + TPMTRY(TPM_DECRYPT_ERROR, Crypto_symcrypto_decrypt (symkey, &data_cipher, unsealed_data) ); vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Envelope Decrypte Output[%d]: 0x", buffer_len(unsealed_data)); for (i=0; i< buffer_len(unsealed_data); i++) @@ -175,26 +200,64 @@ TPM_RESULT envelope_decrypt(const buffer_t *cipher, buffer_free ( &data_cipher); buffer_free ( &symkey_clear); buffer_free ( &symkey_cipher); - Crypto_symcrypto_freekey (&symkey); + BSG_Destroy(BSG_TPM_SIZE32_DATA, &symkey_cipher32); + BSG_Destroy(BSG_TPM_SIZE32_DATA, &data_cipher32); + Crypto_symcrypto_freekey (symkey); + return status; } +TPM_RESULT symkey_decrypt(const buffer_t *cipher, + TCS_CONTEXT_HANDLE TCSContext, + TPM_HANDLE keyHandle, + const TPM_AUTHDATA *key_usage_auth, + buffer_t *symkey_clear) { + + TPM_RESULT status = TPM_SUCCESS; + buffer_t symkey_cipher = NULL_BUF; + struct pack_buf_t symkey_cipher32 = NULL_PACK_BUF; + + BSG_UnpackList(cipher->bytes, 1, + BSG_TPM_SIZE32_DATA, &symkey_cipher32); + + TPMTRYRETURN( buffer_init_alias_convert (&symkey_cipher, + symkey_cipher32.size, + symkey_cipher32.data) ); + + // Decrypt Symmetric Key + TPMTRYRETURN( VTSP_Unbind( TCSContext, + keyHandle, + &symkey_cipher, + key_usage_auth, + symkey_clear, + &(vtpm_globals->keyAuth) ) ); + + goto egress; + abort_egress: + vtpmlogerror(VTPM_LOG_VTPM, "Failed to decrypt symmetric key status=%d\n.", status); + + egress: + BSG_Destroy(BSG_TPM_SIZE32_DATA, &symkey_cipher32); + return status; +} + TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI_RESOURCE *myDMI, const buffer_t *inbuf, buffer_t *outbuf) { TPM_RESULT status = TPM_SUCCESS; - int fh; + int fh = -1; long bytes_written; buffer_t sealed_NVM = NULL_BUF; - - vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Saving %d bytes of NVM.\n", buffer_len(inbuf)); + const buffer_t* nvmbuf = inbuf; + + vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Saving %d bytes of NVM.\n", buffer_len(nvmbuf)); - TPMTRYRETURN( envelope_encrypt(inbuf, + TPMTRYRETURN( envelope_encrypt(nvmbuf, &vtpm_globals->storageKey, &sealed_NVM) ); - + // Write sealed blob off disk from NVMLocation // TODO: How to properly return from these. Do we care if we return failure // after writing the file? We can't get the old one back. @@ -205,7 +268,6 @@ TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI_RESOURCE *myDMI, status = TPM_IOERROR; goto abort_egress; } - close(fh); Crypto_SHA1Full (sealed_NVM.bytes, buffer_len(&sealed_NVM), (BYTE *) &myDMI->NVM_measurement); @@ -215,6 +277,7 @@ TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI_RESOURCE *myDMI, vtpmlogerror(VTPM_LOG_VTPM, "Failed to save NVM\n."); egress: + close(fh); buffer_free(&sealed_NVM); return status; } @@ -229,7 +292,8 @@ TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI_RESOURCE *myDMI, buffer_t sealed_NVM = NULL_BUF; long fh_size; - int fh, stat_ret, i; + int fh = -1; + int stat_ret, i; struct stat file_stat; TPM_DIGEST sealedNVMHash; @@ -241,6 +305,7 @@ TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI_RESOURCE *myDMI, //Read sealed blob off disk from NVMLocation fh = open(myDMI->NVMLocation, O_RDONLY); + printf("Filename: %s\n", myDMI->NVMLocation); stat_ret = fstat(fh, &file_stat); if (stat_ret == 0) fh_size = file_stat.st_size; @@ -254,7 +319,6 @@ TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI_RESOURCE *myDMI, status = TPM_IOERROR; goto abort_egress; } - close(fh); vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Load_NVMing[%d],\n", buffer_len(&sealed_NVM)); @@ -289,14 +353,128 @@ TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI_RESOURCE *myDMI, egress: buffer_free( &sealed_NVM ); + close(fh); + + return status; +} + +TPM_RESULT VTPM_Handle_Load_HashKey(VTPM_DMI_RESOURCE *myDMI, + const buffer_t *inbuf, + buffer_t *outbuf) { + + TPM_RESULT status = TPM_SUCCESS; + + buffer_t sealed_NVM = NULL_BUF; + long fh_size; + int fh = -1; + int stat_ret, i; + struct stat file_stat; + TPM_DIGEST sealedNVMHash; + + if (myDMI->NVMLocation == NULL) { + vtpmlogerror(VTPM_LOG_VTPM, "Unable to load NVM because the file name NULL.\n"); + status = TPM_AUTHFAIL; + goto abort_egress; + } + + //Read sealed blob off disk from NVMLocation + fh = open(myDMI->NVMLocation, O_RDONLY); + printf("Filename: %s\n", myDMI->NVMLocation); + stat_ret = fstat(fh, &file_stat); + if (stat_ret == 0) + fh_size = file_stat.st_size; + else { + status = TPM_IOERROR; + goto abort_egress; + } + + TPMTRYRETURN( buffer_init( &sealed_NVM, fh_size, NULL) ); + if (read(fh, sealed_NVM.bytes, buffer_len(&sealed_NVM)) != fh_size) { + status = TPM_IOERROR; + goto abort_egress; + } + + vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Loading %d byte encryption key,\n", buffer_len(&sealed_NVM)); + + Crypto_SHA1Full(sealed_NVM.bytes, buffer_len(&sealed_NVM), (BYTE *) &sealedNVMHash); + + // Verify measurement of sealed blob. + if (memcmp(&sealedNVMHash, &myDMI->NVM_measurement, sizeof(TPM_DIGEST)) ) { + vtpmlogerror(VTPM_LOG_VTPM, "VTPM LoadKey NVM measurement check failed.\n"); + vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Correct hash: "); + for (i=0; i< sizeof(TPM_DIGEST); i++) + vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", ((BYTE*)&myDMI->NVM_measurement)[i]); + vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); + + vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Measured hash: "); + for (i=0; i< sizeof(TPM_DIGEST); i++) + vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", ((BYTE*)&sealedNVMHash)[i]); + vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); + + status = TPM_AUTHFAIL; + goto abort_egress; + } + + //Decrypt the key into the output buffer + TPMTRYRETURN( symkey_decrypt(&sealed_NVM, + myDMI->TCSContext, + vtpm_globals->storageKeyHandle, + (const TPM_AUTHDATA*)&vtpm_globals->storage_key_usage_auth, + outbuf) ); + goto egress; + + abort_egress: + vtpmlogerror(VTPM_LOG_VTPM, "Failed to load Key\n."); + + egress: + buffer_free( &sealed_NVM ); + close(fh); + + return status; +} + +TPM_RESULT VTPM_Handle_Save_HashKey(VTPM_DMI_RESOURCE *myDMI, + const buffer_t *inbuf, + buffer_t *outbuf) { + TPM_RESULT status = TPM_SUCCESS; + int fh = -1; + long bytes_written; + buffer_t sealed_key = NULL_BUF; + + TPMTRYRETURN( symkey_encrypt(inbuf, + &vtpm_globals->storageKey, + &sealed_key) ); + + vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Saving %d byte Encryption Key.\n", buffer_len(inbuf)); + + // Write sealed blob off disk from NVMLocation + // TODO: How to properly return from these. Do we care if we return failure + // after writing the file? We can't get the old one back. + // TODO: Backup old file and try and recover that way. + fh = open(myDMI->NVMLocation, O_WRONLY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); + if ( (bytes_written = write(fh, sealed_key.bytes, buffer_len(&sealed_key) ) != (long) buffer_len(&sealed_key))) { + vtpmlogerror(VTPM_LOG_VTPM, "We just overwrote a DMI_NVM and failed to finish. %ld/%ld bytes.\n", bytes_written, (long)buffer_len(&sealed_key)); + status = TPM_IOERROR; + goto abort_egress; + } + Crypto_SHA1Full (sealed_key.bytes, buffer_len(&sealed_key), (BYTE *) &myDMI->NVM_measurement); + + goto egress; + + abort_egress: + vtpmlogerror(VTPM_LOG_VTPM, "Failed to save Key\n."); + + egress: + close(fh); + buffer_free(&sealed_key); return status; } TPM_RESULT VTPM_SaveManagerData(void) { TPM_RESULT status=TPM_SUCCESS; - int fh, dmis=-1; + int fh = -1, dmis=-1; BYTE *flat_boot_key=NULL, *flat_dmis=NULL, *flat_enc=NULL; buffer_t clear_flat_global=NULL_BUF, enc_flat_global=NULL_BUF; @@ -364,6 +542,7 @@ TPM_RESULT VTPM_SaveManagerData(void) { BSG_TPM_DIGEST, &dmi_res->DMI_measurement); } while (hashtable_iterator_advance(dmi_itr)); + free(dmi_itr); } fh = open(STATE_FILE, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE); @@ -389,6 +568,7 @@ TPM_RESULT VTPM_SaveManagerData(void) { free(flat_boot_key); free(flat_enc); + buffer_free(&clear_flat_global); buffer_free(&enc_flat_global); free(flat_dmis); close(fh); @@ -403,9 +583,10 @@ TPM_RESULT VTPM_LoadManagerData(void) { int fh, stat_ret, dmis=0; long fh_size = 0, step_size; BYTE *flat_table=NULL; - buffer_t unsealed_data, enc_table_abuf; - struct pack_buf_t storage_key_pack, boot_key_pack; - UINT32 *dmi_id_key, enc_size; + buffer_t unsealed_data = NULL_BUF; + buffer_t enc_table_abuf; + struct pack_buf_t storage_key_pack = NULL_PACK_BUF, boot_key_pack = NULL_PACK_BUF; + UINT32 enc_size; BYTE vtpm_manager_gen; VTPM_DMI_RESOURCE *dmi_res; @@ -438,9 +619,9 @@ TPM_RESULT VTPM_LoadManagerData(void) { BSG_TPM_SIZE32_DATA, &boot_key_pack, BSG_TYPE_UINT32, &enc_size); - TPMTRYRETURN(buffer_init(&vtpm_globals->bootKeyWrap, 0, 0) ); TPMTRYRETURN(buffer_init_alias_convert(&enc_table_abuf, enc_size, flat_table + step_size) ); - TPMTRYRETURN(buffer_append_raw(&vtpm_globals->bootKeyWrap, boot_key_pack.size, boot_key_pack.data) ); + TPMTRYRETURN(buffer_init(&vtpm_globals->bootKeyWrap, boot_key_pack.size, boot_key_pack.data) ); + //Load Boot Key TPMTRYRETURN( VTSP_LoadKey( vtpm_globals->manager_tcs_handle, @@ -471,8 +652,8 @@ TPM_RESULT VTPM_LoadManagerData(void) { BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth, BSG_TPM_SIZE32_DATA, &storage_key_pack); - TPMTRYRETURN(buffer_init(&vtpm_globals->storageKeyWrap, 0, 0) ); - TPMTRYRETURN(buffer_append_raw(&vtpm_globals->storageKeyWrap, storage_key_pack.size, storage_key_pack.data) ); + TPMTRYRETURN(buffer_init(&vtpm_globals->storageKeyWrap, storage_key_pack.size, storage_key_pack.data) ); + // Per DMI values to be saved while ( step_size < fh_size ){ @@ -501,7 +682,10 @@ TPM_RESULT VTPM_LoadManagerData(void) { abort_egress: vtpmlogerror(VTPM_LOG_VTPM, "Failed to load service data with error = %s\n", tpm_get_error_name(status)); egress: + BSG_Destroy(BSG_TPM_SIZE32_DATA, &boot_key_pack); + BSG_Destroy(BSG_TPM_SIZE32_DATA, &storage_key_pack); + buffer_free(&unsealed_data); free(flat_table); close(fh); diff --git a/tools/vtpm_manager/manager/vtpm_ipc.c b/tools/vtpm_manager/manager/vtpm_ipc.c --- a/tools/vtpm_manager/manager/vtpm_ipc.c +++ b/tools/vtpm_manager/manager/vtpm_ipc.c @@ -36,26 +36,49 @@ // // =================================================================== +#include <sys/types.h> #include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/select.h> #include "vtpm_ipc.h" #include "vtpmpriv.h" #include "log.h" -int vtpm_ipc_init(vtpm_ipc_handle_t *ipc_h, char* name, int flags, BOOL create) { +volatile sig_atomic_t IPC_QUIT_FLAG = 0; + +const static struct timeval TIMEOUT = { + .tv_sec = 1, + .tv_usec = 0 +}; + +int vtpm_ipc_init(vtpm_ipc_handle_t *ipc_h, char* name, int flags, BOOL create, BOOL preopen) { + int rc; + ipc_h->name = name; ipc_h->flags = flags; ipc_h->fh = VTPM_IPC_CLOSED; - if (create) - return(vtpm_ipc_create(ipc_h)); - else - return 0; + if (create) { + if((rc = vtpm_ipc_create(ipc_h) != 0)) { + return rc; + } + } + + if(preopen) { + ipc_h->fh = open(ipc_h->name, ipc_h->flags); + if ( ipc_h->fh == VTPM_IPC_CLOSED ) { + vtpmlogerror(VTPM_LOG_VTPM, "VTPM ERROR: Can't open %s\n", ipc_h->name); + return -1; + } + } + return 0; + } // Create the file that needs opening. Used only for FIFOs // FYI: This may cause problems in other file IO schemes. We'll see. int vtpm_ipc_create(vtpm_ipc_handle_t *ipc_h) { - int fh; struct stat file_info; if ((!ipc_h) || (!ipc_h->name)) @@ -68,8 +91,6 @@ int vtpm_ipc_create(vtpm_ipc_handle_t *ipc_h) { } } - ipc_h->fh = VTPM_IPC_CLOSED; - return 0; } @@ -78,6 +99,8 @@ int vtpm_ipc_create(vtpm_ipc_handle_t *ipc_h) { int vtpm_ipc_read(vtpm_ipc_handle_t *ipc_h, vtpm_ipc_handle_t *alt_ipc_h, BYTE *bytes, UINT32 size){ vtpm_ipc_handle_t *my_ipc_h; int result; + fd_set fds; + struct timeval timeout; if (ipc_h) { my_ipc_h = ipc_h; @@ -94,9 +117,19 @@ int vtpm_ipc_read(vtpm_ipc_handle_t *ipc_h, vtpm_ipc_handle_t *alt_ipc_h, BYTE * return -1; } + FD_ZERO(&fds); + while(!FD_ISSET( my_ipc_h->fh, &fds )) { + timeout = TIMEOUT; + if (IPC_QUIT_FLAG) { + return -1; + } + FD_SET(my_ipc_h->fh, &fds); + select(my_ipc_h->fh + 1, &fds, NULL, NULL, &timeout); + } + result = read(my_ipc_h->fh, bytes, size); if (result < 0) { - my_ipc_h->fh = VTPM_IPC_CLOSED; + my_ipc_h->fh = VTPM_IPC_CLOSED; } return (result); @@ -106,6 +139,8 @@ int vtpm_ipc_read(vtpm_ipc_handle_t *ipc_h, vtpm_ipc_handle_t *alt_ipc_h, BYTE * int vtpm_ipc_write(vtpm_ipc_handle_t *ipc_h, vtpm_ipc_handle_t *alt_ipc_h, BYTE *bytes, UINT32 size) { vtpm_ipc_handle_t *my_ipc_h; int result; + fd_set fds; + struct timeval timeout; if (ipc_h) { my_ipc_h = ipc_h; @@ -122,6 +157,16 @@ int vtpm_ipc_write(vtpm_ipc_handle_t *ipc_h, vtpm_ipc_handle_t *alt_ipc_h, BYTE return -1; } + FD_ZERO(&fds); + while(!FD_ISSET( my_ipc_h->fh, &fds )) { + timeout = TIMEOUT; + if (IPC_QUIT_FLAG) { + return -1; + } + FD_SET(my_ipc_h->fh, &fds); + select(my_ipc_h->fh + 1, NULL, &fds, NULL, &timeout); + } + result = write(my_ipc_h->fh, bytes, size); if (result < 0) { my_ipc_h->fh = VTPM_IPC_CLOSED; diff --git a/tools/vtpm_manager/manager/vtpm_ipc.h b/tools/vtpm_manager/manager/vtpm_ipc.h --- a/tools/vtpm_manager/manager/vtpm_ipc.h +++ b/tools/vtpm_manager/manager/vtpm_ipc.h @@ -39,10 +39,14 @@ #ifndef __VTPM_IO_H__ #define __VTPM_IO_H__ +#include <signal.h> + #include "tcg.h" #define VTPM_IPC_CLOSED -1 +extern volatile sig_atomic_t IPC_QUIT_FLAG; + // Represents an (somewhat) abstracted io handle. typedef struct vtpm_ipc_handle_t { int fh; // IO handle. @@ -53,7 +57,7 @@ typedef struct vtpm_ipc_handle_t { } vtpm_ipc_handle_t; -int vtpm_ipc_init(vtpm_ipc_handle_t *ioh, char* name, int flags, BOOL create); +int vtpm_ipc_init(vtpm_ipc_handle_t *ioh, char* name, int flags, BOOL create, BOOL preopen); // Create the file that needs opening. Used only for FIFOs // FYI: This may cause problems in other file IO schemes. We'll see. diff --git a/tools/vtpm_manager/manager/vtpm_lock.c b/tools/vtpm_manager/manager/vtpm_lock.c --- a/tools/vtpm_manager/manager/vtpm_lock.c +++ b/tools/vtpm_manager/manager/vtpm_lock.c @@ -40,24 +40,24 @@ static pthread_rwlock_t vtpm_lock; -void vtpm_lock_init() { +void vtpm_lock_init(void) { pthread_rwlock_init( &vtpm_lock, NULL); } -void vtpm_lock_destroy(){ +void vtpm_lock_destroy(void){ pthread_rwlock_destroy(&vtpm_lock); } -void vtpm_lock_rdlock(){ +void vtpm_lock_rdlock(void){ pthread_rwlock_rdlock(&vtpm_lock); } -void vtpm_lock_wrlock(){ +void vtpm_lock_wrlock(void){ pthread_rwlock_wrlock(&vtpm_lock); } -void vtpm_lock_unlock(){ +void vtpm_lock_unlock(void){ pthread_rwlock_unlock(&vtpm_lock); } diff --git a/tools/vtpm_manager/manager/vtpm_lock.h b/tools/vtpm_manager/manager/vtpm_lock.h --- a/tools/vtpm_manager/manager/vtpm_lock.h +++ b/tools/vtpm_manager/manager/vtpm_lock.h @@ -38,11 +38,11 @@ #ifndef __VTPM_LOCK_H__ #define __VTPM_LOCK_H__ -void vtpm_lock_init(); -void vtpm_lock_destroy(); +void vtpm_lock_init(void); +void vtpm_lock_destroy(void); -void vtpm_lock_rdlock(); -void vtpm_lock_wrlock(); -void vtpm_lock_unlock(); +void vtpm_lock_rdlock(void); +void vtpm_lock_wrlock(void); +void vtpm_lock_unlock(void); #endif diff --git a/tools/vtpm_manager/manager/vtpm_manager.c b/tools/vtpm_manager/manager/vtpm_manager.c --- a/tools/vtpm_manager/manager/vtpm_manager.c +++ b/tools/vtpm_manager/manager/vtpm_manager.c @@ -40,10 +40,12 @@ #include <stdio.h> #include <unistd.h> #include <string.h> +#include <stdlib.h> #include "vtpm_manager.h" #include "vtpmpriv.h" #include "vtsp.h" +#include "tpmddl.h" #include "bsg.h" #include "hashtable.h" #include "hashtable_itr.h" @@ -54,8 +56,8 @@ VTPM_GLOBALS *vtpm_globals=NULL; // --------------------------- Well Known Auths -------------------------- -const TPM_AUTHDATA SRK_AUTH = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +const TPM_AUTHDATA SRK_AUTH = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; #ifdef WELL_KNOWN_OWNER_AUTH static BYTE FIXED_OWNER_AUTH[20] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -74,7 +76,6 @@ static int equals32(void *k1, void *k2) { } // --------------------------- Functions ------------------------------ - TPM_RESULT VTPM_Create_Manager(){ TPM_RESULT status = TPM_SUCCESS; @@ -104,6 +105,7 @@ TPM_RESULT VTPM_Create_Manager(){ TPMTRYRETURN(VTSP_DisablePubekRead(vtpm_globals->manager_tcs_handle, (const TPM_AUTHDATA*)&vtpm_globals->owner_usage_auth, &vtpm_globals->keyAuth)); + Crypto_RSACryptoInfoFree(&ek_cryptoInfo); } else { vtpmloginfo(VTPM_LOG_VTPM, "Failed to readEK meaning TPM has an owner. Creating Keys off existing SRK.\n"); } @@ -181,7 +183,7 @@ TPM_RESULT VTPM_Create_Manager(){ } /////////////////////////////////////////////////////////////////////////////// -TPM_RESULT VTPM_Init_Manager() { +TPM_RESULT VTPM_Init_Manager(void) { TPM_RESULT status = TPM_FAIL, serviceStatus; BYTE *randomsead; UINT32 randomsize=256; @@ -203,6 +205,11 @@ TPM_RESULT VTPM_Init_Manager() { vtpm_globals->manager_tcs_handle = 0; TPMTRYRETURN(TCS_create()); + + // Blow away all stale handles left in the tpm + if(TDDL_FlushAllResources() != TPM_SUCCESS) { + vtpmlogerror(VTPM_LOG_VTPM, "VTPM_FlushResources failed, continuing anyway..\n"); + } // Create TCS Context for service TPMTRYRETURN( TCS_OpenContext(&vtpm_globals->manager_tcs_handle ) ); @@ -228,7 +235,7 @@ TPM_RESULT VTPM_Init_Manager() { TPMTRYRETURN( VTPM_Create_Manager() ); TPMTRYRETURN( VTPM_SaveManagerData() ); } else if (serviceStatus != TPM_SUCCESS) { - vtpmlogerror(VTPM_LOG_VTPM, "Failed to read existing manager file"); + vtpmlogerror(VTPM_LOG_VTPM, "Failed to read existing manager file\n"); exit(1); } @@ -254,7 +261,7 @@ TPM_RESULT VTPM_Init_Manager() { } /////////////////////////////////////////////////////////////////////////////// -void VTPM_Stop_Manager() { +void VTPM_Stop_Manager(void) { VTPM_DMI_RESOURCE *dmi_res; struct hashtable_itr *dmi_itr; @@ -267,7 +274,7 @@ void VTPM_Stop_Manager() { close_dmi( dmi_res ); // Not really interested in return code } while (hashtable_iterator_advance(dmi_itr)); - free (dmi_itr); + free (dmi_itr); } if ( VTPM_SaveManagerData() != TPM_SUCCESS ) @@ -276,7 +283,21 @@ void VTPM_Stop_Manager() { TCS_CloseContext(vtpm_globals->manager_tcs_handle); TCS_destroy(); - hashtable_destroy(vtpm_globals->dmi_map, 1); + if (hashtable_count(vtpm_globals->dmi_map) > 0) { + dmi_itr = hashtable_iterator(vtpm_globals->dmi_map); + do { + dmi_res = (VTPM_DMI_RESOURCE *) hashtable_iterator_value(dmi_itr); + free_dmi(dmi_res); + } while (hashtable_iterator_advance(dmi_itr)); + free (dmi_itr); + } + hashtable_destroy(vtpm_globals->dmi_map, 0); + + /* Cleanup resources */ + Crypto_RSACryptoInfoFree(&vtpm_globals->bootKey); + Crypto_RSACryptoInfoFree(&vtpm_globals->storageKey); + buffer_free(&vtpm_globals->bootKeyWrap); + buffer_free(&vtpm_globals->storageKeyWrap); free(vtpm_globals); Crypto_Exit(); diff --git a/tools/vtpm_manager/manager/vtpm_manager.h b/tools/vtpm_manager/manager/vtpm_manager.h --- a/tools/vtpm_manager/manager/vtpm_manager.h +++ b/tools/vtpm_manager/manager/vtpm_manager.h @@ -61,6 +61,8 @@ #define VTPM_ORD_TPMCOMMAND (VTPM_ORD_BASE + 3) // DMI issues HW TPM Command #define VTPM_ORD_GET_MIG_KEY (VTPM_ORD_BASE + 4) // Get manager's migration key #define VTPM_ORD_LOAD_MIG_KEY (VTPM_ORD_BASE + 5) // load dest migration key +#define VTPM_ORD_SAVEHASHKEY (VTPM_ORD_BASE + 7) // DMI requests encryption key for persistent storage +#define VTPM_ORD_LOADHASHKEY (VTPM_ORD_BASE + 8) // DMI requests symkey to be regenerated // Priviledged VTPM Commands (From management console) #define VTPM_ORD_OPEN (VTPM_PRIV_BASE + 1) // Creates/reopens DMI @@ -147,4 +149,23 @@ VTPM_TPMCommand *********************************************************************/ +#ifndef VTPM_STUBDOM +#define TPM_EMULATOR_PATH "/usr/bin/vtpmd" +#endif + +#define VTPM_BE_FNAME "/dev/vtpm" +#define VTPM_DUMMY_TX_BE_FNAME "/var/vtpm/fifos/dummy_out.fifo" +#define VTPM_DUMMY_RX_BE_FNAME "/var/vtpm/fifos/dummy_in.fifo" +#ifndef VTPM_STUBDOM +#define VTPM_TX_TPM_FNAME "/var/vtpm/fifos/tpm_cmd_to_%d.fifo" +#define VTPM_RX_TPM_FNAME "/var/vtpm/fifos/tpm_rsp_from_all.fifo" +#define VTPM_TX_VTPM_FNAME "/var/vtpm/fifos/vtpm_rsp_to_%d.fifo" +#define VTPM_RX_VTPM_FNAME "/var/vtpm/fifos/vtpm_cmd_from_all.fifo" +#endif +#define VTPM_TX_HP_FNAME "/var/vtpm/fifos/to_console.fifo" +#define VTPM_RX_HP_FNAME "/var/vtpm/fifos/from_console.fifo" + +#define VTPM_TYPE_PVM_STRING "pvm" +#define VTPM_TYPE_HVM_STRING "hvm" + #endif //_VTPM_MANAGER_H_ diff --git a/tools/vtpm_manager/manager/vtpm_manager_handler.c b/tools/vtpm_manager/manager/vtpm_manager_handler.c --- a/tools/vtpm_manager/manager/vtpm_manager_handler.c +++ b/tools/vtpm_manager/manager/vtpm_manager_handler.c @@ -41,6 +41,8 @@ #include <unistd.h> #include <string.h> #include <errno.h> +#include <signal.h> +#include <stdlib.h> #include "vtpm_manager.h" #include "vtpmpriv.h" @@ -50,26 +52,13 @@ #include "hashtable_itr.h" #include "log.h" #include "buffer.h" +#include "vtpm_manager_handler.h" #define vtpmhandlerloginfo(module,fmt,args...) vtpmloginfo (module, "[%s]: " fmt, thread_name, ##args ); #define vtpmhandlerloginfomore(module,fmt,args...) vtpmloginfomore (module, fmt, ##args ); #define vtpmhandlerlogerror(module,fmt,args...) vtpmlogerror (module, "[%s]: " fmt, thread_name, ##args ); -// ---------------------- Prototypes ------------------- -TPM_RESULT vtpm_manager_handle_vtpm_cmd(VTPM_DMI_RESOURCE *dmi_res, - TPM_COMMAND_CODE ord, - buffer_t *command_buf, - buffer_t *result_buf, - BOOL is_priv, - char *thread_name); - -TPM_RESULT vtpm_manager_handle_tpm_cmd(vtpm_ipc_handle_t *tx_ipc_h, - vtpm_ipc_handle_t *rx_ipc_h, - VTPM_DMI_RESOURCE *dmi_res, - BYTE *cmd_header, - buffer_t *param_buf, - buffer_t *result_buf, - char *thread_name); +volatile sig_atomic_t HANDLER_QUIT_FLAG = 0; TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t *tx_ipc_h, vtpm_ipc_handle_t *rx_ipc_h, @@ -80,12 +69,13 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t *tx_ipc_h, char *thread_name) { TPM_RESULT status = TPM_FAIL; // Should never return UINT32 dmi, in_param_size, cmd_size, out_param_size, out_message_size, reply_size; - BYTE *cmd_header=NULL, *in_param=NULL, *out_message=NULL, *reply; + BYTE *cmd_header=NULL, *in_param=NULL, *out_header=NULL, *reply; buffer_t *command_buf=NULL, *result_buf=NULL; TPM_TAG tag; TPM_COMMAND_CODE ord; VTPM_DMI_RESOURCE *dmi_res; int size_read, size_write, i; + int locked; BOOL add_header=TRUE; // This indicates to prepend a header on result_buf before sending cmd_header = (BYTE *) malloc(VTPM_COMMAND_HEADER_SIZE_SRV); @@ -93,7 +83,11 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t *tx_ipc_h, result_buf = (buffer_t *) malloc(sizeof(buffer_t)); // ------------------------ Main Loop -------------------------------- - while(1) { + while(!HANDLER_QUIT_FLAG) { + locked = 0; + + buffer_init(command_buf, 0, NULL); + buffer_init(result_buf, 0, NULL); vtpmhandlerloginfo(VTPM_LOG_VTPM, "%s waiting for messages.\n", thread_name); @@ -106,7 +100,9 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t *tx_ipc_h, for (i=0; i<size_read; i++) vtpmhandlerloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cmd_header[i]); } else { - vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s can't read from ipc. Errono = %d. Aborting... \n", thread_name, errno); + if (!IPC_QUIT_FLAG) { + vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s can't read from ipc. Errono = %d. Aborting... \n", thread_name, errno); + } goto abort_command; } @@ -155,6 +151,7 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t *tx_ipc_h, vtpmhandlerlogerror(VTPM_LOG_VTPM, "Failed to setup buffers. Aborting...\n"); goto abort_command; } + result_buf->is_owner = TRUE; // -------------- Dispatch Commands to Handlers ----------- if ((tag == VTPM_TAG_REQ) && (ord & VTPM_PRIV_MASK)) { @@ -162,6 +159,7 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t *tx_ipc_h, } else { vtpm_lock_rdlock(); } + locked = 1; if ( !(dmi_res = (VTPM_DMI_RESOURCE *) hashtable_search(vtpm_globals->dmi_map, &dmi)) || (!dmi_res->connected) ) { @@ -174,10 +172,22 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t *tx_ipc_h, if (tag == VTPM_TAG_REQ) { status = vtpm_manager_handle_vtpm_cmd(dmi_res, ord, command_buf, result_buf, is_priv, thread_name); + result_buf->is_owner = TRUE; } else { // This is not a VTPM Command at all. if (fw_tpm) { +#ifdef VTPM_STUBDOM + /* In stubdom mode, we allow the vtpm domains to send raw tpm commands down the pipe + * They can also just embed their tpm commands inside VTPM commands if they wish to*/ + + /* Stick the header back onto the raw command (minus the dmiid) */ + buffer_prepend_raw(command_buf, VTPM_COMMAND_HEADER_SIZE_CLT, cmd_header + sizeof(UINT32)); + status = VTPM_Handle_TPM_Command(dmi_res, command_buf, result_buf); +#else + /* In normal mode, this is used for the guest to forward a raw command to the vtpm process */ status = vtpm_manager_handle_tpm_cmd(fw_tx_ipc_h, fw_rx_ipc_h, dmi_res, cmd_header, command_buf, result_buf, thread_name); +#endif + result_buf->is_owner = TRUE; // This means calling the DMI failed, not that the cmd failed in the DMI // Since the return will be interpretted by a TPM app, all errors are IO_ERRORs to the app @@ -207,36 +217,42 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t *tx_ipc_h, // ------------------- Respond to Sender ------------------ // Errors while handling responses jump here to reply with error messages - // NOTE: Currently there are no recoverable errors in multi-VM mode. If one - // is added to the code, this ifdef should be removed. - // Also note this is NOT referring to errors in commands, but rather - // this is about I/O errors and such. -#ifndef VTPM_MULTI_VM - abort_with_error: -#endif +abort_with_error: if (add_header) { // Prepend VTPM header with destination DM stamped out_param_size = buffer_len(result_buf); out_message_size = VTPM_COMMAND_HEADER_SIZE_CLT + out_param_size; - reply_size = VTPM_COMMAND_HEADER_SIZE_SRV + out_param_size; - out_message = (BYTE *) malloc (reply_size); - reply = out_message; + out_header = (BYTE *) malloc (VTPM_COMMAND_HEADER_SIZE_SRV); - BSG_PackList(out_message, 4, + BSG_PackList(out_header, 4, BSG_TYPE_UINT32, (BYTE *) &dmi, BSG_TPM_TAG, (BYTE *) &tag, BSG_TYPE_UINT32, (BYTE *) &out_message_size, BSG_TPM_RESULT, (BYTE *) &status); - if (buffer_len(result_buf) > 0) - memcpy(out_message + VTPM_COMMAND_HEADER_SIZE_SRV, result_buf->bytes, out_param_size); - //Note: Send message + dmi_id + buffer_prepend_raw(result_buf, VTPM_COMMAND_HEADER_SIZE_SRV, out_header); + free(out_header); } else { - reply = result_buf->bytes; - reply_size = buffer_len(result_buf); +#ifdef VTPM_STUBDOM + //In stubdom mode, we need to always prepend the dmiid so the raw command can be returned to the right domain + out_header = (BYTE*) malloc(sizeof(UINT32)); + BSG_PackList(out_header, 1, + BSG_TYPE_UINT32, (BYTE*) &dmi); + buffer_prepend_raw(result_buf, sizeof(UINT32), out_header); + free(out_header); +#endif } + reply = result_buf->bytes; + reply_size = buffer_len(result_buf); +#ifndef VTPM_STUBDOM size_write = vtpm_ipc_write(tx_ipc_h, (dmi_res ? dmi_res->tx_vtpm_ipc_h : NULL), reply, reply_size ); +#else + if(reply_size >= 4096) { + vtpmhandlerlogerror(VTPM_LOG_VTPM, "MESSAGE TOO BIG!!!"); + } + size_write = vtpm_ipc_write(tx_ipc_h, NULL, reply, reply_size ); +#endif if (size_write > 0) { vtpmhandlerloginfo(VTPM_LOG_VTPM_DEEP, "SENT: 0x"); for (i=0; i < reply_size; i++) @@ -247,7 +263,6 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t *tx_ipc_h, vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s had error writing to ipc. Aborting... \n", thread_name); goto abort_command; } - free(out_message); out_message=NULL; if (size_write < (int)reply_size) { vtpmhandlerlogerror(VTPM_LOG_VTPM, "%s unable to write full command to ipc (%d/%d)\n", thread_name, size_write, reply_size); @@ -264,14 +279,22 @@ TPM_RESULT VTPM_Manager_Handler( vtpm_ipc_handle_t *tx_ipc_h, buffer_free(command_buf); // If we have a write lock, save the manager table - if ((tag == VTPM_TAG_REQ) && (ord & VTPM_PRIV_MASK) && + if (locked && (tag == VTPM_TAG_REQ) && (ord & VTPM_PRIV_MASK) && (VTPM_SaveManagerData() != TPM_SUCCESS) ) { vtpmhandlerlogerror(VTPM_LOG_VTPM, "ERROR: Unable to save manager data.\n"); } - vtpm_lock_unlock(); + if(locked) { + vtpm_lock_unlock(); + } add_header = TRUE; // Reset to the default } // End while(1) + + free(cmd_header); + free(command_buf); + free(result_buf); + + vtpmhandlerloginfo(VTPM_LOG_VTPM, "exiting\n", thread_name); } @@ -313,6 +336,16 @@ TPM_RESULT vtpm_manager_handle_vtpm_cmd(VTPM_DMI_RESOURCE *dmi_res, status = VTPM_Handle_Load_Migration_key(command_buf, result_buf); break; + case VTPM_ORD_SAVEHASHKEY: + status = VTPM_Handle_Save_HashKey(dmi_res, + command_buf, + result_buf); + break; + case VTPM_ORD_LOADHASHKEY: + status = VTPM_Handle_Load_HashKey(dmi_res, + command_buf, + result_buf); + break; default: // Privileged handlers can do maintanance @@ -350,6 +383,7 @@ TPM_RESULT vtpm_manager_handle_vtpm_cmd(VTPM_DMI_RESOURCE *dmi_res, return(status); } +#ifndef VTPM_STUBDOM ///////////////////////////////////////////////////////////////////// TPM_RESULT vtpm_manager_handle_tpm_cmd(vtpm_ipc_handle_t *tx_ipc_h, vtpm_ipc_handle_t *rx_ipc_h, @@ -485,4 +519,5 @@ TPM_RESULT vtpm_manager_handle_tpm_cmd(vtpm_ipc_handle_t *tx_ipc_h, return status; } +#endif diff --git a/tools/vtpm_manager/manager/vtpm_manager_handler.h b/tools/vtpm_manager/manager/vtpm_manager_handler.h --- /dev/null +++ b/tools/vtpm_manager/manager/vtpm_manager_handler.h @@ -0,0 +1,21 @@ +#ifndef VTPM_MANAGER_HANDLER_H +#define VTPM_MANAGER_HANDLER_H +// ---------------------- Prototypes ------------------- +TPM_RESULT vtpm_manager_handle_vtpm_cmd(VTPM_DMI_RESOURCE *dmi_res, + TPM_COMMAND_CODE ord, + buffer_t *command_buf, + buffer_t *result_buf, + BOOL is_priv, + char *thread_name); + +#ifndef VTPM_STUBDOM +TPM_RESULT vtpm_manager_handle_tpm_cmd(vtpm_ipc_handle_t *tx_ipc_h, + vtpm_ipc_handle_t *rx_ipc_h, + VTPM_DMI_RESOURCE *dmi_res, + BYTE *cmd_header, + buffer_t *param_buf, + buffer_t *result_buf, + char *thread_name); +#endif + +#endif diff --git a/tools/vtpm_manager/manager/vtpmd.c b/tools/vtpm_manager/manager/vtpmd.c --- a/tools/vtpm_manager/manager/vtpmd.c +++ b/tools/vtpm_manager/manager/vtpmd.c @@ -45,27 +45,13 @@ #include <signal.h> #include <string.h> #include <pthread.h> +#include <stdlib.h> #include "vtpm_manager.h" #include "vtpmpriv.h" #include "tcg.h" #include "log.h" #include "vtpm_ipc.h" -#define TPM_EMULATOR_PATH "/usr/bin/vtpmd" - -#define VTPM_BE_FNAME "/dev/vtpm" -#define VTPM_DUMMY_TX_BE_FNAME "/var/vtpm/fifos/dummy_out.fifo" -#define VTPM_DUMMY_RX_BE_FNAME "/var/vtpm/fifos/dummy_in.fifo" -#define VTPM_TX_TPM_FNAME "/var/vtpm/fifos/tpm_cmd_to_%d.fifo" -#define VTPM_RX_TPM_FNAME "/var/vtpm/fifos/tpm_rsp_from_all.fifo" -#define VTPM_TX_VTPM_FNAME "/var/vtpm/fifos/vtpm_rsp_to_%d.fifo" -#define VTPM_RX_VTPM_FNAME "/var/vtpm/fifos/vtpm_cmd_from_all.fifo" -#define VTPM_TX_HP_FNAME "/var/vtpm/fifos/to_console.fifo" -#define VTPM_RX_HP_FNAME "/var/vtpm/fifos/from_console.fifo" - -#define VTPM_TYPE_PVM_STRING "pvm" -#define VTPM_TYPE_HVM_STRING "hvm" - struct vtpm_thread_params_s { vtpm_ipc_handle_t *tx_ipc_h; vtpm_ipc_handle_t *rx_ipc_h; @@ -76,180 +62,46 @@ struct vtpm_thread_params_s { char *thread_name; }; +static pthread_t master_thread; +static pthread_t be_thread; +static pthread_t hp_thread; +#ifndef VTPM_STUBDOM +static pthread_t dmi_thread; +#endif + + +#ifndef VTPM_STUBDOM // This is needed to all extra_close_dmi to close this to prevent a // broken pipe when no DMIs are left. -static vtpm_ipc_handle_t *g_rx_tpm_ipc_h; +extern vtpm_ipc_handle_t *g_rx_tpm_ipc_h; +#endif void *vtpm_manager_thread(void *arg_void) { - TPM_RESULT *status = (TPM_RESULT *) malloc(sizeof(TPM_RESULT) ); struct vtpm_thread_params_s *arg = (struct vtpm_thread_params_s *) arg_void; - *status = VTPM_Manager_Handler(arg->tx_ipc_h, arg->rx_ipc_h, + VTPM_Manager_Handler(arg->tx_ipc_h, arg->rx_ipc_h, arg->fw_tpm, arg->fw_tx_ipc_h, arg->fw_rx_ipc_h, arg->is_priv, arg->thread_name); - return (status); + return NULL; } - -void signal_handler(int reason) { - if (pthread_equal(pthread_self(), vtpm_globals->master_pid)) { - vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager shutting down for signal %d.\n", reason); - } else { - // For old Linux Thread machines, signals are delivered to each thread. Deal with them. - vtpmloginfo(VTPM_LOG_VTPM, "Child shutting down\n"); - pthread_exit(NULL); +void signal_handler(int signal) { + if (pthread_equal(pthread_self(), master_thread)) { + vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager shutting down for signal %s(%d). Please wait..\n", strsignal(signal), signal); + HANDLER_QUIT_FLAG = IPC_QUIT_FLAG = 1; } - - VTPM_Stop_Manager(); - exit(-1); } struct sigaction ctl_c_handler; -TPM_RESULT VTPM_New_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res, BYTE vm_type, BYTE startup_mode) { - - TPM_RESULT status = TPM_SUCCESS; - int fh; - char dmi_id_str[11]; // UINT32s are up to 10 digits + NULL - char *tx_vtpm_name, *tx_tpm_name, *vm_type_string; - struct stat file_info; - - if (dmi_res->dmi_id == VTPM_CTL_DM) { - dmi_res->tx_tpm_ipc_h = NULL; - dmi_res->rx_tpm_ipc_h = NULL; - dmi_res->tx_vtpm_ipc_h = NULL; - dmi_res->rx_vtpm_ipc_h = NULL; - } else { - // Create a pair of fifo pipes - dmi_res->rx_tpm_ipc_h = NULL; - dmi_res->rx_vtpm_ipc_h = NULL; - - if ( ((dmi_res->tx_tpm_ipc_h = (vtpm_ipc_handle_t *) malloc (sizeof(vtpm_ipc_handle_t))) == NULL ) || - ((dmi_res->tx_vtpm_ipc_h =(vtpm_ipc_handle_t *) malloc (sizeof(vtpm_ipc_handle_t))) == NULL ) || - ((tx_tpm_name = (char *) malloc(11 + strlen(VTPM_TX_TPM_FNAME))) == NULL ) || - ((tx_vtpm_name =(char *) malloc(11 + strlen(VTPM_TX_VTPM_FNAME))) == NULL) ) { - status =TPM_RESOURCES; - goto abort_egress; - } - - sprintf(tx_tpm_name, VTPM_TX_TPM_FNAME, (uint32_t) dmi_res->dmi_id); - sprintf(tx_vtpm_name, VTPM_TX_VTPM_FNAME, (uint32_t) dmi_res->dmi_id); - - if ( (vtpm_ipc_init(dmi_res->tx_tpm_ipc_h, tx_tpm_name, O_WRONLY | O_NONBLOCK, TRUE) != 0) || - (vtpm_ipc_init(dmi_res->tx_vtpm_ipc_h, tx_vtpm_name, O_WRONLY, TRUE) != 0) ) { //FIXME: O_NONBLOCK? - status = TPM_IOERROR; - goto abort_egress; - } - - // Measure DMI - // FIXME: This will measure DMI. Until then use a fixed DMI_Measurement value - // Also, this mechanism is specific to 1 VM architecture. - /* - fh = open(TPM_EMULATOR_PATH, O_RDONLY); - stat_ret = fstat(fh, &file_stat); - if (stat_ret == 0) - dmi_size = file_stat.st_size; - else { - vtpmlogerror(VTPM_LOG_VTPM, "Could not open vtpmd!!\n"); - status = TPM_IOERROR; - goto abort_egress; - } - dmi_buffer - */ - memset(&dmi_res->DMI_measurement, 0xcc, sizeof(TPM_DIGEST)); - - if (vm_type == VTPM_TYPE_PVM) - vm_type_string = (BYTE *)&VTPM_TYPE_PVM_STRING; - else - vm_type_string = (BYTE *)&VTPM_TYPE_HVM_STRING; - - // Launch DMI - sprintf(dmi_id_str, "%d", (int) dmi_res->dmi_id); -#ifdef MANUAL_DM_LAUNCH - vtpmlogerror(VTPM_LOG_VTPM, "Manually start VTPM with dmi=%s now.\n", dmi_id_str); - dmi_res->dmi_pid = 0; -#else - pid_t pid = fork(); - - if (pid == -1) { - vtpmlogerror(VTPM_LOG_VTPM, "Could not fork to launch vtpm\n"); - status = TPM_RESOURCES; - goto abort_egress; - } else if (pid == 0) { - switch (startup_mode) { - case TPM_ST_CLEAR: - execl (TPM_EMULATOR_PATH, "vtpmd", "clear", vm_type_string, dmi_id_str, NULL); - break; - case TPM_ST_STATE: - execl (TPM_EMULATOR_PATH, "vtpmd", "save", vm_type_string, dmi_id_str, NULL); - break; - case TPM_ST_DEACTIVATED: - execl (TPM_EMULATOR_PATH, "vtpmd", "deactivated", vm_type_string, dmi_id_str, NULL); - break; - default: - status = TPM_BAD_PARAMETER; - goto abort_egress; - } - - // Returning from these at all is an error. - vtpmlogerror(VTPM_LOG_VTPM, "Could not exec to launch vtpm\n"); - } else { - dmi_res->dmi_pid = pid; - vtpmloginfo(VTPM_LOG_VTPM, "Launching DMI on PID = %d\n", pid); - } -#endif // MANUAL_DM_LAUNCH - - } // If DMI = VTPM_CTL_DM - status = TPM_SUCCESS; - -abort_egress: - return (status); -} - -TPM_RESULT VTPM_Close_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res) { - TPM_RESULT status = TPM_SUCCESS; - - if (vtpm_globals->connected_dmis == 0) { - // No more DMI's connected. Close fifo to prevent a broken pipe. - // This is hackish. Need to think of another way. - vtpm_ipc_close(g_rx_tpm_ipc_h); - } - - - if (dmi_res->dmi_id != VTPM_CTL_DM) { - vtpm_ipc_close(dmi_res->tx_tpm_ipc_h); - vtpm_ipc_close(dmi_res->tx_vtpm_ipc_h); - - free(dmi_res->tx_tpm_ipc_h->name); - free(dmi_res->tx_vtpm_ipc_h->name); - -#ifndef MANUAL_DM_LAUNCH - if (dmi_res->dmi_id != VTPM_CTL_DM) { - if (dmi_res->dmi_pid != 0) { - vtpmloginfo(VTPM_LOG_VTPM, "Killing dmi on pid %d.\n", dmi_res->dmi_pid); - if (kill(dmi_res->dmi_pid, SIGKILL) !=0) { - vtpmloginfo(VTPM_LOG_VTPM, "DMI on pid %d is already dead.\n", dmi_res->dmi_pid); - } else if (waitpid(dmi_res->dmi_pid, NULL, 0) != dmi_res->dmi_pid) { - vtpmlogerror(VTPM_LOG_VTPM, "DMI on pid %d failed to stop.\n", dmi_res->dmi_pid); - status = TPM_FAIL; - } - } else { - vtpmlogerror(VTPM_LOG_VTPM, "Could not kill dmi because it's pid was 0.\n"); - status = TPM_FAIL; - } - } -#endif - - } //endif ! dom0 - return status; -} - - int main(int argc, char **argv) { - vtpm_ipc_handle_t *tx_be_ipc_h, *rx_be_ipc_h, rx_tpm_ipc_h, rx_vtpm_ipc_h, tx_hp_ipc_h, rx_hp_ipc_h; - struct vtpm_thread_params_s be_thread_params, dmi_thread_params, hp_thread_params; - pthread_t be_thread, dmi_thread, hp_thread; + vtpm_ipc_handle_t *tx_be_ipc_h, *rx_be_ipc_h, tx_hp_ipc_h, rx_hp_ipc_h; + struct vtpm_thread_params_s be_thread_params, hp_thread_params; +#ifndef VTPM_STUBDOM + vtpm_ipc_handle_t rx_tpm_ipc_h, rx_vtpm_ipc_h; + struct vtpm_thread_params_s dmi_thread_params; +#endif #ifdef DUMMY_BACKEND vtpm_ipc_handle_t tx_dummy_ipc_h, rx_dummy_ipc_h; @@ -258,34 +110,28 @@ int main(int argc, char **argv) { #endif vtpmloginfo(VTPM_LOG_VTPM, "Starting VTPM.\n"); - - // -------------------- Initialize Manager ----------------- - if (VTPM_Init_Manager() != TPM_SUCCESS) { - vtpmlogerror(VTPM_LOG_VTPM, "Closing vtpmd due to error during startup.\n"); - return -1; - } - + // -------------------- Setup Ctrl+C Handlers -------------- ctl_c_handler.sa_handler = signal_handler; sigemptyset(&ctl_c_handler.sa_mask); ctl_c_handler.sa_flags = 0; - if (sigaction(SIGINT, &ctl_c_handler, NULL) == -1) + if ((sigaction(SIGINT, &ctl_c_handler, NULL) == -1) + || (sigaction(SIGQUIT, &ctl_c_handler, NULL) == -1) + || (sigaction(SIGHUP, &ctl_c_handler, NULL) == -1) ) // For easier debugging with gdb + { vtpmlogerror(VTPM_LOG_VTPM, "Could not install SIGINT handler. Ctl+break will not stop manager gently.\n"); + } - // For easier debuggin with gdb - if (sigaction(SIGHUP, &ctl_c_handler, NULL) == -1) - vtpmlogerror(VTPM_LOG_VTPM, "Could not install SIGHUP handler. Ctl+break will not stop manager gently.\n"); - + //Block all signals for child threads sigset_t sig_mask; - sigemptyset(&sig_mask); - sigaddset(&sig_mask, SIGPIPE); - sigprocmask(SIG_BLOCK, &sig_mask, NULL); + sigfillset(&sig_mask); + pthread_sigmask(SIG_SETMASK, &sig_mask, NULL); // ------------------- Set up file ipc structures ---------- #ifdef DUMMY_BACKEND - if ( (vtpm_ipc_init(&tx_dummy_ipc_h, VTPM_DUMMY_TX_BE_FNAME, O_RDWR, TRUE) != 0) || - (vtpm_ipc_init(&rx_dummy_ipc_h, VTPM_DUMMY_RX_BE_FNAME, O_RDWR, TRUE) != 0) ) { + if ( (vtpm_ipc_init(&tx_dummy_ipc_h, VTPM_DUMMY_TX_BE_FNAME, O_RDWR, TRUE, FALSE) != 0) || + (vtpm_ipc_init(&rx_dummy_ipc_h, VTPM_DUMMY_RX_BE_FNAME, O_RDWR, TRUE, FALSE) != 0) ) { vtpmlogerror(VTPM_LOG_VTPM, "Unable to create Dummy BE FIFOs.\n"); exit(-1); @@ -294,21 +140,29 @@ int main(int argc, char **argv) { tx_be_ipc_h = &tx_dummy_ipc_h; rx_be_ipc_h = &rx_dummy_ipc_h; #else - vtpm_ipc_init(&real_be_ipc_h, VTPM_BE_FNAME, O_RDWR, FALSE); + if(vtpm_ipc_init(&real_be_ipc_h, VTPM_BE_FNAME, O_RDWR, FALSE, TRUE) != 0) { + vtpmlogerror(VTPM_LOG_VTPM, "Unable to open backend device " VTPM_BE_FNAME "\n"); + exit(-1); + } tx_be_ipc_h = &real_be_ipc_h; rx_be_ipc_h = &real_be_ipc_h; #endif - if ( (vtpm_ipc_init(&rx_tpm_ipc_h, VTPM_RX_TPM_FNAME, O_RDONLY, TRUE) != 0) || - (vtpm_ipc_init(&rx_vtpm_ipc_h, VTPM_RX_VTPM_FNAME, O_RDWR, TRUE) != 0) || //FIXME: O_RDONLY? - (vtpm_ipc_init(&tx_hp_ipc_h, VTPM_TX_HP_FNAME, O_RDWR, TRUE) != 0) || - (vtpm_ipc_init(&rx_hp_ipc_h, VTPM_RX_HP_FNAME, O_RDWR, TRUE) != 0) ) { + if ( +#ifndef VTPM_STUBDOM + (vtpm_ipc_init(&rx_tpm_ipc_h, VTPM_RX_TPM_FNAME, O_RDONLY, TRUE, FALSE) != 0) || + (vtpm_ipc_init(&rx_vtpm_ipc_h, VTPM_RX_VTPM_FNAME, O_RDWR, TRUE, FALSE) != 0) || //FIXME: O_RDONLY? +#endif + (vtpm_ipc_init(&tx_hp_ipc_h, VTPM_TX_HP_FNAME, O_RDWR, TRUE, TRUE) != 0) || + (vtpm_ipc_init(&rx_hp_ipc_h, VTPM_RX_HP_FNAME, O_RDWR, TRUE, TRUE) != 0) ) { vtpmlogerror(VTPM_LOG_VTPM, "Unable to create initial FIFOs.\n"); exit(-1); } +#ifndef VTPM_STUBDOM g_rx_tpm_ipc_h = &rx_tpm_ipc_h; +#endif // -------------------- Set up thread params ------------- @@ -316,10 +170,15 @@ int main(int argc, char **argv) { be_thread_params.rx_ipc_h = rx_be_ipc_h; be_thread_params.fw_tpm = TRUE; be_thread_params.fw_tx_ipc_h = NULL; +#ifndef VTPM_STUBDOM be_thread_params.fw_rx_ipc_h = &rx_tpm_ipc_h; +#else + be_thread_params.fw_rx_ipc_h = NULL; +#endif be_thread_params.is_priv = FALSE; be_thread_params.thread_name = "Backend Listener"; +#ifndef VTPM_STUBDOM dmi_thread_params.tx_ipc_h = NULL; dmi_thread_params.rx_ipc_h = &rx_vtpm_ipc_h; dmi_thread_params.fw_tpm = FALSE; @@ -327,6 +186,7 @@ int main(int argc, char **argv) { dmi_thread_params.fw_rx_ipc_h = NULL; dmi_thread_params.is_priv = FALSE; dmi_thread_params.thread_name = "VTPM Listener"; +#endif hp_thread_params.tx_ipc_h = &tx_hp_ipc_h; hp_thread_params.rx_ipc_h = &rx_hp_ipc_h; @@ -335,35 +195,51 @@ int main(int argc, char **argv) { hp_thread_params.fw_rx_ipc_h = NULL; hp_thread_params.is_priv = TRUE; hp_thread_params.thread_name = "Hotplug Listener"; + + // -------------------- Initialize Manager ----------------- + if (VTPM_Init_Manager() != TPM_SUCCESS) { + vtpmlogerror(VTPM_LOG_VTPM, "Closing vtpmd due to error during startup.\n"); + return -1; + } + // --------------------- Launch Threads ----------------- vtpm_lock_init(); - vtpm_globals->master_pid = pthread_self(); + master_thread = pthread_self(); + if (pthread_create(&be_thread, NULL, vtpm_manager_thread, &be_thread_params) != 0) { vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch BE Thread.\n"); exit(-1); } +#ifndef VTPM_STUBDOM if (pthread_create(&dmi_thread, NULL, vtpm_manager_thread, &dmi_thread_params) != 0) { vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch DMI Thread.\n"); exit(-1); } - +#endif if (pthread_create(&hp_thread, NULL, vtpm_manager_thread, &hp_thread_params) != 0) { vtpmlogerror(VTPM_LOG_VTPM, "Failed to launch HP Thread.\n"); exit(-1); } + //Turn signals back on for the master thread only + sigemptyset(&sig_mask); + sigaddset(&sig_mask, SIGPIPE); + pthread_sigmask(SIG_SETMASK, &sig_mask, NULL); + //Join the other threads until exit time. pthread_join(be_thread, NULL); +#ifndef VTPM_STUBDOM pthread_join(dmi_thread, NULL); +#endif pthread_join(hp_thread, NULL); - vtpmlogerror(VTPM_LOG_VTPM, "VTPM Manager shut down unexpectedly.\n"); + vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager shutting down...\n"); VTPM_Stop_Manager(); vtpm_lock_destroy(); diff --git a/tools/vtpm_manager/manager/vtpmpriv.h b/tools/vtpm_manager/manager/vtpmpriv.h --- a/tools/vtpm_manager/manager/vtpmpriv.h +++ b/tools/vtpm_manager/manager/vtpmpriv.h @@ -40,6 +40,8 @@ #ifndef __VTPMPRIV_H__ #define __VTPMPRIV_H__ +#include <signal.h> + #include "vtpm_manager.h" #include "tcg.h" #include "tcs.h" @@ -54,16 +56,19 @@ #define DMI_NVM_FILE "/var/vtpm/vtpm_dm_%d.data" #define VTPM_CTL_DM 0 +extern volatile sig_atomic_t HANDLER_QUIT_FLAG; + // ------------------------ Private Structures ----------------------- typedef struct VTPM_DMI_RESOURCE_T { +#ifndef VTPM_STUBDOM // I/O info for Manager to talk to DMI's and controllers vtpm_ipc_handle_t *tx_vtpm_ipc_h; // TX VTPM Results to DMI vtpm_ipc_handle_t *rx_vtpm_ipc_h; // RX VTPM Commands from DMI vtpm_ipc_handle_t *tx_tpm_ipc_h; // TX TPM Commands to DMI vtpm_ipc_handle_t *rx_tpm_ipc_h; // RX TPM Results from DMI + + pid_t dmi_pid; -#ifndef VTPM_MULTI_VM - pid_t dmi_pid; #endif // Non-persistent Information @@ -77,6 +82,9 @@ typedef struct VTPM_DMI_RESOURCE_T { BYTE dmi_type; TPM_DIGEST NVM_measurement; // Equal to the SHA1 of the blob TPM_DIGEST DMI_measurement; // Correct measurement of the owning DMI + + char* uuid; + } VTPM_DMI_RESOURCE; typedef struct tdVTPM_MIGKEY_LIST { @@ -89,10 +97,6 @@ typedef struct tdVTPM_MIGKEY_LIST { typedef struct tdVTPM_GLOBALS { // Non-persistent data -#ifndef VTPM_MULTI_VM - pid_t master_pid; -#endif - int connected_dmis; // To close guest_rx when no dmis are connected struct hashtable *dmi_map; // Table of all DMI's known indexed by persistent instance # @@ -123,8 +127,8 @@ extern VTPM_GLOBALS *vtpm_globals; // Key info and DMI states extern const TPM_AUTHDATA SRK_AUTH; // SRK Well Known Auth Value // ********************** VTPM Functions ************************* -TPM_RESULT VTPM_Init_Manager(); // Start VTPM Service -void VTPM_Stop_Manager(); // Stop VTPM Service +TPM_RESULT VTPM_Init_Manager(void); // Start VTPM Service +void VTPM_Stop_Manager(void); // Stop VTPM Service TPM_RESULT VTPM_Manager_Handler(vtpm_ipc_handle_t *tx_ipc_h, vtpm_ipc_handle_t *rx_ipc_h, BOOL fw_tpm, // Should forward TPM cmds @@ -143,6 +147,11 @@ TPM_RESULT VTPM_Handle_Save_NVM( VTPM_DMI_RESOURCE *myDMI, const buffer_t *inbuf, buffer_t *outbuf); +TPM_RESULT VTPM_Handle_Get_NVM_Size( VTPM_DMI_RESOURCE *myDMI, + const buffer_t *inbuf, + buffer_t *outbuf); + + TPM_RESULT VTPM_Handle_TPM_Command( VTPM_DMI_RESOURCE *dmi, buffer_t *inbuf, buffer_t *outbuf); @@ -173,6 +182,9 @@ TPM_RESULT VTPM_Close_DMI_Extra(VTPM_DMI_RESOURCE *dmi_res); TPM_RESULT close_dmi(VTPM_DMI_RESOURCE *dmi_res); TPM_RESULT init_dmi(UINT32 dmi_id, BYTE type, VTPM_DMI_RESOURCE **dmi_res); +/* Free's dmi_res and all of it's resources */ +void free_dmi(VTPM_DMI_RESOURCE *dmi_res); + TPM_RESULT envelope_encrypt(const buffer_t *inbuf, CRYPTO_INFO *asymkey, buffer_t *sealed_data); @@ -183,4 +195,14 @@ TPM_RESULT envelope_decrypt(const buffer_t *cipher, const TPM_AUTHDATA *key_usage_auth, buffer_t *unsealed_data); +TPM_RESULT symkey_encrypt(const buffer_t *inbuf, + CRYPTO_INFO *asymkey, + buffer_t *sealed_key); + +TPM_RESULT symkey_decrypt(const buffer_t *cipher, + TCS_CONTEXT_HANDLE TCSContext, + TPM_HANDLE keyHandle, + const TPM_AUTHDATA *key_usage_auth, + buffer_t *symkey_clear); + #endif // __VTPMPRIV_H__ diff --git a/tools/vtpm_manager/manager/vtsp.c b/tools/vtpm_manager/manager/vtsp.c --- a/tools/vtpm_manager/manager/vtsp.c +++ b/tools/vtpm_manager/manager/vtsp.c @@ -38,6 +38,7 @@ // ================================================================== #include <string.h> +#include <stdlib.h> #include "tcg.h" #include "tcs.h" #include "bsg.h" @@ -312,7 +313,7 @@ TPM_RESULT VTSP_TakeOwnership( const TCS_CONTEXT_HANDLE hContext, TPM_PROTOCOL_ID proto_id = TPM_PID_OWNER; BYTE *new_srk; - BYTE *paramText; // Digest to make Auth. + BYTE *paramText = NULL; // Digest to make Auth. UINT32 paramTextSize; // vars for srkpubkey parameter @@ -458,7 +459,7 @@ TPM_RESULT VTSP_CreateWrapKey( const TCS_CONTEXT_HANDLE hContext, vtpmloginfo(VTPM_LOG_VTSP, "Creating new key of type %d.\n", usage); // vars for Calculate encUsageAuth - BYTE *paramText; + BYTE *paramText = NULL; UINT32 paramTextSize; // vars for Calculate encUsageAuth @@ -567,8 +568,7 @@ TPM_RESULT VTSP_CreateWrapKey( const TCS_CONTEXT_HANDLE hContext, osapSharedSecret, auth, 0) ); // Unpack/return key structure - TPMTRYRETURN(buffer_init(pubKeyBuf, 0, 0) ); - TPMTRYRETURN(buffer_append_raw(pubKeyBuf, newKeyText.size, newKeyText.data) ); + TPMTRYRETURN(buffer_init(pubKeyBuf, newKeyText.size, newKeyText.data) ); goto egress; @@ -664,6 +664,7 @@ TPM_RESULT VTSP_LoadKey(const TCS_CONTEXT_HANDLE hContext, // Destroy rsaKeyParms BSG_Destroy(BSG_TPM_RSA_KEY_PARMS, &rsaKeyParms); + BSG_Destroy(BSG_TPM_KEY, &newKey); // Set encryption scheme cryptoinfo->encScheme = CRYPTO_ES_RSAESOAEP_SHA1_MGF1; @@ -733,8 +734,7 @@ TPM_RESULT VTSP_Unbind( const TCS_CONTEXT_HANDLE hContext, hContext) ); // Unpack/return key structure - TPMTRYRETURN(buffer_init(clear_data, 0, 0)); - TPMTRYRETURN(buffer_append_raw (clear_data, clear_data_size, clear_data_text) ); + TPMTRYRETURN(buffer_init(clear_data, clear_data_size, clear_data_text) ); goto egress; @@ -793,8 +793,7 @@ TPM_RESULT VTSP_Bind( CRYPTO_INFO *cryptoInfo, vtpmlogerror(VTPM_LOG_VTSP, "Enc buffer just overflowed.\n"); } - buffer_init(outData, 0, NULL); - buffer_append_raw(outData, out_tmp_size, out_tmp); + buffer_init(outData, out_tmp_size, out_tmp); vtpmloginfo(VTPM_LOG_TXDATA, "Bind Generated[%d] = 0x", out_tmp_size); for(i = 0 ; i < out_tmp_size ; i++) { @@ -1005,8 +1004,6 @@ TPM_RESULT VTSP_SaveState( const TCS_CONTEXT_HANDLE hContext) { vtpmloginfo(VTPM_LOG_VTSP, "Calling TPM_SaveState.\n"); - TPM_RESULT status = TPM_SUCCESS; - // Call TCS return ( TCSP_SaveState ( hContext ) ); @@ -1040,3 +1037,4 @@ TPM_RESULT VTSP_RawTransmit(const TCS_CONTEXT_HANDLE hContext, free(resultText); return status; } + diff --git a/tools/vtpm_manager/manager/vtsp.h b/tools/vtpm_manager/manager/vtsp.h --- a/tools/vtpm_manager/manager/vtsp.h +++ b/tools/vtpm_manager/manager/vtsp.h @@ -42,6 +42,7 @@ #include "tcg.h" #include "tcs.h" +#include "crypto.h" #define KEY_BUFFER_SIZE 2048 diff --git a/tools/vtpm_manager/migration/Makefile b/tools/vtpm_manager/migration/Makefile --- a/tools/vtpm_manager/migration/Makefile +++ b/tools/vtpm_manager/migration/Makefile @@ -1,5 +1,11 @@ -XEN_ROOT = $(CURDIR)/../../.. -include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk +XEN_ROOT = $(realpath ../../..) +include ../Rules.mk + +CFLAGS += -I../crypto +CFLAGS += -I../util +CFLAGS += -I../tcs +CFLAGS += -I../manager + VPATH = ../manager @@ -33,10 +39,10 @@ mrproper: clean rm -f *~ $(BIND): $(OBJSD) - $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ + $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LIBS) -o $@ $(BINC): $(OBJSC) - $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ + $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LIBS) -o $@ # libraries LIBS += ../util/libTCGUtils.a diff --git a/tools/vtpm_manager/migration/vtpm_manager_if.c b/tools/vtpm_manager/migration/vtpm_manager_if.c --- a/tools/vtpm_manager/migration/vtpm_manager_if.c +++ b/tools/vtpm_manager/migration/vtpm_manager_if.c @@ -50,15 +50,12 @@ #include "vtpm_migrator.h" #include "vtpm_manager.h" -#define VTPM_TX_HP_FNAME "/var/vtpm/fifos/from_console.fifo" -#define VTPM_RX_HP_FNAME "/var/vtpm/fifos/to_console.fifo" - static vtpm_ipc_handle_t tx_ipc_h, rx_ipc_h; TPM_RESULT vtpm_manager_open(){ - if ( (vtpm_ipc_init(&tx_ipc_h, VTPM_TX_HP_FNAME, O_RDWR, TRUE) != 0) || //FIXME: wronly - (vtpm_ipc_init(&rx_ipc_h, VTPM_RX_HP_FNAME, O_RDWR, TRUE) != 0) ) { //FIXME: rdonly + if ( (vtpm_ipc_init(&tx_ipc_h, VTPM_TX_HP_FNAME, O_RDWR, TRUE, TRUE) != 0) || //FIXME: wronly + (vtpm_ipc_init(&rx_ipc_h, VTPM_RX_HP_FNAME, O_RDWR, TRUE, TRUE) != 0) ) { //FIXME: rdonly vtpmlogerror(VTPM_LOG_VTPM, "Unable to connect to vtpm_manager.\n"); return TPM_IOERROR; } diff --git a/tools/vtpm_manager/tcs/Makefile b/tools/vtpm_manager/tcs/Makefile --- a/tools/vtpm_manager/tcs/Makefile +++ b/tools/vtpm_manager/tcs/Makefile @@ -1,5 +1,10 @@ -XEN_ROOT = $(CURDIR)/../../.. -include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk +XEN_ROOT = $(realpath ../../..) +include ../Rules.mk + +CFLAGS += -I../crypto +CFLAGS += -I../util +CFLAGS += -I../manager + BIN = libTCS.a diff --git a/tools/vtpm_manager/tcs/contextmgr.c b/tools/vtpm_manager/tcs/contextmgr.c --- a/tools/vtpm_manager/tcs/contextmgr.c +++ b/tools/vtpm_manager/tcs/contextmgr.c @@ -195,6 +195,7 @@ BOOL DeleteHandleFromList( TCS_CONTEXT_HANDLE hContext, // in BOOL FreeHandleList( CONTEXT_HANDLE* pContextHandle) { // in HANDLE_LIST* pCurrentHandle; + HANDLE_LIST* pNext; BOOL returncode = TRUE; vtpmloginfo(VTPM_LOG_TCS_DEEP, "Freeing all handles for context\n"); @@ -205,6 +206,7 @@ BOOL FreeHandleList( CONTEXT_HANDLE* pContextHandle) { // in pCurrentHandle = pContextHandle->pHandleList; while (pCurrentHandle != NULL) { + pNext = pCurrentHandle->pNextHandle; switch (pCurrentHandle->type) { case TPM_RT_KEY: returncode = returncode && !TCSP_EvictKey(pContextHandle->handle, pCurrentHandle->handle); @@ -216,7 +218,7 @@ BOOL FreeHandleList( CONTEXT_HANDLE* pContextHandle) { // in returncode = FALSE; } - pCurrentHandle = pCurrentHandle->pNextHandle; + pCurrentHandle = pNext; } diff --git a/tools/vtpm_manager/tcs/tcs.c b/tools/vtpm_manager/tcs/tcs.c --- a/tools/vtpm_manager/tcs/tcs.c +++ b/tools/vtpm_manager/tcs/tcs.c @@ -77,7 +77,7 @@ CONTEXT_HANDLE *LookupContext( TCS_CONTEXT_HANDLE hContext) { // --------------------------------------------------------------------------------- // Initialization/Uninitialization SubComponent API // --------------------------------------------------------------------------------- -TPM_RESULT TCS_create() { +TPM_RESULT TCS_create(void) { TDDL_RESULT hRes = TDDL_E_FAIL; TPM_RESULT result = TPM_FAIL; @@ -101,7 +101,7 @@ TPM_RESULT TCS_create() { } -void TCS_destroy() +void TCS_destroy(void) { TCS_m_nCount--; @@ -113,14 +113,13 @@ void TCS_destroy() TCS_CONTEXT_HANDLE *hContext; // Close all the TCS contexts. TCS should evict keys based on this - if (hashtable_count(context_ht) > 0) { + while (hashtable_count(context_ht) > 0) { context_itr = hashtable_iterator(context_ht); - do { - hContext = (TCS_CONTEXT_HANDLE *) hashtable_iterator_key(context_itr); - if (TCS_CloseContext(*hContext) != TPM_SUCCESS) - vtpmlogerror(VTPM_LOG_TCS, "Failed to close context %d properly.\n", *hContext); + + hContext = (TCS_CONTEXT_HANDLE *) hashtable_iterator_key(context_itr); + if (TCS_CloseContext(*hContext) != TPM_SUCCESS) + vtpmlogerror(VTPM_LOG_TCS, "Failed to close context %d properly.\n", *hContext); - } while (hashtable_iterator_advance(context_itr)); free(context_itr); } hashtable_destroy(context_ht, 1); @@ -534,6 +533,10 @@ TPM_RESULT TCSP_TerminateHandle(TCS_CONTEXT_HANDLE hContext, // in BSG_TYPE_UINT32, &handle); // fill paramSize again as we now have the correct size BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2); + + if (!DeleteHandleFromList(hContext, handle)) { + vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n"); + } // call the TPM driver if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) @@ -545,9 +548,6 @@ TPM_RESULT TCSP_TerminateHandle(TCS_CONTEXT_HANDLE hContext, // in BSG_TYPE_UINT32, ¶mSize, BSG_TPM_COMMAND_CODE, &returnCode); - if (!DeleteHandleFromList(hContext, handle)) - vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n"); - if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) { // Print debug info @@ -882,6 +882,7 @@ TPM_RESULT TCSP_CreateWrapKey(TCS_CONTEXT_HANDLE hContext, // in memcpy(*prgbKey, tempBuf, *pcKeySize); + BSG_Destroy(BSG_TPM_KEY, &wrappedKey); vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize); } else vtpmlogerror(VTPM_LOG_TCS, "TCSP_CreateWrapKey Failed with return code %s\n", tpm_get_error_name(returnCode)); @@ -980,6 +981,10 @@ TPM_RESULT TCSP_EvictKey(TCS_CONTEXT_HANDLE hContext, // in BSG_Pack(BSG_TYPE_UINT32, &InLength, InBuf+2); vtpmloginfo(VTPM_LOG_TCS_DEEP, "Sending paramSize = %d\n", InLength); + + if (!DeleteHandleFromList(hContext, hKey)) { + vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n"); + } // call the TPM driver if ((hRes = TDDL_TransmitData(InBuf, InLength, OutBuf, &OutLength)) == TDDL_SUCCESS) { @@ -989,10 +994,6 @@ TPM_RESULT TCSP_EvictKey(TCS_CONTEXT_HANDLE hContext, // in BSG_TYPE_UINT32, ¶mSize, BSG_TPM_COMMAND_CODE, &returnCode); - if (!DeleteHandleFromList(hContext, hKey)) { - vtpmlogerror(VTPM_LOG_TCS, "KeyHandle not removed from list\n"); - } - if (returnCode == TPM_SUCCESS && tag == TPM_TAG_RSP_COMMAND) { vtpmloginfo(VTPM_LOG_TCS_DEEP, "Received paramSize : %d\n", paramSize); } else { @@ -1019,7 +1020,7 @@ TPM_RESULT TCSP_GetRandom(TCS_CONTEXT_HANDLE hContext, // in TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH; // check input params - if (bytesRequested == NULL || *randomBytes == NULL){ + if (bytesRequested == NULL || randomBytes == NULL){ return TPM_BAD_PARAMETER; } diff --git a/tools/vtpm_manager/tcs/tcs.h b/tools/vtpm_manager/tcs/tcs.h --- a/tools/vtpm_manager/tcs/tcs.h +++ b/tools/vtpm_manager/tcs/tcs.h @@ -50,8 +50,8 @@ // Exposed API // ------------------------------------------------------------------ -TPM_RESULT TCS_create(); -void TCS_destroy(); +TPM_RESULT TCS_create(void); +void TCS_destroy(void); TPM_RESULT TCS_OpenContext( /* OUT */ TCS_CONTEXT_HANDLE* hContext ); diff --git a/tools/vtpm_manager/tcs/tpmddl.c b/tools/vtpm_manager/tcs/tpmddl.c --- /dev/null +++ b/tools/vtpm_manager/tcs/tpmddl.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2010-2012 United States Government, as represented by + * the Secretary of Defense. All rights reserved. + * + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE + * SOFTWARE. + */ + +#include <string.h> +#include "tpmddl.h" +#include "tcs.h" +#include "bsg.h" +#include "log.h" + +#define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) + +TDDL_RESULT TDDL_GetCapability( TDDL_UINT32 cap, + TDDL_UINT32 sub, + TDDL_BYTE* buffer, + TDDL_UINT32* size) +{ + TDDL_RESULT status; + + TPM_TAG tag = TPM_TAG_RQU_COMMAND; + UINT32 paramsize = 22; + UINT32 outsize; + TPM_COMMAND_CODE ord = TPM_ORD_GetCapability; + UINT32 subcapsize = 4; + + BYTE inbuf[TCPA_MAX_BUFFER_LENGTH]; + BYTE outbuf[TCPA_MAX_BUFFER_LENGTH]; + + int offset; + + BSG_PackList(inbuf, 6, + BSG_TPM_TAG, &(tag), + BSG_TYPE_UINT32, &(paramsize), + BSG_TPM_COMMAND_CODE, &(ord), + BSG_TYPE_UINT32, &(cap), + BSG_TYPE_UINT32, &(subcapsize), + BSG_TYPE_UINT32, &(sub) + ); + + //Send the command, get the response + TPMTRYRETURN(TDDL_TransmitData( inbuf, paramsize, outbuf, &outsize)); + + offset = BSG_UnpackList(outbuf, 4, + BSG_TPM_TAG, &(tag), + BSG_TYPE_UINT32, &(paramsize), + BSG_TPM_RESULT, &(status), + BSG_TYPE_UINT32, size + ); + if (status != TPM_SUCCESS || tag != TPM_TAG_RSP_COMMAND) { + return status; + } + if(*size >= TCPA_MAX_BUFFER_LENGTH - offset) { + return TPM_FAIL; + } + memcpy(buffer, outbuf + offset, *size); + +abort_egress: + return status; +} + +TDDL_RESULT TDDL_FlushSpecific(TDDL_UINT32 handle, TDDL_UINT32 res) { + /* FIXME: Add code here to check if TPM_FlushSpecific is not supported (on 1.1 only TPMS?) + * If this is the case then we need to use TPM_EvictKey for key handles + * and TPM_Terminate_Handle/TPM_Reset for auth handles */ + TDDL_RESULT status; + + TPM_TAG tag = TPM_TAG_RQU_COMMAND; + UINT32 paramsize = 18; + TPM_COMMAND_CODE ord = TPM_ORD_FlushSpecific; + + BYTE inbuf[TCPA_MAX_BUFFER_LENGTH]; + BYTE outbuf[TCPA_MAX_BUFFER_LENGTH]; + UINT32 outsize; + + int offset; + + BSG_PackList(inbuf, 5, + BSG_TPM_TAG, &(tag), + BSG_TYPE_UINT32, &(paramsize), + BSG_TPM_COMMAND_CODE, &(ord), + BSG_TPM_HANDLE, &(handle), + BSG_TPM_RESOURCE_TYPE, &(res) + ); + + //Send command + TPMTRYRETURN(TDDL_TransmitData( inbuf, paramsize, outbuf, &outsize )); + + offset = BSG_UnpackList(outbuf, 4, + BSG_TPM_TAG, &(tag), + BSG_TYPE_UINT32, &(paramsize), + BSG_TPM_RESULT, &(status) + ); + +abort_egress: + return status; + +} + +TDDL_RESULT TDDL_FlushAllResources(void) { + TDDL_RESULT status = TPM_SUCCESS; + + TDDL_BYTE buf[TCPA_MAX_BUFFER_LENGTH]; + TDDL_UINT32 bufsiz; + + UINT16 packedsz; + int size; + UINT32 handle; + BYTE* ptr; + + int i, j; + +#define RLISTSZ 6 + TPM_RESOURCE_TYPE reslist[RLISTSZ] = { TPM_RT_KEY, TPM_RT_AUTH, TPM_RT_TRANS, TPM_RT_COUNTER, TPM_RT_DAA_TPM, TPM_RT_CONTEXT }; + + //Iterate through each resource type and flush all handles + for(i = 0; i < RLISTSZ; ++i) { + TPM_RESOURCE_TYPE res = reslist[i]; + // Get list of current key handles + if((status = TDDL_GetCapability( TPM_CAP_HANDLE, res, buf, &bufsiz)) != TPM_SUCCESS) { + //This can happen if the resource type is not supported + //If this happens just silently skip the resource type + if(status == TPM_BAD_MODE) { + status = TPM_SUCCESS; + continue; + //Otherwise we just fail + } else { + TPMTRYRETURN(status); + } + } + +#if 0 + //DEBUG PRINTOUTS + printf("TPM_GetCapability(TPM_CAP_HANDLE, %lu)\n", (unsigned long) res); + for(j = 0; j < bufsiz; ++j) { + printf("%02X ", buf[j]); + } + printf("\n"); +#endif + + ptr = buf; + ptr += BSG_Unpack(BSG_TYPE_UINT16, ptr, &(packedsz)); + size = packedsz; + + //Flush each handle + if(size) { + vtpmloginfo(VTPM_LOG_VTPM, "Flushing %u handle(s) of type %lu\n", size, (unsigned long) res); + for(j = 0; j < size; ++j) { + ptr += BSG_Unpack(BSG_TPM_HANDLE, ptr, &(handle)); + TPMTRYRETURN(TDDL_FlushSpecific(handle, res)); + } + } + + } + + goto egress; +abort_egress: +egress: + return status; +} + diff --git a/tools/vtpm_manager/tcs/tpmddl.h b/tools/vtpm_manager/tcs/tpmddl.h --- a/tools/vtpm_manager/tcs/tpmddl.h +++ b/tools/vtpm_manager/tcs/tpmddl.h @@ -50,13 +50,14 @@ typedef unsigned int TDDL_UINT32; typedef TDDL_UINT32 TDDL_RESULT; typedef unsigned char TDDL_BYTE; -TDDL_RESULT TDDL_Open(); -void TDDL_Close(); +TDDL_RESULT TDDL_Open(void); +TDDL_RESULT TDDL_Open_use_fd(int fd); +void TDDL_Close(void); TDDL_RESULT TDDL_TransmitData( TDDL_BYTE* in, TDDL_UINT32 insize, TDDL_BYTE* out, TDDL_UINT32* outsize); -TDDL_RESULT TDDL_GetStatus(); +TDDL_RESULT TDDL_GetStatus(void); TDDL_RESULT TDDL_GetCapability( TDDL_UINT32 cap, TDDL_UINT32 sub, TDDL_BYTE* buffer, @@ -66,4 +67,10 @@ TDDL_RESULT TDDL_SetCapability( TDDL_UINT32 cap, TDDL_BYTE* buffer, TDDL_UINT32* size); +TDDL_RESULT TDDL_FlushSpecific(TDDL_UINT32 handle, + TDDL_UINT32 res); + +TDDL_RESULT TDDL_FlushAllResources(void); + + #endif // __TPMDDL_H__ diff --git a/tools/vtpm_manager/tcs/transmit.c b/tools/vtpm_manager/tcs/transmit.c --- a/tools/vtpm_manager/tcs/transmit.c +++ b/tools/vtpm_manager/tcs/transmit.c @@ -104,12 +104,13 @@ TDDL_TransmitData( TDDL_BYTE* in, return status; } -TPM_RESULT TDDL_Open() { +TDDL_RESULT TDDL_Open(void) { TDDL_RESULT status = TDDL_SUCCESS; + /* If tpm device is already open just silently return success */ if (g_TDDL_open) - return TPM_FAIL; + return TPM_SUCCESS; #ifdef DUMMY_TPM *g_rx_fdp = open (TPM_RX_FNAME, O_RDWR); @@ -117,7 +118,7 @@ TPM_RESULT TDDL_Open() { g_tx_fd = open (TPM_TX_FNAME, O_RDWR); if (g_tx_fd < 0) { - vtpmlogerror(VTPM_LOG_TXDATA, "TPM open failed"); + vtpmlogerror(VTPM_LOG_TXDATA, "TPM open failed\n"); return TPM_IOERROR; } @@ -126,7 +127,20 @@ TPM_RESULT TDDL_Open() { return status; } -void TDDL_Close() { +TDDL_RESULT TDDL_Open_use_fd(int fd) { + TDDL_RESULT status = TDDL_SUCCESS; + + if(g_TDDL_open) + return TPM_FAIL; + + g_tx_fd = fd; + + g_TDDL_open = 1; + + return status; +} + +void TDDL_Close(void) { if (! g_TDDL_open) return; diff --git a/tools/vtpm_manager/util/Makefile b/tools/vtpm_manager/util/Makefile --- a/tools/vtpm_manager/util/Makefile +++ b/tools/vtpm_manager/util/Makefile @@ -1,5 +1,10 @@ -XEN_ROOT = $(CURDIR)/../../.. -include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk +XEN_ROOT = $(realpath ../../..) +include ../Rules.mk + +CFLAGS += -I../crypto +CFLAGS += -I../tcs +CFLAGS += -I../manager + BIN = libTCGUtils.a diff --git a/tools/vtpm_manager/util/bsg.c b/tools/vtpm_manager/util/bsg.c --- a/tools/vtpm_manager/util/bsg.c +++ b/tools/vtpm_manager/util/bsg.c @@ -41,6 +41,7 @@ #include <string.h> #include <stdarg.h> #include <malloc.h> +#include <stdlib.h> #include "tcg.h" #include "crypto.h" #include "bsg.h" @@ -317,7 +318,7 @@ static const BSG_Format* find_format (BSG_Type t) { // FIXME: should have a function be passed in here which is called if the test // fails. Then the caller can decide what to do: abort, notify, whatever // -BOOL BSG_static_selfcheck () +BOOL BSG_static_selfcheck (void) { int i; diff --git a/tools/vtpm_manager/util/bsg.h b/tools/vtpm_manager/util/bsg.h --- a/tools/vtpm_manager/util/bsg.h +++ b/tools/vtpm_manager/util/bsg.h @@ -161,6 +161,6 @@ TPM_RESULT BSG_DestroyTuple (int numParams, pack_tuple_t params[]); void BSG_PackConst(BSG_UINT32 val, int size, BSG_BYTE* dst); BSG_UINT32 BSG_UnpackConst(const BSG_BYTE* src, int size); -BOOL BSG_static_selfcheck (); +BOOL BSG_static_selfcheck (void); #endif diff --git a/tools/vtpm_manager/util/buffer.c b/tools/vtpm_manager/util/buffer.c --- a/tools/vtpm_manager/util/buffer.c +++ b/tools/vtpm_manager/util/buffer.c @@ -40,6 +40,7 @@ #include "tcg.h" #include "bsg.h" +#include "log.h" #include "buffer.h" static TPM_RESULT buffer_priv_realloc (buffer_t * buf, tpm_size_t newsize); @@ -51,6 +52,7 @@ static TPM_RESULT buffer_priv_realloc (buffer_t * buf, tpm_size_t newsize); TPM_RESULT buffer_init (buffer_t * buf, tpm_size_t initsize, const BYTE* initval) { if (initsize == 0) { memset(buf, 0, sizeof(*buf)); + buf->bytes = NULL; return TPM_SUCCESS; } @@ -62,8 +64,11 @@ TPM_RESULT buffer_init (buffer_t * buf, tpm_size_t initsize, const BYTE* initval buf->size = initsize; buf->alloc_size = initsize; - if (initval) + if (initval) { memcpy (buf->bytes, initval, initsize); + } else { + memset(buf->bytes, 0, initsize); + } buf->is_owner = TRUE; @@ -190,6 +195,29 @@ TPM_RESULT buffer_append_raw (buffer_t * buf, tpm_size_t len, const BYTE* bytes) return status; } +TPM_RESULT buffer_prepend_raw(buffer_t * buf, tpm_size_t len, const BYTE* bytes) { + TPM_RESULT status = TPM_SUCCESS; + + if (buf->alloc_size < buf->size + len) { + TPMTRYRETURN( buffer_priv_realloc (buf, buf->size + len) ); + } + + if(buf->size > 0) { + memmove(buf->bytes + len, buf->bytes, buf->size); + } + memcpy(buf->bytes, bytes, len); + + buf->size += len; + + goto egress; + + abort_egress: + + egress: + + return status; +} + tpm_size_t buffer_len (const buffer_t* buf) { return buf->size; } @@ -199,7 +227,6 @@ TPM_RESULT buffer_free (buffer_t * buf) { free (buf->bytes); buf->bytes = NULL; buf->size = buf->alloc_size = 0; - } return TPM_SUCCESS; @@ -224,3 +251,13 @@ TPM_RESULT buffer_priv_realloc (buffer_t * buf, tpm_size_t newsize) { return TPM_SUCCESS; } + +TPM_RESULT buffer_truncate(buffer_t* buf, tpm_size_t len) +{ + if(len <= buf->size) { + buf->size = len; + return TPM_SUCCESS; + } + + return TPM_FAIL; +} diff --git a/tools/vtpm_manager/util/buffer.h b/tools/vtpm_manager/util/buffer.h --- a/tools/vtpm_manager/util/buffer.h +++ b/tools/vtpm_manager/util/buffer.h @@ -92,4 +92,9 @@ TPM_RESULT buffer_free (buffer_t * buf); TPM_RESULT buffer_append_raw (buffer_t * buf, tpm_size_t len, const BYTE* bytes); +TPM_RESULT buffer_prepend_raw(buffer_t * buf, tpm_size_t len, const BYTE* bytes); + +//Reduce the size of the buffer, if len > buffer size returns an error +TPM_RESULT buffer_truncate(buffer_t* buf, tpm_size_t len); + #endif // _TOOLS_H_ diff --git a/tools/vtpm_manager/util/hashtable.c b/tools/vtpm_manager/util/hashtable.c --- a/tools/vtpm_manager/util/hashtable.c +++ b/tools/vtpm_manager/util/hashtable.c @@ -32,12 +32,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * There are duplicates of this code in: - * - tools/xenstore/hashtable.c - * - tools/blktap2/drivers/hashtable.c - */ - #include "hashtable.h" #include "hashtable_private.h" #include <stdlib.h> diff --git a/tools/vtpm_manager/util/hashtable.h b/tools/vtpm_manager/util/hashtable.h --- a/tools/vtpm_manager/util/hashtable.h +++ b/tools/vtpm_manager/util/hashtable.h @@ -32,11 +32,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * There are duplicates of this code in: - * - tools/xenstore/hashtable.h - * - tools/blktap2/drivers/hashtable.h - */ #ifndef __HASHTABLE_CWC22_H__ #define __HASHTABLE_CWC22_H__ diff --git a/tools/vtpm_manager/util/hashtable_itr.c b/tools/vtpm_manager/util/hashtable_itr.c --- a/tools/vtpm_manager/util/hashtable_itr.c +++ b/tools/vtpm_manager/util/hashtable_itr.c @@ -32,11 +32,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * There are duplicates of this code in: - * - tools/blktap2/drivers/hashtable_itr.c - */ - #include "hashtable.h" #include "hashtable_private.h" #include "hashtable_itr.h" diff --git a/tools/vtpm_manager/util/hashtable_itr.h b/tools/vtpm_manager/util/hashtable_itr.h --- a/tools/vtpm_manager/util/hashtable_itr.h +++ b/tools/vtpm_manager/util/hashtable_itr.h @@ -32,11 +32,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * There are duplicates of this code in: - * - tools/blktap2/drivers/hashtable_itr.h - */ - #ifndef __HASHTABLE_ITR_CWC22__ #define __HASHTABLE_ITR_CWC22__ diff --git a/tools/vtpm_manager/util/hashtable_private.h b/tools/vtpm_manager/util/hashtable_private.h --- a/tools/vtpm_manager/util/hashtable_private.h +++ b/tools/vtpm_manager/util/hashtable_private.h @@ -32,12 +32,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * There are duplicates of this code in: - * - tools/xenstore/hashtable_private.h - * - tools/blktap2/drivers/hashtable_private.h - */ - #ifndef __HASHTABLE_PRIVATE_CWC22_H__ #define __HASHTABLE_PRIVATE_CWC22_H__ diff --git a/tools/vtpm_manager/util/log.c b/tools/vtpm_manager/util/log.c --- a/tools/vtpm_manager/util/log.c +++ b/tools/vtpm_manager/util/log.c @@ -38,6 +38,17 @@ #include "buffer.h" #include "tcg.h" +char *module_names[] = { "", + "CRYPTO", + "BSG", + "TXDATA", + "TCS", + "TCS", + "VTSP", + "VTPM", + "VTPM", + "VTSP" + }; // Helper code for the consts, eg. to produce messages for error codes. typedef struct error_code_entry_t { diff --git a/tools/vtpm_manager/util/log.h b/tools/vtpm_manager/util/log.h --- a/tools/vtpm_manager/util/log.h +++ b/tools/vtpm_manager/util/log.h @@ -36,6 +36,8 @@ #include <stdint.h> // for uint32_t #include <stddef.h> // for pointer NULL +#include <stdio.h> +#include <tcg.h> // =========================== LOGGING ============================== @@ -50,17 +52,7 @@ #define VTPM_LOG_VTPM_DEEP 8 #define VTPM_LOG_VTSP_DEEP 9 -static char *module_names[] = { "", - "CRYPTO", - "BSG", - "TXDATA", - "TCS", - "TCS", - "VTSP", - "VTPM", - "VTPM", - "VTSP" - }; +extern char *module_names[]; // Default to standard logging #ifndef LOGGING_MODULES diff --git a/tools/vtpm_manager/util/tcg.h b/tools/vtpm_manager/util/tcg.h --- a/tools/vtpm_manager/util/tcg.h +++ b/tools/vtpm_manager/util/tcg.h @@ -197,6 +197,7 @@ typedef struct pack_buf_t { UINT32 size; BYTE * data; } pack_buf_t; +#define NULL_PACK_BUF {0,0} typedef struct pack_constbuf_t { UINT32 size; @@ -295,6 +296,35 @@ typedef struct pack_constbuf_t { #define TPM_ORD_LoadKeyContext (181UL + TPM_PROTECTED_ORDINAL) #define TPM_ORD_SaveAuthContext (182UL + TPM_PROTECTED_ORDINAL) #define TPM_ORD_LoadAuthContext (183UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_SaveContext (184UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_LoadContext (185UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_FlushSpecific (186UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_PCR_Reset (200UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_NV_DefineSpace (204UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_NV_WriteValue (205UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_NV_WriteValueAuth (206UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_NV_ReadValue (207UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_NV_ReadValueAuth (208UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_Delegate_UpdateVerification (209UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_Delegate_Manage (210UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_Delegate_CreateKeyDelegation (212UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_Delegate_CreateOwnerDelegation (213UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_Delegate_VerifyDelegation (214UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_Delegate_LoadOwnerDelegation (216UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_Delegate_ReadAuth (217UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_Delegate_ReadTable (219UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_CreateCounter (220UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_IncrementCounter (221UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_ReadCounter (222UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_ReleaseCounter (223UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_ReleaseCounterOwner (224UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_EstablishTransport (230UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_ExecuteTransport (231UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_ReleaseTransportSigned (232UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_GetTicks (241UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_TickStampBlob (242UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_MAX (256UL + TPM_PROTECTED_ORDINAL) + #define TSC_ORD_PhysicalPresence (10UL + TPM_CONNECTION_ORDINAL) @@ -419,8 +449,16 @@ typedef struct pack_constbuf_t { /// TPM_ResourceTypes #define TPM_RT_KEY 0x00000001 #define TPM_RT_AUTH 0x00000002 +#define TPM_RT_HASH 0x00000003 #define TPM_RT_TRANS 0x00000004 #define TPM_RT_CONTEXT 0x00000005 +#define TPM_RT_COUNTER 0x00000006 +#define TPM_RT_DELEGATE 0x00000007 +#define TPM_RT_DAA_TPM 0x00000008 +#define TPM_RT_DAA_V0 0x00000009 +#define TPM_RT_DAA_V1 0x0000000A + + // TPM_PROTOCOL_ID values #define TPM_PID_OIAP 0x0001 @@ -447,6 +485,64 @@ typedef struct pack_constbuf_t { #define TPM_SS_RSASSAPKCS1v15_SHA1 0x0002 #define TPM_SS_RSASSAPKCS1v15_DER 0x0003 +/* + * TPM_CAPABILITY_AREA Values for TPM_GetCapability ([TPM_Part2], Section 21.1) + */ +#define TPM_CAP_ORD 0x00000001 +#define TPM_CAP_ALG 0x00000002 +#define TPM_CAP_PID 0x00000003 +#define TPM_CAP_FLAG 0x00000004 +#define TPM_CAP_PROPERTY 0x00000005 +#define TPM_CAP_VERSION 0x00000006 +#define TPM_CAP_KEY_HANDLE 0x00000007 +#define TPM_CAP_CHECK_LOADED 0x00000008 +#define TPM_CAP_SYM_MODE 0x00000009 +#define TPM_CAP_KEY_STATUS 0x0000000C +#define TPM_CAP_NV_LIST 0x0000000D +#define TPM_CAP_MFR 0x00000010 +#define TPM_CAP_NV_INDEX 0x00000011 +#define TPM_CAP_TRANS_ALG 0x00000012 +#define TPM_CAP_HANDLE 0x00000014 +#define TPM_CAP_TRANS_ES 0x00000015 +#define TPM_CAP_AUTH_ENCRYPT 0x00000017 +#define TPM_CAP_SELECT_SIZE 0x00000018 +#define TPM_CAP_DA_LOGIC 0x00000019 +#define TPM_CAP_VERSION_VAL 0x0000001A + +/* subCap definitions ([TPM_Part2], Section 21.2) */ +#define TPM_CAP_PROP_PCR 0x00000101 +#define TPM_CAP_PROP_DIR 0x00000102 +#define TPM_CAP_PROP_MANUFACTURER 0x00000103 +#define TPM_CAP_PROP_KEYS 0x00000104 +#define TPM_CAP_PROP_MIN_COUNTER 0x00000107 +#define TPM_CAP_FLAG_PERMANENT 0x00000108 +#define TPM_CAP_FLAG_VOLATILE 0x00000109 +#define TPM_CAP_PROP_AUTHSESS 0x0000010A +#define TPM_CAP_PROP_TRANSESS 0x0000010B +#define TPM_CAP_PROP_COUNTERS 0x0000010C +#define TPM_CAP_PROP_MAX_AUTHSESS 0x0000010D +#define TPM_CAP_PROP_MAX_TRANSESS 0x0000010E +#define TPM_CAP_PROP_MAX_COUNTERS 0x0000010F +#define TPM_CAP_PROP_MAX_KEYS 0x00000110 +#define TPM_CAP_PROP_OWNER 0x00000111 +#define TPM_CAP_PROP_CONTEXT 0x00000112 +#define TPM_CAP_PROP_MAX_CONTEXT 0x00000113 +#define TPM_CAP_PROP_FAMILYROWS 0x00000114 +#define TPM_CAP_PROP_TIS_TIMEOUT 0x00000115 +#define TPM_CAP_PROP_STARTUP_EFFECT 0x00000116 +#define TPM_CAP_PROP_DELEGATE_ROW 0x00000117 +#define TPM_CAP_PROP_MAX_DAASESS 0x00000119 +#define TPM_CAP_PROP_DAASESS 0x0000011A +#define TPM_CAP_PROP_CONTEXT_DIST 0x0000011B +#define TPM_CAP_PROP_DAA_INTERRUPT 0x0000011C +#define TPM_CAP_PROP_SESSIONS 0x0000011D +#define TPM_CAP_PROP_MAX_SESSIONS 0x0000011E +#define TPM_CAP_PROP_CMK_RESTRICTION 0x0000011F +#define TPM_CAP_PROP_DURATION 0x00000120 +#define TPM_CAP_PROP_ACTIVE_COUNTER 0x00000122 +#define TPM_CAP_PROP_MAX_NV_AVAILABLE 0x00000123 +#define TPM_CAP_PROP_INPUT_BUFFER 0x00000124 + // TPM_KEY_USAGE values #define TPM_KEY_EK 0x0000 #define TPM_KEY_SIGNING 0x0010 diff --git a/tools/vtpm_manager/vtpmconnd/Makefile b/tools/vtpm_manager/vtpmconnd/Makefile --- /dev/null +++ b/tools/vtpm_manager/vtpmconnd/Makefile @@ -0,0 +1,30 @@ +# Copyright (c) 2010-2012 United States Government, as represented by +# the Secretary of Defense. All rights reserved. +# +# THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT +# ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES +# INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS +# FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY +# DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE +# SOFTWARE. +# + +XEN_ROOT = $(realpath ../../..) +include ../Rules.mk + +BIN=vtpmconnd +OBJS=vtpmconnd.o +CFLAGS=-O2 -Wall + +all: ${BIN} + +${BIN}: ${OBJS} + gcc -o $@ $< + +install: ${BIN} + install -m 0755 ${BIN} $(DESTDIR)$(BINDIR)/$(BIN) + +.PHONY: mrproper +mrproper: clean +clean: + -rm ${BIN} ${OBJS} diff --git a/tools/vtpm_manager/vtpmconnd/vtpmconnd.c b/tools/vtpm_manager/vtpmconnd/vtpmconnd.c --- /dev/null +++ b/tools/vtpm_manager/vtpmconnd/vtpmconnd.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2010-2012 United States Government, as represented by + * the Secretary of Defense. All rights reserved. + * + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE + * SOFTWARE. + */ + +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <getopt.h> +#include <stdint.h> +#include <unistd.h> +#include <fcntl.h> +#include <signal.h> +#include <ctype.h> +#include "../manager/vtpm_manager.h" + +#define VTPM_BE "/dev/vtpm" +#define TPM_DEV "/dev/tpm0" +#define MAX_CMD 4096 +#define DEVNULL "/dev/null" +#define TPM_SUCCESS_RESP "\x00\x00\x00\x00" "\x01\xC1" "\x00\x00\x00\x00" "\x00\x00\x00\x00" +#define TPM_SUCCESS_RESPLEN 14 + +static int quit = 0; + +struct Opts { + const char* vtpmbe; + const char* tpmdev; + int verbosity; + int daemon; +}; + +struct Opts opts = { + .vtpmbe = VTPM_BE, + .tpmdev = TPM_DEV, + .verbosity = 0, + .daemon = 1, +}; + +void usage(char* argv0) { +fprintf(stderr, "Usage:\n \ +\t%s [options] [tpm device node]\n\ +\n\ +-h\t\tdisplay usage message\n\ +-v\t\tturn up verbosity level\n\ +-t <FILE>\tuse FILE for tpm device (default " TPM_DEV ")\n\ +-b <FILE>\tset vtpm backend device to FILE (default: " VTPM_BE ")\n\ +-f\t\trun in the foreground\n", +argv0 +); +} + +void sighandler(int signum) { + quit = 1; +} + +int main_loop(int vbefd, int tpmfd) { + uint8_t buf[MAX_CMD]; + ssize_t size, wrote; + int i; + + while(!quit) { + /* Wait for cmd from vtpm_manager */ + if((size = read(vbefd, buf, MAX_CMD)) < 0) { + if(errno == EFAULT) { + if(opts.verbosity > 0) { + fprintf(stderr, "read() failed with error: %s, non-fatal\n", strerror(errno)); + } + continue; + } + fprintf(stderr,"Error reading from %s, (%s)\n", opts.vtpmbe, strerror(errno)); + return 1; + } + if(opts.verbosity > 0) { + printf("\nvtpm_manager req(%ld):", (long) size); + for(i = 0; i < size; ++i) { + printf(" %02X", buf[i]); + } + printf("\n"); + } + + if(quit) { + break; + } + + /* Forward the cmd to the tpm, exclude the dmi id */ + if((wrote = write(tpmfd, buf + 4, size - 4)) != size - 4) { + fprintf(stderr,"Error writing to %s, (%s)\n", opts.tpmdev, strerror(errno)); + return 1; + } + + if(quit) { + break; + } + + /* Wait for response from tpm */ + if((size = read(tpmfd, buf + 4, MAX_CMD - 4)) < 0) { + fprintf(stderr,"Error reading from %s, (%s)\n", opts.tpmdev, strerror(errno)); + return 1; + } + if(opts.verbosity > 0) { + printf("tpm resp(%ld):", (long) size); + for(i = 0; i < size + 4; ++i) { + printf(" %02X", buf[i]); + } + printf("\n"); + } + + if(quit) { + break; + } + + /* Send response back to vtpm_manager */ + if((wrote = write(vbefd, buf, size + 4)) != size + 4) { + fprintf(stderr, "Error writing to %s, (%s)\n", opts.vtpmbe, strerror(errno)); + return 1; + } + } + + return 0; + +} + +int main(int argc, char** argv) +{ + int rc; + int vbefd, tpmfd; + int c; + int fd = -1; + struct sigaction sig; + pid_t pid; + + /* Do cmdline opts */ + opterr = 0; + + while ((c = getopt (argc, argv, "hfvb:t:")) != -1) + { + switch (c) + { + case 'h': + usage(argv[0]); + return 0; + case 'f': + opts.daemon = 0; + break; + case 'v': + ++opts.verbosity; + break; + case 'b': + opts.vtpmbe = optarg; + break; + case 't': + opts.tpmdev = optarg; + break; + case '?': + if (optopt == 'c') + fprintf (stderr, "Option -%c requires an argument.\n", optopt); + else if (isprint (optopt)) + fprintf (stderr, "Unknown option `-%c'.\n", optopt); + else + fprintf (stderr, + "Unknown option character `\\x%x'.\n", + optopt); + usage(argv[0]); + return 1; + default: + return 1; + } + } + + /* DAEMONIZE */ + if(opts.daemon) { + pid = fork(); + if(pid < 0) { + fprintf(stderr, "failed to daemonize! fork() failed : %s\n", strerror(errno)); + return 1; + } + + if (pid > 0) { + return 0; + } + } + + + /* SIGNAL HANDLING */ + sig.sa_handler = sighandler; + sigemptyset(&sig.sa_mask); + sig.sa_flags = 0; + + sigaction(SIGINT, &sig, NULL); + sigaction(SIGQUIT, &sig, NULL); + sigaction(SIGTERM, &sig, NULL); + + /* FAKE OUT THE HOTPLUG SYSTEM */ + /* Whenever hotplug writes a message let it go to dev null */ + if(remove(VTPM_RX_HP_FNAME) != 0 && errno != ENOENT) { + fprintf(stderr, "Unable to remove %s : %s\n", VTPM_RX_HP_FNAME, strerror(errno)); + return -1; + } + if(symlink(DEVNULL, VTPM_RX_HP_FNAME) != 0) { + fprintf(stderr, "Unable to create symlink %s -> %s : %s\n", VTPM_RX_HP_FNAME, DEVNULL, strerror(errno)); + } + + /* Whenever hotplug tries to read a response, always return success */ + if(remove(VTPM_TX_HP_FNAME) != 0 && errno != ENOENT) { + fprintf(stderr, "Unable to remove %s : %s\n", VTPM_TX_HP_FNAME, strerror(errno)); + return -1; + } + if((fd = open(VTPM_TX_HP_FNAME, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR)) < 0) { + fprintf(stderr, "Unable to open %s for writing : %s\n", VTPM_TX_HP_FNAME, strerror(errno)); + return -1; + } + if(write(fd, TPM_SUCCESS_RESP, TPM_SUCCESS_RESPLEN) != TPM_SUCCESS_RESPLEN) { + fprintf(stderr, "Unable to write to %s : %s\n", VTPM_TX_HP_FNAME, strerror(errno)); + return -1; + } + close(fd); + /* HOTPLUG FAKE OUT DONE */ + + /* Open the backend and tpm device */ + if((vbefd = open(opts.vtpmbe, O_RDWR)) < 0) { + fprintf(stderr, "Unable to open `%s', (%s)\n", opts.vtpmbe, strerror(errno)); + return 1; + } + if((tpmfd = open(opts.tpmdev, O_RDWR)) < 0) { + fprintf(stderr, "Unable to open `%s', (%s)\n", opts.tpmdev, strerror(errno)); + return 1; + } + if(opts.verbosity > 0) { + fprintf(stderr, "Connected to vtpm backend: %s\n", opts.vtpmbe); + fprintf(stderr, "Connected to tpm: %s\n", opts.tpmdev); + } + + rc = main_loop(vbefd, tpmfd); + + close(vbefd); + close(tpmfd); + + remove(VTPM_RX_HP_FNAME); + remove(VTPM_TX_HP_FNAME); + + + return rc; + + +} diff --git a/tools/vtpm_manager/vtpmmgrtalk/Makefile b/tools/vtpm_manager/vtpmmgrtalk/Makefile --- /dev/null +++ b/tools/vtpm_manager/vtpmmgrtalk/Makefile @@ -0,0 +1,35 @@ +# Copyright (c) 2010-2012 United States Government, as represented by +# the Secretary of Defense. All rights reserved. +# +# THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT +# ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES +# INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS +# FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY +# DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE +# SOFTWARE. +# + +XEN_ROOT = $(realpath ../../..) +include ../Rules.mk + +BIN=vtpmmgrtalk +OBJS=vtpmmgrtalk.o +CFLAGS=-Wall -O2 -g +CFLAGS += -I../crypto +CFLAGS += -I../util +CFLAGS += -I../tcs +CFLAGS += -I../manager + + +all: ${BIN} + +${BIN}: ${OBJS} + gcc -o $@ $< + +install: all + install -m 0755 ${BIN} $(DESTDIR)$(BINDIR)/$(BIN) + +.PHONY: mrproper +mrproper: clean +clean: + rm -f ${BIN} ${OBJS} diff --git a/tools/vtpm_manager/vtpmmgrtalk/vtpmmgrtalk.c b/tools/vtpm_manager/vtpmmgrtalk/vtpmmgrtalk.c --- /dev/null +++ b/tools/vtpm_manager/vtpmmgrtalk/vtpmmgrtalk.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2010-2012 United States Government, as represented by + * the Secretary of Defense. All rights reserved. + * + * THIS SOFTWARE AND ITS DOCUMENTATION ARE PROVIDED AS IS AND WITHOUT + * ANY EXPRESS OR IMPLIED WARRANTIES WHATSOEVER. ALL WARRANTIES + * INCLUDING, BUT NOT LIMITED TO, PERFORMANCE, MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT ARE HEREBY + * DISCLAIMED. USERS ASSUME THE ENTIRE RISK AND LIABILITY OF USING THE + * SOFTWARE. + */ +#include <unistd.h> +#include <fcntl.h> +#include <sys/file.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdint.h> + +#include "../manager/vtpm_manager.h" + +int main(int argc, char** argv) { + int wfd, rfd; + uint8_t buf[COMMAND_BUFFER_SIZE]; + ssize_t size; + int i, c; + int rc = 0; + + const char* wfile = VTPM_RX_HP_FNAME; + const char* rfile = VTPM_TX_HP_FNAME; + + /* Open for writing in non-blocking mode and exit if + * the manager is not waiting on the other side */ + if((wfd = open(wfile, O_WRONLY | O_NONBLOCK)) < 0) { + fprintf(stderr, "Error opening %s for writing : %s\n", wfile,strerror(errno)); + return 1; + } + /* Set the pipe back to blocking mode */ + fcntl(wfd, F_SETFL, 0); + + /* Open the read pipe */ + if((rfd = open(rfile, O_RDONLY)) < 0) { + close(wfd); + fprintf(stderr, "Error opening %s for reading : %s\n", rfile,strerror(errno)); + return 1; + } + + /*Grab the ASCII hex input from stdin and convert to binary */ + for(i = 0; i < COMMAND_BUFFER_SIZE; ++i) { + c = scanf("%02hhX", buf + i); + if(c == EOF) { + break; + } else if ( c != 1) { + fprintf(stderr, "Malformed Input! Use ASCII hex!\n"); + rc = 1; + goto quit; + } + } + size = i; + + /* Send request to the manager only if a request was actually given */ + if(size > 0) { + /* Lock the pipes for reading/writing */ + if(flock(wfd, LOCK_EX)) { + fprintf(stderr, "Unable to lock %s : %s\n", wfile, strerror(errno)); + rc = 1; + goto quit; + } + if(flock(rfd, LOCK_EX)) { + fprintf(stderr, "Unable to lock %s : %s\n", wfile, strerror(errno)); + rc = 1; + goto quit; + } + + /* Write the binary data to the pipe */ + if(write(wfd, buf, size) != size) { + fprintf(stderr, "Error writing to %s : %s\n", wfile, strerror(errno)); + rc = 1; + goto quit; + } + + /* Read the response from the manager */ + size = read(rfd, buf, COMMAND_BUFFER_SIZE); + if(size < 0) { + fprintf(stderr, "Error reading %s : %s\n", rfile, strerror(errno)); + rc = 1; + goto quit; + } + /* Output the hex */ + for(i = 0; i < size; ++i) { + printf("%02X", buf[i]); + } + fprintf(stderr,"\n"); + + /* Unlock the pipes */ + flock(rfd, LOCK_UN); + flock(wfd, LOCK_UN); + } + + rc = 0; +quit: + close(rfd); + close(wfd); + return rc; +} Attachment:
smime.p7s _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |