// This file was extracted from the TCG Published
// Trusted Platform Module Library
// Part 3: Commands
// Family "2.0"
// Level 00 Revision 01.16
// October 30, 2014
#include "InternalRoutines.h"
#include "EventSequenceComplete_fp.h"
//
//
// Error Returns Meaning
//
// TPM_RC_LOCALITY PCR extension is not allowed at the current locality
// TPM_RC_MODE input handle is not a valid event sequence object
//
TPM_RC
TPM2_EventSequenceComplete(
EventSequenceComplete_In *in, // IN: input parameter list
EventSequenceComplete_Out *out // OUT: output parameter list
)
{
TPM_RC result;
HASH_OBJECT *hashObject;
UINT32 i;
TPM_ALG_ID hashAlg;
// Input validation
// get the event sequence object pointer
hashObject = (HASH_OBJECT *)ObjectGet(in->sequenceHandle);
// input handle must reference an event sequence object
if(hashObject->attributes.eventSeq != SET)
return TPM_RC_MODE + RC_EventSequenceComplete_sequenceHandle;
// see if a PCR extend is requested in call
if(in->pcrHandle != TPM_RH_NULL)
{
// see if extend of the PCR is allowed at the locality of the command,
if(!PCRIsExtendAllowed(in->pcrHandle))
return TPM_RC_LOCALITY;
// if an extend is going to take place, then check to see if there has
// been an orderly shutdown. If so, and the selected PCR is one of the
// state saved PCR, then the orderly state has to change. The orderly state
// does not change for PCR that are not preserved.
// NOTE: This doesn't just check for Shutdown(STATE) because the orderly
// state will have to change if this is a state-saved PCR regardless
// of the current state. This is because a subsequent Shutdown(STATE) will
// check to see if there was an orderly shutdown and not do anything if
// there was. So, this must indicate that a future Shutdown(STATE) has
// something to do.
if(gp.orderlyState != SHUTDOWN_NONE && PCRIsStateSaved(in->pcrHandle))
{
result = NvIsAvailable();
if(result != TPM_RC_SUCCESS) return result;
g_clearOrderly = TRUE;
}
}
// Command Output
out->results.count = 0;
for(i = 0; i < HASH_COUNT; i++)
{
hashAlg = CryptGetHashAlgByIndex(i);
// Update last piece of data
CryptUpdateDigest2B(&hashObject->state.hashState[i], &in->buffer.b);
// Complete hash
out->results.digests[out->results.count].hashAlg = hashAlg;
CryptCompleteHash(&hashObject->state.hashState[i],
CryptGetHashDigestSize(hashAlg),
(BYTE *) &out->results.digests[out->results.count].digest);
// Extend PCR
if(in->pcrHandle != TPM_RH_NULL)
PCRExtend(in->pcrHandle, hashAlg,
CryptGetHashDigestSize(hashAlg),
(BYTE *) &out->results.digests[out->results.count].digest);
out->results.count++;
}
// Internal Data Update
// mark sequence object as evict so it will be flushed on the way out
hashObject->attributes.evict = SET;
return TPM_RC_SUCCESS;
}