| // 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 "SequenceComplete_fp.h" |
| #include <Platform.h> |
| // |
| // |
| // Error Returns Meaning |
| // |
| // TPM_RC_TYPE sequenceHandle does not reference a hash or HMAC sequence |
| // object |
| // |
| TPM_RC |
| TPM2_SequenceComplete( |
| SequenceComplete_In *in, // IN: input parameter list |
| SequenceComplete_Out *out // OUT: output parameter list |
| ) |
| { |
| OBJECT *object; |
| |
| // Input validation |
| |
| // Get hash object pointer |
| object = ObjectGet(in->sequenceHandle); |
| |
| // input handle must be a hash or HMAC sequence object. |
| if( object->attributes.hashSeq == CLEAR |
| && object->attributes.hmacSeq == CLEAR) |
| return TPM_RC_MODE + RC_SequenceComplete_sequenceHandle; |
| |
| // Command Output |
| |
| if(object->attributes.hashSeq == SET) // sequence object for hash |
| { |
| // Update last piece of data |
| HASH_OBJECT *hashObject = (HASH_OBJECT *)object; |
| |
| // Get the hash algorithm before the algorithm is lost in CryptCompleteHash |
| TPM_ALG_ID hashAlg = hashObject->state.hashState[0].state.hashAlg; |
| |
| CryptUpdateDigest2B(&hashObject->state.hashState[0], &in->buffer.b); |
| |
| // Complete hash |
| out->result.t.size |
| = CryptGetHashDigestSize( |
| CryptGetContextAlg(&hashObject->state.hashState[0])); |
| |
| CryptCompleteHash2B(&hashObject->state.hashState[0], &out->result.b); |
| |
| // Check if the first block of the sequence has been received |
| if(hashObject->attributes.firstBlock == CLEAR) |
| { |
| // If not, then this is the first block so see if it is 'safe' |
| // to sign. |
| if(TicketIsSafe(&in->buffer.b)) |
| hashObject->attributes.ticketSafe = SET; |
| } |
| |
| // Output ticket |
| out->validation.tag = TPM_ST_HASHCHECK; |
| out->validation.hierarchy = in->hierarchy; |
| |
| if(in->hierarchy == TPM_RH_NULL) |
| { |
| // Ticket is not required |
| out->validation.digest.t.size = 0; |
| } |
| else if(object->attributes.ticketSafe == CLEAR) |
| { |
| // Ticket is not safe to generate |
| out->validation.hierarchy = TPM_RH_NULL; |
| out->validation.digest.t.size = 0; |
| } |
| else |
| { |
| // Compute ticket |
| TicketComputeHashCheck(out->validation.hierarchy, hashAlg, |
| &out->result, &out->validation); |
| } |
| } |
| else |
| { |
| HASH_OBJECT *hashObject = (HASH_OBJECT *)object; |
| |
| // Update last piece of data |
| CryptUpdateDigest2B(&hashObject->state.hmacState, &in->buffer.b); |
| // Complete hash/HMAC |
| out->result.t.size = |
| CryptGetHashDigestSize( |
| CryptGetContextAlg(&hashObject->state.hmacState.hashState)); |
| CryptCompleteHMAC2B(&(hashObject->state.hmacState), &out->result.b); |
| |
| // No ticket is generated for HMAC sequence |
| out->validation.tag = TPM_ST_HASHCHECK; |
| out->validation.hierarchy = TPM_RH_NULL; |
| out->validation.digest.t.size = 0; |
| } |
| |
| // Internal Data Update |
| |
| // mark sequence object as evict so it will be flushed on the way out |
| object->attributes.evict = SET; |
| |
| return TPM_RC_SUCCESS; |
| } |