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