1 // This file was extracted from the TCG Published 2 // Trusted Platform Module Library 3 // Part 3: Commands 4 // Family "2.0" 5 // Level 00 Revision 01.16 6 // October 30, 2014 7 8 #include "InternalRoutines.h" 9 #include "SequenceComplete_fp.h" 10 #include "Platform.h" 11 // 12 // 13 // Error Returns Meaning 14 // 15 // TPM_RC_TYPE sequenceHandle does not reference a hash or HMAC sequence 16 // object 17 // 18 TPM_RC 19 TPM2_SequenceComplete( 20 SequenceComplete_In *in, // IN: input parameter list 21 SequenceComplete_Out *out // OUT: output parameter list 22 ) 23 { 24 OBJECT *object; 25 26 // Input validation 27 28 // Get hash object pointer 29 object = ObjectGet(in->sequenceHandle); 30 31 // input handle must be a hash or HMAC sequence object. 32 if( object->attributes.hashSeq == CLEAR 33 && object->attributes.hmacSeq == CLEAR) 34 return TPM_RC_MODE + RC_SequenceComplete_sequenceHandle; 35 36 // Command Output 37 38 if(object->attributes.hashSeq == SET) // sequence object for hash 39 { 40 // Update last piece of data 41 HASH_OBJECT *hashObject = (HASH_OBJECT *)object; 42 43 // Get the hash algorithm before the algorithm is lost in CryptCompleteHash 44 TPM_ALG_ID hashAlg = hashObject->state.hashState[0].state.hashAlg; 45 46 CryptUpdateDigest2B(&hashObject->state.hashState[0], &in->buffer.b); 47 48 // Complete hash 49 out->result.t.size 50 = CryptGetHashDigestSize( 51 CryptGetContextAlg(&hashObject->state.hashState[0])); 52 53 CryptCompleteHash2B(&hashObject->state.hashState[0], &out->result.b); 54 55 // Check if the first block of the sequence has been received 56 if(hashObject->attributes.firstBlock == CLEAR) 57 { 58 // If not, then this is the first block so see if it is 'safe' 59 // to sign. 60 if(TicketIsSafe(&in->buffer.b)) 61 hashObject->attributes.ticketSafe = SET; 62 } 63 64 // Output ticket 65 out->validation.tag = TPM_ST_HASHCHECK; 66 out->validation.hierarchy = in->hierarchy; 67 68 if(in->hierarchy == TPM_RH_NULL) 69 { 70 // Ticket is not required 71 out->validation.digest.t.size = 0; 72 } 73 else if(object->attributes.ticketSafe == CLEAR) 74 { 75 // Ticket is not safe to generate 76 out->validation.hierarchy = TPM_RH_NULL; 77 out->validation.digest.t.size = 0; 78 } 79 else 80 { 81 // Compute ticket 82 TicketComputeHashCheck(out->validation.hierarchy, hashAlg, 83 &out->result, &out->validation); 84 } 85 } 86 else 87 { 88 HASH_OBJECT *hashObject = (HASH_OBJECT *)object; 89 90 // Update last piece of data 91 CryptUpdateDigest2B(&hashObject->state.hmacState, &in->buffer.b); 92 // Complete hash/HMAC 93 out->result.t.size = 94 CryptGetHashDigestSize( 95 CryptGetContextAlg(&hashObject->state.hmacState.hashState)); 96 CryptCompleteHMAC2B(&(hashObject->state.hmacState), &out->result.b); 97 98 // No ticket is generated for HMAC sequence 99 out->validation.tag = TPM_ST_HASHCHECK; 100 out->validation.hierarchy = TPM_RH_NULL; 101 out->validation.digest.t.size = 0; 102 } 103 104 // Internal Data Update 105 106 // mark sequence object as evict so it will be flushed on the way out 107 object->attributes.evict = SET; 108 109 return TPM_RC_SUCCESS; 110 } 111