Line | Count | Source (jump to first uncovered line) |
1 | | /********************************************************************************/ |
2 | | /* */ |
3 | | /* PCR access and manipulation */ |
4 | | /* Written by Ken Goldman */ |
5 | | /* IBM Thomas J. Watson Research Center */ |
6 | | /* $Id: PCR.c 1311 2018-08-23 21:39:29Z 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 - 2018 */ |
59 | | /* */ |
60 | | /********************************************************************************/ |
61 | | |
62 | | /* 8.7 PCR.c */ |
63 | | /* 8.7.1 Introduction */ |
64 | | /* This function contains the functions needed for PCR access and manipulation. */ |
65 | | /* This implementation uses a static allocation for the PCR. The amount of memory is allocated based |
66 | | on the number of PCR in the implementation and the number of implemented hash algorithms. This is |
67 | | not the expected implementation. PCR SPACE DEFINITIONS. */ |
68 | | /* In the definitions below, the g_hashPcrMap is a bit array that indicates which of the PCR are |
69 | | implemented. The g_hashPcr array is an array of digests. In this implementation, the space is |
70 | | allocated whether the PCR is implemented or not. */ |
71 | | /* 8.7.2 Includes, Defines, and Data Definitions */ |
72 | | #define PCR_C |
73 | | #include "Tpm.h" |
74 | | /* The initial value of PCR attributes. The value of these fields should be consistent with PC |
75 | | Client specification In this implementation, we assume the total number of implemented PCR is |
76 | | 24. */ |
77 | | static const PCR_Attributes s_initAttributes[] = |
78 | | { |
79 | | // PCR 0 - 15, static RTM |
80 | | {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, |
81 | | {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, |
82 | | {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, |
83 | | {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, |
84 | | {0, 0x0F, 0x1F}, // PCR 16, Debug |
85 | | {0, 0x10, 0x1C}, // PCR 17, Locality 4 |
86 | | {0, 0x10, 0x1C}, // PCR 18, Locality 3 |
87 | | {0, 0x10, 0x0C}, // PCR 19, Locality 2 |
88 | | {0, 0x14, 0x0E}, // PCR 20, Locality 1 |
89 | | {0, 0x14, 0x04}, // PCR 21, Dynamic OS |
90 | | {0, 0x14, 0x04}, // PCR 22, Dynamic OS |
91 | | {0, 0x0F, 0x1F}, // PCR 23, Application specific |
92 | | {0, 0x0F, 0x1F} // PCR 24, testing policy |
93 | | }; |
94 | | /* 8.7.3 Functions */ |
95 | | /* 8.7.3.1 PCRBelongsAuthGroup() */ |
96 | | /* This function indicates if a PCR belongs to a group that requires an authValue in order to modify |
97 | | the PCR. If it does, groupIndex is set to value of the group index. This feature of PCR is |
98 | | decided by the platform specification. */ |
99 | | /* Return Values Meaning */ |
100 | | /* TRUE: PCR belongs an authorization group */ |
101 | | /* FALSE: PCR does not belong an authorization group */ |
102 | | BOOL |
103 | | PCRBelongsAuthGroup( |
104 | | TPMI_DH_PCR handle, // IN: handle of PCR |
105 | | UINT32 *groupIndex // OUT: group index if PCR belongs a |
106 | | // group that allows authValue. If PCR |
107 | | // does not belong to an authorization |
108 | | // group, the value in this parameter is |
109 | | // invalid |
110 | | ) |
111 | 0 | { |
112 | 0 | #if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0 |
113 | | // Platform specification determines to which authorization group a PCR belongs |
114 | | // (if any). In this implementation, we assume there is only |
115 | | // one authorization group which contains PCR[20-22]. If the platform |
116 | | // specification requires differently, the implementation should be changed |
117 | | // accordingly |
118 | 0 | if(handle >= 20 && handle <= 22) |
119 | 0 | { |
120 | 0 | *groupIndex = 0; |
121 | 0 | return TRUE; |
122 | 0 | } |
123 | 0 | #endif |
124 | 0 | return FALSE; |
125 | 0 | } |
126 | | /* 8.7.3.2 PCRBelongsPolicyGroup() */ |
127 | | /* This function indicates if a PCR belongs to a group that requires a policy authorization in order |
128 | | to modify the PCR. If it does, groupIndex is set to value of the group index. This feature of |
129 | | PCR is decided by the platform specification. */ |
130 | | /* Return Values Meaning */ |
131 | | /* TRUE: PCR belongs a policy group */ |
132 | | /* FALSE: PCR does not belong a policy group */ |
133 | | BOOL |
134 | | PCRBelongsPolicyGroup( |
135 | | TPMI_DH_PCR handle, // IN: handle of PCR |
136 | | UINT32 *groupIndex // OUT: group index if PCR belongs a group that |
137 | | // allows policy. If PCR does not belong to |
138 | | // a policy group, the value in this |
139 | | // parameter is invalid |
140 | | ) |
141 | 0 | { |
142 | 0 | #if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 |
143 | | // Platform specification decides if a PCR belongs to a policy group and |
144 | | // belongs to which group. In this implementation, we assume there is only |
145 | | // one policy group which contains PCR20-22. If the platform specification |
146 | | // requires differently, the implementation should be changed accordingly |
147 | 0 | if(handle >= 20 && handle <= 22) |
148 | 0 | { |
149 | 0 | *groupIndex = 0; |
150 | 0 | return TRUE; |
151 | 0 | } |
152 | 0 | #endif |
153 | 0 | return FALSE; |
154 | 0 | } |
155 | | /* 8.7.3.3 PCRBelongsTCBGroup() */ |
156 | | /* This function indicates if a PCR belongs to the TCB group. */ |
157 | | /* Return Values Meaning */ |
158 | | /* TRUE: PCR belongs to TCB group */ |
159 | | /* FALSE: PCR does not belong to TCB group */ |
160 | | static BOOL |
161 | | PCRBelongsTCBGroup( |
162 | | TPMI_DH_PCR handle // IN: handle of PCR |
163 | | ) |
164 | 0 | { |
165 | 0 | #if ENABLE_PCR_NO_INCREMENT == YES |
166 | | // Platform specification decides if a PCR belongs to a TCB group. In this |
167 | | // implementation, we assume PCR[20-22] belong to TCB group. If the platform |
168 | | // specification requires differently, the implementation should be |
169 | | // changed accordingly |
170 | 0 | if(handle >= 20 && handle <= 22) |
171 | 0 | return TRUE; |
172 | 0 | #endif |
173 | 0 | return FALSE; |
174 | 0 | } |
175 | | /* 8.7.3.4 PCRPolicyIsAvailable() */ |
176 | | /* This function indicates if a policy is available for a PCR. */ |
177 | | /* Return Values Meaning */ |
178 | | /* TRUE the PCR should be authorized by policy */ |
179 | | /* FALSE the PCR does not allow policy */ |
180 | | BOOL |
181 | | PCRPolicyIsAvailable( |
182 | | TPMI_DH_PCR handle // IN: PCR handle |
183 | | ) |
184 | 0 | { |
185 | 0 | UINT32 groupIndex; |
186 | 0 | return PCRBelongsPolicyGroup(handle, &groupIndex); |
187 | 0 | } |
188 | | /* 8.7.3.5 PCRGetAuthValue() */ |
189 | | /* This function is used to access the authValue of a PCR. If PCR does not belong to an authValue |
190 | | group, an EmptyAuth() will be returned. */ |
191 | | TPM2B_AUTH * |
192 | | PCRGetAuthValue( |
193 | | TPMI_DH_PCR handle // IN: PCR handle |
194 | | ) |
195 | 0 | { |
196 | 0 | UINT32 groupIndex; |
197 | 0 | if(PCRBelongsAuthGroup(handle, &groupIndex)) |
198 | 0 | { |
199 | 0 | return &gc.pcrAuthValues.auth[groupIndex]; |
200 | 0 | } |
201 | 0 | else |
202 | 0 | { |
203 | 0 | return NULL; |
204 | 0 | } |
205 | 0 | } |
206 | | /* 8.7.3.6 PCRGetAuthPolicy() */ |
207 | | /* This function is used to access the authorization policy of a PCR. It sets policy to the |
208 | | authorization policy and returns the hash algorithm for policy If the PCR does not allow a |
209 | | policy, TPM_ALG_NULL is returned. */ |
210 | | TPMI_ALG_HASH |
211 | | PCRGetAuthPolicy( |
212 | | TPMI_DH_PCR handle, // IN: PCR handle |
213 | | TPM2B_DIGEST *policy // OUT: policy of PCR |
214 | | ) |
215 | 0 | { |
216 | 0 | UINT32 groupIndex; |
217 | 0 | if(PCRBelongsPolicyGroup(handle, &groupIndex)) |
218 | 0 | { |
219 | 0 | *policy = gp.pcrPolicies.policy[groupIndex]; |
220 | 0 | return gp.pcrPolicies.hashAlg[groupIndex]; |
221 | 0 | } |
222 | 0 | else |
223 | 0 | { |
224 | 0 | policy->t.size = 0; |
225 | 0 | return TPM_ALG_NULL; |
226 | 0 | } |
227 | 0 | } |
228 | | /* 8.7.3.7 PCRSimStart() */ |
229 | | /* This function is used to initialize the policies when a TPM is manufactured. This function would |
230 | | only be called in a manufacturing environment or in a TPM simulator. */ |
231 | | void |
232 | | PCRSimStart( |
233 | | void |
234 | | ) |
235 | 644 | { |
236 | 644 | UINT32 i; |
237 | 644 | #if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 |
238 | 1.28k | for(i = 0; i < NUM_POLICY_PCR_GROUP; i++) |
239 | 644 | { |
240 | 644 | gp.pcrPolicies.hashAlg[i] = TPM_ALG_NULL; |
241 | 644 | gp.pcrPolicies.policy[i].t.size = 0; |
242 | 644 | } |
243 | 644 | #endif |
244 | 644 | #if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0 |
245 | 1.28k | for(i = 0; i < NUM_AUTHVALUE_PCR_GROUP; i++) |
246 | 644 | { |
247 | 644 | gc.pcrAuthValues.auth[i].t.size = 0; |
248 | 644 | } |
249 | 644 | #endif |
250 | | // We need to give an initial configuration on allocated PCR before |
251 | | // receiving any TPM2_PCR_Allocate command to change this configuration |
252 | | // When the simulation environment starts, we allocate all the PCRs |
253 | 3.22k | for(gp.pcrAllocated.count = 0; gp.pcrAllocated.count < HASH_COUNT; |
254 | 2.57k | gp.pcrAllocated.count++) |
255 | 2.57k | { |
256 | 2.57k | gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].hash |
257 | 2.57k | = CryptHashGetAlgByIndex(gp.pcrAllocated.count); |
258 | 2.57k | gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].sizeofSelect |
259 | 2.57k | = PCR_SELECT_MAX; |
260 | 10.3k | for(i = 0; i < PCR_SELECT_MAX; i++) |
261 | 7.72k | gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].pcrSelect[i] |
262 | 7.72k | = 0xFF; |
263 | 2.57k | } |
264 | | // Store the initial configuration to NV |
265 | 644 | NV_SYNC_PERSISTENT(pcrPolicies); |
266 | 644 | NV_SYNC_PERSISTENT(pcrAllocated); |
267 | 644 | return; |
268 | 644 | } |
269 | | /* 8.7.3.8 GetSavedPcrPointer() */ |
270 | | /* This function returns the address of an array of state saved PCR based on the hash algorithm. */ |
271 | | /* Return Values Meaning */ |
272 | | /* NULL no such algorithm */ |
273 | | /* not NULL pointer to the 0th byte of the 0th PCR */ |
274 | | static BYTE * |
275 | | GetSavedPcrPointer( |
276 | | TPM_ALG_ID alg, // IN: algorithm for bank |
277 | | UINT32 pcrIndex // IN: PCR index in PCR_SAVE |
278 | | ) |
279 | 0 | { |
280 | 0 | switch(alg) |
281 | 0 | { |
282 | 0 | #if ALG_SHA1 |
283 | 0 | case TPM_ALG_SHA1: |
284 | 0 | return gc.pcrSave.sha1[pcrIndex]; |
285 | 0 | break; |
286 | 0 | #endif |
287 | 0 | #if ALG_SHA256 |
288 | 0 | case TPM_ALG_SHA256: |
289 | 0 | return gc.pcrSave.sha256[pcrIndex]; |
290 | 0 | break; |
291 | 0 | #endif |
292 | 0 | #if ALG_SHA384 |
293 | 0 | case TPM_ALG_SHA384: |
294 | 0 | return gc.pcrSave.sha384[pcrIndex]; |
295 | 0 | break; |
296 | 0 | #endif |
297 | 0 | #if ALG_SHA512 |
298 | 0 | case TPM_ALG_SHA512: |
299 | 0 | return gc.pcrSave.sha512[pcrIndex]; |
300 | 0 | break; |
301 | 0 | #endif |
302 | | #if ALG_SM3_256 |
303 | | case TPM_ALG_SM3_256: |
304 | | return gc.pcrSave.sm3_256[pcrIndex]; |
305 | | break; |
306 | | #endif |
307 | 0 | default: |
308 | 0 | break; |
309 | 0 | } |
310 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
311 | 0 | } |
312 | | /* 8.7.3.9 PcrIsAllocated() */ |
313 | | /* This function indicates if a PCR number for the particular hash algorithm is allocated. */ |
314 | | /* Return Values Meaning */ |
315 | | /* FALSE PCR is not allocated */ |
316 | | /* TRUE PCR is allocated */ |
317 | | BOOL |
318 | | PcrIsAllocated( |
319 | | UINT32 pcr, // IN: The number of the PCR |
320 | | TPMI_ALG_HASH hashAlg // IN: The PCR algorithm |
321 | | ) |
322 | 22.1k | { |
323 | 22.1k | UINT32 i; |
324 | 22.1k | BOOL allocated = FALSE; |
325 | 22.1k | if(pcr < IMPLEMENTATION_PCR) |
326 | 22.1k | { |
327 | 55.4k | for(i = 0; i < gp.pcrAllocated.count; i++) |
328 | 55.4k | { |
329 | 55.4k | if(gp.pcrAllocated.pcrSelections[i].hash == hashAlg) |
330 | 22.1k | { |
331 | 22.1k | if(((gp.pcrAllocated.pcrSelections[i].pcrSelect[pcr / 8]) |
332 | 22.1k | & (1 << (pcr % 8))) != 0) |
333 | 22.1k | allocated = TRUE; |
334 | 0 | else |
335 | 0 | allocated = FALSE; |
336 | 22.1k | break; |
337 | 22.1k | } |
338 | 55.4k | } |
339 | 22.1k | } |
340 | 22.1k | return allocated; |
341 | 22.1k | } |
342 | | /* 8.7.3.10 GetPcrPointer() */ |
343 | | /* This function returns the address of an array of PCR based on the hash algorithm. */ |
344 | | /* Return Values Meaning */ |
345 | | /* NULL no such algorithm */ |
346 | | /* not NULL pointer to the 0th byte of the 0th PCR */ |
347 | | static BYTE * |
348 | | GetPcrPointer( |
349 | | TPM_ALG_ID alg, // IN: algorithm for bank |
350 | | UINT32 pcrNumber // IN: PCR number |
351 | | ) |
352 | 14.2k | { |
353 | 14.2k | static BYTE *pcr = NULL; |
354 | 14.2k | if(!PcrIsAllocated(pcrNumber, alg)) |
355 | 0 | return NULL; |
356 | 14.2k | switch(alg) |
357 | 14.2k | { |
358 | 0 | #if ALG_SHA1 |
359 | 3.56k | case TPM_ALG_SHA1: |
360 | 3.56k | pcr = s_pcrs[pcrNumber].sha1Pcr; |
361 | 3.56k | break; |
362 | 0 | #endif |
363 | 0 | #if ALG_SHA256 |
364 | 3.56k | case TPM_ALG_SHA256: |
365 | 3.56k | pcr = s_pcrs[pcrNumber].sha256Pcr; |
366 | 3.56k | break; |
367 | 0 | #endif |
368 | 0 | #if ALG_SHA384 |
369 | 3.56k | case TPM_ALG_SHA384: |
370 | 3.56k | pcr = s_pcrs[pcrNumber].sha384Pcr; |
371 | 3.56k | break; |
372 | 0 | #endif |
373 | 0 | #if ALG_SHA512 |
374 | 3.56k | case TPM_ALG_SHA512: |
375 | 3.56k | pcr = s_pcrs[pcrNumber].sha512Pcr; |
376 | 3.56k | break; |
377 | 0 | #endif |
378 | | #if ALG_SM3_256 |
379 | | case TPM_ALG_SM3_256: |
380 | | pcr = s_pcrs[pcrNumber].sm3_256Pcr; |
381 | | break; |
382 | | #endif |
383 | 0 | default: |
384 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
385 | 0 | break; |
386 | 14.2k | } |
387 | 14.2k | return pcr; |
388 | 14.2k | } |
389 | | /* 8.7.3.11 IsPcrSelected() */ |
390 | | /* This function indicates if an indicated PCR number is selected by the bit map in selection. */ |
391 | | /* Return Values Meaning */ |
392 | | /* FALSE PCR is not selected */ |
393 | | /* TRUE PCR is selected */ |
394 | | static BOOL |
395 | | IsPcrSelected( |
396 | | UINT32 pcr, // IN: The number of the PCR |
397 | | TPMS_PCR_SELECTION *selection // IN: The selection structure |
398 | | ) |
399 | 0 | { |
400 | 0 | BOOL selected; |
401 | 0 | selected = (pcr < IMPLEMENTATION_PCR |
402 | 0 | && ((selection->pcrSelect[pcr / 8]) & (1 << (pcr % 8))) != 0); |
403 | 0 | return selected; |
404 | 0 | } |
405 | | /* 8.7.3.12 FilterPcr() */ |
406 | | /* This function modifies a PCR selection array based on the implemented PCR. */ |
407 | | static void |
408 | | FilterPcr( |
409 | | TPMS_PCR_SELECTION *selection // IN: input PCR selection |
410 | | ) |
411 | 0 | { |
412 | 0 | UINT32 i; |
413 | 0 | TPMS_PCR_SELECTION *allocated = NULL; |
414 | | // If size of select is less than PCR_SELECT_MAX, zero the unspecified PCR |
415 | 0 | for(i = selection->sizeofSelect; i < PCR_SELECT_MAX; i++) |
416 | 0 | selection->pcrSelect[i] = 0; |
417 | | // Find the internal configuration for the bank |
418 | 0 | for(i = 0; i < gp.pcrAllocated.count; i++) |
419 | 0 | { |
420 | 0 | if(gp.pcrAllocated.pcrSelections[i].hash == selection->hash) |
421 | 0 | { |
422 | 0 | allocated = &gp.pcrAllocated.pcrSelections[i]; |
423 | 0 | break; |
424 | 0 | } |
425 | 0 | } |
426 | 0 | for(i = 0; i < selection->sizeofSelect; i++) |
427 | 0 | { |
428 | 0 | if(allocated == NULL) |
429 | 0 | { |
430 | | // If the required bank does not exist, clear input selection |
431 | 0 | selection->pcrSelect[i] = 0; |
432 | 0 | } |
433 | 0 | else |
434 | 0 | selection->pcrSelect[i] &= allocated->pcrSelect[i]; |
435 | 0 | } |
436 | 0 | return; |
437 | 0 | } |
438 | | /* 8.7.3.13 PcrDrtm() */ |
439 | | /* This function does the DRTM and H-CRTM processing it is called from _TPM_Hash_End(). */ |
440 | | void |
441 | | PcrDrtm( |
442 | | const TPMI_DH_PCR pcrHandle, // IN: the index of the PCR to be |
443 | | // modified |
444 | | const TPMI_ALG_HASH hash, // IN: the bank identifier |
445 | | const TPM2B_DIGEST *digest // IN: the digest to modify the PCR |
446 | | ) |
447 | 7.13k | { |
448 | 7.13k | BYTE *pcrData = GetPcrPointer(hash, pcrHandle); |
449 | 7.13k | if(pcrData != NULL) |
450 | 7.13k | { |
451 | | // Rest the PCR to zeros |
452 | 7.13k | MemorySet(pcrData, 0, digest->t.size); |
453 | | // if the TPM has not started, then set the PCR to 0...04 and then extend |
454 | 7.13k | if(!TPMIsStarted()) |
455 | 7.13k | { |
456 | 7.13k | pcrData[digest->t.size - 1] = 4; |
457 | 7.13k | } |
458 | | // Now, extend the value |
459 | 7.13k | PCRExtend(pcrHandle, hash, digest->t.size, (BYTE *)digest->t.buffer); |
460 | 7.13k | } |
461 | 7.13k | } |
462 | | /* 8.7.3.14 PCR_ClearAuth() */ |
463 | | /* This function is used to reset the PCR authorization values. It is called on TPM2_Startup(CLEAR) |
464 | | and TPM2_Clear(). */ |
465 | | void |
466 | | PCR_ClearAuth( |
467 | | void |
468 | | ) |
469 | 0 | { |
470 | 0 | #if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0 |
471 | 0 | int j; |
472 | 0 | for(j = 0; j < NUM_AUTHVALUE_PCR_GROUP; j++) |
473 | 0 | { |
474 | 0 | gc.pcrAuthValues.auth[j].t.size = 0; |
475 | 0 | } |
476 | 0 | #endif |
477 | 0 | } |
478 | | /* 8.7.3.15 PCRStartup() */ |
479 | | /* This function initializes the PCR subsystem at TPM2_Startup(). */ |
480 | | void |
481 | | PCRStartup( |
482 | | STARTUP_TYPE type, // IN: startup type |
483 | | BYTE locality // IN: startup locality |
484 | | ) |
485 | 0 | { |
486 | 0 | UINT32 pcr, j; |
487 | 0 | UINT32 saveIndex = 0; |
488 | 0 | g_pcrReConfig = FALSE; |
489 | | // Don't test for SU_RESET because that should be the default when nothing |
490 | | // else is selected |
491 | 0 | if(type != SU_RESUME && type != SU_RESTART) |
492 | 0 | { |
493 | | // PCR generation counter is cleared at TPM_RESET |
494 | 0 | gr.pcrCounter = 0; |
495 | 0 | } |
496 | | // Initialize/Restore PCR values |
497 | 0 | for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) |
498 | 0 | { |
499 | | // On resume, need to know if this PCR had its state saved or not |
500 | 0 | UINT32 stateSaved; |
501 | 0 | if(type == SU_RESUME |
502 | 0 | && s_initAttributes[pcr].stateSave == SET) |
503 | 0 | { |
504 | 0 | stateSaved = 1; |
505 | 0 | } |
506 | 0 | else |
507 | 0 | { |
508 | 0 | stateSaved = 0; |
509 | 0 | PCRChanged(pcr); |
510 | 0 | } |
511 | | // If this is the H-CRTM PCR and we are not doing a resume and we |
512 | | // had an H-CRTM event, then we don't change this PCR |
513 | 0 | if(pcr == HCRTM_PCR && type != SU_RESUME && g_DrtmPreStartup == TRUE) |
514 | 0 | continue; |
515 | | // Iterate each hash algorithm bank |
516 | 0 | for(j = 0; j < gp.pcrAllocated.count; j++) |
517 | 0 | { |
518 | 0 | TPMI_ALG_HASH hash = gp.pcrAllocated.pcrSelections[j].hash; |
519 | 0 | BYTE *pcrData = GetPcrPointer(hash, pcr); |
520 | 0 | UINT16 pcrSize = CryptHashGetDigestSize(hash); |
521 | 0 | if(pcrData != NULL) |
522 | 0 | { |
523 | | // if state was saved |
524 | 0 | if(stateSaved == 1) |
525 | 0 | { |
526 | | // Restore saved PCR value |
527 | 0 | BYTE *pcrSavedData; |
528 | 0 | pcrSavedData = GetSavedPcrPointer( |
529 | 0 | gp.pcrAllocated.pcrSelections[j].hash, |
530 | 0 | saveIndex); |
531 | 0 | MemoryCopy(pcrData, pcrSavedData, pcrSize); |
532 | 0 | } |
533 | 0 | else |
534 | | // PCR was not restored by state save |
535 | 0 | { |
536 | | // If the reset locality of the PCR is 4, then |
537 | | // the reset value is all one's, otherwise it is |
538 | | // all zero. |
539 | 0 | if((s_initAttributes[pcr].resetLocality & 0x10) != 0) |
540 | 0 | MemorySet(pcrData, 0xFF, pcrSize); |
541 | 0 | else |
542 | 0 | { |
543 | 0 | MemorySet(pcrData, 0, pcrSize); |
544 | 0 | if(pcr == HCRTM_PCR) |
545 | 0 | pcrData[pcrSize - 1] = locality; |
546 | 0 | } |
547 | 0 | } |
548 | 0 | } |
549 | 0 | } |
550 | 0 | saveIndex += stateSaved; |
551 | 0 | } |
552 | | // Reset authValues on TPM2_Startup(CLEAR) |
553 | 0 | if(type != SU_RESUME) |
554 | 0 | PCR_ClearAuth(); |
555 | 0 | } |
556 | | /* 8.7.3.16 PCRStateSave() */ |
557 | | /* This function is used to save the PCR values that will be restored on TPM Resume. */ |
558 | | void |
559 | | PCRStateSave( |
560 | | TPM_SU type // IN: startup type |
561 | | ) |
562 | 0 | { |
563 | 0 | UINT32 pcr, j; |
564 | 0 | UINT32 saveIndex = 0; |
565 | | // if state save CLEAR, nothing to be done. Return here |
566 | 0 | if(type == TPM_SU_CLEAR) |
567 | 0 | return; |
568 | | // Copy PCR values to the structure that should be saved to NV |
569 | 0 | for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) |
570 | 0 | { |
571 | 0 | UINT32 stateSaved = (s_initAttributes[pcr].stateSave == SET) ? 1 : 0; |
572 | | // Iterate each hash algorithm bank |
573 | 0 | for(j = 0; j < gp.pcrAllocated.count; j++) |
574 | 0 | { |
575 | 0 | BYTE *pcrData; |
576 | 0 | UINT32 pcrSize; |
577 | 0 | pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[j].hash, pcr); |
578 | 0 | if(pcrData != NULL) |
579 | 0 | { |
580 | 0 | pcrSize |
581 | 0 | = CryptHashGetDigestSize(gp.pcrAllocated.pcrSelections[j].hash); |
582 | 0 | if(stateSaved == 1) |
583 | 0 | { |
584 | | // Restore saved PCR value |
585 | 0 | BYTE *pcrSavedData; |
586 | 0 | pcrSavedData |
587 | 0 | = GetSavedPcrPointer(gp.pcrAllocated.pcrSelections[j].hash, |
588 | 0 | saveIndex); |
589 | 0 | MemoryCopy(pcrSavedData, pcrData, pcrSize); |
590 | 0 | } |
591 | 0 | } |
592 | 0 | } |
593 | 0 | saveIndex += stateSaved; |
594 | 0 | } |
595 | 0 | return; |
596 | 0 | } |
597 | | /* 8.7.3.17 PCRIsStateSaved() */ |
598 | | /* This function indicates if the selected PCR is a PCR that is state saved on |
599 | | TPM2_Shutdown(STATE). The return value is based on PCR attributes. */ |
600 | | /* Return Values Meaning */ |
601 | | /* TRUE PCR is state saved */ |
602 | | /* FALSE PCR is not state saved */ |
603 | | BOOL |
604 | | PCRIsStateSaved( |
605 | | TPMI_DH_PCR handle // IN: PCR handle to be extended |
606 | | ) |
607 | 0 | { |
608 | 0 | UINT32 pcr = handle - PCR_FIRST; |
609 | 0 | if(s_initAttributes[pcr].stateSave == SET) |
610 | 0 | return TRUE; |
611 | 0 | else |
612 | 0 | return FALSE; |
613 | 0 | } |
614 | | /* 8.7.3.18 PCRIsResetAllowed() */ |
615 | | /* This function indicates if a PCR may be reset by the current command locality. The return value |
616 | | is based on PCR attributes, and not the PCR allocation. */ |
617 | | /* Return Values Meaning */ |
618 | | /* TRUE TPM2_PCR_Reset() is allowed */ |
619 | | /* FALSE TPM2_PCR_Reset() is not allowed */ |
620 | | BOOL |
621 | | PCRIsResetAllowed( |
622 | | TPMI_DH_PCR handle // IN: PCR handle to be extended |
623 | | ) |
624 | 0 | { |
625 | 0 | UINT8 commandLocality; |
626 | 0 | UINT8 localityBits = 1; |
627 | 0 | UINT32 pcr = handle - PCR_FIRST; |
628 | | // Check for the locality |
629 | 0 | commandLocality = _plat__LocalityGet(); |
630 | 0 | #ifdef DRTM_PCR |
631 | | // For a TPM that does DRTM, Reset is not allowed at locality 4 |
632 | 0 | if(commandLocality == 4) |
633 | 0 | return FALSE; |
634 | 0 | #endif |
635 | 0 | localityBits = localityBits << commandLocality; |
636 | 0 | if((localityBits & s_initAttributes[pcr].resetLocality) == 0) |
637 | 0 | return FALSE; |
638 | 0 | else |
639 | 0 | return TRUE; |
640 | 0 | } |
641 | | /* 8.7.3.19 PCRChanged() */ |
642 | | /* This function checks a PCR handle to see if the attributes for the PCR are set so that any change |
643 | | to the PCR causes an increment of the pcrCounter. If it does, then the function increments the |
644 | | counter. Will also bump the counter if the handle is zero which means that PCR 0 can not be in |
645 | | the TCB group. Bump on zero is used by TPM2_Clear(). */ |
646 | | void |
647 | | PCRChanged( |
648 | | TPM_HANDLE pcrHandle // IN: the handle of the PCR that changed. |
649 | | ) |
650 | 7.13k | { |
651 | | // For the reference implementation, the only change that does not cause |
652 | | // increment is a change to a PCR in the TCB group. |
653 | 7.13k | if((pcrHandle == 0) || !PCRBelongsTCBGroup(pcrHandle)) |
654 | 7.13k | { |
655 | 7.13k | gr.pcrCounter++; |
656 | 7.13k | if(gr.pcrCounter == 0) |
657 | 0 | FAIL(FATAL_ERROR_COUNTER_OVERFLOW); |
658 | 7.13k | } |
659 | 7.13k | } |
660 | | /* 8.7.3.20 PCRIsExtendAllowed() */ |
661 | | /* This function indicates a PCR may be extended at the current command locality. The return value |
662 | | is based on PCR attributes, and not the PCR allocation. */ |
663 | | /* Return Values Meaning */ |
664 | | /* TRUE extend is allowed */ |
665 | | /* FALSE extend is not allowed */ |
666 | | BOOL |
667 | | PCRIsExtendAllowed( |
668 | | TPMI_DH_PCR handle // IN: PCR handle to be extended |
669 | | ) |
670 | 0 | { |
671 | 0 | UINT8 commandLocality; |
672 | 0 | UINT8 localityBits = 1; |
673 | 0 | UINT32 pcr = handle - PCR_FIRST; |
674 | | // Check for the locality |
675 | 0 | commandLocality = _plat__LocalityGet(); |
676 | 0 | localityBits = localityBits << commandLocality; |
677 | 0 | if((localityBits & s_initAttributes[pcr].extendLocality) == 0) |
678 | 0 | return FALSE; |
679 | 0 | else |
680 | 0 | return TRUE; |
681 | 0 | } |
682 | | /* 8.7.3.21 PCRExtend() */ |
683 | | /* This function is used to extend a PCR in a specific bank. */ |
684 | | void |
685 | | PCRExtend( |
686 | | TPMI_DH_PCR handle, // IN: PCR handle to be extended |
687 | | TPMI_ALG_HASH hash, // IN: hash algorithm of PCR |
688 | | UINT32 size, // IN: size of data to be extended |
689 | | BYTE *data // IN: data to be extended |
690 | | ) |
691 | 7.13k | { |
692 | 7.13k | BYTE *pcrData; |
693 | 7.13k | HASH_STATE hashState; |
694 | 7.13k | UINT16 pcrSize; |
695 | 7.13k | pcrData = GetPcrPointer(hash, handle - PCR_FIRST); |
696 | | // Extend PCR if it is allocated |
697 | 7.13k | if(pcrData != NULL) |
698 | 7.13k | { |
699 | 7.13k | pcrSize = CryptHashGetDigestSize(hash); |
700 | 7.13k | CryptHashStart(&hashState, hash); |
701 | 7.13k | CryptDigestUpdate(&hashState, pcrSize, pcrData); |
702 | 7.13k | CryptDigestUpdate(&hashState, size, data); |
703 | 7.13k | CryptHashEnd(&hashState, pcrSize, pcrData); |
704 | | // PCR has changed so update the pcrCounter if necessary |
705 | 7.13k | PCRChanged(handle); |
706 | 7.13k | } |
707 | 7.13k | return; |
708 | 7.13k | } |
709 | | /* 8.7.3.22 PCRComputeCurrentDigest() */ |
710 | | /* This function computes the digest of the selected PCR. */ |
711 | | /* As a side-effect, selection is modified so that only the implemented PCR will have their bits |
712 | | still set. */ |
713 | | void |
714 | | PCRComputeCurrentDigest( |
715 | | TPMI_ALG_HASH hashAlg, // IN: hash algorithm to compute digest |
716 | | TPML_PCR_SELECTION *selection, // IN/OUT: PCR selection (filtered on |
717 | | // output) |
718 | | TPM2B_DIGEST *digest // OUT: digest |
719 | | ) |
720 | 0 | { |
721 | 0 | HASH_STATE hashState; |
722 | 0 | TPMS_PCR_SELECTION *select; |
723 | 0 | BYTE *pcrData; // will point to a digest |
724 | 0 | UINT32 pcrSize; |
725 | 0 | UINT32 pcr; |
726 | 0 | UINT32 i; |
727 | | // Initialize the hash |
728 | 0 | digest->t.size = CryptHashStart(&hashState, hashAlg); |
729 | 0 | pAssert(digest->t.size > 0 && digest->t.size < UINT16_MAX); |
730 | | // Iterate through the list of PCR selection structures |
731 | 0 | for(i = 0; i < selection->count; i++) |
732 | 0 | { |
733 | | // Point to the current selection |
734 | 0 | select = &selection->pcrSelections[i]; // Point to the current selection |
735 | 0 | FilterPcr(select); // Clear out the bits for unimplemented PCR |
736 | | // Need the size of each digest |
737 | 0 | pcrSize = CryptHashGetDigestSize(selection->pcrSelections[i].hash); |
738 | | // Iterate through the selection |
739 | 0 | for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) |
740 | 0 | { |
741 | 0 | if(IsPcrSelected(pcr, select)) // Is this PCR selected |
742 | 0 | { |
743 | | // Get pointer to the digest data for the bank |
744 | 0 | pcrData = GetPcrPointer(selection->pcrSelections[i].hash, pcr); |
745 | 0 | pAssert(pcrData != NULL); |
746 | 0 | CryptDigestUpdate(&hashState, pcrSize, pcrData); // add to digest |
747 | 0 | } |
748 | 0 | } |
749 | 0 | } |
750 | | // Complete hash stack |
751 | 0 | CryptHashEnd2B(&hashState, &digest->b); |
752 | 0 | return; |
753 | 0 | } |
754 | | /* 8.7.3.23 PCRRead() */ |
755 | | /* This function is used to read a list of selected PCR. If the requested PCR number exceeds the |
756 | | maximum number that can be output, the selection is adjusted to reflect the actual output PCR. */ |
757 | | void |
758 | | PCRRead( |
759 | | TPML_PCR_SELECTION *selection, // IN/OUT: PCR selection (filtered on |
760 | | // output) |
761 | | TPML_DIGEST *digest, // OUT: digest |
762 | | UINT32 *pcrCounter // OUT: the current value of PCR generation |
763 | | // number |
764 | | ) |
765 | 0 | { |
766 | 0 | TPMS_PCR_SELECTION *select; |
767 | 0 | BYTE *pcrData; // will point to a digest |
768 | 0 | UINT32 pcr; |
769 | 0 | UINT32 i; |
770 | 0 | digest->count = 0; |
771 | | // Iterate through the list of PCR selection structures |
772 | 0 | for(i = 0; i < selection->count; i++) |
773 | 0 | { |
774 | | // Point to the current selection |
775 | 0 | select = &selection->pcrSelections[i]; // Point to the current selection |
776 | 0 | FilterPcr(select); // Clear out the bits for unimplemented PCR |
777 | | // Iterate through the selection |
778 | 0 | for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) |
779 | 0 | { |
780 | 0 | if(IsPcrSelected(pcr, select)) // Is this PCR selected |
781 | 0 | { |
782 | | // Check if number of digest exceed upper bound |
783 | 0 | if(digest->count > 7) |
784 | 0 | { |
785 | | // Clear rest of the current select bitmap |
786 | 0 | while(pcr < IMPLEMENTATION_PCR |
787 | | // do not round up! |
788 | 0 | && (pcr / 8) < select->sizeofSelect) |
789 | 0 | { |
790 | | // do not round up! |
791 | 0 | select->pcrSelect[pcr / 8] &= (BYTE)~(1 << (pcr % 8)); |
792 | 0 | pcr++; |
793 | 0 | } |
794 | | // Exit inner loop |
795 | 0 | break; |
796 | 0 | } |
797 | | // Need the size of each digest |
798 | 0 | digest->digests[digest->count].t.size = |
799 | 0 | CryptHashGetDigestSize(selection->pcrSelections[i].hash); |
800 | | // Get pointer to the digest data for the bank |
801 | 0 | pcrData = GetPcrPointer(selection->pcrSelections[i].hash, pcr); |
802 | 0 | pAssert(pcrData != NULL); |
803 | | // Add to the data to digest |
804 | 0 | MemoryCopy(digest->digests[digest->count].t.buffer, |
805 | 0 | pcrData, |
806 | 0 | digest->digests[digest->count].t.size); |
807 | 0 | digest->count++; |
808 | 0 | } |
809 | 0 | } |
810 | | // If we exit inner loop because we have exceed the output upper bound |
811 | 0 | if(digest->count > 7 && pcr < IMPLEMENTATION_PCR) |
812 | 0 | { |
813 | | // Clear rest of the selection |
814 | 0 | while(i < selection->count) |
815 | 0 | { |
816 | 0 | MemorySet(selection->pcrSelections[i].pcrSelect, 0, |
817 | 0 | selection->pcrSelections[i].sizeofSelect); |
818 | 0 | i++; |
819 | 0 | } |
820 | | // exit outer loop |
821 | 0 | break; |
822 | 0 | } |
823 | 0 | } |
824 | 0 | *pcrCounter = gr.pcrCounter; |
825 | 0 | return; |
826 | 0 | } |
827 | | /* 8.7.3.24 PcrWrite() */ |
828 | | /* This function is used by _TPM_Hash_End() to set a PCR to the computed hash of the H-CRTM |
829 | | event. */ |
830 | | void |
831 | | PcrWrite( |
832 | | TPMI_DH_PCR handle, // IN: PCR handle to be extended |
833 | | TPMI_ALG_HASH hash, // IN: hash algorithm of PCR |
834 | | TPM2B_DIGEST *digest // IN: the new value |
835 | | ) |
836 | 0 | { |
837 | 0 | UINT32 pcr = handle - PCR_FIRST; |
838 | 0 | BYTE *pcrData; |
839 | | // Copy value to the PCR if it is allocated |
840 | 0 | pcrData = GetPcrPointer(hash, pcr); |
841 | 0 | if(pcrData != NULL) |
842 | 0 | { |
843 | 0 | MemoryCopy(pcrData, digest->t.buffer, digest->t.size); |
844 | 0 | } |
845 | 0 | return; |
846 | 0 | } |
847 | | /* 8.7.3.25 PCRAllocate() */ |
848 | | /* This function is used to change the PCR allocation. */ |
849 | | /* Error Returns Meaning */ |
850 | | /* TPM_RC_SUCCESS allocate success */ |
851 | | /* TPM_RC_NO_RESULT allocate failed */ |
852 | | /* TPM_RC_PCR improper allocation */ |
853 | | TPM_RC |
854 | | PCRAllocate( |
855 | | TPML_PCR_SELECTION *allocate, // IN: required allocation |
856 | | UINT32 *maxPCR, // OUT: Maximum number of PCR |
857 | | UINT32 *sizeNeeded, // OUT: required space |
858 | | UINT32 *sizeAvailable // OUT: available space |
859 | | ) |
860 | 0 | { |
861 | 0 | UINT32 i, j, k; |
862 | 0 | TPML_PCR_SELECTION newAllocate; |
863 | | // Initialize the flags to indicate if HCRTM PCR and DRTM PCR are allocated. |
864 | 0 | BOOL pcrHcrtm = FALSE; |
865 | 0 | BOOL pcrDrtm = FALSE; |
866 | | // Create the expected new PCR allocation based on the existing allocation |
867 | | // and the new input: |
868 | | // 1. if a PCR bank does not appear in the new allocation, the existing |
869 | | // allocation of this PCR bank will be preserved. |
870 | | // 2. if a PCR bank appears multiple times in the new allocation, only the |
871 | | // last one will be in effect. |
872 | 0 | newAllocate = gp.pcrAllocated; |
873 | 0 | for(i = 0; i < allocate->count; i++) |
874 | 0 | { |
875 | 0 | for(j = 0; j < newAllocate.count; j++) |
876 | 0 | { |
877 | | // If hash matches, the new allocation covers the old allocation |
878 | | // for this particular bank. |
879 | | // The assumption is the initial PCR allocation (from manufacture) |
880 | | // has all the supported hash algorithms with an assigned bank |
881 | | // (possibly empty). So there must be a match for any new bank |
882 | | // allocation from the input. |
883 | 0 | if(newAllocate.pcrSelections[j].hash == |
884 | 0 | allocate->pcrSelections[i].hash) |
885 | 0 | { |
886 | 0 | newAllocate.pcrSelections[j] = allocate->pcrSelections[i]; |
887 | 0 | break; |
888 | 0 | } |
889 | 0 | } |
890 | | // The j loop must exit with a match. |
891 | 0 | pAssert(j < newAllocate.count); |
892 | 0 | } |
893 | | // Max PCR in a bank is MIN(implemented PCR, PCR with attributes defined) |
894 | 0 | *maxPCR = sizeof(s_initAttributes) / sizeof(PCR_Attributes); |
895 | 0 | if(*maxPCR > IMPLEMENTATION_PCR) |
896 | 0 | *maxPCR = IMPLEMENTATION_PCR; |
897 | | // Compute required size for allocation |
898 | 0 | *sizeNeeded = 0; |
899 | 0 | for(i = 0; i < newAllocate.count; i++) |
900 | 0 | { |
901 | 0 | UINT32 digestSize |
902 | 0 | = CryptHashGetDigestSize(newAllocate.pcrSelections[i].hash); |
903 | 0 | #if defined(DRTM_PCR) |
904 | | // Make sure that we end up with at least one DRTM PCR |
905 | 0 | pcrDrtm = pcrDrtm || TestBit(DRTM_PCR, |
906 | 0 | newAllocate.pcrSelections[i].pcrSelect, |
907 | 0 | newAllocate.pcrSelections[i].sizeofSelect); |
908 | | #else // if DRTM PCR is not required, indicate that the allocation is OK |
909 | | pcrDrtm = TRUE; |
910 | | #endif |
911 | 0 | #if defined(HCRTM_PCR) |
912 | | // and one HCRTM PCR (since this is usually PCR 0...) |
913 | 0 | pcrHcrtm = pcrHcrtm || TestBit(HCRTM_PCR, |
914 | 0 | newAllocate.pcrSelections[i].pcrSelect, |
915 | 0 | newAllocate.pcrSelections[i].sizeofSelect); |
916 | | #else |
917 | | pcrHcrtm = TRUE; |
918 | | #endif |
919 | 0 | for(j = 0; j < newAllocate.pcrSelections[i].sizeofSelect; j++) |
920 | 0 | { |
921 | 0 | BYTE mask = 1; |
922 | 0 | for(k = 0; k < 8; k++) |
923 | 0 | { |
924 | 0 | if((newAllocate.pcrSelections[i].pcrSelect[j] & mask) != 0) |
925 | 0 | *sizeNeeded += digestSize; |
926 | 0 | mask = mask << 1; |
927 | 0 | } |
928 | 0 | } |
929 | 0 | } |
930 | 0 | if(!pcrDrtm || !pcrHcrtm) |
931 | 0 | return TPM_RC_PCR; |
932 | | // In this particular implementation, we always have enough space to |
933 | | // allocate PCR. Different implementation may return a sizeAvailable less |
934 | | // than the sizeNeed. |
935 | 0 | *sizeAvailable = sizeof(s_pcrs); |
936 | | // Save the required allocation to NV. Note that after NV is written, the |
937 | | // PCR allocation in NV is no longer consistent with the RAM data |
938 | | // gp.pcrAllocated. The NV version reflect the allocate after next |
939 | | // TPM_RESET, while the RAM version reflects the current allocation |
940 | 0 | NV_WRITE_PERSISTENT(pcrAllocated, newAllocate); |
941 | 0 | return TPM_RC_SUCCESS; |
942 | 0 | } |
943 | | /* 8.7.3.26 PCRSetValue() */ |
944 | | /* This function is used to set the designated PCR in all banks to an initial value. The initial |
945 | | value is signed and will be sign extended into the entire PCR. */ |
946 | | void |
947 | | PCRSetValue( |
948 | | TPM_HANDLE handle, // IN: the handle of the PCR to set |
949 | | INT8 initialValue // IN: the value to set |
950 | | ) |
951 | 0 | { |
952 | 0 | int i; |
953 | 0 | UINT32 pcr = handle - PCR_FIRST; |
954 | 0 | TPMI_ALG_HASH hash; |
955 | 0 | UINT16 digestSize; |
956 | 0 | BYTE *pcrData; |
957 | | // Iterate supported PCR bank algorithms to reset |
958 | 0 | for(i = 0; i < HASH_COUNT; i++) |
959 | 0 | { |
960 | 0 | hash = CryptHashGetAlgByIndex(i); |
961 | | // Prevent runaway |
962 | 0 | if(hash == TPM_ALG_NULL) |
963 | 0 | break; |
964 | | // Get a pointer to the data |
965 | 0 | pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr); |
966 | | // If the PCR is allocated |
967 | 0 | if(pcrData != NULL) |
968 | 0 | { |
969 | | // And the size of the digest |
970 | 0 | digestSize = CryptHashGetDigestSize(hash); |
971 | | // Set the LSO to the input value |
972 | 0 | pcrData[digestSize - 1] = initialValue; |
973 | | // Sign extend |
974 | 0 | if(initialValue >= 0) |
975 | 0 | MemorySet(pcrData, 0, digestSize - 1); |
976 | 0 | else |
977 | 0 | MemorySet(pcrData, -1, digestSize - 1); |
978 | 0 | } |
979 | 0 | } |
980 | 0 | } |
981 | | /* 8.7.3.27 PCRResetDynamics */ |
982 | | /* This function is used to reset a dynamic PCR to 0. This function is used in DRTM sequence. */ |
983 | | void |
984 | | PCRResetDynamics( |
985 | | void |
986 | | ) |
987 | 0 | { |
988 | 0 | UINT32 pcr, i; |
989 | | // Initialize PCR values |
990 | 0 | for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) |
991 | 0 | { |
992 | | // Iterate each hash algorithm bank |
993 | 0 | for(i = 0; i < gp.pcrAllocated.count; i++) |
994 | 0 | { |
995 | 0 | BYTE *pcrData; |
996 | 0 | UINT32 pcrSize; |
997 | 0 | pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr); |
998 | 0 | if(pcrData != NULL) |
999 | 0 | { |
1000 | 0 | pcrSize = |
1001 | 0 | CryptHashGetDigestSize(gp.pcrAllocated.pcrSelections[i].hash); |
1002 | | // Reset PCR |
1003 | | // Any PCR can be reset by locality 4 should be reset to 0 |
1004 | 0 | if((s_initAttributes[pcr].resetLocality & 0x10) != 0) |
1005 | 0 | MemorySet(pcrData, 0, pcrSize); |
1006 | 0 | } |
1007 | 0 | } |
1008 | 0 | } |
1009 | 0 | return; |
1010 | 0 | } |
1011 | | /* 8.7.3.28 PCRCapGetAllocation() */ |
1012 | | /* This function is used to get the current allocation of PCR banks. */ |
1013 | | /* Return Values Meaning */ |
1014 | | /* YES: if the return count is 0 */ |
1015 | | /* NO: if the return count is not 0 */ |
1016 | | TPMI_YES_NO |
1017 | | PCRCapGetAllocation( |
1018 | | UINT32 count, // IN: count of return |
1019 | | TPML_PCR_SELECTION *pcrSelection // OUT: PCR allocation list |
1020 | | ) |
1021 | 0 | { |
1022 | 0 | if(count == 0) |
1023 | 0 | { |
1024 | 0 | pcrSelection->count = 0; |
1025 | 0 | return YES; |
1026 | 0 | } |
1027 | 0 | else |
1028 | 0 | { |
1029 | 0 | *pcrSelection = gp.pcrAllocated; |
1030 | 0 | return NO; |
1031 | 0 | } |
1032 | 0 | } |
1033 | | /* 8.7.3.29 PCRSetSelectBit() */ |
1034 | | /* This function sets a bit in a bitmap array. */ |
1035 | | static void |
1036 | | PCRSetSelectBit( |
1037 | | UINT32 pcr, // IN: PCR number |
1038 | | BYTE *bitmap // OUT: bit map to be set |
1039 | | ) |
1040 | 0 | { |
1041 | 0 | bitmap[pcr / 8] |= (1 << (pcr % 8)); |
1042 | 0 | return; |
1043 | 0 | } |
1044 | | /* 8.7.3.30 PCRGetProperty() */ |
1045 | | /* This function returns the selected PCR property. */ |
1046 | | /* Return Values Meaning */ |
1047 | | /* TRUE the property type is implemented */ |
1048 | | /* FALSE the property type is not implemented */ |
1049 | | static BOOL |
1050 | | PCRGetProperty( |
1051 | | TPM_PT_PCR property, |
1052 | | TPMS_TAGGED_PCR_SELECT *select |
1053 | | ) |
1054 | 0 | { |
1055 | 0 | UINT32 pcr; |
1056 | 0 | UINT32 groupIndex; |
1057 | 0 | select->tag = property; |
1058 | | // Always set the bitmap to be the size of all PCR |
1059 | 0 | select->sizeofSelect = (IMPLEMENTATION_PCR + 7) / 8; |
1060 | | // Initialize bitmap |
1061 | 0 | MemorySet(select->pcrSelect, 0, select->sizeofSelect); |
1062 | | // Collecting properties |
1063 | 0 | for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) |
1064 | 0 | { |
1065 | 0 | switch(property) |
1066 | 0 | { |
1067 | 0 | case TPM_PT_PCR_SAVE: |
1068 | 0 | if(s_initAttributes[pcr].stateSave == SET) |
1069 | 0 | PCRSetSelectBit(pcr, select->pcrSelect); |
1070 | 0 | break; |
1071 | 0 | case TPM_PT_PCR_EXTEND_L0: |
1072 | 0 | if((s_initAttributes[pcr].extendLocality & 0x01) != 0) |
1073 | 0 | PCRSetSelectBit(pcr, select->pcrSelect); |
1074 | 0 | break; |
1075 | 0 | case TPM_PT_PCR_RESET_L0: |
1076 | 0 | if((s_initAttributes[pcr].resetLocality & 0x01) != 0) |
1077 | 0 | PCRSetSelectBit(pcr, select->pcrSelect); |
1078 | 0 | break; |
1079 | 0 | case TPM_PT_PCR_EXTEND_L1: |
1080 | 0 | if((s_initAttributes[pcr].extendLocality & 0x02) != 0) |
1081 | 0 | PCRSetSelectBit(pcr, select->pcrSelect); |
1082 | 0 | break; |
1083 | 0 | case TPM_PT_PCR_RESET_L1: |
1084 | 0 | if((s_initAttributes[pcr].resetLocality & 0x02) != 0) |
1085 | 0 | PCRSetSelectBit(pcr, select->pcrSelect); |
1086 | 0 | break; |
1087 | 0 | case TPM_PT_PCR_EXTEND_L2: |
1088 | 0 | if((s_initAttributes[pcr].extendLocality & 0x04) != 0) |
1089 | 0 | PCRSetSelectBit(pcr, select->pcrSelect); |
1090 | 0 | break; |
1091 | 0 | case TPM_PT_PCR_RESET_L2: |
1092 | 0 | if((s_initAttributes[pcr].resetLocality & 0x04) != 0) |
1093 | 0 | PCRSetSelectBit(pcr, select->pcrSelect); |
1094 | 0 | break; |
1095 | 0 | case TPM_PT_PCR_EXTEND_L3: |
1096 | 0 | if((s_initAttributes[pcr].extendLocality & 0x08) != 0) |
1097 | 0 | PCRSetSelectBit(pcr, select->pcrSelect); |
1098 | 0 | break; |
1099 | 0 | case TPM_PT_PCR_RESET_L3: |
1100 | 0 | if((s_initAttributes[pcr].resetLocality & 0x08) != 0) |
1101 | 0 | PCRSetSelectBit(pcr, select->pcrSelect); |
1102 | 0 | break; |
1103 | 0 | case TPM_PT_PCR_EXTEND_L4: |
1104 | 0 | if((s_initAttributes[pcr].extendLocality & 0x10) != 0) |
1105 | 0 | PCRSetSelectBit(pcr, select->pcrSelect); |
1106 | 0 | break; |
1107 | 0 | case TPM_PT_PCR_RESET_L4: |
1108 | 0 | if((s_initAttributes[pcr].resetLocality & 0x10) != 0) |
1109 | 0 | PCRSetSelectBit(pcr, select->pcrSelect); |
1110 | 0 | break; |
1111 | 0 | case TPM_PT_PCR_DRTM_RESET: |
1112 | | // DRTM reset PCRs are the PCR reset by locality 4 |
1113 | 0 | if((s_initAttributes[pcr].resetLocality & 0x10) != 0) |
1114 | 0 | PCRSetSelectBit(pcr, select->pcrSelect); |
1115 | 0 | break; |
1116 | 0 | #if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 |
1117 | 0 | case TPM_PT_PCR_POLICY: |
1118 | 0 | if(PCRBelongsPolicyGroup(pcr + PCR_FIRST, &groupIndex)) |
1119 | 0 | PCRSetSelectBit(pcr, select->pcrSelect); |
1120 | 0 | break; |
1121 | 0 | #endif |
1122 | 0 | #if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0 |
1123 | 0 | case TPM_PT_PCR_AUTH: |
1124 | 0 | if(PCRBelongsAuthGroup(pcr + PCR_FIRST, &groupIndex)) |
1125 | 0 | PCRSetSelectBit(pcr, select->pcrSelect); |
1126 | 0 | break; |
1127 | 0 | #endif |
1128 | 0 | #if ENABLE_PCR_NO_INCREMENT == YES |
1129 | 0 | case TPM_PT_PCR_NO_INCREMENT: |
1130 | 0 | if(PCRBelongsTCBGroup(pcr + PCR_FIRST)) |
1131 | 0 | PCRSetSelectBit(pcr, select->pcrSelect); |
1132 | 0 | break; |
1133 | 0 | #endif |
1134 | 0 | default: |
1135 | | // If property is not supported, stop scanning PCR attributes |
1136 | | // and return. |
1137 | 0 | return FALSE; |
1138 | 0 | break; |
1139 | 0 | } |
1140 | 0 | } |
1141 | 0 | return TRUE; |
1142 | 0 | } |
1143 | | /* 8.7.3.31 PCRCapGetProperties() */ |
1144 | | /* This function returns a list of PCR properties starting at property. */ |
1145 | | /* Return Values Meaning */ |
1146 | | /* YES: if no more property is available */ |
1147 | | /* NO: if there are more properties not reported */ |
1148 | | TPMI_YES_NO |
1149 | | PCRCapGetProperties( |
1150 | | TPM_PT_PCR property, // IN: the starting PCR property |
1151 | | UINT32 count, // IN: count of returned properties |
1152 | | TPML_TAGGED_PCR_PROPERTY *select // OUT: PCR select |
1153 | | ) |
1154 | 0 | { |
1155 | 0 | TPMI_YES_NO more = NO; |
1156 | 0 | UINT32 i; |
1157 | | // Initialize output property list |
1158 | 0 | select->count = 0; |
1159 | | // The maximum count of properties we may return is MAX_PCR_PROPERTIES |
1160 | 0 | if(count > MAX_PCR_PROPERTIES) count = MAX_PCR_PROPERTIES; |
1161 | | // TPM_PT_PCR_FIRST is defined as 0 in spec. It ensures that property |
1162 | | // value would never be less than TPM_PT_PCR_FIRST |
1163 | 0 | cAssert(TPM_PT_PCR_FIRST == 0); |
1164 | | // Iterate PCR properties. TPM_PT_PCR_LAST is the index of the last property |
1165 | | // implemented on the TPM. |
1166 | 0 | for(i = property; i <= TPM_PT_PCR_LAST; i++) |
1167 | 0 | { |
1168 | 0 | if(select->count < count) |
1169 | 0 | { |
1170 | | // If we have not filled up the return list, add more properties to it |
1171 | 0 | if(PCRGetProperty(i, &select->pcrProperty[select->count])) |
1172 | | // only increment if the property is implemented |
1173 | 0 | select->count++; |
1174 | 0 | } |
1175 | 0 | else |
1176 | 0 | { |
1177 | | // If the return list is full but we still have properties |
1178 | | // available, report this and stop iterating. |
1179 | 0 | more = YES; |
1180 | 0 | break; |
1181 | 0 | } |
1182 | 0 | } |
1183 | 0 | return more; |
1184 | 0 | } |
1185 | | /* 8.7.3.32 PCRCapGetHandles() */ |
1186 | | /* This function is used to get a list of handles of PCR, started from handle. If handle exceeds the |
1187 | | maximum PCR handle range, an empty list will be returned and the return value will be NO. */ |
1188 | | /* Return Values Meaning */ |
1189 | | /* YES if there are more handles available */ |
1190 | | /* NO all the available handles has been returned */ |
1191 | | TPMI_YES_NO |
1192 | | PCRCapGetHandles( |
1193 | | TPMI_DH_PCR handle, // IN: start handle |
1194 | | UINT32 count, // IN: count of returned handles |
1195 | | TPML_HANDLE *handleList // OUT: list of handle |
1196 | | ) |
1197 | 0 | { |
1198 | 0 | TPMI_YES_NO more = NO; |
1199 | 0 | UINT32 i; |
1200 | 0 | pAssert(HandleGetType(handle) == TPM_HT_PCR); |
1201 | | // Initialize output handle list |
1202 | 0 | handleList->count = 0; |
1203 | | // The maximum count of handles we may return is MAX_CAP_HANDLES |
1204 | 0 | if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; |
1205 | | // Iterate PCR handle range |
1206 | 0 | for(i = handle & HR_HANDLE_MASK; i <= PCR_LAST; i++) |
1207 | 0 | { |
1208 | 0 | if(handleList->count < count) |
1209 | 0 | { |
1210 | | // If we have not filled up the return list, add this PCR |
1211 | | // handle to it |
1212 | 0 | handleList->handle[handleList->count] = i + PCR_FIRST; |
1213 | 0 | handleList->count++; |
1214 | 0 | } |
1215 | 0 | else |
1216 | 0 | { |
1217 | | // If the return list is full but we still have PCR handle |
1218 | | // available, report this and stop iterating |
1219 | 0 | more = YES; |
1220 | 0 | break; |
1221 | 0 | } |
1222 | 0 | } |
1223 | 0 | return more; |
1224 | 0 | } |