From: Matthew Fioravante <matthew.fioravante@jhuapl.edu>
To: "xen-devel@lists.xen.org" <xen-devel@lists.xen.org>,
"Ian.Campbell@citrix.com" <Ian.Campbell@citrix.com>
Subject: Re: [PATCH VTPM v4 2/5] add stubdom/vtpmmgr code
Date: Tue, 20 Nov 2012 09:25:19 -0500 [thread overview]
Message-ID: <50AB92CF.8040306@jhuapl.edu> (raw)
In-Reply-To: <1353421272-24797-2-git-send-email-matthew.fioravante@jhuapl.edu>
[-- Attachment #1.1: Type: text/plain, Size: 186865 bytes --]
Please be sure to grab this updated version. I fixed an important
comment about the disk image format that was out of date.
On 11/20/2012 09:21 AM, Matthew Fioravante wrote:
> 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>
> ---
> stubdom/vtpmmgr/Makefile | 32 ++
> stubdom/vtpmmgr/init.c | 553 +++++++++++++++++++++
> stubdom/vtpmmgr/log.c | 151 ++++++
> stubdom/vtpmmgr/log.h | 85 ++++
> stubdom/vtpmmgr/marshal.h | 528 ++++++++++++++++++++
> stubdom/vtpmmgr/minios.cfg | 14 +
> stubdom/vtpmmgr/tcg.h | 707 +++++++++++++++++++++++++++
> stubdom/vtpmmgr/tpm.c | 938 ++++++++++++++++++++++++++++++++++++
> stubdom/vtpmmgr/tpm.h | 218 +++++++++
> stubdom/vtpmmgr/tpmrsa.c | 175 +++++++
> stubdom/vtpmmgr/tpmrsa.h | 67 +++
> stubdom/vtpmmgr/uuid.h | 50 ++
> stubdom/vtpmmgr/vtpm_cmd_handler.c | 152 ++++++
> stubdom/vtpmmgr/vtpm_manager.h | 64 +++
> stubdom/vtpmmgr/vtpm_storage.c | 794 ++++++++++++++++++++++++++++++
> stubdom/vtpmmgr/vtpm_storage.h | 68 +++
> stubdom/vtpmmgr/vtpmmgr.c | 93 ++++
> stubdom/vtpmmgr/vtpmmgr.h | 77 +++
> 18 files changed, 4766 insertions(+)
> create mode 100644 stubdom/vtpmmgr/Makefile
> create mode 100644 stubdom/vtpmmgr/init.c
> create mode 100644 stubdom/vtpmmgr/log.c
> create mode 100644 stubdom/vtpmmgr/log.h
> create mode 100644 stubdom/vtpmmgr/marshal.h
> create mode 100644 stubdom/vtpmmgr/minios.cfg
> create mode 100644 stubdom/vtpmmgr/tcg.h
> create mode 100644 stubdom/vtpmmgr/tpm.c
> create mode 100644 stubdom/vtpmmgr/tpm.h
> create mode 100644 stubdom/vtpmmgr/tpmrsa.c
> create mode 100644 stubdom/vtpmmgr/tpmrsa.h
> create mode 100644 stubdom/vtpmmgr/uuid.h
> create mode 100644 stubdom/vtpmmgr/vtpm_cmd_handler.c
> create mode 100644 stubdom/vtpmmgr/vtpm_manager.h
> create mode 100644 stubdom/vtpmmgr/vtpm_storage.c
> create mode 100644 stubdom/vtpmmgr/vtpm_storage.h
> create mode 100644 stubdom/vtpmmgr/vtpmmgr.c
> create mode 100644 stubdom/vtpmmgr/vtpmmgr.h
>
> diff --git a/stubdom/vtpmmgr/Makefile b/stubdom/vtpmmgr/Makefile
> new file mode 100644
> index 0000000..88c83c3
> --- /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 0000000..a158020
> --- /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 0000000..a82c913
> --- /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 0000000..5c7abf5
> --- /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 0000000..77d32f0
> --- /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 0000000..3fb383d
> --- /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 0000000..7687eae
> --- /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 0000000..123a27c
> --- /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(¶mDigest, HMACkey, auth);\
> + ptr = pack_TPM_AUTH_SESSION(ptr, auth);\
> +} while(0)
> +
> +#define TPM_AUTH2_GEN(HMACkey, auth) do {\
> + generateAuth(¶mDigest, HMACkey, auth);\
> + ptr = pack_TPM_AUTH_SESSION(ptr, auth);\
> +} while(0)
> +
> +#define TPM_TRANSMIT() do {\
> + /* Pack the command size */\
> + paramSize = ptr - in_buf;\
> + pack_UINT32(in_buf + sizeof(TPM_TAG), paramSize);\
> + if((status = TPM_TransmitData(in_buf, paramSize, out_buf, &out_len)) != TPM_SUCCESS) {\
> + goto abort_egress;\
> + }\
> +} while(0)
> +
> +#define TPM_AUTH_VERIFY_BEGIN() do {\
> + UINT32 buf[2] = { cpu_to_be32(status), cpu_to_be32(ordinal) };\
> + sha1_starts(&sha1_ctx);\
> + sha1_update(&sha1_ctx, (unsigned char*)buf, sizeof(buf));\
> + authbase = ptr;\
> +} while(0)
> +
> +#define TPM_AUTH1_VERIFY(HMACkey, auth) do {\
> + sha1_finish(&sha1_ctx, paramDigest.digest);\
> + ptr = unpack_TPM_AUTH_SESSION(ptr, auth);\
> + if((status = verifyAuth(¶mDigest, HMACkey, auth)) != TPM_SUCCESS) {\
> + goto abort_egress;\
> + }\
> +} while(0)
> +
> +#define TPM_AUTH2_VERIFY(HMACkey, auth) do {\
> + ptr = unpack_TPM_AUTH_SESSION(ptr, auth);\
> + if((status = verifyAuth(¶mDigest, HMACkey, auth)) != TPM_SUCCESS) {\
> + goto abort_egress;\
> + }\
> +} while(0)
> +
> +
> +
> +#define TPM_UNPACK_VERIFY() do { \
> + ptr = out_buf;\
> + ptr = unpack_TPM_RSP_HEADER(ptr, \
> + &(tag), &(paramSize), &(status));\
> + if((status) != TPM_SUCCESS || (tag) != (intag +3)) { \
> + vtpmlogerror(VTPM_LOG_TPM, "Failed with return code %s\n", tpm_get_error_name(status));\
> + goto abort_egress;\
> + }\
> +} while(0)
> +
> +#define TPM_AUTH_HASH() do {\
> + sha1_update(&sha1_ctx, authbase, ptr - authbase);\
> + authbase = ptr;\
> +} while(0)
> +
> +#define TPM_AUTH_SKIP() do {\
> + authbase = ptr;\
> +} while(0)
> +
> +#define TPM_AUTH_ERR_CHECK(auth) do {\
> + if(status != TPM_SUCCESS || auth->fContinueAuthSession == FALSE) {\
> + vtpmloginfo(VTPM_LOG_TPM, "Auth Session: 0x%x closed by TPM\n", auth->AuthHandle);\
> + auth->AuthHandle = 0;\
> + }\
> +} while(0)
> +
> +static void xorEncrypt(const TPM_SECRET* sharedSecret,
> + TPM_NONCE* nonce,
> + const TPM_AUTHDATA* inAuth0,
> + TPM_ENCAUTH outAuth0,
> + const TPM_AUTHDATA* inAuth1,
> + TPM_ENCAUTH outAuth1) {
> + BYTE XORbuffer[sizeof(TPM_SECRET) + sizeof(TPM_NONCE)];
> + BYTE XORkey[TPM_DIGEST_SIZE];
> + BYTE* ptr = XORbuffer;
> + ptr = pack_TPM_SECRET(ptr, sharedSecret);
> + ptr = pack_TPM_NONCE(ptr, nonce);
> +
> + sha1(XORbuffer, ptr - XORbuffer, XORkey);
> +
> + if(inAuth0) {
> + for(int i = 0; i < TPM_DIGEST_SIZE; ++i) {
> + outAuth0[i] = XORkey[i] ^ (*inAuth0)[i];
> + }
> + }
> + if(inAuth1) {
> + for(int i = 0; i < TPM_DIGEST_SIZE; ++i) {
> + outAuth1[i] = XORkey[i] ^ (*inAuth1)[i];
> + }
> + }
> +
> +}
> +
> +static void generateAuth(const TPM_DIGEST* paramDigest,
> + const TPM_SECRET* HMACkey,
> + TPM_AUTH_SESSION *auth)
> +{
> + //Generate new OddNonce
> + vtpmmgr_rand((BYTE*)auth->NonceOdd.nonce, sizeof(TPM_NONCE));
> +
> + // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).
> + BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];
> + BYTE* ptr = hmacText;
> +
> + ptr = pack_TPM_DIGEST(ptr, paramDigest);
> + ptr = pack_TPM_NONCE(ptr, &auth->NonceEven);
> + ptr = pack_TPM_NONCE(ptr, &auth->NonceOdd);
> + ptr = pack_BOOL(ptr, auth->fContinueAuthSession);
> +
> + sha1_hmac((BYTE *) HMACkey, sizeof(TPM_DIGEST),
> + (BYTE *) hmacText, sizeof(hmacText),
> + auth->HMAC);
> +}
> +
> +static TPM_RESULT verifyAuth(const TPM_DIGEST* paramDigest,
> + /*[IN]*/ const TPM_SECRET *HMACkey,
> + /*[IN,OUT]*/ TPM_AUTH_SESSION *auth)
> +{
> +
> + // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).
> + TPM_AUTHDATA hm;
> + BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];
> + BYTE* ptr = hmacText;
> +
> + ptr = pack_TPM_DIGEST(ptr, paramDigest);
> + ptr = pack_TPM_NONCE(ptr, &auth->NonceEven);
> + ptr = pack_TPM_NONCE(ptr, &auth->NonceOdd);
> + ptr = pack_BOOL(ptr, auth->fContinueAuthSession);
> +
> + sha1_hmac( (BYTE *) HMACkey, sizeof(TPM_DIGEST),
> + (BYTE *) hmacText, sizeof(hmacText),
> + hm);
> +
> + // Compare correct HMAC with provided one.
> + if (memcmp(hm, auth->HMAC, sizeof(TPM_DIGEST)) == 0) { // 0 indicates equality
> + return TPM_SUCCESS;
> + } else {
> + vtpmlogerror(VTPM_LOG_TPM, "Auth Session verification failed!\n");
> + return TPM_AUTHFAIL;
> + }
> +}
> +
> +
> +
> +// ------------------------------------------------------------------
> +// Authorization Commands
> +// ------------------------------------------------------------------
> +
> +TPM_RESULT TPM_OIAP(TPM_AUTH_SESSION* auth) // out
> +{
> + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_OIAP);
> +
> + TPM_TRANSMIT();
> + TPM_UNPACK_VERIFY();
> +
> + memset(&auth->HMAC, 0, sizeof(TPM_DIGEST));
> + auth->fContinueAuthSession = TRUE;
> +
> + ptr = unpack_UINT32(ptr, &auth->AuthHandle);
> + ptr = unpack_TPM_NONCE(ptr, &auth->NonceEven);
> +
> + vtpmloginfo(VTPM_LOG_TPM, "Auth Session: 0x%x opened by TPM_OIAP.\n", auth->AuthHandle);
> +
> +abort_egress:
> + return status;
> +}
> +
> +TPM_RESULT TPM_OSAP(TPM_ENTITY_TYPE entityType, // in
> + UINT32 entityValue, // in
> + const TPM_AUTHDATA* usageAuth, //in
> + TPM_SECRET *sharedSecret, //out
> + TPM_AUTH_SESSION *auth)
> +{
> + BYTE* nonceOddOSAP;
> + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_OSAP);
> +
> + ptr = pack_TPM_ENTITY_TYPE(ptr, entityType);
> + ptr = pack_UINT32(ptr, entityValue);
> +
> + //nonce Odd OSAP
> + nonceOddOSAP = ptr;
> + vtpmmgr_rand(ptr, TPM_DIGEST_SIZE);
> + ptr += TPM_DIGEST_SIZE;
> +
> + TPM_TRANSMIT();
> + TPM_UNPACK_VERIFY();
> +
> + ptr = unpack_UINT32(ptr, &auth->AuthHandle);
> + ptr = unpack_TPM_NONCE(ptr, &auth->NonceEven);
> +
> + //Calculate session secret
> + sha1_context ctx;
> + sha1_hmac_starts(&ctx, *usageAuth, TPM_DIGEST_SIZE);
> + sha1_hmac_update(&ctx, ptr, TPM_DIGEST_SIZE); //ptr = nonceEvenOSAP
> + sha1_hmac_update(&ctx, nonceOddOSAP, TPM_DIGEST_SIZE);
> + sha1_hmac_finish(&ctx, *sharedSecret);
> +
> + memset(&auth->HMAC, 0, sizeof(TPM_DIGEST));
> + auth->fContinueAuthSession = FALSE;
> +
> + vtpmloginfo(VTPM_LOG_TPM, "Auth Session: 0x%x opened by TPM_OSAP.\n", auth->AuthHandle);
> +
> +abort_egress:
> + return status;
> +}
> +
> +TPM_RESULT TPM_TakeOwnership(
> + const TPM_PUBKEY *pubEK, //in
> + const TPM_AUTHDATA* ownerAuth, //in
> + const TPM_AUTHDATA* srkAuth, //in
> + const TPM_KEY* inSrk, //in
> + TPM_KEY* outSrk, //out, optional
> + TPM_AUTH_SESSION* auth) // in, out
> +{
> + int keyAlloced = 0;
> + tpmrsa_context ek_rsa = TPMRSA_CTX_INIT;
> +
> + TPM_BEGIN(TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_TakeOwnership);
> + TPM_AUTH_BEGIN();
> +
> + tpmrsa_set_pubkey(&ek_rsa,
> + pubEK->pubKey.key, pubEK->pubKey.keyLength,
> + pubEK->algorithmParms.parms.rsa.exponent,
> + pubEK->algorithmParms.parms.rsa.exponentSize);
> +
> + /* Pack the protocol ID */
> + ptr = pack_UINT16(ptr, TPM_PID_OWNER);
> +
> + /* Pack the encrypted owner auth */
> + ptr = pack_UINT32(ptr, pubEK->algorithmParms.parms.rsa.keyLength / 8);
> + tpmrsa_pub_encrypt_oaep(&ek_rsa,
> + ctr_drbg_random, &vtpm_globals.ctr_drbg,
> + sizeof(TPM_SECRET),
> + (BYTE*) ownerAuth,
> + ptr);
> + ptr += pubEK->algorithmParms.parms.rsa.keyLength / 8;
> +
> + /* Pack the encrypted srk auth */
> + ptr = pack_UINT32(ptr, pubEK->algorithmParms.parms.rsa.keyLength / 8);
> + tpmrsa_pub_encrypt_oaep(&ek_rsa,
> + ctr_drbg_random, &vtpm_globals.ctr_drbg,
> + sizeof(TPM_SECRET),
> + (BYTE*) srkAuth,
> + ptr);
> + ptr += pubEK->algorithmParms.parms.rsa.keyLength / 8;
> +
> + /* Pack the Srk key */
> + ptr = pack_TPM_KEY(ptr, inSrk);
> +
> + /* Hash everything up to here */
> + TPM_AUTH_HASH();
> +
> + /* Generate the authorization */
> + TPM_AUTH1_GEN(ownerAuth, auth);
> +
> + /* Send the command to the tpm*/
> + TPM_TRANSMIT();
> + /* Unpack and validate the header */
> + TPM_UNPACK_VERIFY();
> + TPM_AUTH_VERIFY_BEGIN();
> +
> + if(outSrk != NULL) {
> + /* If the user wants a copy of the srk we give it to them */
> + keyAlloced = 1;
> + ptr = unpack_TPM_KEY(ptr, outSrk, UNPACK_ALLOC);
> + } else {
> + /*otherwise just parse past it */
> + TPM_KEY temp;
> + ptr = unpack_TPM_KEY(ptr, &temp, UNPACK_ALIAS);
> + }
> +
> + /* Hash the output key */
> + TPM_AUTH_HASH();
> +
> + /* Verify authorizaton */
> + TPM_AUTH1_VERIFY(ownerAuth, auth);
> +
> + goto egress;
> +abort_egress:
> + if(keyAlloced) {
> + free_TPM_KEY(outSrk);
> + }
> +egress:
> + tpmrsa_free(&ek_rsa);
> + TPM_AUTH_ERR_CHECK(auth);
> + return status;
> +}
> +
> +
> +TPM_RESULT TPM_DisablePubekRead (
> + const TPM_AUTHDATA* ownerAuth,
> + TPM_AUTH_SESSION* auth)
> +{
> + TPM_BEGIN(TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_DisablePubekRead);
> + TPM_AUTH_BEGIN();
> +
> + TPM_AUTH_HASH();
> +
> + TPM_AUTH1_GEN(ownerAuth, auth);
> + TPM_TRANSMIT();
> + TPM_UNPACK_VERIFY();
> + TPM_AUTH_VERIFY_BEGIN();
> +
> + TPM_AUTH1_VERIFY(ownerAuth, auth);
> +
> +abort_egress:
> + TPM_AUTH_ERR_CHECK(auth);
> + return status;
> +}
> +
> +
> +TPM_RESULT TPM_TerminateHandle(TPM_AUTHHANDLE handle) // in
> +{
> + if(handle == 0) {
> + return TPM_SUCCESS;
> + }
> +
> + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_Terminate_Handle);
> +
> + ptr = pack_TPM_AUTHHANDLE(ptr, handle);
> +
> + TPM_TRANSMIT();
> + TPM_UNPACK_VERIFY();
> +
> + vtpmloginfo(VTPM_LOG_TPM, "Auth Session: 0x%x closed by TPM_TerminateHandle\n", handle);
> +
> +abort_egress:
> + return status;
> +}
> +
> +TPM_RESULT TPM_Extend( TPM_PCRINDEX pcrNum, // in
> + TPM_DIGEST inDigest, // in
> + TPM_PCRVALUE* outDigest) // out
> +{
> + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_Extend);
> +
> + ptr = pack_TPM_PCRINDEX(ptr, pcrNum);
> + ptr = pack_TPM_DIGEST(ptr, &inDigest);
> +
> + TPM_TRANSMIT();
> + TPM_UNPACK_VERIFY();
> +
> + ptr = unpack_TPM_PCRVALUE(ptr, outDigest);
> +
> +abort_egress:
> + return status;
> +}
> +
> +TPM_RESULT TPM_Seal(
> + TPM_KEY_HANDLE keyHandle, // in
> + UINT32 pcrInfoSize, // in
> + TPM_PCR_INFO* pcrInfo, // in
> + UINT32 inDataSize, // in
> + const BYTE* inData, // in
> + TPM_STORED_DATA* sealedData, //out
> + const TPM_SECRET* osapSharedSecret, //in
> + const TPM_AUTHDATA* sealedDataAuth, //in
> + TPM_AUTH_SESSION* pubAuth // in, out
> + )
> +{
> + int dataAlloced = 0;
> + TPM_BEGIN(TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_Seal);
> + TPM_AUTH_BEGIN();
> +
> + TPM_AUTH_HASH();
> +
> + ptr = pack_TPM_KEY_HANDLE(ptr, keyHandle);
> +
> + TPM_AUTH_SKIP();
> +
> + xorEncrypt(osapSharedSecret, &pubAuth->NonceEven,
> + sealedDataAuth, ptr,
> + NULL, NULL);
> + ptr += sizeof(TPM_ENCAUTH);
> +
> + ptr = pack_UINT32(ptr, pcrInfoSize);
> + ptr = pack_TPM_PCR_INFO(ptr, pcrInfo);
> +
> + ptr = pack_UINT32(ptr, inDataSize);
> + ptr = pack_BUFFER(ptr, inData, inDataSize);
> +
> + TPM_AUTH_HASH();
> +
> + TPM_AUTH1_GEN(osapSharedSecret, pubAuth);
> + TPM_TRANSMIT();
> + TPM_UNPACK_VERIFY();
> + TPM_AUTH_VERIFY_BEGIN();
> +
> + ptr = unpack_TPM_STORED_DATA(ptr, sealedData, UNPACK_ALLOC);
> + dataAlloced = 1;
> +
> + TPM_AUTH_HASH();
> +
> + TPM_AUTH1_VERIFY(osapSharedSecret, pubAuth);
> +
> + goto egress;
> +abort_egress:
> + if(dataAlloced) {
> + free_TPM_STORED_DATA(sealedData);
> + }
> +egress:
> + TPM_AUTH_ERR_CHECK(pubAuth);
> + return status;
> +}
> +
> +TPM_RESULT TPM_Unseal(
> + TPM_KEY_HANDLE parentHandle, // in
> + const TPM_STORED_DATA* sealedData,
> + UINT32* outSize, // out
> + BYTE** out, //out
> + const TPM_AUTHDATA* key_usage_auth, //in
> + const TPM_AUTHDATA* data_usage_auth, //in
> + TPM_AUTH_SESSION* keyAuth, // in, out
> + TPM_AUTH_SESSION* dataAuth // in, out
> + )
> +{
> + TPM_BEGIN(TPM_TAG_RQU_AUTH2_COMMAND, TPM_ORD_Unseal);
> + TPM_AUTH_BEGIN();
> +
> + TPM_AUTH_HASH();
> +
> + ptr = pack_TPM_KEY_HANDLE(ptr, parentHandle);
> +
> + TPM_AUTH_SKIP();
> +
> + ptr = pack_TPM_STORED_DATA(ptr, sealedData);
> +
> + TPM_AUTH_HASH();
> +
> + TPM_AUTH1_GEN(key_usage_auth, keyAuth);
> + TPM_AUTH2_GEN(data_usage_auth, dataAuth);
> + TPM_TRANSMIT();
> + TPM_UNPACK_VERIFY();
> + TPM_AUTH_VERIFY_BEGIN();
> +
> + ptr = unpack_UINT32(ptr, outSize);
> + ptr = unpack_ALLOC(ptr, out, *outSize);
> +
> + TPM_AUTH_HASH();
> +
> + TPM_AUTH1_VERIFY(key_usage_auth, keyAuth);
> + TPM_AUTH2_VERIFY(data_usage_auth, dataAuth);
> +
> +abort_egress:
> + TPM_AUTH_ERR_CHECK(keyAuth);
> + TPM_AUTH_ERR_CHECK(dataAuth);
> + return status;
> +}
> +
> +TPM_RESULT TPM_Bind(
> + const TPM_KEY* key,
> + const BYTE* in,
> + UINT32 ilen,
> + BYTE* out)
> +{
> + TPM_RESULT status;
> + tpmrsa_context rsa = TPMRSA_CTX_INIT;
> + TPM_BOUND_DATA boundData;
> + uint8_t plain[TCPA_MAX_BUFFER_LENGTH];
> + BYTE* ptr = plain;
> +
> + vtpmloginfo(VTPM_LOG_TPM, "%s\n", __func__);
> +
> + tpmrsa_set_pubkey(&rsa,
> + key->pubKey.key, key->pubKey.keyLength,
> + key->algorithmParms.parms.rsa.exponent,
> + key->algorithmParms.parms.rsa.exponentSize);
> +
> + // Fill boundData's accessory information
> + boundData.ver = TPM_STRUCT_VER_1_1;
> + boundData.payload = TPM_PT_BIND;
> + boundData.payloadData = (BYTE*)in;
> +
> + //marshall the bound data object
> + ptr = pack_TPM_BOUND_DATA(ptr, &boundData, ilen);
> +
> + // Encrypt the data
> + TPMTRYRETURN(tpmrsa_pub_encrypt_oaep(&rsa,
> + ctr_drbg_random, &vtpm_globals.ctr_drbg,
> + ptr - plain,
> + plain,
> + out));
> +
> +abort_egress:
> + tpmrsa_free(&rsa);
> + return status;
> +
> +}
> +
> +TPM_RESULT TPM_UnBind(
> + TPM_KEY_HANDLE keyHandle, // in
> + UINT32 ilen, //in
> + const BYTE* in, //
> + UINT32* olen, //
> + BYTE* out, //out
> + const TPM_AUTHDATA* usage_auth,
> + TPM_AUTH_SESSION* auth //in, out
> + )
> +{
> + TPM_BEGIN(TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_UnBind);
> + TPM_AUTH_BEGIN();
> +
> + TPM_AUTH_HASH();
> +
> + ptr = pack_TPM_KEY_HANDLE(ptr, keyHandle);
> +
> + TPM_AUTH_SKIP();
> +
> + ptr = pack_UINT32(ptr, ilen);
> + ptr = pack_BUFFER(ptr, in, ilen);
> +
> + TPM_AUTH_HASH();
> +
> + TPM_AUTH1_GEN(usage_auth, auth);
> + TPM_TRANSMIT();
> + TPM_UNPACK_VERIFY();
> + TPM_AUTH_VERIFY_BEGIN();
> +
> + ptr = unpack_UINT32(ptr, olen);
> + if(*olen > ilen) {
> + vtpmlogerror(VTPM_LOG_TPM, "Output length < input length!\n");
> + status = TPM_IOERROR;
> + goto abort_egress;
> + }
> + ptr = unpack_BUFFER(ptr, out, *olen);
> +
> + TPM_AUTH_HASH();
> +
> + TPM_AUTH1_VERIFY(usage_auth, auth);
> +
> +abort_egress:
> +egress:
> + TPM_AUTH_ERR_CHECK(auth);
> + return status;
> +}
> +
> +TPM_RESULT TPM_CreateWrapKey(
> + TPM_KEY_HANDLE hWrappingKey, // in
> + const TPM_AUTHDATA* osapSharedSecret,
> + const TPM_AUTHDATA* dataUsageAuth, //in
> + const TPM_AUTHDATA* dataMigrationAuth, //in
> + TPM_KEY* key, //in, out
> + TPM_AUTH_SESSION* pAuth) // in, out
> +{
> + int keyAlloced = 0;
> + TPM_BEGIN(TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_CreateWrapKey);
> + TPM_AUTH_BEGIN();
> +
> + TPM_AUTH_HASH();
> +
> + ptr = pack_TPM_KEY_HANDLE(ptr, hWrappingKey);
> +
> + TPM_AUTH_SKIP();
> +
> + //Encrypted auths
> + xorEncrypt(osapSharedSecret, &pAuth->NonceEven,
> + dataUsageAuth, ptr,
> + dataMigrationAuth, ptr + sizeof(TPM_ENCAUTH));
> + ptr += sizeof(TPM_ENCAUTH) * 2;
> +
> + ptr = pack_TPM_KEY(ptr, key);
> +
> + TPM_AUTH_HASH();
> +
> + TPM_AUTH1_GEN(osapSharedSecret, pAuth);
> + TPM_TRANSMIT();
> + TPM_UNPACK_VERIFY();
> + TPM_AUTH_VERIFY_BEGIN();
> +
> + keyAlloced = 1;
> + ptr = unpack_TPM_KEY(ptr, key, UNPACK_ALLOC);
> +
> + TPM_AUTH_HASH();
> +
> + TPM_AUTH1_VERIFY(osapSharedSecret, pAuth);
> +
> + goto egress;
> +abort_egress:
> + if(keyAlloced) {
> + free_TPM_KEY(key);
> + }
> +egress:
> + TPM_AUTH_ERR_CHECK(pAuth);
> + return status;
> +}
> +
> +TPM_RESULT TPM_LoadKey(
> + TPM_KEY_HANDLE parentHandle, //
> + const TPM_KEY* key, //in
> + TPM_HANDLE* keyHandle, // out
> + const TPM_AUTHDATA* usage_auth,
> + TPM_AUTH_SESSION* auth)
> +{
> + TPM_BEGIN(TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_LoadKey);
> + TPM_AUTH_BEGIN();
> +
> + TPM_AUTH_HASH();
> +
> + ptr = pack_TPM_KEY_HANDLE(ptr, parentHandle);
> +
> + TPM_AUTH_SKIP();
> +
> + ptr = pack_TPM_KEY(ptr, key);
> +
> + TPM_AUTH_HASH();
> +
> + TPM_AUTH1_GEN(usage_auth, auth);
> + TPM_TRANSMIT();
> + TPM_UNPACK_VERIFY();
> + TPM_AUTH_VERIFY_BEGIN();
> +
> + ptr = unpack_UINT32(ptr, keyHandle);
> +
> + TPM_AUTH_HASH();
> +
> + TPM_AUTH1_VERIFY(usage_auth, auth);
> +
> + vtpmloginfo(VTPM_LOG_TPM, "Key Handle: 0x%x opened by TPM_LoadKey\n", *keyHandle);
> +
> +abort_egress:
> + TPM_AUTH_ERR_CHECK(auth);
> + return status;
> +}
> +
> +TPM_RESULT TPM_EvictKey( TPM_KEY_HANDLE hKey) // in
> +{
> + if(hKey == 0) {
> + return TPM_SUCCESS;
> + }
> +
> + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_EvictKey);
> +
> + ptr = pack_TPM_KEY_HANDLE(ptr, hKey);
> +
> + TPM_TRANSMIT();
> + TPM_UNPACK_VERIFY();
> +
> + vtpmloginfo(VTPM_LOG_TPM, "Key handle: 0x%x closed by TPM_EvictKey\n", hKey);
> +
> +abort_egress:
> + return status;
> +}
> +
> +TPM_RESULT TPM_FlushSpecific(TPM_HANDLE handle,
> + TPM_RESOURCE_TYPE rt) {
> + if(handle == 0) {
> + return TPM_SUCCESS;
> + }
> +
> + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_FlushSpecific);
> +
> + ptr = pack_TPM_HANDLE(ptr, handle);
> + ptr = pack_TPM_RESOURCE_TYPE(ptr, rt);
> +
> + TPM_TRANSMIT();
> + TPM_UNPACK_VERIFY();
> +
> +abort_egress:
> + return status;
> +}
> +
> +TPM_RESULT TPM_GetRandom( UINT32* bytesRequested, // in, out
> + BYTE* randomBytes) // out
> +{
> + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_GetRandom);
> +
> + // check input params
> + if (bytesRequested == NULL || randomBytes == NULL){
> + return TPM_BAD_PARAMETER;
> + }
> +
> + ptr = pack_UINT32(ptr, *bytesRequested);
> +
> + TPM_TRANSMIT();
> + TPM_UNPACK_VERIFY();
> +
> + ptr = unpack_UINT32(ptr, bytesRequested);
> + ptr = unpack_BUFFER(ptr, randomBytes, *bytesRequested);
> +
> +abort_egress:
> + return status;
> +}
> +
> +
> +TPM_RESULT TPM_ReadPubek(
> + TPM_PUBKEY* pubEK //out
> + )
> +{
> + BYTE* antiReplay = NULL;
> + BYTE* kptr = NULL;
> + BYTE digest[TPM_DIGEST_SIZE];
> + sha1_context ctx;
> +
> + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_ReadPubek);
> +
> + //antiReplay nonce
> + vtpmmgr_rand(ptr, TPM_DIGEST_SIZE);
> + antiReplay = ptr;
> + ptr += TPM_DIGEST_SIZE;
> +
> + TPM_TRANSMIT();
> + TPM_UNPACK_VERIFY();
> +
> + //unpack and allocate the key
> + kptr = ptr;
> + ptr = unpack_TPM_PUBKEY(ptr, pubEK, UNPACK_ALLOC);
> +
> + //Verify the checksum
> + sha1_starts(&ctx);
> + sha1_update(&ctx, kptr, ptr - kptr);
> + sha1_update(&ctx, antiReplay, TPM_DIGEST_SIZE);
> + sha1_finish(&ctx, digest);
> +
> + //ptr points to the checksum computed by TPM
> + if(memcmp(digest, ptr, TPM_DIGEST_SIZE)) {
> + vtpmlogerror(VTPM_LOG_TPM, "TPM_ReadPubek: Checksum returned by TPM was invalid!\n");
> + status = TPM_FAIL;
> + goto abort_egress;
> + }
> +
> + goto egress;
> +abort_egress:
> + if(kptr != NULL) { //If we unpacked the pubEK, we have to free it
> + free_TPM_PUBKEY(pubEK);
> + }
> +egress:
> + return status;
> +}
> +
> +
> +TPM_RESULT TPM_SaveState(void)
> +{
> + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_SaveState);
> +
> + TPM_TRANSMIT();
> + TPM_UNPACK_VERIFY();
> +
> +abort_egress:
> + return status;
> +}
> +
> +TPM_RESULT TPM_GetCapability(
> + TPM_CAPABILITY_AREA capArea,
> + UINT32 subCapSize,
> + const BYTE* subCap,
> + UINT32* respSize,
> + BYTE** resp)
> +{
> + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_GetCapability);
> +
> + ptr = pack_TPM_CAPABILITY_AREA(ptr, capArea);
> + ptr = pack_UINT32(ptr, subCapSize);
> + ptr = pack_BUFFER(ptr, subCap, subCapSize);
> +
> + TPM_TRANSMIT();
> + TPM_UNPACK_VERIFY();
> +
> + ptr = unpack_UINT32(ptr, respSize);
> + ptr = unpack_ALLOC(ptr, resp, *respSize);
> +
> +abort_egress:
> + return status;
> +}
> +
> +TPM_RESULT TPM_CreateEndorsementKeyPair(
> + const TPM_KEY_PARMS* keyInfo,
> + TPM_PUBKEY* pubEK)
> +{
> + BYTE* kptr = NULL;
> + sha1_context ctx;
> + TPM_DIGEST checksum;
> + TPM_DIGEST hash;
> + TPM_NONCE antiReplay;
> + TPM_BEGIN(TPM_TAG_RQU_COMMAND, TPM_ORD_CreateEndorsementKeyPair);
> +
> + //Make anti replay nonce
> + vtpmmgr_rand(antiReplay.nonce, sizeof(antiReplay.nonce));
> +
> + ptr = pack_TPM_NONCE(ptr, &antiReplay);
> + ptr = pack_TPM_KEY_PARMS(ptr, keyInfo);
> +
> + TPM_TRANSMIT();
> + TPM_UNPACK_VERIFY();
> +
> + sha1_starts(&ctx);
> +
> + kptr = ptr;
> + ptr = unpack_TPM_PUBKEY(ptr, pubEK, UNPACK_ALLOC);
> +
> + /* Hash the pub key blob */
> + sha1_update(&ctx, kptr, ptr - kptr);
> + ptr = unpack_TPM_DIGEST(ptr, &checksum);
> +
> + sha1_update(&ctx, antiReplay.nonce, sizeof(antiReplay.nonce));
> +
> + sha1_finish(&ctx, hash.digest);
> + if(memcmp(checksum.digest, hash.digest, TPM_DIGEST_SIZE)) {
> + vtpmloginfo(VTPM_LOG_VTPM, "TPM_CreateEndorsementKey: Checkum verification failed!\n");
> + status = TPM_FAIL;
> + goto abort_egress;
> + }
> +
> + goto egress;
> +abort_egress:
> + if(kptr) {
> + free_TPM_PUBKEY(pubEK);
> + }
> +egress:
> + return status;
> +}
> +
> +TPM_RESULT TPM_TransmitData(
> + BYTE* in,
> + UINT32 insize,
> + BYTE* out,
> + UINT32* outsize) {
> + TPM_RESULT status = TPM_SUCCESS;
> +
> + UINT32 i;
> + vtpmloginfo(VTPM_LOG_TXDATA, "Sending buffer = 0x");
> + for(i = 0 ; i < insize ; i++)
> + vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", in[i]);
> +
> + vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
> +
> + ssize_t size = 0;
> +
> + // send the request
> + size = write (vtpm_globals.tpm_fd, in, insize);
> + if (size < 0) {
> + vtpmlogerror(VTPM_LOG_TXDATA, "write() failed : %s\n", strerror(errno));
> + ERRORDIE (TPM_IOERROR);
> + }
> + else if ((UINT32) size < insize) {
> + vtpmlogerror(VTPM_LOG_TXDATA, "Wrote %d instead of %d bytes!\n", (int) size, insize);
> + ERRORDIE (TPM_IOERROR);
> + }
> +
> + // read the response
> + size = read (vtpm_globals.tpm_fd, out, *outsize);
> + if (size < 0) {
> + vtpmlogerror(VTPM_LOG_TXDATA, "read() failed : %s\n", strerror(errno));
> + ERRORDIE (TPM_IOERROR);
> + }
> +
> + vtpmloginfo(VTPM_LOG_TXDATA, "Receiving buffer = 0x");
> + for(i = 0 ; i < size ; i++)
> + vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", out[i]);
> +
> + vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
> +
> + *outsize = size;
> + goto egress;
> +
> +abort_egress:
> +egress:
> + return status;
> +}
> diff --git a/stubdom/vtpmmgr/tpm.h b/stubdom/vtpmmgr/tpm.h
> new file mode 100644
> index 0000000..304e145
> --- /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 0000000..56094e7
> --- /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 0000000..59579e7
> --- /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 0000000..4737645
> --- /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 0000000..f82a2a9
> --- /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 0000000..a2bbcca
> --- /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 0000000..9ce0c32
> --- /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 0000000..a5a5fd7
> --- /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 0000000..563f4e8
> --- /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 0000000..50a1992
> --- /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
> --
> 1.7.10.4
>
[-- Attachment #1.2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 1459 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
next prev parent reply other threads:[~2012-11-20 14:25 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-11-20 14:21 [PATCH VTPM v4 1/5] add vtpm-stubdom code Matthew Fioravante
2012-11-20 14:21 ` [PATCH VTPM v4 2/5] add stubdom/vtpmmgr code Matthew Fioravante
2012-11-20 14:25 ` Matthew Fioravante [this message]
2012-11-20 14:21 ` [PATCH VTPM v4 3/5] vtpm/vtpmmgr and required libs to stubdom/Makefile Matthew Fioravante
2012-11-20 15:45 ` Samuel Thibault
2012-11-23 9:59 ` Ian Campbell
2012-11-29 11:39 ` Ian Jackson
2012-11-29 11:41 ` Ian Jackson
2012-11-29 13:54 ` Matthew Fioravante
2012-11-29 16:03 ` Ian Campbell
2012-11-29 17:54 ` Ian Jackson
2012-11-29 18:30 ` Matthew Fioravante
2012-11-20 14:21 ` [PATCH VTPM v4 4/5] Add vtpm documentation Matthew Fioravante
2012-11-20 14:21 ` [PATCH VTPM v4 5/5] Add cmake dependency to README Matthew Fioravante
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=50AB92CF.8040306@jhuapl.edu \
--to=matthew.fioravante@jhuapl.edu \
--cc=Ian.Campbell@citrix.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).