aboutsummaryrefslogtreecommitdiffstats
path: root/stubdom
diff options
context:
space:
mode:
authorMatthew Fioravante <matthew.fioravante@jhuapl.edu>2013-01-18 10:55:43 +0000
committerMatthew Fioravante <matthew.fioravante@jhuapl.edu>2013-01-18 10:55:43 +0000
commit095b0b77942ad8e1af1c0a45f65f29458890bdc2 (patch)
treeccc157fee46642fe47297f2667fa3597a9332474 /stubdom
parentd463e3c5a341ece638a7a2067406fab7c03f30de (diff)
downloadxen-095b0b77942ad8e1af1c0a45f65f29458890bdc2.tar.gz
xen-095b0b77942ad8e1af1c0a45f65f29458890bdc2.tar.bz2
xen-095b0b77942ad8e1af1c0a45f65f29458890bdc2.zip
add stubdom/vtpmmgr code
Add the code base for vtpmmgrdom. Makefile changes next patch. Signed-off-by: Matthew Fioravante <matthew.fioravante@jhuapl.edu> Acked-by: Ian Campbell <ian.campbell@citrix.com> Committed-by: Ian Campbell <ian.campbell@citrix.com>
Diffstat (limited to 'stubdom')
-rw-r--r--stubdom/vtpmmgr/Makefile32
-rw-r--r--stubdom/vtpmmgr/init.c553
-rw-r--r--stubdom/vtpmmgr/log.c151
-rw-r--r--stubdom/vtpmmgr/log.h85
-rw-r--r--stubdom/vtpmmgr/marshal.h528
-rw-r--r--stubdom/vtpmmgr/minios.cfg14
-rw-r--r--stubdom/vtpmmgr/tcg.h707
-rw-r--r--stubdom/vtpmmgr/tpm.c938
-rw-r--r--stubdom/vtpmmgr/tpm.h218
-rw-r--r--stubdom/vtpmmgr/tpmrsa.c175
-rw-r--r--stubdom/vtpmmgr/tpmrsa.h67
-rw-r--r--stubdom/vtpmmgr/uuid.h50
-rw-r--r--stubdom/vtpmmgr/vtpm_cmd_handler.c152
-rw-r--r--stubdom/vtpmmgr/vtpm_manager.h64
-rw-r--r--stubdom/vtpmmgr/vtpm_storage.c794
-rw-r--r--stubdom/vtpmmgr/vtpm_storage.h68
-rw-r--r--stubdom/vtpmmgr/vtpmmgr.c93
-rw-r--r--stubdom/vtpmmgr/vtpmmgr.h77
18 files changed, 4766 insertions, 0 deletions
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 <stdint.h>
+#include <stdlib.h>
+
+#include <xen/xen.h>
+#include <mini-os/tpmback.h>
+#include <mini-os/tpmfront.h>
+#include <mini-os/tpm_tis.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <polarssl/sha1.h>
+
+#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 <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#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 <stdint.h> // for uint32_t
+#include <stddef.h> // for pointer NULL
+#include <stdio.h>
+#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 <stdlib.h>
+#include <mini-os/byteorder.h>
+#include <mini-os/endian.h>
+#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 <stdlib.h>
+#include <stdint.h>
+
+// **************************** 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 <stdio.h>
+
+// 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 <stdio.h>
+#include <string.h>
+#include <malloc.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <polarssl/sha1.h>
+
+#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(&paramDigest, HMACkey, auth);\
+ ptr = pack_TPM_AUTH_SESSION(ptr, auth);\
+} while(0)
+
+#define TPM_AUTH2_GEN(HMACkey, auth) do {\
+ generateAuth(&paramDigest, 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(&paramDigest, 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(&paramDigest, 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 <polarssl_maintainer at polarssl.org>
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+
+#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 <polarssl_maintainer at polarssl.org>
+ *
+ * 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 <polarssl/bignum.h>
+
+/* 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 <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+
+#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 <blkfront.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <mini-os/byteorder.h>
+#include <polarssl/aes.h>
+
+#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 <stdint.h>
+#include <mini-os/tpmback.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#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 <mini-os/tpmback.h>
+#include <polarssl/entropy.h>
+#include <polarssl/ctr_drbg.h>
+
+#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