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 "PolicyCounterTimer_fp.h"
10 #include "Policy_spt_fp.h"
11 //
12 //
13 //     Error Returns                  Meaning
14 //
15 //     TPM_RC_POLICY                  the comparison of the selected portion of the TPMS_TIME_INFO with
16 //                                    operandB failed
17 //     TPM_RC_RANGE                   offset + size exceed size of TPMS_TIME_INFO structure
18 //
19 TPM_RC
TPM2_PolicyCounterTimer(PolicyCounterTimer_In * in)20 TPM2_PolicyCounterTimer(
21    PolicyCounterTimer_In      *in              // IN: input parameter list
22    )
23 {
24    TPM_RC                result;
25    SESSION              *session;
26    TIME_INFO             infoData;      // data buffer of TPMS_TIME_INFO
27    TPM_CC                commandCode = TPM_CC_PolicyCounterTimer;
28    HASH_STATE            hashState;
29    TPM2B_DIGEST          argHash;
30 
31 // Input Validation
32 
33    // If the command is going to use any part of the counter or timer, need
34    // to verify that time is advancing.
35    // The time and clock vales are the first two 64-bit values in the clock
36    if(in->offset < sizeof(UINT64) + sizeof(UINT64))
37    {
38        // Using Clock or Time so see if clock is running. Clock doesn't run while
39        // NV is unavailable.
40        // TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned here.
41        result = NvIsAvailable();
42        if(result != TPM_RC_SUCCESS)
43            return result;
44    }
45    // Get pointer to the session structure
46    session = SessionGet(in->policySession);
47 
48    //If this is a trial policy, skip all validations and the operation
49    if(session->attributes.isTrialPolicy == CLEAR)
50    {
51        // Get time data info. The size of time info data equals the input
52        // operand B size. A TPM_RC_RANGE error may be returned at this point
53        result = TimeGetRange(in->offset, in->operandB.t.size, &infoData);
54        if(result != TPM_RC_SUCCESS) return result;
55 
56          // Arithmetic Comparison
57          switch(in->operation)
58          {
59              case TPM_EO_EQ:
60                  // compare A = B
61                  if(CryptCompare(in->operandB.t.size, infoData,
62                                  in->operandB.t.size, in->operandB.t.buffer) != 0)
63                      return TPM_RC_POLICY;
64                  break;
65              case TPM_EO_NEQ:
66                  // compare A != B
67                  if(CryptCompare(in->operandB.t.size, infoData,
68                                 in->operandB.t.size, in->operandB.t.buffer)   == 0)
69                     return TPM_RC_POLICY;
70                 break;
71             case TPM_EO_SIGNED_GT:
72                 // compare A > B signed
73                 if(CryptCompareSigned(in->operandB.t.size, infoData,
74                                 in->operandB.t.size, in->operandB.t.buffer)   <= 0)
75                     return TPM_RC_POLICY;
76                 break;
77             case TPM_EO_UNSIGNED_GT:
78                 // compare A > B unsigned
79                 if(CryptCompare(in->operandB.t.size, infoData,
80                                 in->operandB.t.size, in->operandB.t.buffer)   <= 0)
81                     return TPM_RC_POLICY;
82                 break;
83             case TPM_EO_SIGNED_LT:
84                 // compare A < B signed
85                 if(CryptCompareSigned(in->operandB.t.size, infoData,
86                                 in->operandB.t.size, in->operandB.t.buffer)   >= 0)
87                     return TPM_RC_POLICY;
88                 break;
89             case TPM_EO_UNSIGNED_LT:
90                 // compare A < B unsigned
91                 if(CryptCompare(in->operandB.t.size, infoData,
92                                 in->operandB.t.size, in->operandB.t.buffer)   >= 0)
93                     return TPM_RC_POLICY;
94                 break;
95             case TPM_EO_SIGNED_GE:
96                 // compare A >= B signed
97                 if(CryptCompareSigned(in->operandB.t.size, infoData,
98                                 in->operandB.t.size, in->operandB.t.buffer)   < 0)
99                     return TPM_RC_POLICY;
100                 break;
101             case TPM_EO_UNSIGNED_GE:
102                 // compare A >= B unsigned
103                 if(CryptCompare(in->operandB.t.size, infoData,
104                                 in->operandB.t.size, in->operandB.t.buffer)   < 0)
105                     return TPM_RC_POLICY;
106                 break;
107             case TPM_EO_SIGNED_LE:
108                 // compare A <= B signed
109                 if(CryptCompareSigned(in->operandB.t.size, infoData,
110                                 in->operandB.t.size, in->operandB.t.buffer)   > 0)
111                     return TPM_RC_POLICY;
112                 break;
113             case TPM_EO_UNSIGNED_LE:
114                 // compare A <= B unsigned
115                 if(CryptCompare(in->operandB.t.size, infoData,
116                                 in->operandB.t.size, in->operandB.t.buffer)   > 0)
117                     return TPM_RC_POLICY;
118                 break;
119             case TPM_EO_BITSET:
120                 // All bits SET in B are SET in A. ((A&B)=B)
121             {
122                 UINT32 i;
123                 for (i = 0; i < in->operandB.t.size; i++)
124                     if(   (infoData[i] & in->operandB.t.buffer[i])
125                        != in->operandB.t.buffer[i])
126                         return TPM_RC_POLICY;
127             }
128             break;
129             case TPM_EO_BITCLEAR:
130                 // All bits SET in B are CLEAR in A. ((A&B)=0)
131             {
132                 UINT32 i;
133                 for (i = 0; i < in->operandB.t.size; i++)
134                   if((infoData[i] & in->operandB.t.buffer[i]) != 0)
135                       return TPM_RC_POLICY;
136           }
137           break;
138           default:
139               pAssert(FALSE);
140               break;
141       }
142   }
143 
144 // Internal Data Update
145 
146   // Start argument list hash
147   argHash.t.size = CryptStartHash(session->authHashAlg, &hashState);
148   // add operandB
149   CryptUpdateDigest2B(&hashState, &in->operandB.b);
150   // add offset
151   CryptUpdateDigestInt(&hashState, sizeof(UINT16), &in->offset);
152   // add operation
153   CryptUpdateDigestInt(&hashState, sizeof(TPM_EO), &in->operation);
154   // complete argument hash
155   CryptCompleteHash2B(&hashState, &argHash.b);
156 
157   // update policyDigest
158   // start hash
159   CryptStartHash(session->authHashAlg, &hashState);
160 
161   // add old digest
162   CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
163 
164   // add commandCode
165   CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
166 
167   // add argument digest
168   CryptUpdateDigest2B(&hashState, &argHash.b);
169 
170   // complete the digest
171   CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
172 
173    return TPM_RC_SUCCESS;
174 }
175