| // 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; |
| } |