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//
18TPM_RC
19TPM2_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