blob: 455b57d75deb369e6d86e570dbb5891fd81dee9a [file] [log] [blame]
Vadim Bendebury56797522015-05-20 10:32:25 -07001// 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;
Vadim Bendebury54a3d362015-06-01 15:26:03 -070031 BYTE nvBuffer[sizeof(in->operandB.t.buffer)];
Vadim Bendebury56797522015-05-20 10:32:25 -070032 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
ChromeOS Developere85c65b2015-07-10 10:12:43 -0700182 nvName.t.size = EntityGetName(in->nvIndex, &nvName.t.name);
Vadim Bendebury56797522015-05-20 10:32:25 -0700183 CryptUpdateDigest2B(&hashState, &nvName.b);
184
185 // complete the digest
186 CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
187
188 return TPM_RC_SUCCESS;
189}