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 "PolicyNV_fp.h"
10#include "Policy_spt_fp.h"
11#include "NV_spt_fp.h"         // Include NV support routine for read access check
12//
13//
14//     Error Returns                     Meaning
15//
16//     TPM_RC_AUTH_TYPE                  NV index authorization type is not correct
17//     TPM_RC_NV_LOCKED                  NV index read locked
18//     TPM_RC_NV_UNINITIALIZED           the NV index has not been initialized
19//     TPM_RC_POLICY                     the comparison to the NV contents failed
20//     TPM_RC_SIZE                       the size of nvIndex data starting at offset is less than the size of
21//                                       operandB
22//
23TPM_RC
24TPM2_PolicyNV(
25   PolicyNV_In       *in                  // IN: input parameter list
26   )
27{
28   TPM_RC                   result;
29   SESSION                 *session;
30   NV_INDEX                 nvIndex;
31   BYTE                     nvBuffer[sizeof(in->operandB.t.buffer)];
32   TPM2B_NAME               nvName;
33   TPM_CC                   commandCode = TPM_CC_PolicyNV;
34   HASH_STATE               hashState;
35   TPM2B_DIGEST             argHash;
36
37// Input Validation
38
39   // Get NV index information
40   NvGetIndexInfo(in->nvIndex, &nvIndex);
41
42   // Get pointer to the session structure
43   session = SessionGet(in->policySession);
44
45   //If this is a trial policy, skip all validations and the operation
46   if(session->attributes.isTrialPolicy == CLEAR)
47   {
48       // NV Read access check. NV index should be allowed for read. A
49       // TPM_RC_AUTH_TYPE or TPM_RC_NV_LOCKED error may be return at this
50       // point
51       result = NvReadAccessChecks(in->authHandle, in->nvIndex);
52       if(result != TPM_RC_SUCCESS) return result;
53
54       // Valid NV data size should not be smaller than input operandB size
55       if((nvIndex.publicArea.dataSize - in->offset) < in->operandB.t.size)
56           return TPM_RC_SIZE + RC_PolicyNV_operandB;
57
58       // Arithmetic Comparison
59
60       // Get NV data. The size of NV data equals the input operand B size
61       NvGetIndexData(in->nvIndex, &nvIndex, in->offset,
62                      in->operandB.t.size, nvBuffer);
63
64       switch(in->operation)
65       {
66          case TPM_EO_EQ:
67              // compare A = B
68              if(CryptCompare(in->operandB.t.size, nvBuffer,
69                              in->operandB.t.size, in->operandB.t.buffer)   != 0)
70                  return TPM_RC_POLICY;
71              break;
72          case TPM_EO_NEQ:
73              // compare A != B
74              if(CryptCompare(in->operandB.t.size, nvBuffer,
75                              in->operandB.t.size, in->operandB.t.buffer)   == 0)
76                  return TPM_RC_POLICY;
77              break;
78          case TPM_EO_SIGNED_GT:
79              // compare A > B signed
80              if(CryptCompareSigned(in->operandB.t.size, nvBuffer,
81                              in->operandB.t.size, in->operandB.t.buffer)   <= 0)
82                  return TPM_RC_POLICY;
83              break;
84          case TPM_EO_UNSIGNED_GT:
85              // compare A > B unsigned
86              if(CryptCompare(in->operandB.t.size, nvBuffer,
87                              in->operandB.t.size, in->operandB.t.buffer)   <= 0)
88                  return TPM_RC_POLICY;
89              break;
90          case TPM_EO_SIGNED_LT:
91              // compare A < B signed
92              if(CryptCompareSigned(in->operandB.t.size, nvBuffer,
93                              in->operandB.t.size, in->operandB.t.buffer)   >= 0)
94                  return TPM_RC_POLICY;
95              break;
96          case TPM_EO_UNSIGNED_LT:
97              // compare A < B unsigned
98              if(CryptCompare(in->operandB.t.size, nvBuffer,
99                              in->operandB.t.size, in->operandB.t.buffer)   >= 0)
100                  return TPM_RC_POLICY;
101              break;
102          case TPM_EO_SIGNED_GE:
103              // compare A >= B signed
104              if(CryptCompareSigned(in->operandB.t.size, nvBuffer,
105                              in->operandB.t.size, in->operandB.t.buffer)   < 0)
106                  return TPM_RC_POLICY;
107              break;
108          case TPM_EO_UNSIGNED_GE:
109              // compare A >= B unsigned
110              if(CryptCompare(in->operandB.t.size, nvBuffer,
111                              in->operandB.t.size, in->operandB.t.buffer)   < 0)
112                  return TPM_RC_POLICY;
113              break;
114          case TPM_EO_SIGNED_LE:
115              // compare A <= B signed
116              if(CryptCompareSigned(in->operandB.t.size, nvBuffer,
117                              in->operandB.t.size, in->operandB.t.buffer)   > 0)
118                  return TPM_RC_POLICY;
119              break;
120          case TPM_EO_UNSIGNED_LE:
121              // compare A <= B unsigned
122              if(CryptCompare(in->operandB.t.size, nvBuffer,
123                              in->operandB.t.size, in->operandB.t.buffer)   > 0)
124                  return TPM_RC_POLICY;
125              break;
126          case TPM_EO_BITSET:
127              // All bits SET in B are SET in A. ((A&B)=B)
128          {
129              UINT32 i;
130              for (i = 0; i < in->operandB.t.size; i++)
131                  if((nvBuffer[i] & in->operandB.t.buffer[i])
132                             != in->operandB.t.buffer[i])
133                         return TPM_RC_POLICY;
134            }
135            break;
136            case TPM_EO_BITCLEAR:
137                // All bits SET in B are CLEAR in A. ((A&B)=0)
138            {
139                UINT32 i;
140                for (i = 0; i < in->operandB.t.size; i++)
141                    if((nvBuffer[i] & in->operandB.t.buffer[i]) != 0)
142                        return TPM_RC_POLICY;
143            }
144            break;
145            default:
146                pAssert(FALSE);
147                break;
148       }
149   }
150
151// Internal Data Update
152
153   // Start argument hash
154   argHash.t.size = CryptStartHash(session->authHashAlg, &hashState);
155
156   // add operandB
157   CryptUpdateDigest2B(&hashState, &in->operandB.b);
158
159   // add offset
160   CryptUpdateDigestInt(&hashState, sizeof(UINT16), &in->offset);
161
162   // add operation
163   CryptUpdateDigestInt(&hashState, sizeof(TPM_EO), &in->operation);
164
165   // complete argument digest
166   CryptCompleteHash2B(&hashState, &argHash.b);
167
168   // Update policyDigest
169   // Start digest
170   CryptStartHash(session->authHashAlg, &hashState);
171
172   // add old digest
173   CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
174
175   // add commandCode
176   CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
177
178   // add argument digest
179   CryptUpdateDigest2B(&hashState, &argHash.b);
180
181   // Adding nvName
182   nvName.t.size = EntityGetName(in->nvIndex, &nvName.t.name);
183   CryptUpdateDigest2B(&hashState, &nvName.b);
184
185   // complete the digest
186   CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
187
188   return TPM_RC_SUCCESS;
189}
190