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 //
23 TPM_RC
TPM2_PolicyNV(PolicyNV_In * in)24 TPM2_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