aboutsummaryrefslogtreecommitdiff
path: root/SequenceComplete.c
blob: 222502a4c5109a0ee3d3a86490456df4763b589e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// 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;
}