Commit f4cca17f authored by Robert Ricci's avatar Robert Ricci

Merge branch 'tpm-tmcd'

Conflicts:
	db/libdb.pm.in

Conflict resolved by using libdb.pm.in from master, and moving new
constants committed on the tpm-tmcd branch to the new
EmulabConstants.pm.in file.
parents 9b623f72 4cbd3447
......@@ -94,12 +94,14 @@ use vars qw(@ISA @EXPORT);
TBDB_NODESTATE_PXEFAILED TBDB_NODESTATE_PXELIMBO
TBDB_NODESTATE_PXEBOOTING TBDB_NODESTATE_ALWAYSUP
TBDB_NODESTATE_MFSSETUP TBDB_NODESTATE_TBFAILED
TBDB_NODESTATE_POWEROFF
TBDB_NODESTATE_POWEROFF TBDB_NODESTATE_SECVIOLATION
TBDB_NODESTATE_TPMSIGNOFF
TBDB_NODEOPMODE_NORMAL TBDB_NODEOPMODE_DELAYING
TBDB_NODEOPMODE_UNKNOWNOS TBDB_NODEOPMODE_RELOADING
TBDB_NODEOPMODE_NORMALv1 TBDB_NODEOPMODE_MINIMAL TBDB_NODEOPMODE_PCVM
TBDB_NODEOPMODE_RELOAD TBDB_NODEOPMODE_RELOADMOTE TBDB_NODEOPMODE_RELOADPCVM
TBDB_NODEOPMODE_RELOAD TBDB_NODEOPMODE_RELOADMOTE
TBDB_NODEOPMODE_SECURELOAD TBDB_NODEOPMODE_RELOADPCVM
TBDB_NODEOPMODE_DELAY
TBDB_NODEOPMODE_BOOTWHAT
TBDB_NODEOPMODE_ANY
......@@ -399,6 +401,9 @@ sub TBDB_NODESTATE_PXEWAKEUP() { "PXEWAKEUP"; }
sub TBDB_NODESTATE_PXEFAILED() { "PXEFAILED"; }
sub TBDB_NODESTATE_PXEBOOTING() { "PXEBOOTING"; }
sub TBDB_NODESTATE_POWEROFF() { "POWEROFF"; }
sub TBDB_NODESTATE_TPMSIGNOFF() { "TPMSIGNOFF"; }
sub TBDB_NODESTATE_SECVIOLATION(){ "SECVIOLATION"; }
sub TBDB_NODESTATE_MFSBOOTING() { "MFSBOOTING"; }
sub TBDB_NODEOPMODE_ANY { "*"; } # A wildcard opmode
sub TBDB_NODEOPMODE_NORMAL { "NORMAL"; }
......@@ -410,6 +415,7 @@ sub TBDB_NODEOPMODE_MINIMAL { "MINIMAL"; }
sub TBDB_NODEOPMODE_PCVM { "PCVM"; }
sub TBDB_NODEOPMODE_RELOAD { "RELOAD"; }
sub TBDB_NODEOPMODE_RELOADMOTE { "RELOAD-MOTE"; }
sub TBDB_NODEOPMODE_SECURELOAD { "SECURELOAD"; }
sub TBDB_NODEOPMODE_RELOADPCVM { "RELOAD-PCVM"; }
sub TBDB_NODEOPMODE_DELAY { "DELAY"; }
sub TBDB_NODEOPMODE_BOOTWHAT { "_BOOTWHAT_"; } # A redirection opmode
......
Some notes about the TPM-enforced boot path (SECURELOAD state machine).
The current implementation requires that we boot from a flash device
BEFORE we network boot (see the paper for details). Unfortunately,
there is a lot of magic associated with the PXEBOOTING state, which is
assumed to always be the first state we will see when a node boots.
However, in the secure boot path the first thing we see is a secure
transition to the GPXEBOOTING state, so magic had to be added for that!
In particular:
* When stated gets a transition to GPXEBOOTING, it forces the node into
the SECURELOAD op_mode. This is a new trigger called SECURELOAD and
a new trigger table entry:
insert into state_triggers values \
('*','*','GPXEBOOTING','SECURELOAD');
* Later, when we do get a PXEBOOTING state, we DON'T push the machine
into the PXEBOOT op_mode. We do this with an override trigger:
insert into state_triggers values \
('*','SECURELOAD','PXEBOOTING','SECURELOAD');
This is supposed to override the more general any ('*') op_mode trigger
for the PXEBOOTING state and will just make sure we state in SECURELOAD.
......@@ -140,6 +140,9 @@ my $TB_OSID_MBKERNEL = TB_OSID_MBKERNEL;
# Special PXEBOOT state machine that all local nodes use.
my $PXEKERNEL = "PXEKERNEL";
# Even special-er SECURELOAD state machine that local nodes may use.
my $SECURELOAD = "SECURELOAD";
# Protos.
sub debug(@);
sub fatal($);
......@@ -625,6 +628,14 @@ sub stateTransition($$) {
!$valid{$mode}{$oldstate}{$newstate}) {
notify("Invalid transition for node $node from $mode/$oldstate " .
"to $newstate\n");
# XXX: Bad hack for TPM booting paper: this ought to be in the
# database, not harcoded here for a specific op_mode
# Let specifc op_modes drive nodes into particular states on invalid
# transitions
if ($mode eq TBDB_NODEOPMODE_SECURELOAD) {
$newstate = TBDB_NODESTATE_SECVIOLATION;
notify("Moving $node to $newstate because it's in $mode\n");
}
}
my $now = time();
......@@ -718,6 +729,19 @@ sub stateTransition($$) {
}
next;
};
/^SECURELOAD$/ && do {
#
# Force machine into the SECURELOAD op_mode.
# Currently triggered only by receipt of GPXEBOOTING state.
#
debug("Running $SECURELOAD trigger\n");
if ($mode ne $SECURELOAD) {
info("$node: Forcing mode transition into $SECURELOAD!\n");
opModeTransition($node, $SECURELOAD, 1);
$mode=$SECURELOAD;
}
next;
};
/^$BOOTING$/ && do {
#
# See if we are in the right mode/osid.
......@@ -823,6 +847,18 @@ sub stateTransition($$) {
handleCommand($node,$trig);
next;
};
(/^$TBPOWEROFF$/) && do {
handleCommand($node,$TBPOWEROFF);
next;
};
(/^EMAILNOTIFY$/) && do {
SENDMAIL($REALTBOPS,
"STATED: $node entered state $newstate",
"$node entered state $mode/$newstate from " .
"$mode/$oldstate",
"Stated Daemon <".$TBOPS.">");
next;
};
/^RELOADOLDMFS$/ && do {
my $frisbee_osid = TBNodeDiskloadOSID($node);
my $frisbee_name = DBQuerySingleFatal("select osname from os_info where osid=$frisbee_osid");
......@@ -1040,6 +1076,11 @@ sub handleCtrlEvent($$) {
/^$TBTIMEOUTNOTIFY/ && do {
notify("Node $node has timed out in state $mode/$state\n");
last; };
/^STATE:([-\w\/]+)$/ && do {
my $newstate = $1;
# Force the node into a new state
stateTransition($node,$newstate);
last; };
notify("$node: Unknown Timeout Action: $action\n");
}
next;
......
......@@ -152,13 +152,13 @@ dostype-debug: dostype.o
ssl.o: ssl.c ssl.h decls.h
tpm.o: tpm.c tpm.h
$(CC) -c $(CFLAGS) $(TESTBED_SRCDIR)/tmcd/tpm.c \
tpm.o: tpm.c tpm.h ssl.h
$(CC) -c $(CFLAGS) $(SSLFLAGS) $(TESTBED_SRCDIR)/tmcd/tpm.c \
-I$(TESTBED_SRCDIR)/tmcd/
notpm: tpm.c tpm.h
$(CC) -c $(CFLAGS) -DTPMOVERRIDE $(TESTBED_SRCDIR)/tmcd/tpm.c \
-I$(TESTBED_SRCDIR)/tmcd/
notpm: tpm.c tpm.h ssl.h
$(CC) -c $(CFLAGS) $(SSLFLAGS) -DTPMOVERRIDE \
$(TESTBED_SRCDIR)/tmcd/tpm.c -I$(TESTBED_SRCDIR)/tmcd/
version.c: tmcd.c
echo >$@ "char build_info[] = \"Built `date +%d-%b-%Y` by `id -nu`@`hostname | sed 's/\..*//'`:`pwd`\";"
......
......@@ -28,7 +28,9 @@
#include <unistd.h>
#include <netdb.h>
#include <openssl/engine.h>
#include <openssl/rsa.h>
#include <openssl/ssl.h>
#include <openssl/sha.h>
#include <openssl/err.h>
#include "decls.h"
#include "ssl.h"
......@@ -90,6 +92,7 @@ static char nosslbuf[MAXTMCDPACKET];
static int nosslbuflen, nosslbufidx;
static void tmcd_sslerror();
static void tmcd_sslprint(const char *fmt, ...);
static RSA * convpubkey(struct pubkeydata *);
/*
* Init our SSL context. This is done once, in the parent.
......@@ -649,6 +652,89 @@ tmcd_sslrowtocert(char *in, char *nid)
return local;
}
/*
* SHA1 hashes src of length len and stores the result at dst. dst must be at
* least 20 bytes long.
*/
int
tmcd_quote_hash(void *src, size_t len, void *dst)
{
if (SHA1(src, len, dst) == NULL)
return 1;
return 0;
}
/*
* Verifies that buffer sig of length siglen is indeed the buffer final
* encrypted with the private key to pubkey (or checks the signature of buffer
* sig).
*
* Returns 1 if the signature verified, 0 if it failed
*/
int
tmcd_quote_verifysig(void *final, void *sig, size_t siglen, void *pubkey)
{
struct keydata k;
RSA *rsa;
int ret;
if (!pubkey) {
error("NULL pubkey to %s\n", __FUNCTION__);
return 0;
}
if (!final) {
error("NULL final to %s\n", __FUNCTION__);
return 0;
}
if (!sig) {
error("NULL sig to %s\n", __FUNCTION__);
return 0;
}
/* Cannot fail */
tpm_extract_key((unsigned char *)pubkey, &k);
rsa = convpubkey(&k.pub);
if (!rsa) {
error("Error extracting and converting key\n");
return 0;
}
ret = RSA_verify(NID_sha1, final, 20, sig, siglen, rsa);
RSA_free(rsa);
return ret;
}
static RSA *
convpubkey(struct pubkeydata *k)
{
RSA *rsa;
BIGNUM *mod;
BIGNUM *exp;
/* create the necessary structures */
rsa = RSA_new();
mod = BN_new();
exp = BN_new();
if (rsa == NULL || mod == NULL || exp == NULL) {
if (rsa)
RSA_free(rsa);
if (mod)
BN_free(mod);
if (exp)
BN_free(exp);
return NULL;
}
/* convert the raw public key values to BIGNUMS */
BN_bin2bn(k->modulus, k->keylength, mod);
BN_bin2bn(k->exponent, k->expsize, exp);
/* set up the RSA public key structure */
rsa->n = mod;
rsa->e = exp;
return rsa;
}
/*
* Log an SSL error
*/
......
......@@ -17,6 +17,8 @@ int tmcd_sslwrite(int sock, const void *buf, size_t nbytes);
int tmcd_sslread(int sock, void *buf, size_t nbytes);
int tmcd_sslclose(int sock);
int tmcd_sslverify_client(char *, char *, char *, int);
int tmcd_quote_hash(void *, size_t, void *);
int tmcd_quote_verifysig(void *, void *, size_t, void *);
X509* tmcd_sslgetpeercert(void);
X509* tmcd_sslrowtocert(char*, char*);
int isssl;
......
This diff is collapsed.
......@@ -11,6 +11,15 @@
#define error printf
#endif /* STANDALONE */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <netinet/in.h>
static unsigned int nonce_counter = 0;
/*
* XXX: Teach me how to do this properly . . . This is so boss can build ssl.o
* properly without installing trousers headers
......@@ -25,6 +34,10 @@
#include "tpm.h"
#ifdef WITHSSL
#include "ssl.h"
#endif
EVP_PKEY *tpmk;
#ifdef TPM
......@@ -124,3 +137,270 @@ tmcd_tpm_free(void)
return 1;
#endif /* TPM */
}
int
tmcd_tpm_generate_nonce(unsigned char *nonce)
{
struct timeval time;
pid_t pid;
int byte_count = 0;
bzero(nonce,TPM_NONCE_BYTES);
/* Nonce must be 160 bits long, and we must be quite sure that we will
* never use the same one twice. We put three things into the nonce to
* make it unique:
* 1) Timestamp to the best accuracy we can get
* 2) The PID of the current process, to avoid someone asking two
* different tmcds for nonces at thte same time
* 3) A local counter, in case someone can ask for nonces faster than our
* clock resolution
*/
// timestamp
if (gettimeofday(&time,NULL)) {
return -1;
}
if (sizeof(time) + byte_count > TPM_NONCE_BYTES) {
return -1;
}
bcopy(&time, nonce, sizeof(time));
byte_count += sizeof(time);
// pid
pid = getpid();
if (sizeof(pid) + byte_count > TPM_NONCE_BYTES) {
return -1;
}
bcopy(&pid, nonce + byte_count, sizeof(pid));
byte_count += sizeof(pid);
// counter
if (sizeof(nonce_counter) + byte_count > TPM_NONCE_BYTES) {
return -1;
}
bcopy(&nonce_counter, nonce + byte_count, sizeof(nonce_counter));
byte_count += sizeof(nonce_counter);
// TODO: Maybe hash to avoid giving away info on state on boss?
return 0;
}
/*
* Verify that a quote is what we expect it to be. We need SHA1 hashing to do
* this so we require SSL.
*
* Returns 1 if the quote is valid, 0 otherwise.
*/
int tmcd_tpm_verify_quote(char *quote, ssize_t quotelen, unsigned char *pcomp,
ssize_t pcomplen, ETPM_NONCE nonce, unsigned short wantpcrs,
TPM_PCR *pcrs, unsigned char *idkey)
{
#ifdef WITHSSL
struct signed_pcomp sp;
unsigned short pcrmlen;
/* XXX: The pcr mask is supposedly variable length but really 2 bytes
* in practice */
unsigned short pcrm;
uint32_t pcrlen;
int i, c, pcrtot = 0;
unsigned char hash[20];
if (!quote) {
error("NULL quote to %s\n", __FUNCTION__);
return 0;
}
if (!pcomp) {
error("NULL pcomp to %s\n", __FUNCTION__);
return 0;
}
if (!nonce) {
error("NULL nonce to %s\n", __FUNCTION__);
return 0;
}
if (!pcrs) {
error("NULL pcrs to %s\n", __FUNCTION__);
return 0;
}
if (!idkey) {
error("NULL idkey to %s\n", __FUNCTION__);
return 0;
}
pcrmlen = ntohs(*((unsigned short *)&pcomp[PCOMP_PCRMASK_LEN]));
pcrlen = ntohl(*((uint32_t *)&pcomp[PCOMP_PCRBLOB_LEN]));
/* Some sanity - 28 bytes is the smallest quote size possible on our
* TPMs.
* XXX: We do not deal with variable length pcr masks yet (it is
* probably useless unless you want to quote the dynamic pcrs). */
i = pcrmlen + pcrlen + sizeof(short) + sizeof(uint32_t);
if (pcrmlen != 2 || i != pcomplen || pcomplen < 28) {
error("Corrupt quote blob; unexpected quote size\n");
error("pcr mask len: %d, pcomplen: %d, pcrlen: %d,"
" calculated len: %d\n", pcrmlen, pcomplen, pcrlen, i);
return 0;
}
pcrm = *((unsigned short *)&pcomp[PCOMP_PCRMASK]);
for (i = 0; i < PCOMP_PCRMASK_BITS; i++)
if (pcrm & (1 << i))
pcrtot++;
if (pcrlen != pcrtot * PCOMP_PCR_LEN) {
error("Corrupt quote blob; pcrlen %d, should be: %d\n", pcrlen,
pcrtot * PCOMP_PCR_LEN);
return 0;
}
/* Check that it includes the PCRs we want */
if ((pcrm & wantpcrs) != wantpcrs) {
error("Missing required PCRs; wantpcr: %x pcrmask: %x\n",
wantpcrs, pcrm);
return 0;
}
/* Make sure that the PCRs are what we expect them to be. Dig up
* required PCRs. This assumes our pcrs argument contains the required
* PCR values in ascending order. */
for (i = 0, c = 0; i < PCOMP_PCRMASK_BITS; i++) {
if (pcrm & (1 << i)) {
if (memcmp(&pcomp[PCOMP_PCRBLOB + PCOMP_PCR_LEN * c],
pcrs[c], PCOMP_PCR_LEN)) {
error("PCR %d doesn't match\n", i);
return 0;
}
c++;
}
}
/* SHA1 pcomp and stuff it into struct _signed_comp */
sp.fixed[0] = 1; sp.fixed[1] = 1;
sp.fixed[2] = 0; sp.fixed[3] = 0;
sp.fixed[4] = 'Q'; sp.fixed[5] = 'U';
sp.fixed[6] = 'O'; sp.fixed[7] = 'T';
if (tmcd_quote_hash(pcomp, pcomplen, &sp.comphash)) {
error("Error hashing pcr composite\n");
return 0;
}
memcpy(&sp.nonce, nonce, TPM_NONCE_BYTES);
/* SHA1 _signed_comp */
if (tmcd_quote_hash(&sp, sizeof(sp), hash)) {
error("Error hashing signed pcomp\n");
return 0;
}
/* Verify that quote is indeed a signature of the SHA1 of
* _signed_comp */
if (!tmcd_quote_verifysig(hash, quote, quotelen, idkey)) {
error("Signature check failed\n");
return 0;
}
/* They survived the gauntlet! */
return 1;
#else
error("Can't verify quotes without SSL\n");
return 0;
#endif
}
/*
* Key extracting functions
*
* I use these to verify quotes. We must extract the identity key from the key
* blob. I took these from libtpm.
*
* XXX: I'll minimize these functions later.
*/
#define LOAD32(buffer,offset) ( ntohl(*(uint32_t *)&buffer[offset]) )
#define LOAD16(buffer,offset) ( ntohs(*(uint16_t *)&buffer[offset]) )
#define TPM_U16_SIZE 2
#define TPM_U32_SIZE 4
static int tpm_extract_pubkey(unsigned char *keybuff, struct pubkeydata *k,
int pcrpresent)
{
uint32_t parmsize;
uint32_t pcrisize;
int offset;
offset = 0;
k->algorithm = LOAD32(keybuff, offset);
offset += TPM_U32_SIZE;
k->encscheme = LOAD16(keybuff, offset);
offset += TPM_U16_SIZE;
k->sigscheme = LOAD16(keybuff, offset);
offset += TPM_U16_SIZE;
parmsize = LOAD32(keybuff, offset);
offset += TPM_U32_SIZE;
if (k->algorithm == 0x00000001 && parmsize > 0) { /* RSA */
k->keybitlen = LOAD32(keybuff, offset);
offset += TPM_U32_SIZE;
k->numprimes = LOAD32(keybuff, offset);
offset += TPM_U32_SIZE;
k->expsize = LOAD32(keybuff, offset);
offset += TPM_U32_SIZE;
} else {
offset += parmsize;
}
if (k->expsize == 3) {
k->exponent[0] = *(keybuff + offset + 0);
k->exponent[1] = *(keybuff + offset + 1);
k->exponent[2] = *(keybuff + offset + 2);
offset += k->expsize;
} else if (k->expsize != 0)
offset += k->expsize;
else {
k->exponent[0] = 0x01;
k->exponent[1] = 0x00;
k->exponent[2] = 0x01;
k->expsize = 3;
}
if (pcrpresent) {
pcrisize = LOAD32(keybuff, offset);
offset += TPM_U32_SIZE;
if (pcrisize > 0 && pcrisize <= 256)
memcpy(k->pcrinfo, keybuff + offset, pcrisize);
offset += pcrisize;
k->pcrinfolen = pcrisize;
}
k->keylength = LOAD32(keybuff, offset);
offset += TPM_U32_SIZE;
if (k->keylength > 0 && k->keylength <= 256)
memcpy(k->modulus, keybuff + offset, k->keylength);
offset += k->keylength;
return offset;
}
int tpm_extract_key(unsigned char *keybuff, struct keydata * k)
{
int offset;
int pubkeylen;
/* fill in keydata structure */
offset = 0;
memcpy(k->version, keybuff + offset, sizeof(k->version));
offset += 4;
k->keyusage = LOAD16(keybuff, offset);
offset += TPM_U16_SIZE;
k->keyflags = LOAD32(keybuff, offset);
offset += TPM_U32_SIZE;
k->authdatausage = keybuff[offset];
offset += 1;
pubkeylen = tpm_extract_pubkey(keybuff + offset, &(k->pub), 1);
offset += pubkeylen;
k->privkeylen = LOAD32(keybuff, offset);
offset += TPM_U32_SIZE;
if (k->privkeylen > 0 && k->privkeylen <= 1024)
memcpy(k->encprivkey, keybuff + offset, k->privkeylen);
offset += k->privkeylen;
return offset;
}
......@@ -7,7 +7,8 @@
#ifndef _ETPM_
#define _ETPM_
#include<openssl/engine.h>
#include <sys/types.h>
#include <openssl/engine.h>
extern EVP_PKEY *tpmk;
......@@ -15,4 +16,62 @@ int tmcd_tpm_loadengine();
int tmcd_tpm_getkey(char *);
int tmcd_tpm_free(void);
/*
* Nonce-related functions
*/
#define TPM_NONCE_BYTES 0x14 // 160 bits
#define TPM_PCR_BYTES 0x14 // 160 bits
typedef unsigned char ETPM_NONCE[TPM_NONCE_BYTES];
typedef unsigned char TPM_PCR[TPM_PCR_BYTES];
int tmcd_tpm_generate_nonce(unsigned char*);
/*
* Quote verifying stuff
*/
struct signed_pcomp {
unsigned char fixed[8];
/* Hash of PCR composite */
unsigned char comphash[20];
ETPM_NONCE nonce;
};
struct pubkeydata {
uint32_t algorithm;
uint16_t encscheme;
uint16_t sigscheme;
uint32_t keybitlen;
uint32_t numprimes;
uint32_t expsize;
unsigned char exponent[3];
uint32_t keylength;
unsigned char modulus[256];
uint32_t pcrinfolen;
unsigned char pcrinfo[256];
};
struct keydata {
unsigned char version[4];
uint16_t keyusage;
uint32_t keyflags;
unsigned char authdatausage;
struct pubkeydata pub;
uint32_t privkeylen;
unsigned char encprivkey[1024];
};
/* Help for navigating around a PCR composite - they are variable length
* depending on how many PCRs you request in the quote */
#define PCOMP_PCRMASK_LEN 0
#define PCOMP_PCRMASK 2
#define PCOMP_PCRBLOB_LEN 4
#define PCOMP_PCRBLOB 8
#define PCOMP_PCR_LEN 20
#define PCOMP_PCRMASK_BITS 16
int tmcd_tpm_verify_quote(char *, ssize_t, unsigned char *, ssize_t, ETPM_NONCE,
unsigned short, TPM_PCR*, unsigned char*);
int tpm_extract_key(unsigned char *, struct keydata *);
#endif
all:
gcc -o idkey idkey.c -ltspi #-lcrypto
gcc -o keygen keygen.c -ltspi
gcc -o doquote doquote.c -ltspi
gcc -o tpm-signoff tpm-signoff.c -ltspi
gcc -o getpub getpub.c -ltspi
gcc -o loadkey loadkey.c -ltspi
gcc -o fail fail.c -ltspi
gcc -o pcrcomposite pcrcomposite.c -ltspi
gcc -o ltpmloadkey ltpmloadkey.c libtpm/bind.c libtpm/chgauth.c \
libtpm/hmac.c libtpm/keys.c libtpm/migrate.c libtpm/miscfunc.c \
libtpm/oiaposap.c libtpm/owner.c libtpm/pcrs.c libtpm/seal.c \
libtpm/signature.c libtpm/tpmutil.c -Ilibtpm -lcrypto
These example programs show how to do various things with Trousers and
libtpm. The only important ones are these:
idkey.c - Goes through the trouble of creating an
identity key - this process is fairly complex
under normal circumstances but in our
environment it is much simpler. This is why we
are able to skip all the Privacy CA stuff.
doquote.c - This is a helper program that we use inside
the TPM MFS; it was made to be used in scripts
with tmcc. It will take the output from TMCD
'quoteprep' command, do the proper quote, and
then write the output back out so it can be
piped right back to tmcc for the 'nextstate'
command. See the usage for more details.
loadkey.c - This demonstrates how to load an encrypted
identity key blob and make a quote with it. It
also has some bonus code that shows how to parse
the quote.
ltpmloadkey.c - This also loads an identity key (but it uses
libtpm, unlike all other code here), generates a
quote with the identity key, parses it, and
verifies it. This is fairly valuable because
there is/was practically no documentation on how
to do this.
pcrcomposite.c - Shows the PCR composite structure (also in
ltpmloadkey.c).
tpm-signoff.c - This is another helper program we use in the
TPM MFS. It extends rubbish into the specified
PCR. We use this for the sign-off phase of the
boot chain.
This diff is collapsed.
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2008-2010 University of Utah and the Flux Group.
* All rights reserved.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <err.h>
#include <fcntl.h>
#include <openssl/ssl.h>
#include <sys/stat.h>
#include <tss/tspi.h>
#include <tss/platform.h>
#include <tss/tss_typedef.h>
#include <tss/tss_structs.h>
#define TSS_ERROR_CODE(x) (x & 0xFFF)
#define FATAL(x) do{printf("**\t");printf(x);printf("\n");}while(0);
//#define FATAL(x) do{printf(x);printf("\n");exit(1);}while(0);
void check(char *msg, int cin){
int in = TSS_ERROR_CODE(cin);
printf("%s: ", msg);
if(in == TSS_SUCCESS) {
printf("TSS_SUCCESS\n");
return;
} else if(in == TSS_E_INVALID_HANDLE)
printf("TSS_E_INVALID_HANDLE\n");
else if(in == TSS_E_INTERNAL_ERROR)
printf("TSS_E_INTERNAL_ERROR\n");
else if(in == TSS_E_BAD_PARAMETER)
printf("TSS_E_BAD_PARAMETER\n");
else if(in == TSS_E_HASH_INVALID_LENGTH)