/src/ibmswtpm2/src/Policy_spt.c
Line | Count | Source (jump to first uncovered line) |
1 | | /********************************************************************************/ |
2 | | /* */ |
3 | | /* */ |
4 | | /* Written by Ken Goldman */ |
5 | | /* IBM Thomas J. Watson Research Center */ |
6 | | /* $Id: Policy_spt.c 953 2017-03-06 20:31:40Z kgoldman $ */ |
7 | | /* */ |
8 | | /* Licenses and Notices */ |
9 | | /* */ |
10 | | /* 1. Copyright Licenses: */ |
11 | | /* */ |
12 | | /* - Trusted Computing Group (TCG) grants to the user of the source code in */ |
13 | | /* this specification (the "Source Code") a worldwide, irrevocable, */ |
14 | | /* nonexclusive, royalty free, copyright license to reproduce, create */ |
15 | | /* derivative works, distribute, display and perform the Source Code and */ |
16 | | /* derivative works thereof, and to grant others the rights granted herein. */ |
17 | | /* */ |
18 | | /* - The TCG grants to the user of the other parts of the specification */ |
19 | | /* (other than the Source Code) the rights to reproduce, distribute, */ |
20 | | /* display, and perform the specification solely for the purpose of */ |
21 | | /* developing products based on such documents. */ |
22 | | /* */ |
23 | | /* 2. Source Code Distribution Conditions: */ |
24 | | /* */ |
25 | | /* - Redistributions of Source Code must retain the above copyright licenses, */ |
26 | | /* this list of conditions and the following disclaimers. */ |
27 | | /* */ |
28 | | /* - Redistributions in binary form must reproduce the above copyright */ |
29 | | /* licenses, this list of conditions and the following disclaimers in the */ |
30 | | /* documentation and/or other materials provided with the distribution. */ |
31 | | /* */ |
32 | | /* 3. Disclaimers: */ |
33 | | /* */ |
34 | | /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ |
35 | | /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ |
36 | | /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ |
37 | | /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ |
38 | | /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ |
39 | | /* information on specification licensing rights available through TCG */ |
40 | | /* membership agreements. */ |
41 | | /* */ |
42 | | /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ |
43 | | /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ |
44 | | /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ |
45 | | /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ |
46 | | /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ |
47 | | /* */ |
48 | | /* - Without limitation, TCG and its members and licensors disclaim all */ |
49 | | /* liability, including liability for infringement of any proprietary */ |
50 | | /* rights, relating to use of information in this specification and to the */ |
51 | | /* implementation of this specification, and TCG disclaims all liability for */ |
52 | | /* cost of procurement of substitute goods or services, lost profits, loss */ |
53 | | /* of use, loss of data or any incidental, consequential, direct, indirect, */ |
54 | | /* or special damages, whether under contract, tort, warranty or otherwise, */ |
55 | | /* arising in any way out of use or reliance upon this specification or any */ |
56 | | /* information herein. */ |
57 | | /* */ |
58 | | /* (c) Copyright IBM Corp. and others, 2016 */ |
59 | | /* */ |
60 | | /********************************************************************************/ |
61 | | |
62 | | /* 7.4 Policy Command Support (Policy_spt.c) */ |
63 | | #include "Tpm.h" |
64 | | #include "Policy_spt_fp.h" |
65 | | #include "PolicySigned_fp.h" |
66 | | #include "PolicySecret_fp.h" |
67 | | #include "PolicyTicket_fp.h" |
68 | | /* 7.4.1 PolicyParameterChecks() */ |
69 | | /* This function validates the common parameters of TPM2_PolicySiged() and TPM2_PolicySecret(). The |
70 | | common parameters are nonceTPM, expiration, and cpHashA. */ |
71 | | TPM_RC |
72 | | PolicyParameterChecks( |
73 | | SESSION *session, |
74 | | UINT64 authTimeout, |
75 | | TPM2B_DIGEST *cpHashA, |
76 | | TPM2B_NONCE *nonce, |
77 | | TPM_RC blameNonce, |
78 | | TPM_RC blameCpHash, |
79 | | TPM_RC blameExpiration |
80 | | ) |
81 | 0 | { |
82 | | // Validate that input nonceTPM is correct if present |
83 | 0 | if(nonce != NULL && nonce->t.size != 0) |
84 | 0 | { |
85 | 0 | if(!MemoryEqual2B(&nonce->b, &session->nonceTPM.b)) |
86 | 0 | return TPM_RCS_NONCE + blameNonce; |
87 | 0 | } |
88 | | // If authTimeout is set (expiration != 0... |
89 | 0 | if(authTimeout != 0) |
90 | 0 | { |
91 | | // Validate input expiration. |
92 | | // Cannot compare time if clock stop advancing. A TPM_RC_NV_UNAVAILABLE |
93 | | // or TPM_RC_NV_RATE error may be returned here. |
94 | 0 | RETURN_IF_NV_IS_NOT_AVAILABLE; |
95 | | // if the time has already passed or the time epoch has changed then the |
96 | | // time value is no longer good. |
97 | 0 | if((authTimeout < g_time) |
98 | 0 | || (session->epoch != g_timeEpoch)) |
99 | 0 | return TPM_RCS_EXPIRED + blameExpiration; |
100 | 0 | } |
101 | | // If the cpHash is present, then check it |
102 | 0 | if(cpHashA != NULL && cpHashA->t.size != 0) |
103 | 0 | { |
104 | | // The cpHash input has to have the correct size |
105 | 0 | if(cpHashA->t.size != session->u2.policyDigest.t.size) |
106 | 0 | return TPM_RCS_SIZE + blameCpHash; |
107 | | // If the cpHash has already been set, then this input value |
108 | | // must match the current value. |
109 | 0 | if(session->u1.cpHash.b.size != 0 |
110 | 0 | && !MemoryEqual2B(&cpHashA->b, &session->u1.cpHash.b)) |
111 | 0 | return TPM_RC_CPHASH; |
112 | 0 | } |
113 | 0 | return TPM_RC_SUCCESS; |
114 | 0 | } |
115 | | /* 7.4.2 PolicyContextUpdate() */ |
116 | | /* Update policy hash Update the policyDigest in policy session by extending policyRef and |
117 | | objectName to it. This will also update the cpHash if it is present. */ |
118 | | void |
119 | | PolicyContextUpdate( |
120 | | TPM_CC commandCode, // IN: command code |
121 | | TPM2B_NAME *name, // IN: name of entity |
122 | | TPM2B_NONCE *ref, // IN: the reference data |
123 | | TPM2B_DIGEST *cpHash, // IN: the cpHash (optional) |
124 | | UINT64 policyTimeout, // IN: the timeout value for the policy |
125 | | SESSION *session // IN/OUT: policy session to be updated |
126 | | ) |
127 | 0 | { |
128 | 0 | HASH_STATE hashState; |
129 | | // Start hash |
130 | 0 | CryptHashStart(&hashState, session->authHashAlg); |
131 | | // policyDigest size should always be the digest size of session hash algorithm. |
132 | 0 | pAssert(session->u2.policyDigest.t.size |
133 | 0 | == CryptHashGetDigestSize(session->authHashAlg)); |
134 | | // add old digest |
135 | 0 | CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); |
136 | | // add commandCode |
137 | 0 | CryptDigestUpdateInt(&hashState, sizeof(commandCode), commandCode); |
138 | | // add name if applicable |
139 | 0 | if(name != NULL) |
140 | 0 | CryptDigestUpdate2B(&hashState, &name->b); |
141 | | // Complete the digest and get the results |
142 | 0 | CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); |
143 | | // If the policy reference is not null, do a second update to the digest. |
144 | 0 | if(ref != NULL) |
145 | 0 | { |
146 | | // Start second hash computation |
147 | 0 | CryptHashStart(&hashState, session->authHashAlg); |
148 | | // add policyDigest |
149 | 0 | CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); |
150 | | // add policyRef |
151 | 0 | CryptDigestUpdate2B(&hashState, &ref->b); |
152 | | // Complete second digest |
153 | 0 | CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); |
154 | 0 | } |
155 | | // Deal with the cpHash. If the cpHash value is present |
156 | | // then it would have already been checked to make sure that |
157 | | // it is compatible with the current value so all we need |
158 | | // to do here is copy it and set the isCpHashDefined attribute |
159 | 0 | if(cpHash != NULL && cpHash->t.size != 0) |
160 | 0 | { |
161 | 0 | session->u1.cpHash = *cpHash; |
162 | 0 | session->attributes.isCpHashDefined = SET; |
163 | 0 | } |
164 | | // update the timeout if it is specified |
165 | 0 | if(policyTimeout != 0) |
166 | 0 | { |
167 | | // If the timeout has not been set, then set it to the new value |
168 | | // than the current timeout then set it to the new value |
169 | 0 | if(session->timeout == 0 || session->timeout > policyTimeout) |
170 | 0 | session->timeout = policyTimeout; |
171 | 0 | } |
172 | 0 | return; |
173 | 0 | } |
174 | | /* 7.4.2.1 ComputeAuthTimeout() */ |
175 | | /* This function is used to determine what the authorization timeout value for the session should |
176 | | be. */ |
177 | | UINT64 |
178 | | ComputeAuthTimeout( |
179 | | SESSION *session, // IN: the session containing the time |
180 | | // values |
181 | | INT32 expiration, // IN: either the number of seconds from |
182 | | // the start of the session or the |
183 | | // time in g_timer; |
184 | | TPM2B_NONCE *nonce // IN: indicator of the time base |
185 | | ) |
186 | 0 | { |
187 | 0 | UINT64 policyTime; |
188 | | // If no expiration, policy time is 0 |
189 | 0 | if(expiration == 0) |
190 | 0 | policyTime = 0; |
191 | 0 | else |
192 | 0 | { |
193 | 0 | if(expiration < 0) |
194 | 0 | expiration = -expiration; |
195 | 0 | if(nonce->t.size == 0) |
196 | | // The input time is absolute Time (not Clock), but it is expressed |
197 | | // in seconds. To make sure that we don't time out too early, take the |
198 | | // current value of milliseconds in g_time and add that to the input |
199 | | // seconds value. |
200 | 0 | policyTime = (((UINT64)expiration) * 1000) + g_time % 1000; |
201 | 0 | else |
202 | | // The policy timeout is the absolute value of the expiration in seconds |
203 | | // added to the start time of the policy. |
204 | 0 | policyTime = session->startTime + (((UINT64)expiration) * 1000); |
205 | 0 | } |
206 | 0 | return policyTime; |
207 | 0 | } |
208 | | /* 7.4.2.2 PolicyDigestClear() */ |
209 | | /* Function to reset the policyDigest of a session */ |
210 | | void |
211 | | PolicyDigestClear( |
212 | | SESSION *session |
213 | | ) |
214 | 0 | { |
215 | 0 | session->u2.policyDigest.t.size = CryptHashGetDigestSize(session->authHashAlg); |
216 | 0 | MemorySet(session->u2.policyDigest.t.buffer, 0, |
217 | 0 | session->u2.policyDigest.t.size); |
218 | 0 | } |
219 | | BOOL |
220 | | PolicySptCheckCondition( |
221 | | TPM_EO operation, |
222 | | BYTE *opA, |
223 | | BYTE *opB, |
224 | | UINT16 size |
225 | | ) |
226 | 0 | { |
227 | | // Arithmetic Comparison |
228 | 0 | switch(operation) |
229 | 0 | { |
230 | 0 | case TPM_EO_EQ: |
231 | | // compare A = B |
232 | 0 | return (UnsignedCompareB(size, opA, size, opB) == 0); |
233 | 0 | break; |
234 | 0 | case TPM_EO_NEQ: |
235 | | // compare A != B |
236 | 0 | return (UnsignedCompareB(size, opA, size, opB) != 0); |
237 | 0 | break; |
238 | 0 | case TPM_EO_SIGNED_GT: |
239 | | // compare A > B signed |
240 | 0 | return (SignedCompareB(size, opA, size, opB) > 0); |
241 | 0 | break; |
242 | 0 | case TPM_EO_UNSIGNED_GT: |
243 | | // compare A > B unsigned |
244 | 0 | return (UnsignedCompareB(size, opA, size, opB) > 0); |
245 | 0 | break; |
246 | 0 | case TPM_EO_SIGNED_LT: |
247 | | // compare A < B signed |
248 | 0 | return (SignedCompareB(size, opA, size, opB) < 0); |
249 | 0 | break; |
250 | 0 | case TPM_EO_UNSIGNED_LT: |
251 | | // compare A < B unsigned |
252 | 0 | return (UnsignedCompareB(size, opA, size, opB) < 0); |
253 | 0 | break; |
254 | 0 | case TPM_EO_SIGNED_GE: |
255 | | // compare A >= B signed |
256 | 0 | return (SignedCompareB(size, opA, size, opB) >= 0); |
257 | 0 | break; |
258 | 0 | case TPM_EO_UNSIGNED_GE: |
259 | | // compare A >= B unsigned |
260 | 0 | return (UnsignedCompareB(size, opA, size, opB) >= 0); |
261 | 0 | break; |
262 | 0 | case TPM_EO_SIGNED_LE: |
263 | | // compare A <= B signed |
264 | 0 | return (SignedCompareB(size, opA, size, opB) <= 0); |
265 | 0 | break; |
266 | 0 | case TPM_EO_UNSIGNED_LE: |
267 | | // compare A <= B unsigned |
268 | 0 | return (UnsignedCompareB(size, opA, size, opB) <= 0); |
269 | 0 | break; |
270 | 0 | case TPM_EO_BITSET: |
271 | | // All bits SET in B are SET in A. ((A&B)=B) |
272 | 0 | { |
273 | 0 | UINT32 i; |
274 | 0 | for(i = 0; i < size; i++) |
275 | 0 | if((opA[i] & opB[i]) != opB[i]) |
276 | 0 | return FALSE; |
277 | 0 | } |
278 | 0 | break; |
279 | 0 | case TPM_EO_BITCLEAR: |
280 | | // All bits SET in B are CLEAR in A. ((A&B)=0) |
281 | 0 | { |
282 | 0 | UINT32 i; |
283 | 0 | for(i = 0; i < size; i++) |
284 | 0 | if((opA[i] & opB[i]) != 0) |
285 | 0 | return FALSE; |
286 | 0 | } |
287 | 0 | break; |
288 | 0 | default: |
289 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
290 | 0 | break; |
291 | 0 | } |
292 | 0 | return TRUE; |
293 | 0 | } |