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