mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
add stubdom/vtpmmgr code
Add the code base for vtpmmgrdom. Makefile changes next patch. Signed-off-by: Matthew Fioravante <matthew.fioravante@jhuapl.edu> Acked-by: Ian Campbell <ian.campbell@citrix.com> Committed-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
1 parent
d463e3c5a3
commit
095b0b7794
18 files changed
+4766
No files matched your search
@@ -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
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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__
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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
|
||||