From 095b0b77942ad8e1af1c0a45f65f29458890bdc2 Mon Sep 17 00:00:00 2001 From: Matthew Fioravante Date: Fri, 18 Jan 2013 10:55:43 +0000 Subject: add stubdom/vtpmmgr code Add the code base for vtpmmgrdom. Makefile changes next patch. Signed-off-by: Matthew Fioravante Acked-by: Ian Campbell Committed-by: Ian Campbell --- stubdom/vtpmmgr/Makefile | 32 ++ stubdom/vtpmmgr/init.c | 553 ++++++++++++++++++++++ stubdom/vtpmmgr/log.c | 151 ++++++ stubdom/vtpmmgr/log.h | 85 ++++ stubdom/vtpmmgr/marshal.h | 528 +++++++++++++++++++++ stubdom/vtpmmgr/minios.cfg | 14 + stubdom/vtpmmgr/tcg.h | 707 ++++++++++++++++++++++++++++ stubdom/vtpmmgr/tpm.c | 938 +++++++++++++++++++++++++++++++++++++ stubdom/vtpmmgr/tpm.h | 218 +++++++++ stubdom/vtpmmgr/tpmrsa.c | 175 +++++++ stubdom/vtpmmgr/tpmrsa.h | 67 +++ stubdom/vtpmmgr/uuid.h | 50 ++ stubdom/vtpmmgr/vtpm_cmd_handler.c | 152 ++++++ stubdom/vtpmmgr/vtpm_manager.h | 64 +++ stubdom/vtpmmgr/vtpm_storage.c | 794 +++++++++++++++++++++++++++++++ stubdom/vtpmmgr/vtpm_storage.h | 68 +++ stubdom/vtpmmgr/vtpmmgr.c | 93 ++++ stubdom/vtpmmgr/vtpmmgr.h | 77 +++ 18 files changed, 4766 insertions(+) create mode 100644 stubdom/vtpmmgr/Makefile create mode 100644 stubdom/vtpmmgr/init.c create mode 100644 stubdom/vtpmmgr/log.c create mode 100644 stubdom/vtpmmgr/log.h create mode 100644 stubdom/vtpmmgr/marshal.h create mode 100644 stubdom/vtpmmgr/minios.cfg create mode 100644 stubdom/vtpmmgr/tcg.h create mode 100644 stubdom/vtpmmgr/tpm.c create mode 100644 stubdom/vtpmmgr/tpm.h create mode 100644 stubdom/vtpmmgr/tpmrsa.c create mode 100644 stubdom/vtpmmgr/tpmrsa.h create mode 100644 stubdom/vtpmmgr/uuid.h create mode 100644 stubdom/vtpmmgr/vtpm_cmd_handler.c create mode 100644 stubdom/vtpmmgr/vtpm_manager.h create mode 100644 stubdom/vtpmmgr/vtpm_storage.c create mode 100644 stubdom/vtpmmgr/vtpm_storage.h create mode 100644 stubdom/vtpmmgr/vtpmmgr.c create mode 100644 stubdom/vtpmmgr/vtpmmgr.h (limited to 'stubdom') diff --git a/stubdom/vtpmmgr/Makefile b/stubdom/vtpmmgr/Makefile new file mode 100644 index 0000000000..88c83c3c63 --- /dev/null +++ b/stubdom/vtpmmgr/Makefile @@ -0,0 +1,32 @@ +# 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=../.. + +PSSL_DIR=../polarssl-$(XEN_TARGET_ARCH)/library +PSSL_OBJS=aes.o sha1.o entropy.o ctr_drbg.o bignum.o sha4.o havege.o timing.o entropy_poll.o + +TARGET=vtpmmgr.a +OBJS=vtpmmgr.o vtpm_cmd_handler.o vtpm_storage.o init.o tpmrsa.o tpm.o log.o + +CFLAGS+=-Werror -Iutil -Icrypto -Itcs +CFLAGS+=-Wno-declaration-after-statement -Wno-unused-label + +build: $(TARGET) +$(TARGET): $(OBJS) + ar -rcs $@ $^ $(foreach obj,$(PSSL_OBJS),$(PSSL_DIR)/$(obj)) + +clean: + rm -f $(TARGET) $(OBJS) + +distclean: clean + +.PHONY: clean distclean diff --git a/stubdom/vtpmmgr/init.c b/stubdom/vtpmmgr/init.c new file mode 100644 index 0000000000..a158020f1d --- /dev/null +++ b/stubdom/vtpmmgr/init.c @@ -0,0 +1,553 @@ +/* + * Copyright (c) 2010-2012 United States Government, as represented by + * the Secretary of Defense. All rights reserved. + * + * based off of the original tools/vtpm_manager code base which is: + * Copyright (c) 2005, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "vtpmmgr.h" +#include "vtpm_storage.h" +#include "tpm.h" +#include "marshal.h" + +struct Opts { + enum { + TPMDRV_TPM_TIS, + TPMDRV_TPMFRONT, + } tpmdriver; + unsigned long tpmiomem; + unsigned int tpmirq; + unsigned int tpmlocality; + int gen_owner_auth; +}; + +// --------------------------- Well Known Auths -------------------------- +const TPM_AUTHDATA WELLKNOWN_SRK_AUTH = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +const TPM_AUTHDATA WELLKNOWN_OWNER_AUTH = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + +struct vtpm_globals vtpm_globals = { + .tpm_fd = -1, + .storage_key = TPM_KEY_INIT, + .storage_key_handle = 0, + .oiap = { .AuthHandle = 0 } +}; + +static int tpm_entropy_source(void* dummy, unsigned char* data, size_t len, size_t* olen) { + UINT32 sz = len; + TPM_RESULT rc = TPM_GetRandom(&sz, data); + *olen = sz; + return rc == TPM_SUCCESS ? 0 : POLARSSL_ERR_ENTROPY_SOURCE_FAILED; +} + +static TPM_RESULT check_tpm_version(void) { + TPM_RESULT status; + UINT32 rsize; + BYTE* res = NULL; + TPM_CAP_VERSION_INFO vinfo; + + TPMTRYRETURN(TPM_GetCapability( + TPM_CAP_VERSION_VAL, + 0, + NULL, + &rsize, + &res)); + if(rsize < 4) { + vtpmlogerror(VTPM_LOG_VTPM, "Invalid size returned by GetCapability!\n"); + status = TPM_BAD_PARAMETER; + goto abort_egress; + } + + unpack_TPM_CAP_VERSION_INFO(res, &vinfo, UNPACK_ALIAS); + + vtpmloginfo(VTPM_LOG_VTPM, "Hardware TPM:\n"); + vtpmloginfo(VTPM_LOG_VTPM, " version: %hhd %hhd %hhd %hhd\n", + vinfo.version.major, vinfo.version.minor, vinfo.version.revMajor, vinfo.version.revMinor); + vtpmloginfo(VTPM_LOG_VTPM, " specLevel: %hd\n", vinfo.specLevel); + vtpmloginfo(VTPM_LOG_VTPM, " errataRev: %hhd\n", vinfo.errataRev); + vtpmloginfo(VTPM_LOG_VTPM, " vendorID: %c%c%c%c\n", + vinfo.tpmVendorID[0], vinfo.tpmVendorID[1], + vinfo.tpmVendorID[2], vinfo.tpmVendorID[3]); + vtpmloginfo(VTPM_LOG_VTPM, " vendorSpecificSize: %hd\n", vinfo.vendorSpecificSize); + vtpmloginfo(VTPM_LOG_VTPM, " vendorSpecific: "); + for(int i = 0; i < vinfo.vendorSpecificSize; ++i) { + vtpmloginfomore(VTPM_LOG_VTPM, "%02hhx", vinfo.vendorSpecific[i]); + } + vtpmloginfomore(VTPM_LOG_VTPM, "\n"); + +abort_egress: + free(res); + return status; +} + +static TPM_RESULT flush_tpm(void) { + TPM_RESULT status = TPM_SUCCESS; + const TPM_RESOURCE_TYPE reslist[] = { TPM_RT_KEY, TPM_RT_AUTH, TPM_RT_TRANS, TPM_RT_COUNTER, TPM_RT_DAA_TPM, TPM_RT_CONTEXT }; + BYTE* keylist = NULL; + UINT32 keylistSize; + BYTE* ptr; + + //Iterate through each resource type and flush all handles + for(int i = 0; i < sizeof(reslist) / sizeof(TPM_RESOURCE_TYPE); ++i) { + TPM_RESOURCE_TYPE beres = cpu_to_be32(reslist[i]); + UINT16 size; + TPMTRYRETURN(TPM_GetCapability( + TPM_CAP_HANDLE, + sizeof(TPM_RESOURCE_TYPE), + (BYTE*)(&beres), + &keylistSize, + &keylist)); + + ptr = keylist; + ptr = unpack_UINT16(ptr, &size); + + //Flush each handle + if(size) { + vtpmloginfo(VTPM_LOG_VTPM, "Flushing %u handle(s) of type %lu\n", size, (unsigned long) reslist[i]); + for(int j = 0; j < size; ++j) { + TPM_HANDLE h; + ptr = unpack_TPM_HANDLE(ptr, &h); + TPMTRYRETURN(TPM_FlushSpecific(h, reslist[i])); + } + } + + free(keylist); + keylist = NULL; + } + + goto egress; +abort_egress: + free(keylist); +egress: + return status; +} + + +static TPM_RESULT try_take_ownership(void) { + TPM_RESULT status = TPM_SUCCESS; + TPM_PUBKEY pubEK = TPM_PUBKEY_INIT; + + // If we can read PubEK then there is no owner and we should take it. + status = TPM_ReadPubek(&pubEK); + + switch(status) { + case TPM_DISABLED_CMD: + //Cannot read ek? TPM has owner + vtpmloginfo(VTPM_LOG_VTPM, "Failed to readEK meaning TPM has an owner. Creating Keys off existing SRK.\n"); + status = TPM_SUCCESS; + break; + case TPM_NO_ENDORSEMENT: + { + //If theres no ek, we have to create one + TPM_KEY_PARMS keyInfo = { + .algorithmID = TPM_ALG_RSA, + .encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1, + .sigScheme = TPM_SS_NONE, + .parmSize = 12, + .parms.rsa = { + .keyLength = RSA_KEY_SIZE, + .numPrimes = 2, + .exponentSize = 0, + .exponent = NULL, + }, + }; + TPMTRYRETURN(TPM_CreateEndorsementKeyPair(&keyInfo, &pubEK)); + } + //fall through to take ownership + case TPM_SUCCESS: + { + //Construct the Srk + TPM_KEY srk = { + .ver = TPM_STRUCT_VER_1_1, + .keyUsage = TPM_KEY_STORAGE, + .keyFlags = 0x00, + .authDataUsage = TPM_AUTH_ALWAYS, + .algorithmParms = { + .algorithmID = TPM_ALG_RSA, + .encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1, + .sigScheme = TPM_SS_NONE, + .parmSize = 12, + .parms.rsa = { + .keyLength = RSA_KEY_SIZE, + .numPrimes = 2, + .exponentSize = 0, + .exponent = NULL, + }, + }, + .PCRInfoSize = 0, + .pubKey = { + .keyLength = 0, + .key = NULL, + }, + .encDataSize = 0, + }; + + TPMTRYRETURN(TPM_TakeOwnership( + &pubEK, + (const TPM_AUTHDATA*)&vtpm_globals.owner_auth, + (const TPM_AUTHDATA*)&vtpm_globals.srk_auth, + &srk, + NULL, + &vtpm_globals.oiap)); + + TPMTRYRETURN(TPM_DisablePubekRead( + (const TPM_AUTHDATA*)&vtpm_globals.owner_auth, + &vtpm_globals.oiap)); + } + break; + default: + break; + } +abort_egress: + free_TPM_PUBKEY(&pubEK); + return status; +} + +static void init_storage_key(TPM_KEY* key) { + key->ver.major = 1; + key->ver.minor = 1; + key->ver.revMajor = 0; + key->ver.revMinor = 0; + + key->keyUsage = TPM_KEY_BIND; + key->keyFlags = 0; + key->authDataUsage = TPM_AUTH_ALWAYS; + + TPM_KEY_PARMS* p = &key->algorithmParms; + p->algorithmID = TPM_ALG_RSA; + p->encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1; + p->sigScheme = TPM_SS_NONE; + p->parmSize = 12; + + TPM_RSA_KEY_PARMS* r = &p->parms.rsa; + r->keyLength = RSA_KEY_SIZE; + r->numPrimes = 2; + r->exponentSize = 0; + r->exponent = NULL; + + key->PCRInfoSize = 0; + key->encDataSize = 0; + key->encData = NULL; +} + +static int parse_auth_string(char* authstr, BYTE* target, const TPM_AUTHDATA wellknown, int allowrandom) { + int rc; + /* well known owner auth */ + if(!strcmp(authstr, "well-known")) { + memcpy(target, wellknown, sizeof(TPM_AUTHDATA)); + } + /* Create a randomly generated owner auth */ + else if(allowrandom && !strcmp(authstr, "random")) { + return 1; + } + /* owner auth is a raw hash */ + else if(!strncmp(authstr, "hash:", 5)) { + authstr += 5; + if((rc = strlen(authstr)) != 40) { + vtpmlogerror(VTPM_LOG_VTPM, "Supplied owner auth hex string `%s' must be exactly 40 characters (20 bytes) long, length=%d\n", authstr, rc); + return -1; + } + for(int j = 0; j < 20; ++j) { + if(sscanf(authstr, "%hhX", target + j) != 1) { + vtpmlogerror(VTPM_LOG_VTPM, "Supplied owner auth string `%s' is not a valid hex string\n", authstr); + return -1; + } + authstr += 2; + } + } + /* owner auth is a string that will be hashed */ + else if(!strncmp(authstr, "text:", 5)) { + authstr += 5; + sha1((const unsigned char*)authstr, strlen(authstr), target); + } + else { + vtpmlogerror(VTPM_LOG_VTPM, "Invalid auth string %s\n", authstr); + return -1; + } + + return 0; +} + +int parse_cmdline_opts(int argc, char** argv, struct Opts* opts) +{ + int rc; + int i; + + //Set defaults + memcpy(vtpm_globals.owner_auth, WELLKNOWN_OWNER_AUTH, sizeof(TPM_AUTHDATA)); + memcpy(vtpm_globals.srk_auth, WELLKNOWN_SRK_AUTH, sizeof(TPM_AUTHDATA)); + + for(i = 1; i < argc; ++i) { + if(!strncmp(argv[i], "owner_auth:", 10)) { + if((rc = parse_auth_string(argv[i] + 10, vtpm_globals.owner_auth, WELLKNOWN_OWNER_AUTH, 1)) < 0) { + goto err_invalid; + } + if(rc == 1) { + opts->gen_owner_auth = 1; + } + } + else if(!strncmp(argv[i], "srk_auth:", 8)) { + if((rc = parse_auth_string(argv[i] + 8, vtpm_globals.srk_auth, WELLKNOWN_SRK_AUTH, 0)) != 0) { + goto err_invalid; + } + } + else if(!strncmp(argv[i], "tpmdriver=", 10)) { + if(!strcmp(argv[i] + 10, "tpm_tis")) { + opts->tpmdriver = TPMDRV_TPM_TIS; + } else if(!strcmp(argv[i] + 10, "tpmfront")) { + opts->tpmdriver = TPMDRV_TPMFRONT; + } else { + goto err_invalid; + } + } + else if(!strncmp(argv[i], "tpmiomem=",9)) { + if(sscanf(argv[i] + 9, "0x%lX", &opts->tpmiomem) != 1) { + goto err_invalid; + } + } + else if(!strncmp(argv[i], "tpmirq=",7)) { + if(!strcmp(argv[i] + 7, "probe")) { + opts->tpmirq = TPM_PROBE_IRQ; + } else if( sscanf(argv[i] + 7, "%u", &opts->tpmirq) != 1) { + goto err_invalid; + } + } + else if(!strncmp(argv[i], "tpmlocality=",12)) { + if(sscanf(argv[i] + 12, "%u", &opts->tpmlocality) != 1 || opts->tpmlocality > 4) { + goto err_invalid; + } + } + } + + switch(opts->tpmdriver) { + case TPMDRV_TPM_TIS: + vtpmloginfo(VTPM_LOG_VTPM, "Option: Using tpm_tis driver\n"); + break; + case TPMDRV_TPMFRONT: + vtpmloginfo(VTPM_LOG_VTPM, "Option: Using tpmfront driver\n"); + break; + } + + return 0; +err_invalid: + vtpmlogerror(VTPM_LOG_VTPM, "Invalid Option %s\n", argv[i]); + return -1; +} + + + +static TPM_RESULT vtpmmgr_create(void) { + TPM_RESULT status = TPM_SUCCESS; + TPM_AUTH_SESSION osap = TPM_AUTH_SESSION_INIT; + TPM_AUTHDATA sharedsecret; + + // Take ownership if TPM is unowned + TPMTRYRETURN(try_take_ownership()); + + // Generate storage key's auth + memset(&vtpm_globals.storage_key_usage_auth, 0, sizeof(TPM_AUTHDATA)); + + TPMTRYRETURN( TPM_OSAP( + TPM_ET_KEYHANDLE, + TPM_SRK_KEYHANDLE, + (const TPM_AUTHDATA*)&vtpm_globals.srk_auth, + &sharedsecret, + &osap) ); + + init_storage_key(&vtpm_globals.storage_key); + + //initialize the storage key + TPMTRYRETURN( TPM_CreateWrapKey( + TPM_SRK_KEYHANDLE, + (const TPM_AUTHDATA*)&sharedsecret, + (const TPM_AUTHDATA*)&vtpm_globals.storage_key_usage_auth, + (const TPM_AUTHDATA*)&vtpm_globals.storage_key_usage_auth, + &vtpm_globals.storage_key, + &osap) ); + + //Load Storage Key + TPMTRYRETURN( TPM_LoadKey( + TPM_SRK_KEYHANDLE, + &vtpm_globals.storage_key, + &vtpm_globals.storage_key_handle, + (const TPM_AUTHDATA*) &vtpm_globals.srk_auth, + &vtpm_globals.oiap)); + + //Make sure TPM has commited changes + TPMTRYRETURN( TPM_SaveState() ); + + //Create new disk image + TPMTRYRETURN(vtpm_storage_new_header()); + + goto egress; +abort_egress: +egress: + vtpmloginfo(VTPM_LOG_VTPM, "Finished initialized new VTPM manager\n"); + + //End the OSAP session + if(osap.AuthHandle) { + TPM_TerminateHandle(osap.AuthHandle); + } + + return status; +} + +TPM_RESULT vtpmmgr_init(int argc, char** argv) { + TPM_RESULT status = TPM_SUCCESS; + + /* Default commandline options */ + struct Opts opts = { + .tpmdriver = TPMDRV_TPM_TIS, + .tpmiomem = TPM_BASEADDR, + .tpmirq = 0, + .tpmlocality = 0, + .gen_owner_auth = 0, + }; + + if(parse_cmdline_opts(argc, argv, &opts) != 0) { + vtpmlogerror(VTPM_LOG_VTPM, "Command line parsing failed! exiting..\n"); + status = TPM_BAD_PARAMETER; + goto abort_egress; + } + + //Setup storage system + if(vtpm_storage_init() != 0) { + vtpmlogerror(VTPM_LOG_VTPM, "Unable to initialize storage subsystem!\n"); + status = TPM_IOERROR; + goto abort_egress; + } + + //Setup tpmback device + init_tpmback(); + + //Setup tpm access + switch(opts.tpmdriver) { + case TPMDRV_TPM_TIS: + { + struct tpm_chip* tpm; + if((tpm = init_tpm_tis(opts.tpmiomem, TPM_TIS_LOCL_INT_TO_FLAG(opts.tpmlocality), opts.tpmirq)) == NULL) { + vtpmlogerror(VTPM_LOG_VTPM, "Unable to initialize tpmfront device\n"); + status = TPM_IOERROR; + goto abort_egress; + } + vtpm_globals.tpm_fd = tpm_tis_open(tpm); + tpm_tis_request_locality(tpm, opts.tpmlocality); + } + break; + case TPMDRV_TPMFRONT: + { + struct tpmfront_dev* tpmfront_dev; + if((tpmfront_dev = init_tpmfront(NULL)) == NULL) { + vtpmlogerror(VTPM_LOG_VTPM, "Unable to initialize tpmfront device\n"); + status = TPM_IOERROR; + goto abort_egress; + } + vtpm_globals.tpm_fd = tpmfront_open(tpmfront_dev); + } + break; + } + + //Get the version of the tpm + TPMTRYRETURN(check_tpm_version()); + + // Blow away all stale handles left in the tpm + if(flush_tpm() != TPM_SUCCESS) { + vtpmlogerror(VTPM_LOG_VTPM, "VTPM_FlushResources failed, continuing anyway..\n"); + } + + /* Initialize the rng */ + entropy_init(&vtpm_globals.entropy); + entropy_add_source(&vtpm_globals.entropy, tpm_entropy_source, NULL, 0); + entropy_gather(&vtpm_globals.entropy); + ctr_drbg_init(&vtpm_globals.ctr_drbg, entropy_func, &vtpm_globals.entropy, NULL, 0); + ctr_drbg_set_prediction_resistance( &vtpm_globals.ctr_drbg, CTR_DRBG_PR_OFF ); + + // Generate Auth for Owner + if(opts.gen_owner_auth) { + vtpmmgr_rand(vtpm_globals.owner_auth, sizeof(TPM_AUTHDATA)); + } + + // Create OIAP session for service's authorized commands + TPMTRYRETURN( TPM_OIAP(&vtpm_globals.oiap) ); + + /* Load the Manager data, if it fails create a new manager */ + if (vtpm_storage_load_header() != TPM_SUCCESS) { + /* If the OIAP session was closed by an error, create a new one */ + if(vtpm_globals.oiap.AuthHandle == 0) { + TPMTRYRETURN( TPM_OIAP(&vtpm_globals.oiap) ); + } + vtpmloginfo(VTPM_LOG_VTPM, "Failed to read manager file. Assuming first time initialization.\n"); + TPMTRYRETURN( vtpmmgr_create() ); + } + + goto egress; +abort_egress: + vtpmmgr_shutdown(); +egress: + return status; +} + +void vtpmmgr_shutdown(void) +{ + /* Cleanup resources */ + free_TPM_KEY(&vtpm_globals.storage_key); + + /* Cleanup TPM resources */ + TPM_EvictKey(vtpm_globals.storage_key_handle); + TPM_TerminateHandle(vtpm_globals.oiap.AuthHandle); + + /* Close tpmback */ + shutdown_tpmback(); + + /* Close the storage system and blkfront */ + vtpm_storage_shutdown(); + + /* Close tpmfront/tpm_tis */ + close(vtpm_globals.tpm_fd); + + vtpmloginfo(VTPM_LOG_VTPM, "VTPM Manager stopped.\n"); +} diff --git a/stubdom/vtpmmgr/log.c b/stubdom/vtpmmgr/log.c new file mode 100644 index 0000000000..a82c9139c3 --- /dev/null +++ b/stubdom/vtpmmgr/log.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2010-2012 United States Government, as represented by + * the Secretary of Defense. All rights reserved. + * + * based off of the original tools/vtpm_manager code base which is: + * Copyright (c) 2005, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include + +#include "tcg.h" + +char *module_names[] = { "", + "TPM", + "TPM", + "VTPM", + "VTPM", + "TXDATA", + }; +// Helper code for the consts, eg. to produce messages for error codes. + +typedef struct error_code_entry_t { + TPM_RESULT code; + char * code_name; + char * msg; +} error_code_entry_t; + +static const error_code_entry_t error_msgs [] = { + { TPM_SUCCESS, "TPM_SUCCESS", "Successful completion of the operation" }, + { TPM_AUTHFAIL, "TPM_AUTHFAIL", "Authentication failed" }, + { TPM_BADINDEX, "TPM_BADINDEX", "The index to a PCR, DIR or other register is incorrect" }, + { TPM_BAD_PARAMETER, "TPM_BAD_PARAMETER", "One or more parameter is bad" }, + { TPM_AUDITFAILURE, "TPM_AUDITFAILURE", "An operation completed successfully but the auditing of that operation failed." }, + { TPM_CLEAR_DISABLED, "TPM_CLEAR_DISABLED", "The clear disable flag is set and all clear operations now require physical access" }, + { TPM_DEACTIVATED, "TPM_DEACTIVATED", "The TPM is deactivated" }, + { TPM_DISABLED, "TPM_DISABLED", "The TPM is disabled" }, + { TPM_DISABLED_CMD, "TPM_DISABLED_CMD", "The target command has been disabled" }, + { TPM_FAIL, "TPM_FAIL", "The operation failed" }, + { TPM_BAD_ORDINAL, "TPM_BAD_ORDINAL", "The ordinal was unknown or inconsistent" }, + { TPM_INSTALL_DISABLED, "TPM_INSTALL_DISABLED", "The ability to install an owner is disabled" }, + { TPM_INVALID_KEYHANDLE, "TPM_INVALID_KEYHANDLE", "The key handle presented was invalid" }, + { TPM_KEYNOTFOUND, "TPM_KEYNOTFOUND", "The target key was not found" }, + { TPM_INAPPROPRIATE_ENC, "TPM_INAPPROPRIATE_ENC", "Unacceptable encryption scheme" }, + { TPM_MIGRATEFAIL, "TPM_MIGRATEFAIL", "Migration authorization failed" }, + { TPM_INVALID_PCR_INFO, "TPM_INVALID_PCR_INFO", "PCR information could not be interpreted" }, + { TPM_NOSPACE, "TPM_NOSPACE", "No room to load key." }, + { TPM_NOSRK, "TPM_NOSRK", "There is no SRK set" }, + { TPM_NOTSEALED_BLOB, "TPM_NOTSEALED_BLOB", "An encrypted blob is invalid or was not created by this TPM" }, + { TPM_OWNER_SET, "TPM_OWNER_SET", "There is already an Owner" }, + { TPM_RESOURCES, "TPM_RESOURCES", "The TPM has insufficient internal resources to perform the requested action." }, + { TPM_SHORTRANDOM, "TPM_SHORTRANDOM", "A random string was too short" }, + { TPM_SIZE, "TPM_SIZE", "The TPM does not have the space to perform the operation." }, + { TPM_WRONGPCRVAL, "TPM_WRONGPCRVAL", "The named PCR value does not match the current PCR value." }, + { TPM_BAD_PARAM_SIZE, "TPM_BAD_PARAM_SIZE", "The paramSize argument to the command has the incorrect value" }, + { TPM_SHA_THREAD, "TPM_SHA_THREAD", "There is no existing SHA-1 thread." }, + { TPM_SHA_ERROR, "TPM_SHA_ERROR", "The calculation is unable to proceed because the existing SHA-1 thread has already encountered an error." }, + { TPM_FAILEDSELFTEST, "TPM_FAILEDSELFTEST", "Self-test has failed and the TPM has shutdown." }, + { TPM_AUTH2FAIL, "TPM_AUTH2FAIL", "The authorization for the second key in a 2 key function failed authorization" }, + { TPM_BADTAG, "TPM_BADTAG", "The tag value sent to for a command is invalid" }, + { TPM_IOERROR, "TPM_IOERROR", "An IO error occurred transmitting information to the TPM" }, + { TPM_ENCRYPT_ERROR, "TPM_ENCRYPT_ERROR", "The encryption process had a problem." }, + { TPM_DECRYPT_ERROR, "TPM_DECRYPT_ERROR", "The decryption process did not complete." }, + { TPM_INVALID_AUTHHANDLE, "TPM_INVALID_AUTHHANDLE", "An invalid handle was used." }, + { TPM_NO_ENDORSEMENT, "TPM_NO_ENDORSEMENT", "The TPM does not a EK installed" }, + { TPM_INVALID_KEYUSAGE, "TPM_INVALID_KEYUSAGE", "The usage of a key is not allowed" }, + { TPM_WRONG_ENTITYTYPE, "TPM_WRONG_ENTITYTYPE", "The submitted entity type is not allowed" }, + { TPM_INVALID_POSTINIT, "TPM_INVALID_POSTINIT", "The command was received in the wrong sequence relative to TPM_Init and a subsequent TPM_Startup" }, + { TPM_INAPPROPRIATE_SIG, "TPM_INAPPROPRIATE_SIG", "Signed data cannot include additional DER information" }, + { TPM_BAD_KEY_PROPERTY, "TPM_BAD_KEY_PROPERTY", "The key properties in TPM_KEY_PARMs are not supported by this TPM" }, + + { TPM_BAD_MIGRATION, "TPM_BAD_MIGRATION", "The migration properties of this key are incorrect." }, + { TPM_BAD_SCHEME, "TPM_BAD_SCHEME", "The signature or encryption scheme for this key is incorrect or not permitted in this situation." }, + { TPM_BAD_DATASIZE, "TPM_BAD_DATASIZE", "The size of the data (or blob) parameter is bad or inconsistent with the referenced key" }, + { TPM_BAD_MODE, "TPM_BAD_MODE", "A mode parameter is bad, such as capArea or subCapArea for TPM_GetCapability, phsicalPresence parameter for TPM_PhysicalPresence, or migrationType for TPM_CreateMigrationBlob." }, + { TPM_BAD_PRESENCE, "TPM_BAD_PRESENCE", "Either the physicalPresence or physicalPresenceLock bits have the wrong value" }, + { TPM_BAD_VERSION, "TPM_BAD_VERSION", "The TPM cannot perform this version of the capability" }, + { TPM_NO_WRAP_TRANSPORT, "TPM_NO_WRAP_TRANSPORT", "The TPM does not allow for wrapped transport sessions" }, + { TPM_AUDITFAIL_UNSUCCESSFUL, "TPM_AUDITFAIL_UNSUCCESSFUL", "TPM audit construction failed and the underlying command was returning a failure code also" }, + { TPM_AUDITFAIL_SUCCESSFUL, "TPM_AUDITFAIL_SUCCESSFUL", "TPM audit construction failed and the underlying command was returning success" }, + { TPM_NOTRESETABLE, "TPM_NOTRESETABLE", "Attempt to reset a PCR register that does not have the resettable attribute" }, + { TPM_NOTLOCAL, "TPM_NOTLOCAL", "Attempt to reset a PCR register that requires locality and locality modifier not part of command transport" }, + { TPM_BAD_TYPE, "TPM_BAD_TYPE", "Make identity blob not properly typed" }, + { TPM_INVALID_RESOURCE, "TPM_INVALID_RESOURCE", "When saving context identified resource type does not match actual resource" }, + { TPM_NOTFIPS, "TPM_NOTFIPS", "The TPM is attempting to execute a command only available when in FIPS mode" }, + { TPM_INVALID_FAMILY, "TPM_INVALID_FAMILY", "The command is attempting to use an invalid family ID" }, + { TPM_NO_NV_PERMISSION, "TPM_NO_NV_PERMISSION", "The permission to manipulate the NV storage is not available" }, + { TPM_REQUIRES_SIGN, "TPM_REQUIRES_SIGN", "The operation requires a signed command" }, + { TPM_KEY_NOTSUPPORTED, "TPM_KEY_NOTSUPPORTED", "Wrong operation to load an NV key" }, + { TPM_AUTH_CONFLICT, "TPM_AUTH_CONFLICT", "NV_LoadKey blob requires both owner and blob authorization" }, + { TPM_AREA_LOCKED, "TPM_AREA_LOCKED", "The NV area is locked and not writtable" }, + { TPM_BAD_LOCALITY, "TPM_BAD_LOCALITY", "The locality is incorrect for the attempted operation" }, + { TPM_READ_ONLY, "TPM_READ_ONLY", "The NV area is read only and can't be written to" }, + { TPM_PER_NOWRITE, "TPM_PER_NOWRITE", "There is no protection on the write to the NV area" }, + { TPM_FAMILYCOUNT, "TPM_FAMILYCOUNT", "The family count value does not match" }, + { TPM_WRITE_LOCKED, "TPM_WRITE_LOCKED", "The NV area has already been written to" }, + { TPM_BAD_ATTRIBUTES, "TPM_BAD_ATTRIBUTES", "The NV area attributes conflict" }, + { TPM_INVALID_STRUCTURE, "TPM_INVALID_STRUCTURE", "The structure tag and version are invalid or inconsistent" }, + { TPM_KEY_OWNER_CONTROL, "TPM_KEY_OWNER_CONTROL", "The key is under control of the TPM Owner and can only be evicted by the TPM Owner." }, + { TPM_BAD_COUNTER, "TPM_BAD_COUNTER", "The counter handle is incorrect" }, + { TPM_NOT_FULLWRITE, "TPM_NOT_FULLWRITE", "The write is not a complete write of the area" }, + { TPM_CONTEXT_GAP, "TPM_CONTEXT_GAP", "The gap between saved context counts is too large" }, + { TPM_MAXNVWRITES, "TPM_MAXNVWRITES", "The maximum number of NV writes without an owner has been exceeded" }, + { TPM_NOOPERATOR, "TPM_NOOPERATOR", "No operator authorization value is set" }, + { TPM_RESOURCEMISSING, "TPM_RESOURCEMISSING", "The resource pointed to by context is not loaded" }, + { TPM_DELEGATE_LOCK, "TPM_DELEGATE_LOCK", "The delegate administration is locked" }, + { TPM_DELEGATE_FAMILY, "TPM_DELEGATE_FAMILY", "Attempt to manage a family other then the delegated family" }, + { TPM_DELEGATE_ADMIN, "TPM_DELEGATE_ADMIN", "Delegation table management not enabled" }, + { TPM_TRANSPORT_EXCLUSIVE, "TPM_TRANSPORT_EXCLUSIVE", "There was a command executed outside of an exclusive transport session" }, +}; + + +// helper function for the error codes: +const char* tpm_get_error_name (TPM_RESULT code) { + // just do a linear scan for now + unsigned i; + for (i = 0; i < sizeof(error_msgs)/sizeof(error_msgs[0]); i++) + if (code == error_msgs[i].code) + return error_msgs[i].code_name; + + return("Unknown Error Code"); +} diff --git a/stubdom/vtpmmgr/log.h b/stubdom/vtpmmgr/log.h new file mode 100644 index 0000000000..5c7abf5c83 --- /dev/null +++ b/stubdom/vtpmmgr/log.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2010-2012 United States Government, as represented by + * the Secretary of Defense. All rights reserved. + * + * based off of the original tools/vtpm_manager code base which is: + * Copyright (c) 2005, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __VTPM_LOG_H__ +#define __VTPM_LOG_H__ + +#include // for uint32_t +#include // for pointer NULL +#include +#include "tcg.h" + +// =========================== LOGGING ============================== + +// the logging module numbers +#define VTPM_LOG_TPM 1 +#define VTPM_LOG_TPM_DEEP 2 +#define VTPM_LOG_VTPM 3 +#define VTPM_LOG_VTPM_DEEP 4 +#define VTPM_LOG_TXDATA 5 + +extern char *module_names[]; + +// Default to standard logging +#ifndef LOGGING_MODULES +#define LOGGING_MODULES (BITMASK(VTPM_LOG_VTPM)|BITMASK(VTPM_LOG_TPM)) +#endif + +// bit-access macros +#define BITMASK(idx) ( 1U << (idx) ) +#define GETBIT(num,idx) ( ((num) & BITMASK(idx)) >> idx ) +#define SETBIT(num,idx) (num) |= BITMASK(idx) +#define CLEARBIT(num,idx) (num) &= ( ~ BITMASK(idx) ) + +#define vtpmloginfo(module, fmt, args...) \ + if (GETBIT (LOGGING_MODULES, module) == 1) { \ + fprintf (stdout, "INFO[%s]: " fmt, module_names[module], ##args); \ + } + +#define vtpmloginfomore(module, fmt, args...) \ + if (GETBIT (LOGGING_MODULES, module) == 1) { \ + fprintf (stdout, fmt,##args); \ + } + +#define vtpmlogerror(module, fmt, args...) \ + fprintf (stderr, "ERROR[%s]: " fmt, module_names[module], ##args); + +//typedef UINT32 tpm_size_t; + +// helper function for the error codes: +const char* tpm_get_error_name (TPM_RESULT code); + +#endif // _VTPM_LOG_H_ diff --git a/stubdom/vtpmmgr/marshal.h b/stubdom/vtpmmgr/marshal.h new file mode 100644 index 0000000000..77d32f01fb --- /dev/null +++ b/stubdom/vtpmmgr/marshal.h @@ -0,0 +1,528 @@ +/* + * Copyright (c) 2010-2012 United States Government, as represented by + * the Secretary of Defense. All rights reserved. + * + * based off of the original tools/vtpm_manager code base which is: + * Copyright (c) 2005, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef MARSHAL_H +#define MARSHAL_H + +#include +#include +#include +#include "tcg.h" + +typedef enum UnpackPtr { + UNPACK_ALIAS, + UNPACK_ALLOC +} UnpackPtr; + +inline BYTE* pack_BYTE(BYTE* ptr, BYTE t) { + ptr[0] = t; + return ++ptr; +} + +inline BYTE* unpack_BYTE(BYTE* ptr, BYTE* t) { + t[0] = ptr[0]; + return ++ptr; +} + +#define pack_BOOL(p, t) pack_BYTE(p, t) +#define unpack_BOOL(p, t) unpack_BYTE(p, t) + +inline BYTE* pack_UINT16(BYTE* ptr, UINT16 t) { + BYTE* b = (BYTE*)&t; +#if __BYTE_ORDER == __LITTLE_ENDIAN + ptr[0] = b[1]; + ptr[1] = b[0]; +#elif __BYTE_ORDER == __BIG_ENDIAN + ptr[0] = b[0]; + ptr[1] = b[1]; +#endif + return ptr + sizeof(UINT16); +} + +inline BYTE* unpack_UINT16(BYTE* ptr, UINT16* t) { + BYTE* b = (BYTE*)t; +#if __BYTE_ORDER == __LITTLE_ENDIAN + b[0] = ptr[1]; + b[1] = ptr[0]; +#elif __BYTE_ORDER == __BIG_ENDIAN + b[0] = ptr[0]; + b[1] = ptr[1]; +#endif + return ptr + sizeof(UINT16); +} + +inline BYTE* pack_UINT32(BYTE* ptr, UINT32 t) { + BYTE* b = (BYTE*)&t; +#if __BYTE_ORDER == __LITTLE_ENDIAN + ptr[3] = b[0]; + ptr[2] = b[1]; + ptr[1] = b[2]; + ptr[0] = b[3]; +#elif __BYTE_ORDER == __BIG_ENDIAN + ptr[0] = b[0]; + ptr[1] = b[1]; + ptr[2] = b[2]; + ptr[3] = b[3]; +#endif + return ptr + sizeof(UINT32); +} + +inline BYTE* unpack_UINT32(BYTE* ptr, UINT32* t) { + BYTE* b = (BYTE*)t; +#if __BYTE_ORDER == __LITTLE_ENDIAN + b[0] = ptr[3]; + b[1] = ptr[2]; + b[2] = ptr[1]; + b[3] = ptr[0]; +#elif __BYTE_ORDER == __BIG_ENDIAN + b[0] = ptr[0]; + b[1] = ptr[1]; + b[2] = ptr[2]; + b[3] = ptr[3]; +#endif + return ptr + sizeof(UINT32); +} + +#define pack_TPM_RESULT(p, t) pack_UINT32(p, t) +#define pack_TPM_PCRINDEX(p, t) pack_UINT32(p, t) +#define pack_TPM_DIRINDEX(p, t) pack_UINT32(p, t) +#define pack_TPM_HANDLE(p, t) pack_UINT32(p, t) +#define pack_TPM_AUTHHANDLE(p, t) pack_TPM_HANDLE(p, t) +#define pack_TCPA_HASHHANDLE(p, t) pack_TPM_HANDLE(p, t) +#define pack_TCPA_HMACHANDLE(p, t) pack_TPM_HANDLE(p, t) +#define pack_TCPA_ENCHANDLE(p, t) pack_TPM_HANDLE(p, t) +#define pack_TPM_KEY_HANDLE(p, t) pack_TPM_HANDLE(p, t) +#define pack_TCPA_ENTITYHANDLE(p, t) pack_TPM_HANDLE(p, t) +#define pack_TPM_RESOURCE_TYPE(p, t) pack_UINT32(p, t) +#define pack_TPM_COMMAND_CODE(p, t) pack_UINT32(p, t) +#define pack_TPM_PROTOCOL_ID(p, t) pack_UINT16(p, t) +#define pack_TPM_AUTH_DATA_USAGE(p, t) pack_BYTE(p, t) +#define pack_TPM_ENTITY_TYPE(p, t) pack_UINT16(p, t) +#define pack_TPM_ALGORITHM_ID(p, t) pack_UINT32(p, t) +#define pack_TPM_KEY_USAGE(p, t) pack_UINT16(p, t) +#define pack_TPM_STARTUP_TYPE(p, t) pack_UINT16(p, t) +#define pack_TPM_CAPABILITY_AREA(p, t) pack_UINT32(p, t) +#define pack_TPM_ENC_SCHEME(p, t) pack_UINT16(p, t) +#define pack_TPM_SIG_SCHEME(p, t) pack_UINT16(p, t) +#define pack_TPM_MIGRATE_SCHEME(p, t) pack_UINT16(p, t) +#define pack_TPM_PHYSICAL_PRESENCE(p, t) pack_UINT16(p, t) +#define pack_TPM_KEY_FLAGS(p, t) pack_UINT32(p, t) + +#define unpack_TPM_RESULT(p, t) unpack_UINT32(p, t) +#define unpack_TPM_PCRINDEX(p, t) unpack_UINT32(p, t) +#define unpack_TPM_DIRINDEX(p, t) unpack_UINT32(p, t) +#define unpack_TPM_HANDLE(p, t) unpack_UINT32(p, t) +#define unpack_TPM_AUTHHANDLE(p, t) unpack_TPM_HANDLE(p, t) +#define unpack_TCPA_HASHHANDLE(p, t) unpack_TPM_HANDLE(p, t) +#define unpack_TCPA_HMACHANDLE(p, t) unpack_TPM_HANDLE(p, t) +#define unpack_TCPA_ENCHANDLE(p, t) unpack_TPM_HANDLE(p, t) +#define unpack_TPM_KEY_HANDLE(p, t) unpack_TPM_HANDLE(p, t) +#define unpack_TCPA_ENTITYHANDLE(p, t) unpack_TPM_HANDLE(p, t) +#define unpack_TPM_RESOURCE_TYPE(p, t) unpack_UINT32(p, t) +#define unpack_TPM_COMMAND_CODE(p, t) unpack_UINT32(p, t) +#define unpack_TPM_PROTOCOL_ID(p, t) unpack_UINT16(p, t) +#define unpack_TPM_AUTH_DATA_USAGE(p, t) unpack_BYTE(p, t) +#define unpack_TPM_ENTITY_TYPE(p, t) unpack_UINT16(p, t) +#define unpack_TPM_ALGORITHM_ID(p, t) unpack_UINT32(p, t) +#define unpack_TPM_KEY_USAGE(p, t) unpack_UINT16(p, t) +#define unpack_TPM_STARTUP_TYPE(p, t) unpack_UINT16(p, t) +#define unpack_TPM_CAPABILITY_AREA(p, t) unpack_UINT32(p, t) +#define unpack_TPM_ENC_SCHEME(p, t) unpack_UINT16(p, t) +#define unpack_TPM_SIG_SCHEME(p, t) unpack_UINT16(p, t) +#define unpack_TPM_MIGRATE_SCHEME(p, t) unpack_UINT16(p, t) +#define unpack_TPM_PHYSICAL_PRESENCE(p, t) unpack_UINT16(p, t) +#define unpack_TPM_KEY_FLAGS(p, t) unpack_UINT32(p, t) + +#define pack_TPM_AUTH_HANDLE(p, t) pack_UINT32(p, t); +#define pack_TCS_CONTEXT_HANDLE(p, t) pack_UINT32(p, t); +#define pack_TCS_KEY_HANDLE(p, t) pack_UINT32(p, t); + +#define unpack_TPM_AUTH_HANDLE(p, t) unpack_UINT32(p, t); +#define unpack_TCS_CONTEXT_HANDLE(p, t) unpack_UINT32(p, t); +#define unpack_TCS_KEY_HANDLE(p, t) unpack_UINT32(p, t); + +inline BYTE* pack_BUFFER(BYTE* ptr, const BYTE* buf, UINT32 size) { + memcpy(ptr, buf, size); + return ptr + size; +} + +inline BYTE* unpack_BUFFER(BYTE* ptr, BYTE* buf, UINT32 size) { + memcpy(buf, ptr, size); + return ptr + size; +} + +inline BYTE* unpack_ALIAS(BYTE* ptr, BYTE** buf, UINT32 size) { + *buf = ptr; + return ptr + size; +} + +inline BYTE* unpack_ALLOC(BYTE* ptr, BYTE** buf, UINT32 size) { + if(size) { + *buf = malloc(size); + memcpy(*buf, ptr, size); + } else { + *buf = NULL; + } + return ptr + size; +} + +inline BYTE* unpack_PTR(BYTE* ptr, BYTE** buf, UINT32 size, UnpackPtr alloc) { + if(alloc == UNPACK_ALLOC) { + return unpack_ALLOC(ptr, buf, size); + } else { + return unpack_ALIAS(ptr, buf, size); + } +} + +inline BYTE* pack_TPM_AUTHDATA(BYTE* ptr, const TPM_AUTHDATA* d) { + return pack_BUFFER(ptr, *d, TPM_DIGEST_SIZE); +} + +inline BYTE* unpack_TPM_AUTHDATA(BYTE* ptr, TPM_AUTHDATA* d) { + return unpack_BUFFER(ptr, *d, TPM_DIGEST_SIZE); +} + +#define pack_TPM_SECRET(p, t) pack_TPM_AUTHDATA(p, t) +#define pack_TPM_ENCAUTH(p, t) pack_TPM_AUTHDATA(p, t) +#define pack_TPM_PAYLOAD_TYPE(p, t) pack_BYTE(p, t) +#define pack_TPM_TAG(p, t) pack_UINT16(p, t) +#define pack_TPM_STRUCTURE_TAG(p, t) pack_UINT16(p, t) + +#define unpack_TPM_SECRET(p, t) unpack_TPM_AUTHDATA(p, t) +#define unpack_TPM_ENCAUTH(p, t) unpack_TPM_AUTHDATA(p, t) +#define unpack_TPM_PAYLOAD_TYPE(p, t) unpack_BYTE(p, t) +#define unpack_TPM_TAG(p, t) unpack_UINT16(p, t) +#define unpack_TPM_STRUCTURE_TAG(p, t) unpack_UINT16(p, t) + +inline BYTE* pack_TPM_VERSION(BYTE* ptr, const TPM_VERSION* t) { + ptr[0] = t->major; + ptr[1] = t->minor; + ptr[2] = t->revMajor; + ptr[3] = t->revMinor; + return ptr + 4; +} + +inline BYTE* unpack_TPM_VERSION(BYTE* ptr, TPM_VERSION* t) { + t->major = ptr[0]; + t->minor = ptr[1]; + t->revMajor = ptr[2]; + t->revMinor = ptr[3]; + return ptr + 4; +} + +inline BYTE* pack_TPM_CAP_VERSION_INFO(BYTE* ptr, const TPM_CAP_VERSION_INFO* v) { + ptr = pack_TPM_STRUCTURE_TAG(ptr, v->tag); + ptr = pack_TPM_VERSION(ptr, &v->version); + ptr = pack_UINT16(ptr, v->specLevel); + ptr = pack_BYTE(ptr, v->errataRev); + ptr = pack_BUFFER(ptr, v->tpmVendorID, sizeof(v->tpmVendorID)); + ptr = pack_UINT16(ptr, v->vendorSpecificSize); + ptr = pack_BUFFER(ptr, v->vendorSpecific, v->vendorSpecificSize); + return ptr; +} + +inline BYTE* unpack_TPM_CAP_VERSION_INFO(BYTE* ptr, TPM_CAP_VERSION_INFO* v, UnpackPtr alloc) { + ptr = unpack_TPM_STRUCTURE_TAG(ptr, &v->tag); + ptr = unpack_TPM_VERSION(ptr, &v->version); + ptr = unpack_UINT16(ptr, &v->specLevel); + ptr = unpack_BYTE(ptr, &v->errataRev); + ptr = unpack_BUFFER(ptr, v->tpmVendorID, sizeof(v->tpmVendorID)); + ptr = unpack_UINT16(ptr, &v->vendorSpecificSize); + ptr = unpack_PTR(ptr, &v->vendorSpecific, v->vendorSpecificSize, alloc); + return ptr; +} + +inline BYTE* pack_TPM_DIGEST(BYTE* ptr, const TPM_DIGEST* d) { + return pack_BUFFER(ptr, d->digest, TPM_DIGEST_SIZE); +} + +inline BYTE* unpack_TPM_DIGEST(BYTE* ptr, TPM_DIGEST* d) { + return unpack_BUFFER(ptr, d->digest, TPM_DIGEST_SIZE); +} + +#define pack_TPM_PCRVALUE(ptr, d) pack_TPM_DIGEST(ptr, d); +#define unpack_TPM_PCRVALUE(ptr, d) unpack_TPM_DIGEST(ptr, d); + +#define pack_TPM_COMPOSITE_HASH(ptr, d) pack_TPM_DIGEST(ptr, d); +#define unpack_TPM_COMPOSITE_HASH(ptr, d) unpack_TPM_DIGEST(ptr, d); + +#define pack_TPM_DIRVALUE(ptr, d) pack_TPM_DIGEST(ptr, d); +#define unpack_TPM_DIRVALUE(ptr, d) unpack_TPM_DIGEST(ptr, d); + +#define pack_TPM_HMAC(ptr, d) pack_TPM_DIGEST(ptr, d); +#define unpack_TPM_HMAC(ptr, d) unpack_TPM_DIGEST(ptr, d); + +#define pack_TPM_CHOSENID_HASH(ptr, d) pack_TPM_DIGEST(ptr, d); +#define unpack_TPM_CHOSENID_HASH(ptr, d) unpack_TPM_DIGEST(ptr, d); + +inline BYTE* pack_TPM_NONCE(BYTE* ptr, const TPM_NONCE* n) { + return pack_BUFFER(ptr, n->nonce, TPM_DIGEST_SIZE); +} + +inline BYTE* unpack_TPM_NONCE(BYTE* ptr, TPM_NONCE* n) { + return unpack_BUFFER(ptr, n->nonce, TPM_DIGEST_SIZE); +} + +inline BYTE* pack_TPM_SYMMETRIC_KEY_PARMS(BYTE* ptr, const TPM_SYMMETRIC_KEY_PARMS* k) { + ptr = pack_UINT32(ptr, k->keyLength); + ptr = pack_UINT32(ptr, k->blockSize); + ptr = pack_UINT32(ptr, k->ivSize); + return pack_BUFFER(ptr, k->IV, k->ivSize); +} + +inline BYTE* unpack_TPM_SYMMETRIC_KEY_PARMS(BYTE* ptr, TPM_SYMMETRIC_KEY_PARMS* k, UnpackPtr alloc) { + ptr = unpack_UINT32(ptr, &k->keyLength); + ptr = unpack_UINT32(ptr, &k->blockSize); + ptr = unpack_UINT32(ptr, &k->ivSize); + return unpack_PTR(ptr, &k->IV, k->ivSize, alloc); +} + +inline BYTE* pack_TPM_RSA_KEY_PARMS(BYTE* ptr, const TPM_RSA_KEY_PARMS* k) { + ptr = pack_UINT32(ptr, k->keyLength); + ptr = pack_UINT32(ptr, k->numPrimes); + ptr = pack_UINT32(ptr, k->exponentSize); + return pack_BUFFER(ptr, k->exponent, k->exponentSize); +} + +inline BYTE* unpack_TPM_RSA_KEY_PARMS(BYTE* ptr, TPM_RSA_KEY_PARMS* k, UnpackPtr alloc) { + ptr = unpack_UINT32(ptr, &k->keyLength); + ptr = unpack_UINT32(ptr, &k->numPrimes); + ptr = unpack_UINT32(ptr, &k->exponentSize); + return unpack_PTR(ptr, &k->exponent, k->exponentSize, alloc); +} + +inline BYTE* pack_TPM_KEY_PARMS(BYTE* ptr, const TPM_KEY_PARMS* k) { + ptr = pack_TPM_ALGORITHM_ID(ptr, k->algorithmID); + ptr = pack_TPM_ENC_SCHEME(ptr, k->encScheme); + ptr = pack_TPM_SIG_SCHEME(ptr, k->sigScheme); + ptr = pack_UINT32(ptr, k->parmSize); + + if(k->parmSize) { + switch(k->algorithmID) { + case TPM_ALG_RSA: + return pack_TPM_RSA_KEY_PARMS(ptr, &k->parms.rsa); + case TPM_ALG_AES128: + case TPM_ALG_AES192: + case TPM_ALG_AES256: + return pack_TPM_SYMMETRIC_KEY_PARMS(ptr, &k->parms.sym); + } + } + return ptr; +} + +inline BYTE* unpack_TPM_KEY_PARMS(BYTE* ptr, TPM_KEY_PARMS* k, UnpackPtr alloc) { + ptr = unpack_TPM_ALGORITHM_ID(ptr, &k->algorithmID); + ptr = unpack_TPM_ENC_SCHEME(ptr, &k->encScheme); + ptr = unpack_TPM_SIG_SCHEME(ptr, &k->sigScheme); + ptr = unpack_UINT32(ptr, &k->parmSize); + + if(k->parmSize) { + switch(k->algorithmID) { + case TPM_ALG_RSA: + return unpack_TPM_RSA_KEY_PARMS(ptr, &k->parms.rsa, alloc); + case TPM_ALG_AES128: + case TPM_ALG_AES192: + case TPM_ALG_AES256: + return unpack_TPM_SYMMETRIC_KEY_PARMS(ptr, &k->parms.sym, alloc); + } + } + return ptr; +} + +inline BYTE* pack_TPM_STORE_PUBKEY(BYTE* ptr, const TPM_STORE_PUBKEY* k) { + ptr = pack_UINT32(ptr, k->keyLength); + ptr = pack_BUFFER(ptr, k->key, k->keyLength); + return ptr; +} + +inline BYTE* unpack_TPM_STORE_PUBKEY(BYTE* ptr, TPM_STORE_PUBKEY* k, UnpackPtr alloc) { + ptr = unpack_UINT32(ptr, &k->keyLength); + ptr = unpack_PTR(ptr, &k->key, k->keyLength, alloc); + return ptr; +} + +inline BYTE* pack_TPM_PUBKEY(BYTE* ptr, const TPM_PUBKEY* k) { + ptr = pack_TPM_KEY_PARMS(ptr, &k->algorithmParms); + return pack_TPM_STORE_PUBKEY(ptr, &k->pubKey); +} + +inline BYTE* unpack_TPM_PUBKEY(BYTE* ptr, TPM_PUBKEY* k, UnpackPtr alloc) { + ptr = unpack_TPM_KEY_PARMS(ptr, &k->algorithmParms, alloc); + return unpack_TPM_STORE_PUBKEY(ptr, &k->pubKey, alloc); +} + +inline BYTE* pack_TPM_PCR_SELECTION(BYTE* ptr, const TPM_PCR_SELECTION* p) { + ptr = pack_UINT16(ptr, p->sizeOfSelect); + ptr = pack_BUFFER(ptr, p->pcrSelect, p->sizeOfSelect); + return ptr; +} + +inline BYTE* unpack_TPM_PCR_SELECTION(BYTE* ptr, TPM_PCR_SELECTION* p, UnpackPtr alloc) { + ptr = unpack_UINT16(ptr, &p->sizeOfSelect); + ptr = unpack_PTR(ptr, &p->pcrSelect, p->sizeOfSelect, alloc); + return ptr; +} + +inline BYTE* pack_TPM_PCR_INFO(BYTE* ptr, const TPM_PCR_INFO* p) { + ptr = pack_TPM_PCR_SELECTION(ptr, &p->pcrSelection); + ptr = pack_TPM_COMPOSITE_HASH(ptr, &p->digestAtRelease); + ptr = pack_TPM_COMPOSITE_HASH(ptr, &p->digestAtCreation); + return ptr; +} + +inline BYTE* unpack_TPM_PCR_INFO(BYTE* ptr, TPM_PCR_INFO* p, UnpackPtr alloc) { + ptr = unpack_TPM_PCR_SELECTION(ptr, &p->pcrSelection, alloc); + ptr = unpack_TPM_COMPOSITE_HASH(ptr, &p->digestAtRelease); + ptr = unpack_TPM_COMPOSITE_HASH(ptr, &p->digestAtCreation); + return ptr; +} + +inline BYTE* pack_TPM_PCR_COMPOSITE(BYTE* ptr, const TPM_PCR_COMPOSITE* p) { + ptr = pack_TPM_PCR_SELECTION(ptr, &p->select); + ptr = pack_UINT32(ptr, p->valueSize); + ptr = pack_BUFFER(ptr, (const BYTE*)p->pcrValue, p->valueSize); + return ptr; +} + +inline BYTE* unpack_TPM_PCR_COMPOSITE(BYTE* ptr, TPM_PCR_COMPOSITE* p, UnpackPtr alloc) { + ptr = unpack_TPM_PCR_SELECTION(ptr, &p->select, alloc); + ptr = unpack_UINT32(ptr, &p->valueSize); + ptr = unpack_PTR(ptr, (BYTE**)&p->pcrValue, p->valueSize, alloc); + return ptr; +} + +inline BYTE* pack_TPM_KEY(BYTE* ptr, const TPM_KEY* k) { + ptr = pack_TPM_VERSION(ptr, &k->ver); + ptr = pack_TPM_KEY_USAGE(ptr, k->keyUsage); + ptr = pack_TPM_KEY_FLAGS(ptr, k->keyFlags); + ptr = pack_TPM_AUTH_DATA_USAGE(ptr, k->authDataUsage); + ptr = pack_TPM_KEY_PARMS(ptr, &k->algorithmParms); + ptr = pack_UINT32(ptr, k->PCRInfoSize); + if(k->PCRInfoSize) { + ptr = pack_TPM_PCR_INFO(ptr, &k->PCRInfo); + } + ptr = pack_TPM_STORE_PUBKEY(ptr, &k->pubKey); + ptr = pack_UINT32(ptr, k->encDataSize); + return pack_BUFFER(ptr, k->encData, k->encDataSize); +} + +inline BYTE* unpack_TPM_KEY(BYTE* ptr, TPM_KEY* k, UnpackPtr alloc) { + ptr = unpack_TPM_VERSION(ptr, &k->ver); + ptr = unpack_TPM_KEY_USAGE(ptr, &k->keyUsage); + ptr = unpack_TPM_KEY_FLAGS(ptr, &k->keyFlags); + ptr = unpack_TPM_AUTH_DATA_USAGE(ptr, &k->authDataUsage); + ptr = unpack_TPM_KEY_PARMS(ptr, &k->algorithmParms, alloc); + ptr = unpack_UINT32(ptr, &k->PCRInfoSize); + if(k->PCRInfoSize) { + ptr = unpack_TPM_PCR_INFO(ptr, &k->PCRInfo, alloc); + } + ptr = unpack_TPM_STORE_PUBKEY(ptr, &k->pubKey, alloc); + ptr = unpack_UINT32(ptr, &k->encDataSize); + return unpack_PTR(ptr, &k->encData, k->encDataSize, alloc); +} + +inline BYTE* pack_TPM_BOUND_DATA(BYTE* ptr, const TPM_BOUND_DATA* b, UINT32 payloadSize) { + ptr = pack_TPM_VERSION(ptr, &b->ver); + ptr = pack_TPM_PAYLOAD_TYPE(ptr, b->payload); + return pack_BUFFER(ptr, b->payloadData, payloadSize); +} + +inline BYTE* unpack_TPM_BOUND_DATA(BYTE* ptr, TPM_BOUND_DATA* b, UINT32 payloadSize, UnpackPtr alloc) { + ptr = unpack_TPM_VERSION(ptr, &b->ver); + ptr = unpack_TPM_PAYLOAD_TYPE(ptr, &b->payload); + return unpack_PTR(ptr, &b->payloadData, payloadSize, alloc); +} + +inline BYTE* pack_TPM_STORED_DATA(BYTE* ptr, const TPM_STORED_DATA* d) { + ptr = pack_TPM_VERSION(ptr, &d->ver); + ptr = pack_UINT32(ptr, d->sealInfoSize); + if(d->sealInfoSize) { + ptr = pack_TPM_PCR_INFO(ptr, &d->sealInfo); + } + ptr = pack_UINT32(ptr, d->encDataSize); + ptr = pack_BUFFER(ptr, d->encData, d->encDataSize); + return ptr; +} + +inline BYTE* unpack_TPM_STORED_DATA(BYTE* ptr, TPM_STORED_DATA* d, UnpackPtr alloc) { + ptr = unpack_TPM_VERSION(ptr, &d->ver); + ptr = unpack_UINT32(ptr, &d->sealInfoSize); + if(d->sealInfoSize) { + ptr = unpack_TPM_PCR_INFO(ptr, &d->sealInfo, alloc); + } + ptr = unpack_UINT32(ptr, &d->encDataSize); + ptr = unpack_PTR(ptr, &d->encData, d->encDataSize, alloc); + return ptr; +} + +inline BYTE* pack_TPM_AUTH_SESSION(BYTE* ptr, const TPM_AUTH_SESSION* auth) { + ptr = pack_TPM_AUTH_HANDLE(ptr, auth->AuthHandle); + ptr = pack_TPM_NONCE(ptr, &auth->NonceOdd); + ptr = pack_BOOL(ptr, auth->fContinueAuthSession); + ptr = pack_TPM_AUTHDATA(ptr, &auth->HMAC); + return ptr; +} + +inline BYTE* unpack_TPM_AUTH_SESSION(BYTE* ptr, TPM_AUTH_SESSION* auth) { + ptr = unpack_TPM_NONCE(ptr, &auth->NonceEven); + ptr = unpack_BOOL(ptr, &auth->fContinueAuthSession); + ptr = unpack_TPM_AUTHDATA(ptr, &auth->HMAC); + return ptr; +} + +inline BYTE* pack_TPM_RQU_HEADER(BYTE* ptr, + TPM_TAG tag, + UINT32 size, + TPM_COMMAND_CODE ord) { + ptr = pack_UINT16(ptr, tag); + ptr = pack_UINT32(ptr, size); + return pack_UINT32(ptr, ord); +} + +inline BYTE* unpack_TPM_RQU_HEADER(BYTE* ptr, + TPM_TAG* tag, + UINT32* size, + TPM_COMMAND_CODE* ord) { + ptr = unpack_UINT16(ptr, tag); + ptr = unpack_UINT32(ptr, size); + ptr = unpack_UINT32(ptr, ord); + return ptr; +} + +#define pack_TPM_RSP_HEADER(p, t, s, r) pack_TPM_RQU_HEADER(p, t, s, r); +#define unpack_TPM_RSP_HEADER(p, t, s, r) unpack_TPM_RQU_HEADER(p, t, s, r); + +#endif diff --git a/stubdom/vtpmmgr/minios.cfg b/stubdom/vtpmmgr/minios.cfg new file mode 100644 index 0000000000..3fb383d30f --- /dev/null +++ b/stubdom/vtpmmgr/minios.cfg @@ -0,0 +1,14 @@ +CONFIG_TPMFRONT=y +CONFIG_TPM_TIS=y +CONFIG_TPMBACK=y +CONFIG_START_NETWORK=n +CONFIG_TEST=n +CONFIG_PCIFRONT=n +CONFIG_BLKFRONT=y +CONFIG_NETFRONT=n +CONFIG_FBFRONT=n +CONFIG_KBDFRONT=n +CONFIG_CONSFRONT=n +CONFIG_XENBUS=y +CONFIG_LWIP=n +CONFIG_XC=n diff --git a/stubdom/vtpmmgr/tcg.h b/stubdom/vtpmmgr/tcg.h new file mode 100644 index 0000000000..7687eae6e5 --- /dev/null +++ b/stubdom/vtpmmgr/tcg.h @@ -0,0 +1,707 @@ +/* + * Copyright (c) 2010-2012 United States Government, as represented by + * the Secretary of Defense. All rights reserved. + * + * based off of the original tools/vtpm_manager code base which is: + * Copyright (c) 2005 Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __TCG_H__ +#define __TCG_H__ + +#include +#include + +// **************************** CONSTANTS ********************************* + +// BOOL values +#define TRUE 0x01 +#define FALSE 0x00 + +#define TCPA_MAX_BUFFER_LENGTH 0x2000 + +// +// TPM_COMMAND_CODE values +#define TPM_PROTECTED_ORDINAL 0x00000000UL +#define TPM_UNPROTECTED_ORDINAL 0x80000000UL +#define TPM_CONNECTION_ORDINAL 0x40000000UL +#define TPM_VENDOR_ORDINAL 0x20000000UL + +#define TPM_ORD_OIAP (10UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_OSAP (11UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_ChangeAuth (12UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_TakeOwnership (13UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_ChangeAuthAsymStart (14UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_ChangeAuthAsymFinish (15UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_ChangeAuthOwner (16UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_Extend (20UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_PcrRead (21UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_Quote (22UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_Seal (23UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_Unseal (24UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_DirWriteAuth (25UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_DirRead (26UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_UnBind (30UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_CreateWrapKey (31UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_LoadKey (32UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_GetPubKey (33UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_EvictKey (34UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_CreateMigrationBlob (40UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_ReWrapKey (41UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_ConvertMigrationBlob (42UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_AuthorizeMigrationKey (43UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_CreateMaintenanceArchive (44UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_LoadMaintenanceArchive (45UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_KillMaintenanceFeature (46UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_LoadManuMaintPub (47UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_ReadManuMaintPub (48UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_CertifyKey (50UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_Sign (60UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_GetRandom (70UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_StirRandom (71UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_SelfTestFull (80UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_SelfTestStartup (81UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_CertifySelfTest (82UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_ContinueSelfTest (83UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_GetTestResult (84UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_Reset (90UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_OwnerClear (91UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_DisableOwnerClear (92UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_ForceClear (93UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_DisableForceClear (94UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_GetCapabilitySigned (100UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_GetCapability (101UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_GetCapabilityOwner (102UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_OwnerSetDisable (110UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_PhysicalEnable (111UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_PhysicalDisable (112UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_SetOwnerInstall (113UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_PhysicalSetDeactivated (114UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_SetTempDeactivated (115UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_CreateEndorsementKeyPair (120UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_MakeIdentity (121UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_ActivateIdentity (122UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_ReadPubek (124UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_OwnerReadPubek (125UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_DisablePubekRead (126UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_GetAuditEvent (130UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_GetAuditEventSigned (131UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_GetOrdinalAuditStatus (140UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_SetOrdinalAuditStatus (141UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_Terminate_Handle (150UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_Init (151UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_SaveState (152UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_Startup (153UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_SetRedirection (154UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_SHA1Start (160UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_SHA1Update (161UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_SHA1Complete (162UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_SHA1CompleteExtend (163UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_FieldUpgrade (170UL + TPM_PROTECTED_ORDINAL) +#define TPM_ORD_SaveKeyContext (180UL + TPM_PROTECTED_ORDINAL) +#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) + + + +// +// TPM_RESULT values +// +// just put in the whole table from spec 1.2 + +#define TPM_BASE 0x0 // The start of TPM return codes +#define TPM_VENDOR_ERROR 0x00000400 // Mask to indicate that the error code is vendor specific for vendor specific commands +#define TPM_NON_FATAL 0x00000800 // Mask to indicate that the error code is a non-fatal failure. + +#define TPM_SUCCESS TPM_BASE // Successful completion of the operation +#define TPM_AUTHFAIL TPM_BASE + 1 // Authentication failed +#define TPM_BADINDEX TPM_BASE + 2 // The index to a PCR, DIR or other register is incorrect +#define TPM_BAD_PARAMETER TPM_BASE + 3 // One or more parameter is bad +#define TPM_AUDITFAILURE TPM_BASE + 4 // An operation completed successfully but the auditing of that operation failed. +#define TPM_CLEAR_DISABLED TPM_BASE + 5 // The clear disable flag is set and all clear operations now require physical access +#define TPM_DEACTIVATED TPM_BASE + 6 // The TPM is deactivated +#define TPM_DISABLED TPM_BASE + 7 // The TPM is disabled +#define TPM_DISABLED_CMD TPM_BASE + 8 // The target command has been disabled +#define TPM_FAIL TPM_BASE + 9 // The operation failed +#define TPM_BAD_ORDINAL TPM_BASE + 10 // The ordinal was unknown or inconsistent +#define TPM_INSTALL_DISABLED TPM_BASE + 11 // The ability to install an owner is disabled +#define TPM_INVALID_KEYHANDLE TPM_BASE + 12 // The key handle presented was invalid +#define TPM_KEYNOTFOUND TPM_BASE + 13 // The target key was not found +#define TPM_INAPPROPRIATE_ENC TPM_BASE + 14 // Unacceptable encryption scheme +#define TPM_MIGRATEFAIL TPM_BASE + 15 // Migration authorization failed +#define TPM_INVALID_PCR_INFO TPM_BASE + 16 // PCR information could not be interpreted +#define TPM_NOSPACE TPM_BASE + 17 // No room to load key. +#define TPM_NOSRK TPM_BASE + 18 // There is no SRK set +#define TPM_NOTSEALED_BLOB TPM_BASE + 19 // An encrypted blob is invalid or was not created by this TPM +#define TPM_OWNER_SET TPM_BASE + 20 // There is already an Owner +#define TPM_RESOURCES TPM_BASE + 21 // The TPM has insufficient internal resources to perform the requested action. +#define TPM_SHORTRANDOM TPM_BASE + 22 // A random string was too short +#define TPM_SIZE TPM_BASE + 23 // The TPM does not have the space to perform the operation. +#define TPM_WRONGPCRVAL TPM_BASE + 24 // The named PCR value does not match the current PCR value. +#define TPM_BAD_PARAM_SIZE TPM_BASE + 25 // The paramSize argument to the command has the incorrect value +#define TPM_SHA_THREAD TPM_BASE + 26 // There is no existing SHA-1 thread. +#define TPM_SHA_ERROR TPM_BASE + 27 // The calculation is unable to proceed because the existing SHA-1 thread has already encountered an error. +#define TPM_FAILEDSELFTEST TPM_BASE + 28 // Self-test has failed and the TPM has shutdown. +#define TPM_AUTH2FAIL TPM_BASE + 29 // The authorization for the second key in a 2 key function failed authorization +#define TPM_BADTAG TPM_BASE + 30 // The tag value sent to for a command is invalid +#define TPM_IOERROR TPM_BASE + 31 // An IO error occurred transmitting information to the TPM +#define TPM_ENCRYPT_ERROR TPM_BASE + 32 // The encryption process had a problem. +#define TPM_DECRYPT_ERROR TPM_BASE + 33 // The decryption process did not complete. +#define TPM_INVALID_AUTHHANDLE TPM_BASE + 34 // An invalid handle was used. +#define TPM_NO_ENDORSEMENT TPM_BASE + 35 // The TPM does not a EK installed +#define TPM_INVALID_KEYUSAGE TPM_BASE + 36 // The usage of a key is not allowed +#define TPM_WRONG_ENTITYTYPE TPM_BASE + 37 // The submitted entity type is not allowed +#define TPM_INVALID_POSTINIT TPM_BASE + 38 // The command was received in the wrong sequence relative to TPM_Init and a subsequent TPM_Startup +#define TPM_INAPPROPRIATE_SIG TPM_BASE + 39 // Signed data cannot include additional DER information +#define TPM_BAD_KEY_PROPERTY TPM_BASE + 40 // The key properties in TPM_KEY_PARMs are not supported by this TPM + +#define TPM_BAD_MIGRATION TPM_BASE + 41 // The migration properties of this key are incorrect. +#define TPM_BAD_SCHEME TPM_BASE + 42 // The signature or encryption scheme for this key is incorrect or not permitted in this situation. +#define TPM_BAD_DATASIZE TPM_BASE + 43 // The size of the data (or blob) parameter is bad or inconsistent with the referenced key +#define TPM_BAD_MODE TPM_BASE + 44 // A mode parameter is bad, such as capArea or subCapArea for TPM_GetCapability, phsicalPresence parameter for TPM_PhysicalPresence, or migrationType for TPM_CreateMigrationBlob. +#define TPM_BAD_PRESENCE TPM_BASE + 45 // Either the physicalPresence or physicalPresenceLock bits have the wrong value +#define TPM_BAD_VERSION TPM_BASE + 46 // The TPM cannot perform this version of the capability +#define TPM_NO_WRAP_TRANSPORT TPM_BASE + 47 // The TPM does not allow for wrapped transport sessions +#define TPM_AUDITFAIL_UNSUCCESSFUL TPM_BASE + 48 // TPM audit construction failed and the underlying command was returning a failure code also +#define TPM_AUDITFAIL_SUCCESSFUL TPM_BASE + 49 // TPM audit construction failed and the underlying command was returning success +#define TPM_NOTRESETABLE TPM_BASE + 50 // Attempt to reset a PCR register that does not have the resettable attribute +#define TPM_NOTLOCAL TPM_BASE + 51 // Attempt to reset a PCR register that requires locality and locality modifier not part of command transport +#define TPM_BAD_TYPE TPM_BASE + 52 // Make identity blob not properly typed +#define TPM_INVALID_RESOURCE TPM_BASE + 53 // When saving context identified resource type does not match actual resource +#define TPM_NOTFIPS TPM_BASE + 54 // The TPM is attempting to execute a command only available when in FIPS mode +#define TPM_INVALID_FAMILY TPM_BASE + 55 // The command is attempting to use an invalid family ID +#define TPM_NO_NV_PERMISSION TPM_BASE + 56 // The permission to manipulate the NV storage is not available +#define TPM_REQUIRES_SIGN TPM_BASE + 57 // The operation requires a signed command +#define TPM_KEY_NOTSUPPORTED TPM_BASE + 58 // Wrong operation to load an NV key +#define TPM_AUTH_CONFLICT TPM_BASE + 59 // NV_LoadKey blob requires both owner and blob authorization +#define TPM_AREA_LOCKED TPM_BASE + 60 // The NV area is locked and not writtable +#define TPM_BAD_LOCALITY TPM_BASE + 61 // The locality is incorrect for the attempted operation +#define TPM_READ_ONLY TPM_BASE + 62 // The NV area is read only and can't be written to +#define TPM_PER_NOWRITE TPM_BASE + 63 // There is no protection on the write to the NV area +#define TPM_FAMILYCOUNT TPM_BASE + 64 // The family count value does not match +#define TPM_WRITE_LOCKED TPM_BASE + 65 // The NV area has already been written to +#define TPM_BAD_ATTRIBUTES TPM_BASE + 66 // The NV area attributes conflict +#define TPM_INVALID_STRUCTURE TPM_BASE + 67 // The structure tag and version are invalid or inconsistent +#define TPM_KEY_OWNER_CONTROL TPM_BASE + 68 // The key is under control of the TPM Owner and can only be evicted by the TPM Owner. +#define TPM_BAD_COUNTER TPM_BASE + 69 // The counter handle is incorrect +#define TPM_NOT_FULLWRITE TPM_BASE + 70 // The write is not a complete write of the area +#define TPM_CONTEXT_GAP TPM_BASE + 71 // The gap between saved context counts is too large +#define TPM_MAXNVWRITES TPM_BASE + 72 // The maximum number of NV writes without an owner has been exceeded +#define TPM_NOOPERATOR TPM_BASE + 73 // No operator authorization value is set +#define TPM_RESOURCEMISSING TPM_BASE + 74 // The resource pointed to by context is not loaded +#define TPM_DELEGATE_LOCK TPM_BASE + 75 // The delegate administration is locked +#define TPM_DELEGATE_FAMILY TPM_BASE + 76 // Attempt to manage a family other then the delegated family +#define TPM_DELEGATE_ADMIN TPM_BASE + 77 // Delegation table management not enabled +#define TPM_TRANSPORT_EXCLUSIVE TPM_BASE + 78 // There was a command executed outside of an exclusive transport session + +// TPM_STARTUP_TYPE values +#define TPM_ST_CLEAR 0x0001 +#define TPM_ST_STATE 0x0002 +#define TPM_ST_DEACTIVATED 0x003 + +// TPM_TAG values +#define TPM_TAG_RQU_COMMAND 0x00c1 +#define TPM_TAG_RQU_AUTH1_COMMAND 0x00c2 +#define TPM_TAG_RQU_AUTH2_COMMAND 0x00c3 +#define TPM_TAG_RSP_COMMAND 0x00c4 +#define TPM_TAG_RSP_AUTH1_COMMAND 0x00c5 +#define TPM_TAG_RSP_AUTH2_COMMAND 0x00c6 + +// TPM_PAYLOAD_TYPE values +#define TPM_PT_ASYM 0x01 +#define TPM_PT_BIND 0x02 +#define TPM_PT_MIGRATE 0x03 +#define TPM_PT_MAINT 0x04 +#define TPM_PT_SEAL 0x05 + +// TPM_ENTITY_TYPE values +#define TPM_ET_KEYHANDLE 0x0001 +#define TPM_ET_OWNER 0x0002 +#define TPM_ET_DATA 0x0003 +#define TPM_ET_SRK 0x0004 +#define TPM_ET_KEY 0x0005 + +/// 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 +#define TPM_PID_OSAP 0x0002 +#define TPM_PID_ADIP 0x0003 +#define TPM_PID_ADCP 0x0004 +#define TPM_PID_OWNER 0x0005 + +// TPM_ALGORITHM_ID values +#define TPM_ALG_RSA 0x00000001 +#define TPM_ALG_SHA 0x00000004 +#define TPM_ALG_HMAC 0x00000005 +#define TPM_ALG_AES128 0x00000006 +#define TPM_ALG_MFG1 0x00000007 +#define TPM_ALG_AES192 0x00000008 +#define TPM_ALG_AES256 0x00000009 +#define TPM_ALG_XOR 0x0000000A + +// TPM_ENC_SCHEME values +#define TPM_ES_NONE 0x0001 +#define TPM_ES_RSAESPKCSv15 0x0002 +#define TPM_ES_RSAESOAEP_SHA1_MGF1 0x0003 + +// TPM_SIG_SCHEME values +#define TPM_SS_NONE 0x0001 +#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 +#define TPM_KEY_STORAGE 0x0011 +#define TPM_KEY_IDENTITY 0x0012 +#define TPM_KEY_AUTHCHANGE 0X0013 +#define TPM_KEY_BIND 0x0014 +#define TPM_KEY_LEGACY 0x0015 + +// TPM_AUTH_DATA_USAGE values +#define TPM_AUTH_NEVER 0x00 +#define TPM_AUTH_ALWAYS 0x01 + +// Key Handle of owner and srk +#define TPM_OWNER_KEYHANDLE 0x40000001 +#define TPM_SRK_KEYHANDLE 0x40000000 + + + +// *************************** TYPEDEFS ********************************* +typedef unsigned char BYTE; +typedef unsigned char BOOL; +typedef uint16_t UINT16; +typedef uint32_t UINT32; +typedef uint64_t UINT64; + +typedef UINT32 TPM_RESULT; +typedef UINT32 TPM_PCRINDEX; +typedef UINT32 TPM_DIRINDEX; +typedef UINT32 TPM_HANDLE; +typedef TPM_HANDLE TPM_AUTHHANDLE; +typedef TPM_HANDLE TCPA_HASHHANDLE; +typedef TPM_HANDLE TCPA_HMACHANDLE; +typedef TPM_HANDLE TCPA_ENCHANDLE; +typedef TPM_HANDLE TPM_KEY_HANDLE; +typedef TPM_HANDLE TCPA_ENTITYHANDLE; +typedef UINT32 TPM_RESOURCE_TYPE; +typedef UINT32 TPM_COMMAND_CODE; +typedef UINT16 TPM_PROTOCOL_ID; +typedef BYTE TPM_AUTH_DATA_USAGE; +typedef UINT16 TPM_ENTITY_TYPE; +typedef UINT32 TPM_ALGORITHM_ID; +typedef UINT16 TPM_KEY_USAGE; +typedef UINT16 TPM_STARTUP_TYPE; +typedef UINT32 TPM_CAPABILITY_AREA; +typedef UINT16 TPM_ENC_SCHEME; +typedef UINT16 TPM_SIG_SCHEME; +typedef UINT16 TPM_MIGRATE_SCHEME; +typedef UINT16 TPM_PHYSICAL_PRESENCE; +typedef UINT32 TPM_KEY_FLAGS; + +#define TPM_DIGEST_SIZE 20 // Don't change this +typedef BYTE TPM_AUTHDATA[TPM_DIGEST_SIZE]; +typedef TPM_AUTHDATA TPM_SECRET; +typedef TPM_AUTHDATA TPM_ENCAUTH; +typedef BYTE TPM_PAYLOAD_TYPE; +typedef UINT16 TPM_TAG; +typedef UINT16 TPM_STRUCTURE_TAG; + +// Data Types of the TCS +typedef UINT32 TCS_AUTHHANDLE; // Handle addressing a authorization session +typedef UINT32 TCS_CONTEXT_HANDLE; // Basic context handle +typedef UINT32 TCS_KEY_HANDLE; // Basic key handle + +// ************************* STRUCTURES ********************************** + +typedef struct TPM_VERSION { + BYTE major; + BYTE minor; + BYTE revMajor; + BYTE revMinor; +} TPM_VERSION; + +static const TPM_VERSION TPM_STRUCT_VER_1_1 = { 1,1,0,0 }; + +typedef struct TPM_CAP_VERSION_INFO { + TPM_STRUCTURE_TAG tag; + TPM_VERSION version; + UINT16 specLevel; + BYTE errataRev; + BYTE tpmVendorID[4]; + UINT16 vendorSpecificSize; + BYTE* vendorSpecific; +} TPM_CAP_VERSION_INFO; + +inline void free_TPM_CAP_VERSION_INFO(TPM_CAP_VERSION_INFO* v) { + free(v->vendorSpecific); + v->vendorSpecific = NULL; +} + +typedef struct TPM_DIGEST { + BYTE digest[TPM_DIGEST_SIZE]; +} TPM_DIGEST; + +typedef TPM_DIGEST TPM_PCRVALUE; +typedef TPM_DIGEST TPM_COMPOSITE_HASH; +typedef TPM_DIGEST TPM_DIRVALUE; +typedef TPM_DIGEST TPM_HMAC; +typedef TPM_DIGEST TPM_CHOSENID_HASH; + +typedef struct TPM_NONCE { + BYTE nonce[TPM_DIGEST_SIZE]; +} TPM_NONCE; + +typedef struct TPM_SYMMETRIC_KEY_PARMS { + UINT32 keyLength; + UINT32 blockSize; + UINT32 ivSize; + BYTE* IV; +} TPM_SYMMETRIC_KEY_PARMS; + +inline void free_TPM_SYMMETRIC_KEY_PARMS(TPM_SYMMETRIC_KEY_PARMS* p) { + free(p->IV); + p->IV = NULL; +} + +#define TPM_SYMMETRIC_KEY_PARMS_INIT { 0, 0, 0, NULL } + +typedef struct TPM_RSA_KEY_PARMS { + UINT32 keyLength; + UINT32 numPrimes; + UINT32 exponentSize; + BYTE* exponent; +} TPM_RSA_KEY_PARMS; + +#define TPM_RSA_KEY_PARMS_INIT { 0, 0, 0, NULL } + +inline void free_TPM_RSA_KEY_PARMS(TPM_RSA_KEY_PARMS* p) { + free(p->exponent); + p->exponent = NULL; +} + +typedef struct TPM_KEY_PARMS { + TPM_ALGORITHM_ID algorithmID; + TPM_ENC_SCHEME encScheme; + TPM_SIG_SCHEME sigScheme; + UINT32 parmSize; + union { + TPM_SYMMETRIC_KEY_PARMS sym; + TPM_RSA_KEY_PARMS rsa; + } parms; +} TPM_KEY_PARMS; + +#define TPM_KEY_PARMS_INIT { 0, 0, 0, 0 } + +inline void free_TPM_KEY_PARMS(TPM_KEY_PARMS* p) { + if(p->parmSize) { + switch(p->algorithmID) { + case TPM_ALG_RSA: + free_TPM_RSA_KEY_PARMS(&p->parms.rsa); + break; + case TPM_ALG_AES128: + case TPM_ALG_AES192: + case TPM_ALG_AES256: + free_TPM_SYMMETRIC_KEY_PARMS(&p->parms.sym); + break; + } + } +} + +typedef struct TPM_STORE_PUBKEY { + UINT32 keyLength; + BYTE* key; +} TPM_STORE_PUBKEY; + +#define TPM_STORE_PUBKEY_INIT { 0, NULL } + +inline void free_TPM_STORE_PUBKEY(TPM_STORE_PUBKEY* p) { + free(p->key); + p->key = NULL; +} + +typedef struct TPM_PUBKEY { + TPM_KEY_PARMS algorithmParms; + TPM_STORE_PUBKEY pubKey; +} TPM_PUBKEY; + +#define TPM_PUBKEY_INIT { TPM_KEY_PARMS_INIT, TPM_STORE_PUBKEY_INIT } + +inline void free_TPM_PUBKEY(TPM_PUBKEY* k) { + free_TPM_KEY_PARMS(&k->algorithmParms); + free_TPM_STORE_PUBKEY(&k->pubKey); +} + +typedef struct TPM_PCR_SELECTION { + UINT16 sizeOfSelect; + BYTE* pcrSelect; +} TPM_PCR_SELECTION; + +#define TPM_PCR_SELECTION_INIT { 0, NULL } + +inline void free_TPM_PCR_SELECTION(TPM_PCR_SELECTION* p) { + free(p->pcrSelect); + p->pcrSelect = NULL; +} + +typedef struct TPM_PCR_INFO { + TPM_PCR_SELECTION pcrSelection; + TPM_COMPOSITE_HASH digestAtRelease; + TPM_COMPOSITE_HASH digestAtCreation; +} TPM_PCR_INFO; + +#define TPM_PCR_INFO_INIT { TPM_PCR_SELECTION_INIT } + +inline void free_TPM_PCR_INFO(TPM_PCR_INFO* p) { + free_TPM_PCR_SELECTION(&p->pcrSelection); +} + +typedef struct TPM_PCR_COMPOSITE { + TPM_PCR_SELECTION select; + UINT32 valueSize; + TPM_PCRVALUE* pcrValue; +} TPM_PCR_COMPOSITE; + +#define TPM_PCR_COMPOSITE_INIT { TPM_PCR_SELECTION_INIT, 0, NULL } + +inline void free_TPM_PCR_COMPOSITE(TPM_PCR_COMPOSITE* p) { + free_TPM_PCR_SELECTION(&p->select); + free(p->pcrValue); + p->pcrValue = NULL; +} + +typedef struct TPM_KEY { + TPM_VERSION ver; + TPM_KEY_USAGE keyUsage; + TPM_KEY_FLAGS keyFlags; + TPM_AUTH_DATA_USAGE authDataUsage; + TPM_KEY_PARMS algorithmParms; + UINT32 PCRInfoSize; + TPM_PCR_INFO PCRInfo; + TPM_STORE_PUBKEY pubKey; + UINT32 encDataSize; + BYTE* encData; +} TPM_KEY; + +#define TPM_KEY_INIT { .algorithmParms = TPM_KEY_PARMS_INIT,\ + .PCRInfoSize = 0, .PCRInfo = TPM_PCR_INFO_INIT, \ + .pubKey = TPM_STORE_PUBKEY_INIT, \ + .encDataSize = 0, .encData = NULL } + +inline void free_TPM_KEY(TPM_KEY* k) { + if(k->PCRInfoSize) { + free_TPM_PCR_INFO(&k->PCRInfo); + } + free_TPM_STORE_PUBKEY(&k->pubKey); + free(k->encData); + k->encData = NULL; +} + +typedef struct TPM_BOUND_DATA { + TPM_VERSION ver; + TPM_PAYLOAD_TYPE payload; + BYTE* payloadData; +} TPM_BOUND_DATA; + +#define TPM_BOUND_DATA_INIT { .payloadData = NULL } + +inline void free_TPM_BOUND_DATA(TPM_BOUND_DATA* d) { + free(d->payloadData); + d->payloadData = NULL; +} + +typedef struct TPM_STORED_DATA { + TPM_VERSION ver; + UINT32 sealInfoSize; + TPM_PCR_INFO sealInfo; + UINT32 encDataSize; + BYTE* encData; +} TPM_STORED_DATA; + +#define TPM_STORED_DATA_INIT { .sealInfoSize = 0, sealInfo = TPM_PCR_INFO_INIT,\ + .encDataSize = 0, .encData = NULL } + +inline void free_TPM_STORED_DATA(TPM_STORED_DATA* d) { + if(d->sealInfoSize) { + free_TPM_PCR_INFO(&d->sealInfo); + } + free(d->encData); + d->encData = NULL; +} + +typedef struct TPM_AUTH_SESSION { + TPM_AUTHHANDLE AuthHandle; + TPM_NONCE NonceOdd; // system + TPM_NONCE NonceEven; // TPM + BOOL fContinueAuthSession; + TPM_AUTHDATA HMAC; +} TPM_AUTH_SESSION; + +#define TPM_AUTH_SESSION_INIT { .AuthHandle = 0, .fContinueAuthSession = FALSE } + +// ---------------------- Functions for checking TPM_RESULTs ----------------- + +#include + +// FIXME: Review use of these and delete unneeded ones. + +// these are really badly dependent on local structure: +// DEPENDS: local var 'status' of type TPM_RESULT +// DEPENDS: label 'abort_egress' which cleans up and returns the status +#define ERRORDIE(s) do { status = s; \ + fprintf (stderr, "*** ERRORDIE in %s at %s: %i\n", __func__, __FILE__, __LINE__); \ + goto abort_egress; } \ + while (0) + +// DEPENDS: local var 'status' of type TPM_RESULT +// DEPENDS: label 'abort_egress' which cleans up and returns the status +// Try command c. If it fails, set status to s and goto abort. +#define TPMTRY(s,c) if (c != TPM_SUCCESS) { \ + status = s; \ + printf("ERROR in %s at %s:%i code: %s.\n", __func__, __FILE__, __LINE__, tpm_get_error_name(status)); \ + goto abort_egress; \ + } else {\ + status = c; \ + } + +// Try command c. If it fails, print error message, set status to actual return code. Goto abort +#define TPMTRYRETURN(c) do { status = c; \ + if (status != TPM_SUCCESS) { \ + fprintf(stderr, "ERROR in %s at %s:%i code: %s.\n", __func__, __FILE__, __LINE__, tpm_get_error_name(status)); \ + goto abort_egress; \ + } \ + } while(0) + + +#endif //__TCPA_H__ diff --git a/stubdom/vtpmmgr/tpm.c b/stubdom/vtpmmgr/tpm.c new file mode 100644 index 0000000000..123a27c22f --- /dev/null +++ b/stubdom/vtpmmgr/tpm.c @@ -0,0 +1,938 @@ +/* + * Copyright (c) 2010-2012 United States Government, as represented by + * the Secretary of Defense. All rights reserved. + * + * based off of the original tools/vtpm_manager code base which is: + * Copyright (c) 2005, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include + +#include + +#include "tcg.h" +#include "tpm.h" +#include "log.h" +#include "marshal.h" +#include "tpmrsa.h" +#include "vtpmmgr.h" + +#define TCPA_MAX_BUFFER_LENGTH 0x2000 + +#define TPM_BEGIN(TAG, ORD) \ + const TPM_TAG intag = TAG;\ +TPM_TAG tag = intag;\ +UINT32 paramSize;\ +const TPM_COMMAND_CODE ordinal = ORD;\ +TPM_RESULT status = TPM_SUCCESS;\ +BYTE in_buf[TCPA_MAX_BUFFER_LENGTH];\ +BYTE out_buf[TCPA_MAX_BUFFER_LENGTH];\ +UINT32 out_len = sizeof(out_buf);\ +BYTE* ptr = in_buf;\ +/*Print a log message */\ +vtpmloginfo(VTPM_LOG_TPM, "%s\n", __func__);\ +/* Pack the header*/\ +ptr = pack_TPM_TAG(ptr, tag);\ +ptr += sizeof(UINT32);\ +ptr = pack_TPM_COMMAND_CODE(ptr, ordinal)\ + +#define TPM_AUTH_BEGIN() \ + sha1_context sha1_ctx;\ +BYTE* authbase = ptr - sizeof(TPM_COMMAND_CODE);\ +TPM_DIGEST paramDigest;\ +sha1_starts(&sha1_ctx) + +#define TPM_AUTH1_GEN(HMACkey, auth) do {\ + sha1_finish(&sha1_ctx, paramDigest.digest);\ + generateAuth(¶mDigest, HMACkey, auth);\ + ptr = pack_TPM_AUTH_SESSION(ptr, auth);\ +} while(0) + +#define TPM_AUTH2_GEN(HMACkey, auth) do {\ + generateAuth(¶mDigest, HMACkey, auth);\ + ptr = pack_TPM_AUTH_SESSION(ptr, auth);\ +} while(0) + +#define TPM_TRANSMIT() do {\ + /* Pack the command size */\ + paramSize = ptr - in_buf;\ + pack_UINT32(in_buf + sizeof(TPM_TAG), paramSize);\ + if((status = TPM_TransmitData(in_buf, paramSize, out_buf, &out_len)) != TPM_SUCCESS) {\ + goto abort_egress;\ + }\ +} while(0) + +#define TPM_AUTH_VERIFY_BEGIN() do {\ + UINT32 buf[2] = { cpu_to_be32(status), cpu_to_be32(ordinal) };\ + sha1_starts(&sha1_ctx);\ + sha1_update(&sha1_ctx, (unsigned char*)buf, sizeof(buf));\ + authbase = ptr;\ +} while(0) + +#define TPM_AUTH1_VERIFY(HMACkey, auth) do {\ + sha1_finish(&sha1_ctx, paramDigest.digest);\ + ptr = unpack_TPM_AUTH_SESSION(ptr, auth);\ + if((status = verifyAuth(¶mDigest, HMACkey, auth)) != TPM_SUCCESS) {\ + goto abort_egress;\ + }\ +} while(0) + +#define TPM_AUTH2_VERIFY(HMACkey, auth) do {\ + ptr = unpack_TPM_AUTH_SESSION(ptr, auth);\ + if((status = verifyAuth(¶mDigest, HMACkey, auth)) != TPM_SUCCESS) {\ + goto abort_egress;\ + }\ +} while(0) + + + +#define TPM_UNPACK_VERIFY() do { \ + ptr = out_buf;\ + ptr = unpack_TPM_RSP_HEADER(ptr, \ + &(tag), &(paramSize), &(status));\ + if((status) != TPM_SUCCESS || (tag) != (intag +3)) { \ + vtpmlogerror(VTPM_LOG_TPM, "Failed with return code %s\n", tpm_get_error_name(status));\ + goto abort_egress;\ + }\ +} while(0) + +#define TPM_AUTH_HASH() do {\ + sha1_update(&sha1_ctx, authbase, ptr - authbase);\ + authbase = ptr;\ +} while(0) + +#define TPM_AUTH_SKIP() do {\ + authbase = ptr;\ +} while(0) + +#define TPM_AUTH_ERR_CHECK(auth) do {\ + if(status != TPM_SUCCESS || auth->fContinueAuthSession == FALSE) {\ + vtpmloginfo(VTPM_LOG_TPM, "Auth Session: 0x%x closed by TPM\n", auth->AuthHandle);\ + auth->AuthHandle = 0;\ + }\ +} while(0) + +static void xorEncrypt(const TPM_SECRET* sharedSecret, + TPM_NONCE* nonce, + const TPM_AUTHDATA* inAuth0, + TPM_ENCAUTH outAuth0, + const TPM_AUTHDATA* inAuth1, + TPM_ENCAUTH outAuth1) { + BYTE XORbuffer[sizeof(TPM_SECRET) + sizeof(TPM_NONCE)]; + BYTE XORkey[TPM_DIGEST_SIZE]; + BYTE* ptr = XORbuffer; + ptr = pack_TPM_SECRET(ptr, sharedSecret); + ptr = pack_TPM_NONCE(ptr, nonce); + + sha1(XORbuffer, ptr - XORbuffer, XORkey); + + if(inAuth0) { + for(int i = 0; i < TPM_DIGEST_SIZE; ++i) { + outAuth0[i] = XORkey[i] ^ (*inAuth0)[i]; + } + } + if(inAuth1) { + for(int i = 0; i < TPM_DIGEST_SIZE; ++i) { + outAuth1[i] = XORkey[i] ^ (*inAuth1)[i]; + } + } + +} + +static void generateAuth(const TPM_DIGEST* paramDigest, + const TPM_SECRET* HMACkey, + TPM_AUTH_SESSION *auth) +{ + //Generate new OddNonce + vtpmmgr_rand((BYTE*)auth->NonceOdd.nonce, sizeof(TPM_NONCE)); + + // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams). + BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)]; + BYTE* ptr = hmacText; + + ptr = pack_TPM_DIGEST(ptr, paramDigest); + ptr = pack_TPM_NONCE(ptr, &auth->NonceEven); + ptr = pack_TPM_NONCE(ptr, &auth->NonceOdd); + ptr = pack_BOOL(ptr, auth->fContinueAuthSession); + + sha1_hmac((BYTE *) HMACkey, sizeof(TPM_DIGEST), + (BYTE *) hmacText, sizeof(hmacText), + auth->HMAC); +} + +static TPM_RESULT verifyAuth(const TPM_DIGEST* paramDigest, + /*[IN]*/ const TPM_SECRET *HMACkey, + /*[IN,OUT]*/ TPM_AUTH_SESSION *auth) +{ + + // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams). + TPM_AUTHDATA hm; + BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)]; + BYTE* ptr = hmacText; + + ptr = pack_TPM_DIGEST(ptr, paramDigest); + ptr = pack_TPM_NONCE(ptr, &auth->NonceEven); + ptr = pack_TPM_NONCE(ptr, &auth->NonceOdd); + ptr = pack_BOOL(ptr, auth->fContinueAuthSession); + + sha1_hmac( (BYTE *) HMACkey, sizeof(TPM_DIGEST), + (BYTE *) hmacText, sizeof(hmacText), + hm); + + // Compare correct HMAC with provided one. + if (memcmp(hm, auth->HMAC, sizeof(TPM_DIGEST)) == 0) { // 0 indicates equality + return TPM_SUCCESS; + } else { + vtpmlogerror(VTPM_LOG_TPM, "Auth Session verification failed!\n"); + return TPM_AUTHFAIL; + } +} + + + +// ------------------------------------------------------------------ +// Authorization Commands +// ------------------------------------------------------------------ + +TPM_RESULT TPM_OIAP(TPM_AUTH_SESSION* auth) // out +{ + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_OIAP); + + TPM_TRANSMIT(); + TPM_UNPACK_VERIFY(); + + memset(&auth->HMAC, 0, sizeof(TPM_DIGEST)); + auth->fContinueAuthSession = TRUE; + + ptr = unpack_UINT32(ptr, &auth->AuthHandle); + ptr = unpack_TPM_NONCE(ptr, &auth->NonceEven); + + vtpmloginfo(VTPM_LOG_TPM, "Auth Session: 0x%x opened by TPM_OIAP.\n", auth->AuthHandle); + +abort_egress: + return status; +} + +TPM_RESULT TPM_OSAP(TPM_ENTITY_TYPE entityType, // in + UINT32 entityValue, // in + const TPM_AUTHDATA* usageAuth, //in + TPM_SECRET *sharedSecret, //out + TPM_AUTH_SESSION *auth) +{ + BYTE* nonceOddOSAP; + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_OSAP); + + ptr = pack_TPM_ENTITY_TYPE(ptr, entityType); + ptr = pack_UINT32(ptr, entityValue); + + //nonce Odd OSAP + nonceOddOSAP = ptr; + vtpmmgr_rand(ptr, TPM_DIGEST_SIZE); + ptr += TPM_DIGEST_SIZE; + + TPM_TRANSMIT(); + TPM_UNPACK_VERIFY(); + + ptr = unpack_UINT32(ptr, &auth->AuthHandle); + ptr = unpack_TPM_NONCE(ptr, &auth->NonceEven); + + //Calculate session secret + sha1_context ctx; + sha1_hmac_starts(&ctx, *usageAuth, TPM_DIGEST_SIZE); + sha1_hmac_update(&ctx, ptr, TPM_DIGEST_SIZE); //ptr = nonceEvenOSAP + sha1_hmac_update(&ctx, nonceOddOSAP, TPM_DIGEST_SIZE); + sha1_hmac_finish(&ctx, *sharedSecret); + + memset(&auth->HMAC, 0, sizeof(TPM_DIGEST)); + auth->fContinueAuthSession = FALSE; + + vtpmloginfo(VTPM_LOG_TPM, "Auth Session: 0x%x opened by TPM_OSAP.\n", auth->AuthHandle); + +abort_egress: + return status; +} + +TPM_RESULT TPM_TakeOwnership( + const TPM_PUBKEY *pubEK, //in + const TPM_AUTHDATA* ownerAuth, //in + const TPM_AUTHDATA* srkAuth, //in + const TPM_KEY* inSrk, //in + TPM_KEY* outSrk, //out, optional + TPM_AUTH_SESSION* auth) // in, out +{ + int keyAlloced = 0; + tpmrsa_context ek_rsa = TPMRSA_CTX_INIT; + + TPM_BEGIN(TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_TakeOwnership); + TPM_AUTH_BEGIN(); + + tpmrsa_set_pubkey(&ek_rsa, + pubEK->pubKey.key, pubEK->pubKey.keyLength, + pubEK->algorithmParms.parms.rsa.exponent, + pubEK->algorithmParms.parms.rsa.exponentSize); + + /* Pack the protocol ID */ + ptr = pack_UINT16(ptr, TPM_PID_OWNER); + + /* Pack the encrypted owner auth */ + ptr = pack_UINT32(ptr, pubEK->algorithmParms.parms.rsa.keyLength / 8); + tpmrsa_pub_encrypt_oaep(&ek_rsa, + ctr_drbg_random, &vtpm_globals.ctr_drbg, + sizeof(TPM_SECRET), + (BYTE*) ownerAuth, + ptr); + ptr += pubEK->algorithmParms.parms.rsa.keyLength / 8; + + /* Pack the encrypted srk auth */ + ptr = pack_UINT32(ptr, pubEK->algorithmParms.parms.rsa.keyLength / 8); + tpmrsa_pub_encrypt_oaep(&ek_rsa, + ctr_drbg_random, &vtpm_globals.ctr_drbg, + sizeof(TPM_SECRET), + (BYTE*) srkAuth, + ptr); + ptr += pubEK->algorithmParms.parms.rsa.keyLength / 8; + + /* Pack the Srk key */ + ptr = pack_TPM_KEY(ptr, inSrk); + + /* Hash everything up to here */ + TPM_AUTH_HASH(); + + /* Generate the authorization */ + TPM_AUTH1_GEN(ownerAuth, auth); + + /* Send the command to the tpm*/ + TPM_TRANSMIT(); + /* Unpack and validate the header */ + TPM_UNPACK_VERIFY(); + TPM_AUTH_VERIFY_BEGIN(); + + if(outSrk != NULL) { + /* If the user wants a copy of the srk we give it to them */ + keyAlloced = 1; + ptr = unpack_TPM_KEY(ptr, outSrk, UNPACK_ALLOC); + } else { + /*otherwise just parse past it */ + TPM_KEY temp; + ptr = unpack_TPM_KEY(ptr, &temp, UNPACK_ALIAS); + } + + /* Hash the output key */ + TPM_AUTH_HASH(); + + /* Verify authorizaton */ + TPM_AUTH1_VERIFY(ownerAuth, auth); + + goto egress; +abort_egress: + if(keyAlloced) { + free_TPM_KEY(outSrk); + } +egress: + tpmrsa_free(&ek_rsa); + TPM_AUTH_ERR_CHECK(auth); + return status; +} + + +TPM_RESULT TPM_DisablePubekRead ( + const TPM_AUTHDATA* ownerAuth, + TPM_AUTH_SESSION* auth) +{ + TPM_BEGIN(TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_DisablePubekRead); + TPM_AUTH_BEGIN(); + + TPM_AUTH_HASH(); + + TPM_AUTH1_GEN(ownerAuth, auth); + TPM_TRANSMIT(); + TPM_UNPACK_VERIFY(); + TPM_AUTH_VERIFY_BEGIN(); + + TPM_AUTH1_VERIFY(ownerAuth, auth); + +abort_egress: + TPM_AUTH_ERR_CHECK(auth); + return status; +} + + +TPM_RESULT TPM_TerminateHandle(TPM_AUTHHANDLE handle) // in +{ + if(handle == 0) { + return TPM_SUCCESS; + } + + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_Terminate_Handle); + + ptr = pack_TPM_AUTHHANDLE(ptr, handle); + + TPM_TRANSMIT(); + TPM_UNPACK_VERIFY(); + + vtpmloginfo(VTPM_LOG_TPM, "Auth Session: 0x%x closed by TPM_TerminateHandle\n", handle); + +abort_egress: + return status; +} + +TPM_RESULT TPM_Extend( TPM_PCRINDEX pcrNum, // in + TPM_DIGEST inDigest, // in + TPM_PCRVALUE* outDigest) // out +{ + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_Extend); + + ptr = pack_TPM_PCRINDEX(ptr, pcrNum); + ptr = pack_TPM_DIGEST(ptr, &inDigest); + + TPM_TRANSMIT(); + TPM_UNPACK_VERIFY(); + + ptr = unpack_TPM_PCRVALUE(ptr, outDigest); + +abort_egress: + return status; +} + +TPM_RESULT TPM_Seal( + TPM_KEY_HANDLE keyHandle, // in + UINT32 pcrInfoSize, // in + TPM_PCR_INFO* pcrInfo, // in + UINT32 inDataSize, // in + const BYTE* inData, // in + TPM_STORED_DATA* sealedData, //out + const TPM_SECRET* osapSharedSecret, //in + const TPM_AUTHDATA* sealedDataAuth, //in + TPM_AUTH_SESSION* pubAuth // in, out + ) +{ + int dataAlloced = 0; + TPM_BEGIN(TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_Seal); + TPM_AUTH_BEGIN(); + + TPM_AUTH_HASH(); + + ptr = pack_TPM_KEY_HANDLE(ptr, keyHandle); + + TPM_AUTH_SKIP(); + + xorEncrypt(osapSharedSecret, &pubAuth->NonceEven, + sealedDataAuth, ptr, + NULL, NULL); + ptr += sizeof(TPM_ENCAUTH); + + ptr = pack_UINT32(ptr, pcrInfoSize); + ptr = pack_TPM_PCR_INFO(ptr, pcrInfo); + + ptr = pack_UINT32(ptr, inDataSize); + ptr = pack_BUFFER(ptr, inData, inDataSize); + + TPM_AUTH_HASH(); + + TPM_AUTH1_GEN(osapSharedSecret, pubAuth); + TPM_TRANSMIT(); + TPM_UNPACK_VERIFY(); + TPM_AUTH_VERIFY_BEGIN(); + + ptr = unpack_TPM_STORED_DATA(ptr, sealedData, UNPACK_ALLOC); + dataAlloced = 1; + + TPM_AUTH_HASH(); + + TPM_AUTH1_VERIFY(osapSharedSecret, pubAuth); + + goto egress; +abort_egress: + if(dataAlloced) { + free_TPM_STORED_DATA(sealedData); + } +egress: + TPM_AUTH_ERR_CHECK(pubAuth); + return status; +} + +TPM_RESULT TPM_Unseal( + TPM_KEY_HANDLE parentHandle, // in + const TPM_STORED_DATA* sealedData, + UINT32* outSize, // out + BYTE** out, //out + const TPM_AUTHDATA* key_usage_auth, //in + const TPM_AUTHDATA* data_usage_auth, //in + TPM_AUTH_SESSION* keyAuth, // in, out + TPM_AUTH_SESSION* dataAuth // in, out + ) +{ + TPM_BEGIN(TPM_TAG_RQU_AUTH2_COMMAND, TPM_ORD_Unseal); + TPM_AUTH_BEGIN(); + + TPM_AUTH_HASH(); + + ptr = pack_TPM_KEY_HANDLE(ptr, parentHandle); + + TPM_AUTH_SKIP(); + + ptr = pack_TPM_STORED_DATA(ptr, sealedData); + + TPM_AUTH_HASH(); + + TPM_AUTH1_GEN(key_usage_auth, keyAuth); + TPM_AUTH2_GEN(data_usage_auth, dataAuth); + TPM_TRANSMIT(); + TPM_UNPACK_VERIFY(); + TPM_AUTH_VERIFY_BEGIN(); + + ptr = unpack_UINT32(ptr, outSize); + ptr = unpack_ALLOC(ptr, out, *outSize); + + TPM_AUTH_HASH(); + + TPM_AUTH1_VERIFY(key_usage_auth, keyAuth); + TPM_AUTH2_VERIFY(data_usage_auth, dataAuth); + +abort_egress: + TPM_AUTH_ERR_CHECK(keyAuth); + TPM_AUTH_ERR_CHECK(dataAuth); + return status; +} + +TPM_RESULT TPM_Bind( + const TPM_KEY* key, + const BYTE* in, + UINT32 ilen, + BYTE* out) +{ + TPM_RESULT status; + tpmrsa_context rsa = TPMRSA_CTX_INIT; + TPM_BOUND_DATA boundData; + uint8_t plain[TCPA_MAX_BUFFER_LENGTH]; + BYTE* ptr = plain; + + vtpmloginfo(VTPM_LOG_TPM, "%s\n", __func__); + + tpmrsa_set_pubkey(&rsa, + key->pubKey.key, key->pubKey.keyLength, + key->algorithmParms.parms.rsa.exponent, + key->algorithmParms.parms.rsa.exponentSize); + + // Fill boundData's accessory information + boundData.ver = TPM_STRUCT_VER_1_1; + boundData.payload = TPM_PT_BIND; + boundData.payloadData = (BYTE*)in; + + //marshall the bound data object + ptr = pack_TPM_BOUND_DATA(ptr, &boundData, ilen); + + // Encrypt the data + TPMTRYRETURN(tpmrsa_pub_encrypt_oaep(&rsa, + ctr_drbg_random, &vtpm_globals.ctr_drbg, + ptr - plain, + plain, + out)); + +abort_egress: + tpmrsa_free(&rsa); + return status; + +} + +TPM_RESULT TPM_UnBind( + TPM_KEY_HANDLE keyHandle, // in + UINT32 ilen, //in + const BYTE* in, // + UINT32* olen, // + BYTE* out, //out + const TPM_AUTHDATA* usage_auth, + TPM_AUTH_SESSION* auth //in, out + ) +{ + TPM_BEGIN(TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_UnBind); + TPM_AUTH_BEGIN(); + + TPM_AUTH_HASH(); + + ptr = pack_TPM_KEY_HANDLE(ptr, keyHandle); + + TPM_AUTH_SKIP(); + + ptr = pack_UINT32(ptr, ilen); + ptr = pack_BUFFER(ptr, in, ilen); + + TPM_AUTH_HASH(); + + TPM_AUTH1_GEN(usage_auth, auth); + TPM_TRANSMIT(); + TPM_UNPACK_VERIFY(); + TPM_AUTH_VERIFY_BEGIN(); + + ptr = unpack_UINT32(ptr, olen); + if(*olen > ilen) { + vtpmlogerror(VTPM_LOG_TPM, "Output length < input length!\n"); + status = TPM_IOERROR; + goto abort_egress; + } + ptr = unpack_BUFFER(ptr, out, *olen); + + TPM_AUTH_HASH(); + + TPM_AUTH1_VERIFY(usage_auth, auth); + +abort_egress: +egress: + TPM_AUTH_ERR_CHECK(auth); + return status; +} + +TPM_RESULT TPM_CreateWrapKey( + TPM_KEY_HANDLE hWrappingKey, // in + const TPM_AUTHDATA* osapSharedSecret, + const TPM_AUTHDATA* dataUsageAuth, //in + const TPM_AUTHDATA* dataMigrationAuth, //in + TPM_KEY* key, //in, out + TPM_AUTH_SESSION* pAuth) // in, out +{ + int keyAlloced = 0; + TPM_BEGIN(TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_CreateWrapKey); + TPM_AUTH_BEGIN(); + + TPM_AUTH_HASH(); + + ptr = pack_TPM_KEY_HANDLE(ptr, hWrappingKey); + + TPM_AUTH_SKIP(); + + //Encrypted auths + xorEncrypt(osapSharedSecret, &pAuth->NonceEven, + dataUsageAuth, ptr, + dataMigrationAuth, ptr + sizeof(TPM_ENCAUTH)); + ptr += sizeof(TPM_ENCAUTH) * 2; + + ptr = pack_TPM_KEY(ptr, key); + + TPM_AUTH_HASH(); + + TPM_AUTH1_GEN(osapSharedSecret, pAuth); + TPM_TRANSMIT(); + TPM_UNPACK_VERIFY(); + TPM_AUTH_VERIFY_BEGIN(); + + keyAlloced = 1; + ptr = unpack_TPM_KEY(ptr, key, UNPACK_ALLOC); + + TPM_AUTH_HASH(); + + TPM_AUTH1_VERIFY(osapSharedSecret, pAuth); + + goto egress; +abort_egress: + if(keyAlloced) { + free_TPM_KEY(key); + } +egress: + TPM_AUTH_ERR_CHECK(pAuth); + return status; +} + +TPM_RESULT TPM_LoadKey( + TPM_KEY_HANDLE parentHandle, // + const TPM_KEY* key, //in + TPM_HANDLE* keyHandle, // out + const TPM_AUTHDATA* usage_auth, + TPM_AUTH_SESSION* auth) +{ + TPM_BEGIN(TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_LoadKey); + TPM_AUTH_BEGIN(); + + TPM_AUTH_HASH(); + + ptr = pack_TPM_KEY_HANDLE(ptr, parentHandle); + + TPM_AUTH_SKIP(); + + ptr = pack_TPM_KEY(ptr, key); + + TPM_AUTH_HASH(); + + TPM_AUTH1_GEN(usage_auth, auth); + TPM_TRANSMIT(); + TPM_UNPACK_VERIFY(); + TPM_AUTH_VERIFY_BEGIN(); + + ptr = unpack_UINT32(ptr, keyHandle); + + TPM_AUTH_HASH(); + + TPM_AUTH1_VERIFY(usage_auth, auth); + + vtpmloginfo(VTPM_LOG_TPM, "Key Handle: 0x%x opened by TPM_LoadKey\n", *keyHandle); + +abort_egress: + TPM_AUTH_ERR_CHECK(auth); + return status; +} + +TPM_RESULT TPM_EvictKey( TPM_KEY_HANDLE hKey) // in +{ + if(hKey == 0) { + return TPM_SUCCESS; + } + + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_EvictKey); + + ptr = pack_TPM_KEY_HANDLE(ptr, hKey); + + TPM_TRANSMIT(); + TPM_UNPACK_VERIFY(); + + vtpmloginfo(VTPM_LOG_TPM, "Key handle: 0x%x closed by TPM_EvictKey\n", hKey); + +abort_egress: + return status; +} + +TPM_RESULT TPM_FlushSpecific(TPM_HANDLE handle, + TPM_RESOURCE_TYPE rt) { + if(handle == 0) { + return TPM_SUCCESS; + } + + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_FlushSpecific); + + ptr = pack_TPM_HANDLE(ptr, handle); + ptr = pack_TPM_RESOURCE_TYPE(ptr, rt); + + TPM_TRANSMIT(); + TPM_UNPACK_VERIFY(); + +abort_egress: + return status; +} + +TPM_RESULT TPM_GetRandom( UINT32* bytesRequested, // in, out + BYTE* randomBytes) // out +{ + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_GetRandom); + + // check input params + if (bytesRequested == NULL || randomBytes == NULL){ + return TPM_BAD_PARAMETER; + } + + ptr = pack_UINT32(ptr, *bytesRequested); + + TPM_TRANSMIT(); + TPM_UNPACK_VERIFY(); + + ptr = unpack_UINT32(ptr, bytesRequested); + ptr = unpack_BUFFER(ptr, randomBytes, *bytesRequested); + +abort_egress: + return status; +} + + +TPM_RESULT TPM_ReadPubek( + TPM_PUBKEY* pubEK //out + ) +{ + BYTE* antiReplay = NULL; + BYTE* kptr = NULL; + BYTE digest[TPM_DIGEST_SIZE]; + sha1_context ctx; + + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_ReadPubek); + + //antiReplay nonce + vtpmmgr_rand(ptr, TPM_DIGEST_SIZE); + antiReplay = ptr; + ptr += TPM_DIGEST_SIZE; + + TPM_TRANSMIT(); + TPM_UNPACK_VERIFY(); + + //unpack and allocate the key + kptr = ptr; + ptr = unpack_TPM_PUBKEY(ptr, pubEK, UNPACK_ALLOC); + + //Verify the checksum + sha1_starts(&ctx); + sha1_update(&ctx, kptr, ptr - kptr); + sha1_update(&ctx, antiReplay, TPM_DIGEST_SIZE); + sha1_finish(&ctx, digest); + + //ptr points to the checksum computed by TPM + if(memcmp(digest, ptr, TPM_DIGEST_SIZE)) { + vtpmlogerror(VTPM_LOG_TPM, "TPM_ReadPubek: Checksum returned by TPM was invalid!\n"); + status = TPM_FAIL; + goto abort_egress; + } + + goto egress; +abort_egress: + if(kptr != NULL) { //If we unpacked the pubEK, we have to free it + free_TPM_PUBKEY(pubEK); + } +egress: + return status; +} + + +TPM_RESULT TPM_SaveState(void) +{ + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_SaveState); + + TPM_TRANSMIT(); + TPM_UNPACK_VERIFY(); + +abort_egress: + return status; +} + +TPM_RESULT TPM_GetCapability( + TPM_CAPABILITY_AREA capArea, + UINT32 subCapSize, + const BYTE* subCap, + UINT32* respSize, + BYTE** resp) +{ + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_GetCapability); + + ptr = pack_TPM_CAPABILITY_AREA(ptr, capArea); + ptr = pack_UINT32(ptr, subCapSize); + ptr = pack_BUFFER(ptr, subCap, subCapSize); + + TPM_TRANSMIT(); + TPM_UNPACK_VERIFY(); + + ptr = unpack_UINT32(ptr, respSize); + ptr = unpack_ALLOC(ptr, resp, *respSize); + +abort_egress: + return status; +} + +TPM_RESULT TPM_CreateEndorsementKeyPair( + const TPM_KEY_PARMS* keyInfo, + TPM_PUBKEY* pubEK) +{ + BYTE* kptr = NULL; + sha1_context ctx; + TPM_DIGEST checksum; + TPM_DIGEST hash; + TPM_NONCE antiReplay; + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_CreateEndorsementKeyPair); + + //Make anti replay nonce + vtpmmgr_rand(antiReplay.nonce, sizeof(antiReplay.nonce)); + + ptr = pack_TPM_NONCE(ptr, &antiReplay); + ptr = pack_TPM_KEY_PARMS(ptr, keyInfo); + + TPM_TRANSMIT(); + TPM_UNPACK_VERIFY(); + + sha1_starts(&ctx); + + kptr = ptr; + ptr = unpack_TPM_PUBKEY(ptr, pubEK, UNPACK_ALLOC); + + /* Hash the pub key blob */ + sha1_update(&ctx, kptr, ptr - kptr); + ptr = unpack_TPM_DIGEST(ptr, &checksum); + + sha1_update(&ctx, antiReplay.nonce, sizeof(antiReplay.nonce)); + + sha1_finish(&ctx, hash.digest); + if(memcmp(checksum.digest, hash.digest, TPM_DIGEST_SIZE)) { + vtpmloginfo(VTPM_LOG_VTPM, "TPM_CreateEndorsementKey: Checkum verification failed!\n"); + status = TPM_FAIL; + goto abort_egress; + } + + goto egress; +abort_egress: + if(kptr) { + free_TPM_PUBKEY(pubEK); + } +egress: + return status; +} + +TPM_RESULT TPM_TransmitData( + BYTE* in, + UINT32 insize, + BYTE* out, + UINT32* outsize) { + TPM_RESULT status = TPM_SUCCESS; + + UINT32 i; + vtpmloginfo(VTPM_LOG_TXDATA, "Sending buffer = 0x"); + for(i = 0 ; i < insize ; i++) + vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", in[i]); + + vtpmloginfomore(VTPM_LOG_TXDATA, "\n"); + + ssize_t size = 0; + + // send the request + size = write (vtpm_globals.tpm_fd, in, insize); + if (size < 0) { + vtpmlogerror(VTPM_LOG_TXDATA, "write() failed : %s\n", strerror(errno)); + ERRORDIE (TPM_IOERROR); + } + else if ((UINT32) size < insize) { + vtpmlogerror(VTPM_LOG_TXDATA, "Wrote %d instead of %d bytes!\n", (int) size, insize); + ERRORDIE (TPM_IOERROR); + } + + // read the response + size = read (vtpm_globals.tpm_fd, out, *outsize); + if (size < 0) { + vtpmlogerror(VTPM_LOG_TXDATA, "read() failed : %s\n", strerror(errno)); + ERRORDIE (TPM_IOERROR); + } + + vtpmloginfo(VTPM_LOG_TXDATA, "Receiving buffer = 0x"); + for(i = 0 ; i < size ; i++) + vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", out[i]); + + vtpmloginfomore(VTPM_LOG_TXDATA, "\n"); + + *outsize = size; + goto egress; + +abort_egress: +egress: + return status; +} diff --git a/stubdom/vtpmmgr/tpm.h b/stubdom/vtpmmgr/tpm.h new file mode 100644 index 0000000000..304e1450f8 --- /dev/null +++ b/stubdom/vtpmmgr/tpm.h @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2010-2012 United States Government, as represented by + * the Secretary of Defense. All rights reserved. + * + * based off of the original tools/vtpm_manager code base which is: + * Copyright (c) 2005/2006, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __TPM_H__ +#define __TPM_H__ + +#include "tcg.h" + +// ------------------------------------------------------------------ +// Exposed API +// ------------------------------------------------------------------ + +// TPM v1.1B Command Set + +// Authorzation +TPM_RESULT TPM_OIAP( + TPM_AUTH_SESSION* auth //out + ); + +TPM_RESULT TPM_OSAP ( + TPM_ENTITY_TYPE entityType, // in + UINT32 entityValue, // in + const TPM_AUTHDATA* usageAuth, //in + TPM_SECRET *sharedSecret, //out + TPM_AUTH_SESSION *auth); + +TPM_RESULT TPM_TakeOwnership( + const TPM_PUBKEY *pubEK, //in + const TPM_AUTHDATA* ownerAuth, //in + const TPM_AUTHDATA* srkAuth, //in + const TPM_KEY* inSrk, //in + TPM_KEY* outSrk, //out, optional + TPM_AUTH_SESSION* auth // in, out + ); + +TPM_RESULT TPM_DisablePubekRead ( + const TPM_AUTHDATA* ownerAuth, + TPM_AUTH_SESSION* auth + ); + +TPM_RESULT TPM_TerminateHandle ( TPM_AUTHHANDLE handle // in + ); + +TPM_RESULT TPM_FlushSpecific ( TPM_HANDLE handle, // in + TPM_RESOURCE_TYPE resourceType //in + ); + +// TPM Mandatory +TPM_RESULT TPM_Extend ( TPM_PCRINDEX pcrNum, // in + TPM_DIGEST inDigest, // in + TPM_PCRVALUE* outDigest // out + ); + +TPM_RESULT TPM_PcrRead ( TPM_PCRINDEX pcrNum, // in + TPM_PCRVALUE* outDigest // out + ); + +TPM_RESULT TPM_Quote ( TCS_KEY_HANDLE keyHandle, // in + TPM_NONCE antiReplay, // in + UINT32* PcrDataSize, // in, out + BYTE** PcrData, // in, out + TPM_AUTH_SESSION* privAuth, // in, out + UINT32* sigSize, // out + BYTE** sig // out + ); + +TPM_RESULT TPM_Seal( + TCS_KEY_HANDLE keyHandle, // in + UINT32 pcrInfoSize, // in + TPM_PCR_INFO* pcrInfo, // in + UINT32 inDataSize, // in + const BYTE* inData, // in + TPM_STORED_DATA* sealedData, //out + const TPM_SECRET* osapSharedSecret, //in + const TPM_AUTHDATA* sealDataAuth, //in + TPM_AUTH_SESSION* pubAuth // in, out + ); + +TPM_RESULT TPM_Unseal ( + TPM_KEY_HANDLE parentHandle, // in + const TPM_STORED_DATA* sealedData, + UINT32* outSize, // out + BYTE** out, //out + const TPM_AUTHDATA* key_usage_auth, //in + const TPM_AUTHDATA* data_usage_auth, //in + TPM_AUTH_SESSION* keyAuth, // in, out + TPM_AUTH_SESSION* dataAuth // in, out + ); + +TPM_RESULT TPM_DirWriteAuth ( TPM_DIRINDEX dirIndex, // in + TPM_DIRVALUE newContents, // in + TPM_AUTH_SESSION* ownerAuth // in, out + ); + +TPM_RESULT TPM_DirRead ( TPM_DIRINDEX dirIndex, // in + TPM_DIRVALUE* dirValue // out + ); + +TPM_RESULT TPM_Bind( + const TPM_KEY* key, //in + const BYTE* in, //in + UINT32 ilen, //in + BYTE* out //out, must be at least cipher block size + ); + +TPM_RESULT TPM_UnBind ( + TCS_KEY_HANDLE keyHandle, // in + UINT32 ilen, //in + const BYTE* in, // + UINT32* outDataSize, // out + BYTE* outData, //out + const TPM_AUTHDATA* usage_auth, + TPM_AUTH_SESSION* auth //in, out + ); + +TPM_RESULT TPM_CreateWrapKey ( + TCS_KEY_HANDLE hWrappingKey, // in + const TPM_AUTHDATA* osapSharedSecret, + const TPM_AUTHDATA* dataUsageAuth, //in + const TPM_AUTHDATA* dataMigrationAuth, //in + TPM_KEY* key, //in + TPM_AUTH_SESSION* pAuth // in, out + ); + +TPM_RESULT TPM_LoadKey ( + TPM_KEY_HANDLE parentHandle, // + const TPM_KEY* key, //in + TPM_HANDLE* keyHandle, // out + const TPM_AUTHDATA* usage_auth, + TPM_AUTH_SESSION* auth + ); + +TPM_RESULT TPM_GetPubKey ( TCS_KEY_HANDLE hKey, // in + TPM_AUTH_SESSION* pAuth, // in, out + UINT32* pcPubKeySize, // out + BYTE** prgbPubKey // out + ); + +TPM_RESULT TPM_EvictKey ( TCS_KEY_HANDLE hKey // in + ); + +TPM_RESULT TPM_FlushSpecific(TPM_HANDLE handle, //in + TPM_RESOURCE_TYPE rt //in + ); + +TPM_RESULT TPM_Sign ( TCS_KEY_HANDLE keyHandle, // in + UINT32 areaToSignSize, // in + BYTE* areaToSign, // in + TPM_AUTH_SESSION* privAuth, // in, out + UINT32* sigSize, // out + BYTE** sig // out + ); + +TPM_RESULT TPM_GetRandom ( UINT32* bytesRequested, // in, out + BYTE* randomBytes // out + ); + +TPM_RESULT TPM_StirRandom ( UINT32 inDataSize, // in + BYTE* inData // in + ); + +TPM_RESULT TPM_ReadPubek ( + TPM_PUBKEY* pubEK //out + ); + +TPM_RESULT TPM_GetCapability( + TPM_CAPABILITY_AREA capArea, + UINT32 subCapSize, + const BYTE* subCap, + UINT32* respSize, + BYTE** resp); + +TPM_RESULT TPM_SaveState(void); + +TPM_RESULT TPM_CreateEndorsementKeyPair( + const TPM_KEY_PARMS* keyInfo, + TPM_PUBKEY* pubEK); + +TPM_RESULT TPM_TransmitData( + BYTE* in, + UINT32 insize, + BYTE* out, + UINT32* outsize); + +#endif //TPM_H diff --git a/stubdom/vtpmmgr/tpmrsa.c b/stubdom/vtpmmgr/tpmrsa.c new file mode 100644 index 0000000000..56094e735f --- /dev/null +++ b/stubdom/vtpmmgr/tpmrsa.c @@ -0,0 +1,175 @@ +/* + * The RSA public-key cryptosystem + * + * Copyright (C) 2006-2011, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * RSA was designed by Ron Rivest, Adi Shamir and Len Adleman. + * + * http://theory.lcs.mit.edu/~rivest/rsapaper.pdf + * http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf + */ + +#include "tcg.h" +#include "polarssl/sha1.h" + +#include +#include + +#include "tpmrsa.h" + +#define HASH_LEN 20 + +void tpmrsa_set_pubkey(tpmrsa_context* ctx, + const unsigned char* key, + int keylen, + const unsigned char* exponent, + int explen) { + + tpmrsa_free(ctx); + + if(explen == 0) { //Default e= 2^16+1 + mpi_lset(&ctx->E, 65537); + } else { + mpi_read_binary(&ctx->E, exponent, explen); + } + mpi_read_binary(&ctx->N, key, keylen); + + ctx->len = ( mpi_msb(&ctx->N) + 7) >> 3; +} + +static TPM_RESULT tpmrsa_public( tpmrsa_context *ctx, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t olen; + mpi T; + + mpi_init( &T ); + + MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); + + if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + mpi_free( &T ); + return TPM_ENCRYPT_ERROR; + } + + olen = ctx->len; + MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); + MPI_CHK( mpi_write_binary( &T, output, olen ) ); + +cleanup: + + mpi_free( &T ); + + if( ret != 0 ) + return TPM_ENCRYPT_ERROR; + + return TPM_SUCCESS; +} + +static void mgf_mask( unsigned char *dst, int dlen, unsigned char *src, int slen) +{ + unsigned char mask[HASH_LEN]; + unsigned char counter[4] = {0, 0, 0, 0}; + int i; + sha1_context mctx; + + //We always hash the src with the counter, so save the partial hash + sha1_starts(&mctx); + sha1_update(&mctx, src, slen); + + // Generate and apply dbMask + while(dlen > 0) { + //Copy the sha1 context + sha1_context ctx = mctx; + + //compute hash for input || counter + sha1_update(&ctx, counter, sizeof(counter)); + sha1_finish(&ctx, mask); + + //Apply the mask + for(i = 0; i < (dlen < HASH_LEN ? dlen : HASH_LEN); ++i) { + *(dst++) ^= mask[i]; + } + + //Increment counter + ++counter[3]; + + dlen -= HASH_LEN; + } +} + +/* + * Add the message padding, then do an RSA operation + */ +TPM_RESULT tpmrsa_pub_encrypt_oaep( tpmrsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + int olen; + unsigned char* seed = output + 1; + unsigned char* db = output + HASH_LEN +1; + + olen = ctx->len-1; + + if( f_rng == NULL ) + return TPM_ENCRYPT_ERROR; + + if( ilen > olen - 2 * HASH_LEN - 1) + return TPM_ENCRYPT_ERROR; + + output[0] = 0; + + //Encoding parameter p + sha1((unsigned char*)"TCPA", 4, db); + + //PS + memset(db + HASH_LEN, 0, + olen - ilen - 2 * HASH_LEN - 1); + + //constant 1 byte + db[olen - ilen - HASH_LEN -1] = 0x01; + + //input string + memcpy(db + olen - ilen - HASH_LEN, + input, ilen); + + //Generate random seed + if( ( ret = f_rng( p_rng, seed, HASH_LEN ) ) != 0 ) + return TPM_ENCRYPT_ERROR; + + // maskedDB: Apply dbMask to DB + mgf_mask( db, olen - HASH_LEN, seed, HASH_LEN); + + // maskedSeed: Apply seedMask to seed + mgf_mask( seed, HASH_LEN, db, olen - HASH_LEN); + + // Do the crypto op + return tpmrsa_public(ctx, output, output); +} diff --git a/stubdom/vtpmmgr/tpmrsa.h b/stubdom/vtpmmgr/tpmrsa.h new file mode 100644 index 0000000000..59579e7c3c --- /dev/null +++ b/stubdom/vtpmmgr/tpmrsa.h @@ -0,0 +1,67 @@ +/** + * \file rsa.h + * + * \brief The RSA public-key cryptosystem + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef TPMRSA_H +#define TPMRSA_H + +#include "tcg.h" +#include + +/* tpm software key */ +typedef struct +{ + size_t len; /*!< size(N) in chars */ + + mpi N; /*!< public modulus */ + mpi E; /*!< public exponent */ + + mpi RN; /*!< cached R^2 mod N */ +} +tpmrsa_context; + +#define TPMRSA_CTX_INIT { 0, {0, 0, NULL}, {0, 0, NULL}, {0, 0, NULL}} + +/* Setup the rsa context using tpm public key data */ +void tpmrsa_set_pubkey(tpmrsa_context* ctx, + const unsigned char* key, + int keylen, + const unsigned char* exponent, + int explen); + +/* Do rsa public crypto */ +TPM_RESULT tpmrsa_pub_encrypt_oaep( tpmrsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/* free tpmrsa key */ +inline void tpmrsa_free( tpmrsa_context *ctx ) { + mpi_free( &ctx->RN ); mpi_free( &ctx->E ); mpi_free( &ctx->N ); +} + +#endif /* tpmrsa.h */ diff --git a/stubdom/vtpmmgr/uuid.h b/stubdom/vtpmmgr/uuid.h new file mode 100644 index 0000000000..4737645599 --- /dev/null +++ b/stubdom/vtpmmgr/uuid.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2010-2012 United States Government, as represented by + * the Secretary of Defense. All rights reserved. + * + * based off of the original tools/vtpm_manager code base which is: + * Copyright (c) 2005, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef VTPMMGR_UUID_H +#define VTPMMGR_UUID_H + +#define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx" +#define UUID_FMTLEN ((2*16)+4) /* 16 hex bytes plus 4 hypens */ +#define UUID_BYTES(uuid) uuid[0], uuid[1], uuid[2], uuid[3], \ + uuid[4], uuid[5], uuid[6], uuid[7], \ + uuid[8], uuid[9], uuid[10], uuid[11], \ + uuid[12], uuid[13], uuid[14], uuid[15] + + +typedef uint8_t uuid_t[16]; + +#endif diff --git a/stubdom/vtpmmgr/vtpm_cmd_handler.c b/stubdom/vtpmmgr/vtpm_cmd_handler.c new file mode 100644 index 0000000000..f82a2a9720 --- /dev/null +++ b/stubdom/vtpmmgr/vtpm_cmd_handler.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2010-2012 United States Government, as represented by + * the Secretary of Defense. All rights reserved. + * + * based off of the original tools/vtpm_manager code base which is: + * Copyright (c) 2005, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include + +#include "marshal.h" +#include "log.h" +#include "vtpm_storage.h" +#include "vtpmmgr.h" +#include "tpm.h" +#include "tcg.h" + +static TPM_RESULT vtpmmgr_SaveHashKey( + const uuid_t uuid, + tpmcmd_t* tpmcmd) +{ + TPM_RESULT status = TPM_SUCCESS; + + if(tpmcmd->req_len != VTPM_COMMAND_HEADER_SIZE + HASHKEYSZ) { + vtpmlogerror(VTPM_LOG_VTPM, "VTPM_ORD_SAVEHASHKEY hashkey too short!\n"); + status = TPM_BAD_PARAMETER; + goto abort_egress; + } + + /* Do the command */ + TPMTRYRETURN(vtpm_storage_save_hashkey(uuid, tpmcmd->req + VTPM_COMMAND_HEADER_SIZE)); + +abort_egress: + pack_TPM_RSP_HEADER(tpmcmd->resp, + VTPM_TAG_RSP, VTPM_COMMAND_HEADER_SIZE, status); + tpmcmd->resp_len = VTPM_COMMAND_HEADER_SIZE; + + return status; +} + +static TPM_RESULT vtpmmgr_LoadHashKey( + const uuid_t uuid, + tpmcmd_t* tpmcmd) { + TPM_RESULT status = TPM_SUCCESS; + + tpmcmd->resp_len = VTPM_COMMAND_HEADER_SIZE; + + TPMTRYRETURN(vtpm_storage_load_hashkey(uuid, tpmcmd->resp + VTPM_COMMAND_HEADER_SIZE)); + + tpmcmd->resp_len += HASHKEYSZ; + +abort_egress: + pack_TPM_RSP_HEADER(tpmcmd->resp, + VTPM_TAG_RSP, tpmcmd->resp_len, status); + + return status; +} + + +TPM_RESULT vtpmmgr_handle_cmd( + const uuid_t uuid, + tpmcmd_t* tpmcmd) +{ + TPM_RESULT status = TPM_SUCCESS; + TPM_TAG tag; + UINT32 size; + TPM_COMMAND_CODE ord; + + unpack_TPM_RQU_HEADER(tpmcmd->req, + &tag, &size, &ord); + + /* Handle the command now */ + switch(tag) { + case VTPM_TAG_REQ: + //This is a vTPM command + switch(ord) { + case VTPM_ORD_SAVEHASHKEY: + return vtpmmgr_SaveHashKey(uuid, tpmcmd); + case VTPM_ORD_LOADHASHKEY: + return vtpmmgr_LoadHashKey(uuid, tpmcmd); + default: + vtpmlogerror(VTPM_LOG_VTPM, "Invalid vTPM Ordinal %" PRIu32 "\n", ord); + status = TPM_BAD_ORDINAL; + } + break; + case TPM_TAG_RQU_COMMAND: + case TPM_TAG_RQU_AUTH1_COMMAND: + case TPM_TAG_RQU_AUTH2_COMMAND: + //This is a TPM passthrough command + switch(ord) { + case TPM_ORD_GetRandom: + vtpmloginfo(VTPM_LOG_VTPM, "Passthrough: TPM_GetRandom\n"); + break; + case TPM_ORD_PcrRead: + vtpmloginfo(VTPM_LOG_VTPM, "Passthrough: TPM_PcrRead\n"); + break; + default: + vtpmlogerror(VTPM_LOG_VTPM, "TPM Disallowed Passthrough ord=%" PRIu32 "\n", ord); + status = TPM_DISABLED_CMD; + goto abort_egress; + } + + size = TCPA_MAX_BUFFER_LENGTH; + TPMTRYRETURN(TPM_TransmitData(tpmcmd->req, tpmcmd->req_len, tpmcmd->resp, &size)); + tpmcmd->resp_len = size; + + unpack_TPM_RESULT(tpmcmd->resp + sizeof(TPM_TAG) + sizeof(UINT32), &status); + return status; + + break; + default: + vtpmlogerror(VTPM_LOG_VTPM, "Invalid tag=%" PRIu16 "\n", tag); + status = TPM_BADTAG; + } + +abort_egress: + tpmcmd->resp_len = VTPM_COMMAND_HEADER_SIZE; + pack_TPM_RSP_HEADER(tpmcmd->resp, + tag + 3, tpmcmd->resp_len, status); + + return status; +} diff --git a/stubdom/vtpmmgr/vtpm_manager.h b/stubdom/vtpmmgr/vtpm_manager.h new file mode 100644 index 0000000000..a2bbcca064 --- /dev/null +++ b/stubdom/vtpmmgr/vtpm_manager.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2010-2012 United States Government, as represented by + * the Secretary of Defense. All rights reserved. + * + * based off of the original tools/vtpm_manager code base which is: + * Copyright (c) 2005, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef VTPM_MANAGER_H +#define VTPM_MANAGER_H + +#define VTPM_TAG_REQ 0x01c1 +#define VTPM_TAG_RSP 0x01c4 +#define COMMAND_BUFFER_SIZE 4096 + +// Header size +#define VTPM_COMMAND_HEADER_SIZE ( 2 + 4 + 4) + +//************************ Command Codes **************************** +#define VTPM_ORD_BASE 0x0000 +#define VTPM_PRIV_MASK 0x01000000 // Priviledged VTPM Command +#define VTPM_PRIV_BASE (VTPM_ORD_BASE | VTPM_PRIV_MASK) + +// Non-priviledged VTPM Commands (From DMI's) +#define VTPM_ORD_SAVEHASHKEY (VTPM_ORD_BASE + 1) // DMI requests encryption key for persistent storage +#define VTPM_ORD_LOADHASHKEY (VTPM_ORD_BASE + 2) // DMI requests symkey to be regenerated + +//************************ Return Codes **************************** +#define VTPM_SUCCESS 0 +#define VTPM_FAIL 1 +#define VTPM_UNSUPPORTED 2 +#define VTPM_FORBIDDEN 3 +#define VTPM_RESTORE_CONTEXT_FAILED 4 +#define VTPM_INVALID_REQUEST 5 + +#endif diff --git a/stubdom/vtpmmgr/vtpm_storage.c b/stubdom/vtpmmgr/vtpm_storage.c new file mode 100644 index 0000000000..abb0dba297 --- /dev/null +++ b/stubdom/vtpmmgr/vtpm_storage.c @@ -0,0 +1,794 @@ +/* + * 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. + */ + +/*************************************************************** + * DISK IMAGE LAYOUT + * ************************************************************* + * All data is stored in BIG ENDIAN format + * ************************************************************* + * Section 1: Header + * + * 10 bytes id ID String "VTPMMGRDOM" + * uint32_t version Disk Image version number (current == 1) + * uint32_t storage_key_len Length of the storage Key + * TPM_KEY storage_key Marshalled TPM_KEY structure (See TPM spec v2) + * RSA_BLOCK aes_crypto Encrypted aes key data (RSA_CIPHER_SIZE bytes), bound by the storage_key + * BYTE[32] aes_key Aes key for encrypting the uuid table + * uint32_t cipher_sz Encrypted size of the uuid table + * + * ************************************************************* + * Section 2: Uuid Table + * + * This table is encrypted by the aes_key in the header. The cipher text size is just + * large enough to hold all of the entries plus required padding. + * + * Each entry is as follows + * BYTE[16] uuid Uuid of a vtpm that is stored on this disk + * uint32_t offset Disk offset where the vtpm data is stored + * + * ************************************************************* + * Section 3: Vtpm Table + * + * The rest of the disk stores vtpms. Each vtpm is an RSA_BLOCK encrypted + * by the storage key. Each vtpm must exist on an RSA_BLOCK aligned boundary, + * starting at the first RSA_BLOCK aligned offset after the uuid table. + * As the uuid table grows, vtpms may be relocated. + * + * RSA_BLOCK vtpm_crypto Vtpm data encrypted by storage_key + * BYTE[20] hash Sha1 hash of vtpm encrypted data + * BYTE[16] vtpm_aes_key Encryption key for vtpm data + * + ************************************************************* + */ +#define DISKVERS 1 +#define IDSTR "VTPMMGRDOM" +#define IDSTRLEN 10 +#define AES_BLOCK_SIZE 16 +#define AES_KEY_BITS 256 +#define AES_KEY_SIZE (AES_KEY_BITS/8) +#define BUF_SIZE 4096 + +#define UUID_TBL_ENT_SIZE (sizeof(uuid_t) + sizeof(uint32_t)) + +#define HEADERSZ (10 + 4 + 4) + +#define TRY_READ(buf, size, msg) do {\ + int rc; \ + if((rc = read(blkfront_fd, buf, (size))) != (size)) { \ + vtpmlogerror(VTPM_LOG_VTPM, "read() failed! " msg " : rc=(%d/%d), error=(%s)\n", rc, (int)(size), strerror(errno)); \ + status = TPM_IOERROR;\ + goto abort_egress;\ + } \ +} while(0) + +#define TRY_WRITE(buf, size, msg) do {\ + int rc; \ + if((rc = write(blkfront_fd, buf, (size))) != (size)) { \ + vtpmlogerror(VTPM_LOG_VTPM, "write() failed! " msg " : rc=(%d/%d), error=(%s)\n", rc, (int)(size), strerror(errno)); \ + status = TPM_IOERROR;\ + goto abort_egress;\ + } \ +} while(0) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vtpm_manager.h" +#include "log.h" +#include "marshal.h" +#include "tpm.h" +#include "uuid.h" + +#include "vtpmmgr.h" +#include "vtpm_storage.h" + +#define MAX(a,b) ( ((a) > (b)) ? (a) : (b) ) +#define MIN(a,b) ( ((a) < (b)) ? (a) : (b) ) + +/* blkfront device objets */ +static struct blkfront_dev* blkdev = NULL; +static int blkfront_fd = -1; + +struct Vtpm { + uuid_t uuid; + int offset; +}; +struct Storage { + int aes_offset; + int uuid_offset; + int end_offset; + + int num_vtpms; + int num_vtpms_alloced; + struct Vtpm* vtpms; +}; + +/* Global storage data */ +static struct Storage g_store = { + .vtpms = NULL, +}; + +static int get_offset(void) { + return lseek(blkfront_fd, 0, SEEK_CUR); +} + +static void reset_store(void) { + g_store.aes_offset = 0; + g_store.uuid_offset = 0; + g_store.end_offset = 0; + + g_store.num_vtpms = 0; + g_store.num_vtpms_alloced = 0; + free(g_store.vtpms); + g_store.vtpms = NULL; +} + +static int vtpm_get_index(const uuid_t uuid) { + int st = 0; + int ed = g_store.num_vtpms-1; + while(st <= ed) { + int mid = ((unsigned int)st + (unsigned int)ed) >> 1; //avoid overflow + int c = memcmp(uuid, &g_store.vtpms[mid].uuid, sizeof(uuid_t)); + if(c == 0) { + return mid; + } else if(c > 0) { + st = mid + 1; + } else { + ed = mid - 1; + } + } + return -(st + 1); +} + +static void vtpm_add(const uuid_t uuid, int offset, int index) { + /* Realloc more space if needed */ + if(g_store.num_vtpms >= g_store.num_vtpms_alloced) { + g_store.num_vtpms_alloced += 16; + g_store.vtpms = realloc( + g_store.vtpms, + sizeof(struct Vtpm) * g_store.num_vtpms_alloced); + } + + /* Move everybody after the new guy */ + for(int i = g_store.num_vtpms; i > index; --i) { + g_store.vtpms[i] = g_store.vtpms[i-1]; + } + + vtpmloginfo(VTPM_LOG_VTPM, "Registered vtpm " UUID_FMT "\n", UUID_BYTES(uuid)); + + /* Finally add new one */ + memcpy(g_store.vtpms[index].uuid, uuid, sizeof(uuid_t)); + g_store.vtpms[index].offset = offset; + ++g_store.num_vtpms; +} + +#if 0 +static void vtpm_remove(int index) { + for(i = index; i < g_store.num_vtpms; ++i) { + g_store.vtpms[i] = g_store.vtpms[i+1]; + } + --g_store.num_vtpms; +} +#endif + +static int pack_uuid_table(uint8_t* table, int size, int* nvtpms) { + uint8_t* ptr = table; + while(*nvtpms < g_store.num_vtpms && size >= 0) + { + /* Pack the uuid */ + memcpy(ptr, (uint8_t*)g_store.vtpms[*nvtpms].uuid, sizeof(uuid_t)); + ptr+= sizeof(uuid_t); + + + /* Pack the offset */ + ptr = pack_UINT32(ptr, g_store.vtpms[*nvtpms].offset); + + ++*nvtpms; + size -= UUID_TBL_ENT_SIZE; + } + return ptr - table; +} + +/* Extract the uuids */ +static int extract_uuid_table(uint8_t* table, int size) { + uint8_t* ptr = table; + for(;size >= UUID_TBL_ENT_SIZE; size -= UUID_TBL_ENT_SIZE) { + int index; + uint32_t v32; + + /*uuid_t is just an array of bytes, so we can do a direct cast here */ + uint8_t* uuid = ptr; + ptr += sizeof(uuid_t); + + /* Get the offset of the key */ + ptr = unpack_UINT32(ptr, &v32); + + /* Insert the new vtpm in sorted order */ + if((index = vtpm_get_index(uuid)) >= 0) { + vtpmlogerror(VTPM_LOG_VTPM, "Vtpm (" UUID_FMT ") exists multiple times! ignoring...\n", UUID_BYTES(uuid)); + continue; + } + index = -index -1; + + vtpm_add(uuid, v32, index); + + } + return ptr - table; +} + +static void vtpm_decrypt_block(aes_context* aes, + uint8_t* iv, + uint8_t* cipher, + uint8_t* plain, + int cipher_sz, + int* overlap) +{ + int bytes_ext; + /* Decrypt */ + aes_crypt_cbc(aes, AES_DECRYPT, + cipher_sz, + iv, cipher, plain + *overlap); + + /* Extract */ + bytes_ext = extract_uuid_table(plain, cipher_sz + *overlap); + + /* Copy left overs to the beginning */ + *overlap = cipher_sz + *overlap - bytes_ext; + memcpy(plain, plain + bytes_ext, *overlap); +} + +static int vtpm_encrypt_block(aes_context* aes, + uint8_t* iv, + uint8_t* plain, + uint8_t* cipher, + int block_sz, + int* overlap, + int* num_vtpms) +{ + int bytes_to_crypt; + int bytes_packed; + + /* Pack the uuid table */ + bytes_packed = *overlap + pack_uuid_table(plain + *overlap, block_sz - *overlap, num_vtpms); + bytes_to_crypt = MIN(bytes_packed, block_sz); + + /* Add padding if we aren't on a multiple of the block size */ + if(bytes_to_crypt & (AES_BLOCK_SIZE-1)) { + int oldsz = bytes_to_crypt; + //add padding + bytes_to_crypt += AES_BLOCK_SIZE - (bytes_to_crypt & (AES_BLOCK_SIZE-1)); + //fill padding with random bytes + vtpmmgr_rand(plain + oldsz, bytes_to_crypt - oldsz); + *overlap = 0; + } else { + *overlap = bytes_packed - bytes_to_crypt; + } + + /* Encrypt this chunk */ + aes_crypt_cbc(aes, AES_ENCRYPT, + bytes_to_crypt, + iv, plain, cipher); + + /* Copy the left over partials to the beginning */ + memcpy(plain, plain + bytes_to_crypt, *overlap); + + return bytes_to_crypt; +} + +static TPM_RESULT vtpm_storage_new_vtpm(const uuid_t uuid, int index) { + TPM_RESULT status = TPM_SUCCESS; + uint8_t plain[BUF_SIZE + AES_BLOCK_SIZE]; + uint8_t buf[BUF_SIZE]; + uint8_t* ptr; + int cipher_sz; + aes_context aes; + + /* Add new vtpm to the table */ + vtpm_add(uuid, g_store.end_offset, index); + g_store.end_offset += RSA_CIPHER_SIZE; + + /* Compute the new end location of the encrypted uuid table */ + cipher_sz = AES_BLOCK_SIZE; //IV + cipher_sz += g_store.num_vtpms * UUID_TBL_ENT_SIZE; //uuid table + cipher_sz += (AES_BLOCK_SIZE - (cipher_sz & (AES_BLOCK_SIZE -1))) & (AES_BLOCK_SIZE-1); //aes padding + + /* Does this overlap any key data? If so they need to be relocated */ + int uuid_end = (g_store.uuid_offset + cipher_sz + RSA_CIPHER_SIZE) & ~(RSA_CIPHER_SIZE -1); + for(int i = 0; i < g_store.num_vtpms; ++i) { + if(g_store.vtpms[i].offset < uuid_end) { + + vtpmloginfo(VTPM_LOG_VTPM, "Relocating vtpm data\n"); + + //Read the hashkey cipher text + lseek(blkfront_fd, g_store.vtpms[i].offset, SEEK_SET); + TRY_READ(buf, RSA_CIPHER_SIZE, "vtpm hashkey relocate"); + + //Write the cipher text to new offset + lseek(blkfront_fd, g_store.end_offset, SEEK_SET); + TRY_WRITE(buf, RSA_CIPHER_SIZE, "vtpm hashkey relocate"); + + //Save new offset + g_store.vtpms[i].offset = g_store.end_offset; + g_store.end_offset += RSA_CIPHER_SIZE; + } + } + + vtpmloginfo(VTPM_LOG_VTPM, "Generating a new symmetric key\n"); + + /* Generate an aes key */ + TPMTRYRETURN(vtpmmgr_rand(plain, AES_KEY_SIZE)); + aes_setkey_enc(&aes, plain, AES_KEY_BITS); + ptr = plain + AES_KEY_SIZE; + + /* Pack the crypted size */ + ptr = pack_UINT32(ptr, cipher_sz); + + vtpmloginfo(VTPM_LOG_VTPM, "Binding encrypted key\n"); + + /* Seal the key and size */ + TPMTRYRETURN(TPM_Bind(&vtpm_globals.storage_key, + plain, + ptr - plain, + buf)); + + /* Write the sealed key to disk */ + lseek(blkfront_fd, g_store.aes_offset, SEEK_SET); + TRY_WRITE(buf, RSA_CIPHER_SIZE, "vtpm aes key"); + + /* ENCRYPT AND WRITE UUID TABLE */ + + vtpmloginfo(VTPM_LOG_VTPM, "Encrypting the uuid table\n"); + + int num_vtpms = 0; + int overlap = 0; + int bytes_crypted; + uint8_t iv[AES_BLOCK_SIZE]; + + /* Generate the iv for the first block */ + TPMTRYRETURN(vtpmmgr_rand(iv, AES_BLOCK_SIZE)); + + /* Copy the iv to the cipher text buffer to be written to disk */ + memcpy(buf, iv, AES_BLOCK_SIZE); + ptr = buf + AES_BLOCK_SIZE; + + /* Encrypt the first block of the uuid table */ + bytes_crypted = vtpm_encrypt_block(&aes, + iv, //iv + plain, //plaintext + ptr, //cipher text + BUF_SIZE - AES_BLOCK_SIZE, + &overlap, + &num_vtpms); + + /* Write the iv followed by the crypted table*/ + TRY_WRITE(buf, bytes_crypted + AES_BLOCK_SIZE, "vtpm uuid table"); + + /* Decrement the number of bytes encrypted */ + cipher_sz -= bytes_crypted + AES_BLOCK_SIZE; + + /* If there are more vtpms, encrypt and write them block by block */ + while(cipher_sz > 0) { + /* Encrypt the next block of the uuid table */ + bytes_crypted = vtpm_encrypt_block(&aes, + iv, + plain, + buf, + BUF_SIZE, + &overlap, + &num_vtpms); + + /* Write the cipher text to disk */ + TRY_WRITE(buf, bytes_crypted, "vtpm uuid table"); + + cipher_sz -= bytes_crypted; + } + + goto egress; +abort_egress: +egress: + return status; +} + + +/************************************** + * PUBLIC FUNCTIONS + * ***********************************/ + +int vtpm_storage_init(void) { + struct blkfront_info info; + if((blkdev = init_blkfront(NULL, &info)) == NULL) { + return -1; + } + if((blkfront_fd = blkfront_open(blkdev)) < 0) { + return -1; + } + return 0; +} + +void vtpm_storage_shutdown(void) { + reset_store(); + close(blkfront_fd); +} + +TPM_RESULT vtpm_storage_load_hashkey(const uuid_t uuid, uint8_t hashkey[HASHKEYSZ]) +{ + TPM_RESULT status = TPM_SUCCESS; + int index; + uint8_t cipher[RSA_CIPHER_SIZE]; + uint8_t clear[RSA_CIPHER_SIZE]; + UINT32 clear_size; + + /* Find the index of this uuid */ + if((index = vtpm_get_index(uuid)) < 0) { + index = -index-1; + vtpmlogerror(VTPM_LOG_VTPM, "LoadKey failure: Unrecognized uuid! " UUID_FMT "\n", UUID_BYTES(uuid)); + status = TPM_BAD_PARAMETER; + goto abort_egress; + } + + /* Read the table entry */ + lseek(blkfront_fd, g_store.vtpms[index].offset, SEEK_SET); + TRY_READ(cipher, RSA_CIPHER_SIZE, "vtpm hashkey data"); + + /* Decrypt the table entry */ + TPMTRYRETURN(TPM_UnBind( + vtpm_globals.storage_key_handle, + RSA_CIPHER_SIZE, + cipher, + &clear_size, + clear, + (const TPM_AUTHDATA*)&vtpm_globals.storage_key_usage_auth, + &vtpm_globals.oiap)); + + if(clear_size < HASHKEYSZ) { + vtpmloginfo(VTPM_LOG_VTPM, "Decrypted Hash key size (%" PRIu32 ") was too small!\n", clear_size); + status = TPM_RESOURCES; + goto abort_egress; + } + + memcpy(hashkey, clear, HASHKEYSZ); + + vtpmloginfo(VTPM_LOG_VTPM, "Loaded hash and key for vtpm " UUID_FMT "\n", UUID_BYTES(uuid)); + goto egress; +abort_egress: + vtpmlogerror(VTPM_LOG_VTPM, "Failed to load key\n"); +egress: + return status; +} + +TPM_RESULT vtpm_storage_save_hashkey(const uuid_t uuid, uint8_t hashkey[HASHKEYSZ]) +{ + TPM_RESULT status = TPM_SUCCESS; + int index; + uint8_t buf[RSA_CIPHER_SIZE]; + + /* Find the index of this uuid */ + if((index = vtpm_get_index(uuid)) < 0) { + index = -index-1; + /* Create a new vtpm */ + TPMTRYRETURN( vtpm_storage_new_vtpm(uuid, index) ); + } + + /* Encrypt the hash and key */ + TPMTRYRETURN( TPM_Bind(&vtpm_globals.storage_key, + hashkey, + HASHKEYSZ, + buf)); + + /* Write to disk */ + lseek(blkfront_fd, g_store.vtpms[index].offset, SEEK_SET); + TRY_WRITE(buf, RSA_CIPHER_SIZE, "vtpm hashkey data"); + + vtpmloginfo(VTPM_LOG_VTPM, "Saved hash and key for vtpm " UUID_FMT "\n", UUID_BYTES(uuid)); + goto egress; +abort_egress: + vtpmlogerror(VTPM_LOG_VTPM, "Failed to save key\n"); +egress: + return status; +} + +TPM_RESULT vtpm_storage_new_header() +{ + TPM_RESULT status = TPM_SUCCESS; + uint8_t buf[BUF_SIZE]; + uint8_t keybuf[AES_KEY_SIZE + sizeof(uint32_t)]; + uint8_t* ptr = buf; + uint8_t* sptr; + + /* Clear everything first */ + reset_store(); + + vtpmloginfo(VTPM_LOG_VTPM, "Creating new disk image header\n"); + + /*Copy the ID string */ + memcpy(ptr, IDSTR, IDSTRLEN); + ptr += IDSTRLEN; + + /*Copy the version */ + ptr = pack_UINT32(ptr, DISKVERS); + + /*Save the location of the key size */ + sptr = ptr; + ptr += sizeof(UINT32); + + vtpmloginfo(VTPM_LOG_VTPM, "Saving root storage key..\n"); + + /* Copy the storage key */ + ptr = pack_TPM_KEY(ptr, &vtpm_globals.storage_key); + + /* Now save the size */ + pack_UINT32(sptr, ptr - (sptr + 4)); + + /* Create a fake aes key and set cipher text size to 0 */ + memset(keybuf, 0, sizeof(keybuf)); + + vtpmloginfo(VTPM_LOG_VTPM, "Binding uuid table symmetric key..\n"); + + /* Save the location of the aes key */ + g_store.aes_offset = ptr - buf; + + /* Store the fake aes key and vtpm count */ + TPMTRYRETURN(TPM_Bind(&vtpm_globals.storage_key, + keybuf, + sizeof(keybuf), + ptr)); + ptr+= RSA_CIPHER_SIZE; + + /* Write the header to disk */ + lseek(blkfront_fd, 0, SEEK_SET); + TRY_WRITE(buf, ptr-buf, "vtpm header"); + + /* Save the location of the uuid table */ + g_store.uuid_offset = get_offset(); + + /* Save the end offset */ + g_store.end_offset = (g_store.uuid_offset + RSA_CIPHER_SIZE) & ~(RSA_CIPHER_SIZE -1); + + vtpmloginfo(VTPM_LOG_VTPM, "Saved new manager disk header.\n"); + + goto egress; +abort_egress: +egress: + return status; +} + + +TPM_RESULT vtpm_storage_load_header(void) +{ + TPM_RESULT status = TPM_SUCCESS; + uint32_t v32; + uint8_t buf[BUF_SIZE]; + uint8_t* ptr = buf; + aes_context aes; + + /* Clear everything first */ + reset_store(); + + /* Read the header from disk */ + lseek(blkfront_fd, 0, SEEK_SET); + TRY_READ(buf, IDSTRLEN + sizeof(UINT32) + sizeof(UINT32), "vtpm header"); + + vtpmloginfo(VTPM_LOG_VTPM, "Loading disk image header\n"); + + /* Verify the ID string */ + if(memcmp(ptr, IDSTR, IDSTRLEN)) { + vtpmlogerror(VTPM_LOG_VTPM, "Invalid ID string in disk image!\n"); + status = TPM_FAIL; + goto abort_egress; + } + ptr+=IDSTRLEN; + + /* Unpack the version */ + ptr = unpack_UINT32(ptr, &v32); + + /* Verify the version */ + if(v32 != DISKVERS) { + vtpmlogerror(VTPM_LOG_VTPM, "Unsupported disk image version number %" PRIu32 "\n", v32); + status = TPM_FAIL; + goto abort_egress; + } + + /* Size of the storage key */ + ptr = unpack_UINT32(ptr, &v32); + + /* Sanity check */ + if(v32 > BUF_SIZE) { + vtpmlogerror(VTPM_LOG_VTPM, "Size of storage key (%" PRIu32 ") is too large!\n", v32); + status = TPM_IOERROR; + goto abort_egress; + } + + /* read the storage key */ + TRY_READ(buf, v32, "storage pub key"); + + vtpmloginfo(VTPM_LOG_VTPM, "Unpacking storage key\n"); + + /* unpack the storage key */ + ptr = unpack_TPM_KEY(buf, &vtpm_globals.storage_key, UNPACK_ALLOC); + + /* Load Storage Key into the TPM */ + TPMTRYRETURN( TPM_LoadKey( + TPM_SRK_KEYHANDLE, + &vtpm_globals.storage_key, + &vtpm_globals.storage_key_handle, + (const TPM_AUTHDATA*)&vtpm_globals.srk_auth, + &vtpm_globals.oiap)); + + /* Initialize the storage key auth */ + memset(vtpm_globals.storage_key_usage_auth, 0, sizeof(TPM_AUTHDATA)); + + /* Store the offset of the aes key */ + g_store.aes_offset = get_offset(); + + /* Read the rsa cipher text for the aes key */ + TRY_READ(buf, RSA_CIPHER_SIZE, "aes key"); + ptr = buf + RSA_CIPHER_SIZE; + + vtpmloginfo(VTPM_LOG_VTPM, "Unbinding uuid table symmetric key\n"); + + /* Decrypt the aes key protecting the uuid table */ + UINT32 datalen; + TPMTRYRETURN(TPM_UnBind( + vtpm_globals.storage_key_handle, + RSA_CIPHER_SIZE, + buf, + &datalen, + ptr, + (const TPM_AUTHDATA*)&vtpm_globals.storage_key_usage_auth, + &vtpm_globals.oiap)); + + /* Validate the length of the output buffer */ + if(datalen < AES_KEY_SIZE + sizeof(UINT32)) { + vtpmlogerror(VTPM_LOG_VTPM, "Unbound AES key size (%d) was too small! expected (%ld)\n", datalen, AES_KEY_SIZE + sizeof(UINT32)); + status = TPM_IOERROR; + goto abort_egress; + } + + /* Extract the aes key */ + aes_setkey_dec(&aes, ptr, AES_KEY_BITS); + ptr+= AES_KEY_SIZE; + + /* Extract the ciphertext size */ + ptr = unpack_UINT32(ptr, &v32); + int cipher_size = v32; + + /* Sanity check */ + if(cipher_size & (AES_BLOCK_SIZE-1)) { + vtpmlogerror(VTPM_LOG_VTPM, "Cipher text size (%" PRIu32 ") is not a multiple of the aes block size! (%d)\n", v32, AES_BLOCK_SIZE); + status = TPM_IOERROR; + goto abort_egress; + } + + /* Save the location of the uuid table */ + g_store.uuid_offset = get_offset(); + + /* Only decrypt the table if there are vtpms to decrypt */ + if(cipher_size > 0) { + int rbytes; + int overlap = 0; + uint8_t plain[BUF_SIZE + AES_BLOCK_SIZE]; + uint8_t iv[AES_BLOCK_SIZE]; + + vtpmloginfo(VTPM_LOG_VTPM, "Decrypting uuid table\n"); + + /* Pre allocate the vtpm array */ + g_store.num_vtpms_alloced = cipher_size / UUID_TBL_ENT_SIZE; + g_store.vtpms = malloc(sizeof(struct Vtpm) * g_store.num_vtpms_alloced); + + /* Read the iv and the first chunk of cipher text */ + rbytes = MIN(cipher_size, BUF_SIZE); + TRY_READ(buf, rbytes, "vtpm uuid table\n"); + cipher_size -= rbytes; + + /* Copy the iv */ + memcpy(iv, buf, AES_BLOCK_SIZE); + ptr = buf + AES_BLOCK_SIZE; + + /* Remove the iv from the number of bytes to decrypt */ + rbytes -= AES_BLOCK_SIZE; + + /* Decrypt and extract vtpms */ + vtpm_decrypt_block(&aes, + iv, ptr, plain, + rbytes, &overlap); + + /* Read the rest of the table if there is more */ + while(cipher_size > 0) { + /* Read next chunk of cipher text */ + rbytes = MIN(cipher_size, BUF_SIZE); + TRY_READ(buf, rbytes, "vtpm uuid table"); + cipher_size -= rbytes; + + /* Decrypt a block of text */ + vtpm_decrypt_block(&aes, + iv, buf, plain, + rbytes, &overlap); + + } + vtpmloginfo(VTPM_LOG_VTPM, "Loaded %d vtpms!\n", g_store.num_vtpms); + } + + /* The end of the key table, new vtpms go here */ + int uuid_end = (get_offset() + RSA_CIPHER_SIZE) & ~(RSA_CIPHER_SIZE -1); + g_store.end_offset = uuid_end; + + /* Compute the end offset while validating vtpms*/ + for(int i = 0; i < g_store.num_vtpms; ++i) { + /* offset must not collide with previous data */ + if(g_store.vtpms[i].offset < uuid_end) { + vtpmlogerror(VTPM_LOG_VTPM, "vtpm: " UUID_FMT + " offset (%d) is before end of uuid table (%d)!\n", + UUID_BYTES(g_store.vtpms[i].uuid), + g_store.vtpms[i].offset, uuid_end); + status = TPM_IOERROR; + goto abort_egress; + } + /* offset must be at a multiple of cipher size */ + if(g_store.vtpms[i].offset & (RSA_CIPHER_SIZE-1)) { + vtpmlogerror(VTPM_LOG_VTPM, "vtpm: " UUID_FMT + " offset(%d) is not at a multiple of the rsa cipher text size (%d)!\n", + UUID_BYTES(g_store.vtpms[i].uuid), + g_store.vtpms[i].offset, RSA_CIPHER_SIZE); + status = TPM_IOERROR; + goto abort_egress; + } + /* Save the last offset */ + if(g_store.vtpms[i].offset >= g_store.end_offset) { + g_store.end_offset = g_store.vtpms[i].offset + RSA_CIPHER_SIZE; + } + } + + goto egress; +abort_egress: + //An error occured somewhere + vtpmlogerror(VTPM_LOG_VTPM, "Failed to load manager data!\n"); + + //Clear the data store + reset_store(); + + //Reset the storage key structure + free_TPM_KEY(&vtpm_globals.storage_key); + { + TPM_KEY key = TPM_KEY_INIT; + vtpm_globals.storage_key = key; + } + + //Reset the storage key handle + TPM_EvictKey(vtpm_globals.storage_key_handle); + vtpm_globals.storage_key_handle = 0; +egress: + return status; +} + +#if 0 +/* For testing disk IO */ +void add_fake_vtpms(int num) { + for(int i = 0; i < num; ++i) { + uint32_t ind = cpu_to_be32(i); + + uuid_t uuid; + memset(uuid, 0, sizeof(uuid_t)); + memcpy(uuid, &ind, sizeof(ind)); + int index = vtpm_get_index(uuid); + index = -index-1; + + vtpm_storage_new_vtpm(uuid, index); + } +} +#endif diff --git a/stubdom/vtpmmgr/vtpm_storage.h b/stubdom/vtpmmgr/vtpm_storage.h new file mode 100644 index 0000000000..a5a5fd7704 --- /dev/null +++ b/stubdom/vtpmmgr/vtpm_storage.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2010-2012 United States Government, as represented by + * the Secretary of Defense. All rights reserved. + * + * based off of the original tools/vtpm_manager code base which is: + * Copyright (c) 2005, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef VTPM_STORAGE_H +#define VTPM_STORAGE_h + +#include "uuid.h" + +#define VTPM_NVMKEY_SIZE 32 +#define HASHKEYSZ (sizeof(TPM_DIGEST) + VTPM_NVMKEY_SIZE) + +/* Initialize the storage system and its virtual disk */ +int vtpm_storage_init(void); + +/* Shutdown the storage system and its virtual disk */ +void vtpm_storage_shutdown(void); + +/* Loads Sha1 hash and 256 bit AES key from disk and stores them + * packed together in outbuf. outbuf must be freed + * by the caller using buffer_free() + */ +TPM_RESULT vtpm_storage_load_hashkey(const uuid_t uuid, uint8_t hashkey[HASHKEYSZ]); + +/* inbuf must contain a sha1 hash followed by a 256 bit AES key. + * Encrypts and stores the hash and key to disk */ +TPM_RESULT vtpm_storage_save_hashkey(const uuid_t uuid, uint8_t hashkey[HASHKEYSZ]); + +/* Load the vtpm manager data - call this on startup */ +TPM_RESULT vtpm_storage_load_header(void); + +/* Saves the vtpm manager data - call this on shutdown */ +TPM_RESULT vtpm_storage_new_header(void); + + +#endif diff --git a/stubdom/vtpmmgr/vtpmmgr.c b/stubdom/vtpmmgr/vtpmmgr.c new file mode 100644 index 0000000000..563f4e8c58 --- /dev/null +++ b/stubdom/vtpmmgr/vtpmmgr.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2010-2012 United States Government, as represented by + * the Secretary of Defense. All rights reserved. + * + * based off of the original tools/vtpm_manager code base which is: + * Copyright (c) 2005, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include +#include +#include "log.h" + +#include "vtpmmgr.h" +#include "tcg.h" + + +void main_loop(void) { + tpmcmd_t* tpmcmd; + uint8_t respbuf[TCPA_MAX_BUFFER_LENGTH]; + + while(1) { + /* Wait for requests from a vtpm */ + vtpmloginfo(VTPM_LOG_VTPM, "Waiting for commands from vTPM's:\n"); + if((tpmcmd = tpmback_req_any()) == NULL) { + vtpmlogerror(VTPM_LOG_VTPM, "NULL tpmcmd\n"); + continue; + } + + tpmcmd->resp = respbuf; + + /* Process the command */ + vtpmmgr_handle_cmd(tpmcmd->uuid, tpmcmd); + + /* Send response */ + tpmback_resp(tpmcmd); + } +} + +int main(int argc, char** argv) +{ + int rc = 0; + sleep(2); + vtpmloginfo(VTPM_LOG_VTPM, "Starting vTPM manager domain\n"); + + /* Initialize the vtpm manager */ + if(vtpmmgr_init(argc, argv) != TPM_SUCCESS) { + vtpmlogerror(VTPM_LOG_VTPM, "Unable to initialize vtpmmgr domain!\n"); + rc = -1; + goto exit; + } + + main_loop(); + + vtpmloginfo(VTPM_LOG_VTPM, "vTPM Manager shutting down...\n"); + + vtpmmgr_shutdown(); + +exit: + return rc; + +} diff --git a/stubdom/vtpmmgr/vtpmmgr.h b/stubdom/vtpmmgr/vtpmmgr.h new file mode 100644 index 0000000000..50a1992f97 --- /dev/null +++ b/stubdom/vtpmmgr/vtpmmgr.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2010-2012 United States Government, as represented by + * the Secretary of Defense. All rights reserved. + * + * based off of the original tools/vtpm_manager code base which is: + * Copyright (c) 2005, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef VTPMMGR_H +#define VTPMMGR_H + +#include +#include +#include + +#include "uuid.h" +#include "tcg.h" +#include "vtpm_manager.h" + +#define RSA_KEY_SIZE 0x0800 +#define RSA_CIPHER_SIZE (RSA_KEY_SIZE / 8) + +struct vtpm_globals { + int tpm_fd; + TPM_KEY storage_key; + TPM_HANDLE storage_key_handle; // Key used by persistent store + TPM_AUTH_SESSION oiap; // OIAP session for storageKey + TPM_AUTHDATA storage_key_usage_auth; + + TPM_AUTHDATA owner_auth; + TPM_AUTHDATA srk_auth; + + entropy_context entropy; + ctr_drbg_context ctr_drbg; +}; + +// --------------------------- Global Values -------------------------- +extern struct vtpm_globals vtpm_globals; // Key info and DMI states + +TPM_RESULT vtpmmgr_init(int argc, char** argv); +void vtpmmgr_shutdown(void); + +TPM_RESULT vtpmmgr_handle_cmd(const uuid_t uuid, tpmcmd_t* tpmcmd); + +inline TPM_RESULT vtpmmgr_rand(unsigned char* bytes, size_t num_bytes) { + return ctr_drbg_random(&vtpm_globals.ctr_drbg, bytes, num_bytes) == 0 ? 0 : TPM_FAIL; +} + +#endif -- cgit v1.2.3