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