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