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
TPM2_SequenceComplete(SequenceComplete_In * in,SequenceComplete_Out * out)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