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
PCRBelongsAuthGroup(TPMI_DH_PCR handle,UINT32 * groupIndex)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 {
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 return FALSE;
61 }
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
PCRBelongsPolicyGroup(TPMI_DH_PCR handle,UINT32 * groupIndex)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 {
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 return FALSE;
92 }
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
PCRBelongsTCBGroup(TPMI_DH_PCR handle)105 PCRBelongsTCBGroup(
106 TPMI_DH_PCR handle // IN: handle of PCR
107 )
108 {
109 #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 if(handle == 16 || (handle >= 21 && handle <= 23))
115 return TRUE;
116 #endif
117 return FALSE;
118 }
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
PCRPolicyIsAvailable(TPMI_DH_PCR handle)134 PCRPolicyIsAvailable(
135 TPMI_DH_PCR handle // IN: PCR handle
136 )
137 {
138 UINT32 groupIndex;
139 return PCRBelongsPolicyGroup(handle, &groupIndex);
140 }
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
PCRGetAuthValue(TPMI_DH_PCR handle,TPM2B_AUTH * auth)149 PCRGetAuthValue(
150 TPMI_DH_PCR handle, // IN: PCR handle
151 TPM2B_AUTH *auth // OUT: authValue of PCR
152 )
153 {
154 UINT32 groupIndex;
155 if(PCRBelongsAuthGroup(handle, &groupIndex))
156 {
157 *auth = gc.pcrAuthValues.auth[groupIndex];
158 }
159 else
160 {
161 auth->t.size = 0;
162 }
163 return;
164 }
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
PCRGetAuthPolicy(TPMI_DH_PCR handle,TPM2B_DIGEST * policy)173 PCRGetAuthPolicy(
174 TPMI_DH_PCR handle, // IN: PCR handle
175 TPM2B_DIGEST *policy // OUT: policy of PCR
176 )
177 {
178 UINT32 groupIndex;
179 if(PCRBelongsPolicyGroup(handle, &groupIndex))
180 {
181 *policy = gp.pcrPolicies.policy[groupIndex];
182 return gp.pcrPolicies.hashAlg[groupIndex];
183 }
184 else
185 {
186 policy->t.size = 0;
187 return TPM_ALG_NULL;
188 }
189 }
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
PCRSimStart(void)198 PCRSimStart(
199 void
200 )
201 {
202 UINT32 i;
203 for(i = 0; i < NUM_POLICY_PCR_GROUP; i++)
204 {
205 gp.pcrPolicies.hashAlg[i] = TPM_ALG_NULL;
206 gp.pcrPolicies.policy[i].t.size = 0;
207 }
208 for(i = 0; i < NUM_AUTHVALUE_PCR_GROUP; i++)
209 {
210 gc.pcrAuthValues.auth[i].t.size = 0;
211 }
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 for(gp.pcrAllocated.count = 0; gp.pcrAllocated.count < HASH_COUNT;
216 gp.pcrAllocated.count++)
217 {
218 gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].hash
219 = CryptGetHashAlgByIndex(gp.pcrAllocated.count);
220 gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].sizeofSelect
221 = PCR_SELECT_MAX;
222 for(i = 0; i < PCR_SELECT_MAX; i++)
223 gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].pcrSelect[i]
224 = 0xFF;
225 }
226 // Store the initial configuration to NV
227 NvWriteReserved(NV_PCR_POLICIES, &gp.pcrPolicies);
228 NvWriteReserved(NV_PCR_ALLOCATED, &gp.pcrAllocated);
229 return;
230 }
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 *
GetSavedPcrPointer(TPM_ALG_ID alg,UINT32 pcrIndex)243 GetSavedPcrPointer (
244 TPM_ALG_ID alg, // IN: algorithm for bank
245 UINT32 pcrIndex // IN: PCR index in PCR_SAVE
246 )
247 {
248 switch(alg)
249 {
250 #ifdef TPM_ALG_SHA1
251 case TPM_ALG_SHA1:
252 return gc.pcrSave.sha1[pcrIndex];
253 break;
254 #endif
255 #ifdef TPM_ALG_SHA256
256 case TPM_ALG_SHA256:
257 return gc.pcrSave.sha256[pcrIndex];
258 break;
259 #endif
260 #ifdef TPM_ALG_SHA384
261 case TPM_ALG_SHA384:
262 return gc.pcrSave.sha384[pcrIndex];
263 break;
264 #endif
265 #ifdef TPM_ALG_SHA512
266 case TPM_ALG_SHA512:
267 return gc.pcrSave.sha512[pcrIndex];
268 break;
269 #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 default:
276 FAIL(FATAL_ERROR_INTERNAL);
277 }
278 return NULL; // Never reached.
279 }
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
PcrIsAllocated(UINT32 pcr,TPMI_ALG_HASH hashAlg)292 PcrIsAllocated (
293 UINT32 pcr, // IN: The number of the PCR
294 TPMI_ALG_HASH hashAlg // IN: The PCR algorithm
295 )
296 {
297 UINT32 i;
298 BOOL allocated = FALSE;
299 if(pcr < IMPLEMENTATION_PCR)
300 {
301 for(i = 0; i < gp.pcrAllocated.count; i++)
302 {
303 if(gp.pcrAllocated.pcrSelections[i].hash == hashAlg)
304 {
305 if(((gp.pcrAllocated.pcrSelections[i].pcrSelect[pcr/8])
306 & (1 << (pcr % 8))) != 0)
307 //
308 allocated = TRUE;
309 else
310 allocated = FALSE;
311 break;
312 }
313 }
314 }
315 return allocated;
316 }
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 *
GetPcrPointer(TPM_ALG_ID alg,UINT32 pcrNumber)329 GetPcrPointer (
330 TPM_ALG_ID alg, // IN: algorithm for bank
331 UINT32 pcrNumber // IN: PCR number
332 )
333 {
334 static BYTE *pcr = NULL;
335 if(!PcrIsAllocated(pcrNumber, alg))
336 return NULL;
337 switch(alg)
338 {
339 #ifdef TPM_ALG_SHA1
340 case TPM_ALG_SHA1:
341 pcr = s_pcrs[pcrNumber].sha1Pcr;
342 break;
343 #endif
344 #ifdef TPM_ALG_SHA256
345 case TPM_ALG_SHA256:
346 pcr = s_pcrs[pcrNumber].sha256Pcr;
347 break;
348 #endif
349 #ifdef TPM_ALG_SHA384
350 case TPM_ALG_SHA384:
351 pcr = s_pcrs[pcrNumber].sha384Pcr;
352 break;
353 #endif
354 #ifdef TPM_ALG_SHA512
355 case TPM_ALG_SHA512:
356 pcr = s_pcrs[pcrNumber].sha512Pcr;
357 break;
358 #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 default:
365 pAssert(FALSE);
366 break;
367 }
368 return pcr;
369 //
370 }
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
IsPcrSelected(UINT32 pcr,TPMS_PCR_SELECTION * selection)383 IsPcrSelected (
384 UINT32 pcr, // IN: The number of the PCR
385 TPMS_PCR_SELECTION *selection // IN: The selection structure
386 )
387 {
388 BOOL selected = FALSE;
389 if( pcr < IMPLEMENTATION_PCR
390 && ((selection->pcrSelect[pcr/8]) & (1 << (pcr % 8))) != 0)
391 selected = TRUE;
392 return selected;
393 }
394 //
395 //
396 // FilterPcr()
397 //
398 // This function modifies a PCR selection array based on the implemented PCR.
399 //
400 static void
FilterPcr(TPMS_PCR_SELECTION * selection)401 FilterPcr(
402 TPMS_PCR_SELECTION *selection // IN: input PCR selection
403 )
404 {
405 UINT32 i;
406 TPMS_PCR_SELECTION *allocated = NULL;
407 // If size of select is less than PCR_SELECT_MAX, zero the unspecified PCR
408 for(i = selection->sizeofSelect; i < PCR_SELECT_MAX; i++)
409 selection->pcrSelect[i] = 0;
410 // Find the internal configuration for the bank
411 for(i = 0; i < gp.pcrAllocated.count; i++)
412 {
413 if(gp.pcrAllocated.pcrSelections[i].hash == selection->hash)
414 {
415 allocated = &gp.pcrAllocated.pcrSelections[i];
416 break;
417 }
418 }
419 for (i = 0; i < selection->sizeofSelect; i++)
420 {
421 if(allocated == NULL)
422 {
423 // If the required bank does not exist, clear input selection
424 selection->pcrSelect[i] = 0;
425 }
426 else
427 selection->pcrSelect[i] &= allocated->pcrSelect[i];
428 }
429 return;
430 }
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
PcrDrtm(const TPMI_DH_PCR pcrHandle,const TPMI_ALG_HASH hash,const TPM2B_DIGEST * digest)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 {
445 BYTE *pcrData = GetPcrPointer(hash, pcrHandle);
446 if(pcrData != NULL)
447 {
448 // Rest the PCR to zeros
449 MemorySet(pcrData, 0, digest->t.size);
450 // if the TPM has not started, then set the PCR to 0...04 and then extend
451 if(!TPMIsStarted())
452 {
453 pcrData[digest->t.size - 1] = 4;
454 }
455 // Now, extend the value
456 PCRExtend(pcrHandle, hash, digest->t.size, (BYTE *)digest->t.buffer);
457 }
458 }
459 //
460 //
461 // PCRStartup()
462 //
463 // This function initializes the PCR subsystem at TPM2_Startup().
464 //
465 void
PCRStartup(STARTUP_TYPE type,BYTE locality)466 PCRStartup(
467 STARTUP_TYPE type, // IN: startup type
468 BYTE locality // IN: startup locality
469 )
470 {
471 UINT32 pcr, j;
472 UINT32 saveIndex = 0;
473 g_pcrReConfig = FALSE;
474 if(type != SU_RESUME)
475 {
476 // PCR generation counter is cleared at TPM_RESET and TPM_RESTART
477 gr.pcrCounter = 0;
478 }
479 // Initialize/Restore PCR values
480 for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++)
481 {
482 // On resume, need to know if this PCR had its state saved or not
483 UINT32 stateSaved =
484 (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 if(pcr == HCRTM_PCR && type != SU_RESUME && g_DrtmPreStartup == TRUE)
488 continue;
489 // Iterate each hash algorithm bank
490 for(j = 0; j < gp.pcrAllocated.count; j++)
491 {
492 TPMI_ALG_HASH hash = gp.pcrAllocated.pcrSelections[j].hash;
493 BYTE *pcrData = GetPcrPointer(hash, pcr);
494 UINT16 pcrSize = CryptGetHashDigestSize(hash);
495 if(pcrData != NULL)
496 {
497 // if state was saved
498 if(stateSaved == 1)
499 {
500 // Restore saved PCR value
501 BYTE *pcrSavedData;
502 pcrSavedData = GetSavedPcrPointer(
503 gp.pcrAllocated.pcrSelections[j].hash,
504 saveIndex);
505 MemoryCopy(pcrData, pcrSavedData, pcrSize, pcrSize);
506 }
507 else
508 // PCR was not restored by state save
509 {
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 if((s_initAttributes[pcr].resetLocality & 0x10) != 0)
514 MemorySet(pcrData, 0xFF, pcrSize);
515 else
516 {
517 MemorySet(pcrData, 0, pcrSize);
518 if(pcr == HCRTM_PCR)
519 pcrData[pcrSize-1] = locality;
520 }
521 }
522 }
523 }
524 saveIndex += stateSaved;
525 }
526 // Reset authValues
527 if(type != SU_RESUME)
528 {
529 for(j = 0; j < NUM_AUTHVALUE_PCR_GROUP; j++)
530 {
531 gc.pcrAuthValues.auth[j].t.size = 0;
532 }
533 }
534 }
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
PCRStateSave(TPM_SU type)542 PCRStateSave(
543 TPM_SU type // IN: startup type
544 )
545 {
546 UINT32 pcr, j;
547 UINT32 saveIndex = 0;
548 //
549 // if state save CLEAR, nothing to be done. Return here
550 if(type == TPM_SU_CLEAR) return;
551 // Copy PCR values to the structure that should be saved to NV
552 for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++)
553 {
554 UINT32 stateSaved = (s_initAttributes[pcr].stateSave == SET) ? 1 : 0;
555 // Iterate each hash algorithm bank
556 for(j = 0; j < gp.pcrAllocated.count; j++)
557 {
558 BYTE *pcrData;
559 UINT32 pcrSize;
560 pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[j].hash, pcr);
561 if(pcrData != NULL)
562 {
563 pcrSize
564 = CryptGetHashDigestSize(gp.pcrAllocated.pcrSelections[j].hash);
565 if(stateSaved == 1)
566 {
567 // Restore saved PCR value
568 BYTE *pcrSavedData;
569 pcrSavedData
570 = GetSavedPcrPointer(gp.pcrAllocated.pcrSelections[j].hash,
571 saveIndex);
572 MemoryCopy(pcrSavedData, pcrData, pcrSize, pcrSize);
573 }
574 }
575 }
576 saveIndex += stateSaved;
577 }
578 return;
579 }
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
PCRIsStateSaved(TPMI_DH_PCR handle)593 PCRIsStateSaved(
594 TPMI_DH_PCR handle // IN: PCR handle to be extended
595 )
596 {
597 UINT32 pcr = handle - PCR_FIRST;
598 if(s_initAttributes[pcr].stateSave == SET)
599 return TRUE;
600 else
601 return FALSE;
602 }
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
PCRIsResetAllowed(TPMI_DH_PCR handle)617 PCRIsResetAllowed(
618 TPMI_DH_PCR handle // IN: PCR handle to be extended
619 )
620 {
621 UINT8 commandLocality;
622 UINT8 localityBits = 1;
623 UINT32 pcr = handle - PCR_FIRST;
624 // Check for the locality
625 commandLocality = _plat__LocalityGet();
626 #ifdef DRTM_PCR
627 // For a TPM that does DRTM, Reset is not allowed at locality 4
628 if(commandLocality == 4)
629 return FALSE;
630 #endif
631 localityBits = localityBits << commandLocality;
632 if((localityBits & s_initAttributes[pcr].resetLocality) == 0)
633 return FALSE;
634 else
635 return TRUE;
636 }
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
PCRChanged(TPM_HANDLE pcrHandle)645 PCRChanged(
646 TPM_HANDLE pcrHandle // IN: the handle of the PCR that changed.
647 )
648 {
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 if(!PCRBelongsTCBGroup(pcrHandle))
652 gr.pcrCounter++;
653 }
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
PCRIsExtendAllowed(TPMI_DH_PCR handle)670 PCRIsExtendAllowed(
671 TPMI_DH_PCR handle // IN: PCR handle to be extended
672 )
673 {
674 UINT8 commandLocality;
675 UINT8 localityBits = 1;
676 UINT32 pcr = handle - PCR_FIRST;
677 // Check for the locality
678 commandLocality = _plat__LocalityGet();
679 localityBits = localityBits << commandLocality;
680 if((localityBits & s_initAttributes[pcr].extendLocality) == 0)
681 return FALSE;
682 else
683 return TRUE;
684 }
685 //
686 //
687 // PCRExtend()
688 //
689 // This function is used to extend a PCR in a specific bank.
690 //
691 void
PCRExtend(TPMI_DH_PCR handle,TPMI_ALG_HASH hash,UINT32 size,BYTE * data)692 PCRExtend(
693 TPMI_DH_PCR handle, // IN: PCR handle to be extended
694 TPMI_ALG_HASH hash, // IN: hash algorithm of PCR
695 UINT32 size, // IN: size of data to be extended
696 BYTE *data // IN: data to be extended
697 )
698 {
699 UINT32 pcr = handle - PCR_FIRST;
700 BYTE *pcrData;
701 HASH_STATE hashState;
702 UINT16 pcrSize;
703 pcrData = GetPcrPointer(hash, pcr);
704 // Extend PCR if it is allocated
705 if(pcrData != NULL)
706 {
707 pcrSize = CryptGetHashDigestSize(hash);
708 CryptStartHash(hash, &hashState);
709 CryptUpdateDigest(&hashState, pcrSize, pcrData);
710 CryptUpdateDigest(&hashState, size, data);
711 CryptCompleteHash(&hashState, pcrSize, pcrData);
712 // If PCR does not belong to TCB group, increment PCR counter
713 if(!PCRBelongsTCBGroup(handle))
714 gr.pcrCounter++;
715 }
716 return;
717 }
718 //
719 //
720 //
721 // PCRComputeCurrentDigest()
722 //
723 // This function computes the digest of the selected PCR.
724 // As a side-effect, selection is modified so that only the implemented PCR will have their bits still set.
725 //
726 void
PCRComputeCurrentDigest(TPMI_ALG_HASH hashAlg,TPML_PCR_SELECTION * selection,TPM2B_DIGEST * digest)727 PCRComputeCurrentDigest(
728 TPMI_ALG_HASH hashAlg, // IN: hash algorithm to compute digest
729 TPML_PCR_SELECTION *selection, // IN/OUT: PCR selection (filtered on
730 // output)
731 TPM2B_DIGEST *digest // OUT: digest
732 )
733 {
734 HASH_STATE hashState;
735 TPMS_PCR_SELECTION *select;
736 BYTE *pcrData; // will point to a digest
737 UINT32 pcrSize;
738 UINT32 pcr;
739 UINT32 i;
740 // Initialize the hash
741 digest->t.size = CryptStartHash(hashAlg, &hashState);
742 pAssert(digest->t.size > 0 && digest->t.size < UINT16_MAX);
743 // Iterate through the list of PCR selection structures
744 for(i = 0; i < selection->count; i++)
745 {
746 // Point to the current selection
747 select = &selection->pcrSelections[i]; // Point to the current selection
748 FilterPcr(select); // Clear out the bits for unimplemented PCR
749 // Need the size of each digest
750 pcrSize = CryptGetHashDigestSize(selection->pcrSelections[i].hash);
751 // Iterate through the selection
752 for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++)
753 {
754 if(IsPcrSelected(pcr, select)) // Is this PCR selected
755 {
756 // Get pointer to the digest data for the bank
757 pcrData = GetPcrPointer(selection->pcrSelections[i].hash, pcr);
758 pAssert(pcrData != NULL);
759 CryptUpdateDigest(&hashState, pcrSize, pcrData); // add to digest
760 }
761 }
762 }
763 // Complete hash stack
764 CryptCompleteHash2B(&hashState, &digest->b);
765 return;
766 }
767 //
768 //
769 // PCRRead()
770 //
771 // This function is used to read a list of selected PCR. If the requested PCR number exceeds the maximum
772 // number that can be output, the selection is adjusted to reflect the actual output PCR.
773 //
774 void
PCRRead(TPML_PCR_SELECTION * selection,TPML_DIGEST * digest,UINT32 * pcrCounter)775 PCRRead(
776 TPML_PCR_SELECTION *selection, // IN/OUT: PCR selection (filtered on
777 // output)
778 TPML_DIGEST *digest, // OUT: digest
779 UINT32 *pcrCounter // OUT: the current value of PCR generation
780 // number
781 )
782 {
783 TPMS_PCR_SELECTION *select;
784 BYTE *pcrData; // will point to a digest
785 UINT32 pcr;
786 UINT32 i;
787 digest->count = 0;
788 // Iterate through the list of PCR selection structures
789 for(i = 0; i < selection->count; i++)
790 {
791 // Point to the current selection
792 select = &selection->pcrSelections[i]; // Point to the current selection
793 FilterPcr(select); // Clear out the bits for unimplemented PCR
794 // Iterate through the selection
795 for (pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++)
796 {
797 if(IsPcrSelected(pcr, select)) // Is this PCR selected
798 {
799 // Check if number of digest exceed upper bound
800 if(digest->count > 7)
801 {
802 // Clear rest of the current select bitmap
803 while( pcr < IMPLEMENTATION_PCR
804 // do not round up!
805 && (pcr / 8) < select->sizeofSelect)
806 {
807 // do not round up!
808 select->pcrSelect[pcr/8] &= (BYTE) ~(1 << (pcr % 8));
809 pcr++;
810 }
811 // Exit inner loop
812 break;;
813 }
814 // Need the size of each digest
815 digest->digests[digest->count].t.size =
816 CryptGetHashDigestSize(selection->pcrSelections[i].hash);
817 // Get pointer to the digest data for the bank
818 pcrData = GetPcrPointer(selection->pcrSelections[i].hash, pcr);
819 pAssert(pcrData != NULL);
820 // Add to the data to digest
821 MemoryCopy(digest->digests[digest->count].t.buffer,
822 pcrData,
823 digest->digests[digest->count].t.size,
824 digest->digests[digest->count].t.size);
825 digest->count++;
826 }
827 }
828 // If we exit inner loop because we have exceed the output upper bound
829 if(digest->count > 7 && pcr < IMPLEMENTATION_PCR)
830 {
831 // Clear rest of the selection
832 while(i < selection->count)
833 {
834 MemorySet(selection->pcrSelections[i].pcrSelect, 0,
835 selection->pcrSelections[i].sizeofSelect);
836 i++;
837 }
838 // exit outer loop
839 break;
840 }
841 }
842 *pcrCounter = gr.pcrCounter;
843 return;
844 }
845 //
846 //
847 // PcrWrite()
848 //
849 // This function is used by _TPM_Hash_End() to set a PCR to the computed hash of the H-CRTM event.
850 //
851 void
PcrWrite(TPMI_DH_PCR handle,TPMI_ALG_HASH hash,TPM2B_DIGEST * digest)852 PcrWrite(
853 TPMI_DH_PCR handle, // IN: PCR handle to be extended
854 TPMI_ALG_HASH hash, // IN: hash algorithm of PCR
855 TPM2B_DIGEST *digest // IN: the new value
856 )
857 {
858 UINT32 pcr = handle - PCR_FIRST;
859 BYTE *pcrData;
860 // Copy value to the PCR if it is allocated
861 pcrData = GetPcrPointer(hash, pcr);
862 if(pcrData != NULL)
863 {
864 MemoryCopy(pcrData, digest->t.buffer, digest->t.size, digest->t.size); ;
865 }
866 return;
867 }
868 //
869 //
870 // PCRAllocate()
871 //
872 // This function is used to change the PCR allocation.
873 //
874 // Error Returns Meaning
875 //
876 // TPM_RC_SUCCESS allocate success
877 // TPM_RC_NO_RESULTS allocate failed
878 // TPM_RC_PCR improper allocation
879 //
880 TPM_RC
PCRAllocate(TPML_PCR_SELECTION * allocate,UINT32 * maxPCR,UINT32 * sizeNeeded,UINT32 * sizeAvailable)881 PCRAllocate(
882 TPML_PCR_SELECTION *allocate, // IN: required allocation
883 UINT32 *maxPCR, // OUT: Maximum number of PCR
884 UINT32 *sizeNeeded, // OUT: required space
885 UINT32 *sizeAvailable // OUT: available space
886 )
887 {
888 UINT32 i, j, k;
889 TPML_PCR_SELECTION newAllocate;
890 // Initialize the flags to indicate if HCRTM PCR and DRTM PCR are allocated.
891 BOOL pcrHcrtm = FALSE;
892 BOOL pcrDrtm = FALSE;
893 // Create the expected new PCR allocation based on the existing allocation
894 // and the new input:
895 // 1. if a PCR bank does not appear in the new allocation, the existing
896 // allocation of this PCR bank will be preserved.
897 // 2. if a PCR bank appears multiple times in the new allocation, only the
898 // last one will be in effect.
899 newAllocate = gp.pcrAllocated;
900 for(i = 0; i < allocate->count; i++)
901 {
902 for(j = 0; j < newAllocate.count; j++)
903 {
904 // If hash matches, the new allocation covers the old allocation
905 // for this particular bank.
906 // The assumption is the initial PCR allocation (from manufacture)
907 // has all the supported hash algorithms with an assigned bank
908 // (possibly empty). So there must be a match for any new bank
909 // allocation from the input.
910 if(newAllocate.pcrSelections[j].hash ==
911 allocate->pcrSelections[i].hash)
912 {
913 newAllocate.pcrSelections[j] = allocate->pcrSelections[i];
914 break;
915 }
916 }
917 // The j loop must exit with a match.
918 pAssert(j < newAllocate.count);
919 }
920 // Max PCR in a bank is MIN(implemented PCR, PCR with attributes defined)
921 *maxPCR = sizeof(s_initAttributes) / sizeof(PCR_Attributes);
922 if(*maxPCR > IMPLEMENTATION_PCR)
923 *maxPCR = IMPLEMENTATION_PCR;
924 // Compute required size for allocation
925 *sizeNeeded = 0;
926 for(i = 0; i < newAllocate.count; i++)
927 {
928 UINT32 digestSize
929 = CryptGetHashDigestSize(newAllocate.pcrSelections[i].hash);
930 #if defined(DRTM_PCR)
931 // Make sure that we end up with at least one DRTM PCR
932 # define PCR_DRTM (PCR_FIRST + DRTM_PCR) // for cosmetics
933 pcrDrtm = pcrDrtm || TEST_BIT(PCR_DRTM, newAllocate.pcrSelections[i]);
934 #else // if DRTM PCR is not required, indicate that the allocation is OK
935 pcrDrtm = TRUE;
936 #endif
937 #if defined(HCRTM_PCR)
938 // and one HCRTM PCR (since this is usually PCR 0...)
939 # define PCR_HCRTM (PCR_FIRST + HCRTM_PCR)
940 pcrHcrtm = pcrDrtm || TEST_BIT(PCR_HCRTM, newAllocate.pcrSelections[i]);
941 #else
942 pcrHcrtm = TRUE;
943 #endif
944 for(j = 0; j < newAllocate.pcrSelections[i].sizeofSelect; j++)
945 {
946 BYTE mask = 1;
947 for(k = 0; k < 8; k++)
948 {
949 if((newAllocate.pcrSelections[i].pcrSelect[j] & mask) != 0)
950 *sizeNeeded += digestSize;
951 mask = mask << 1;
952 }
953 }
954 }
955 if(!pcrDrtm || !pcrHcrtm)
956 return TPM_RC_PCR;
957 // In this particular implementation, we always have enough space to
958 // allocate PCR. Different implementation may return a sizeAvailable less
959 // than the sizeNeed.
960 *sizeAvailable = sizeof(s_pcrs);
961 // Save the required allocation to NV. Note that after NV is written, the
962 // PCR allocation in NV is no longer consistent with the RAM data
963 // gp.pcrAllocated. The NV version reflect the allocate after next
964 // TPM_RESET, while the RAM version reflects the current allocation
965 NvWriteReserved(NV_PCR_ALLOCATED, &newAllocate);
966 return TPM_RC_SUCCESS;
967 }
968 //
969 //
970 // PCRSetValue()
971 //
972 // This function is used to set the designated PCR in all banks to an initial value. The initial value is signed
973 // and will be sign extended into the entire PCR.
974 //
975 void
PCRSetValue(TPM_HANDLE handle,INT8 initialValue)976 PCRSetValue(
977 TPM_HANDLE handle, // IN: the handle of the PCR to set
978 INT8 initialValue // IN: the value to set
979 )
980 {
981 int i;
982 UINT32 pcr = handle - PCR_FIRST;
983 TPMI_ALG_HASH hash;
984 UINT16 digestSize;
985 BYTE *pcrData;
986 // Iterate supported PCR bank algorithms to reset
987 for(i = 0; i < HASH_COUNT; i++)
988 {
989 hash = CryptGetHashAlgByIndex(i);
990 // Prevent runaway
991 if(hash == TPM_ALG_NULL)
992 break;
993 // Get a pointer to the data
994 pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr);
995 // If the PCR is allocated
996 if(pcrData != NULL)
997 {
998 // And the size of the digest
999 digestSize = CryptGetHashDigestSize(hash);
1000 // Set the LSO to the input value
1001 pcrData[digestSize - 1] = initialValue;
1002 // Sign extend
1003 if(initialValue >= 0)
1004 MemorySet(pcrData, 0, digestSize - 1);
1005 else
1006 MemorySet(pcrData, -1, digestSize - 1);
1007 }
1008 }
1009 }
1010 //
1011 //
1012 // PCRResetDynamics
1013 //
1014 // This function is used to reset a dynamic PCR to 0. This function is used in DRTM sequence.
1015 //
1016 void
PCRResetDynamics(void)1017 PCRResetDynamics(
1018 void
1019 )
1020 {
1021 UINT32 pcr, i;
1022 // Initialize PCR values
1023 for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++)
1024 {
1025 // Iterate each hash algorithm bank
1026 for(i = 0; i < gp.pcrAllocated.count; i++)
1027 {
1028 BYTE *pcrData;
1029 UINT32 pcrSize;
1030 pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr);
1031 if(pcrData != NULL)
1032 {
1033 pcrSize =
1034 CryptGetHashDigestSize(gp.pcrAllocated.pcrSelections[i].hash);
1035 // Reset PCR
1036 // Any PCR can be reset by locality 4 should be reset to 0
1037 if((s_initAttributes[pcr].resetLocality & 0x10) != 0)
1038 MemorySet(pcrData, 0, pcrSize);
1039 }
1040 }
1041 }
1042 return;
1043 }
1044 //
1045 //
1046 // PCRCapGetAllocation()
1047 //
1048 // This function is used to get the current allocation of PCR banks.
1049 //
1050 // Return Value Meaning
1051 //
1052 // YES: if the return count is 0
1053 // NO: if the return count is not 0
1054 //
1055 TPMI_YES_NO
PCRCapGetAllocation(UINT32 count,TPML_PCR_SELECTION * pcrSelection)1056 PCRCapGetAllocation(
1057 UINT32 count, // IN: count of return
1058 TPML_PCR_SELECTION *pcrSelection // OUT: PCR allocation list
1059 )
1060 {
1061 if(count == 0)
1062 {
1063 pcrSelection->count = 0;
1064 return YES;
1065 }
1066 else
1067 {
1068 *pcrSelection = gp.pcrAllocated;
1069 return NO;
1070 }
1071 }
1072 //
1073 //
1074 // PCRSetSelectBit()
1075 //
1076 // This function sets a bit in a bitmap array.
1077 //
1078 static void
PCRSetSelectBit(UINT32 pcr,BYTE * bitmap)1079 PCRSetSelectBit(
1080 UINT32 pcr, // IN: PCR number
1081 BYTE *bitmap // OUT: bit map to be set
1082 )
1083 {
1084 bitmap[pcr / 8] |= (1 << (pcr % 8));
1085 return;
1086 }
1087 //
1088 //
1089 // PCRGetProperty()
1090 //
1091 // This function returns the selected PCR property.
1092 //
1093 // Return Value Meaning
1094 //
1095 // TRUE the property type is implemented
1096 // FALSE the property type is not implemented
1097 //
1098 static BOOL
PCRGetProperty(TPM_PT_PCR property,TPMS_TAGGED_PCR_SELECT * select)1099 PCRGetProperty(
1100 TPM_PT_PCR property,
1101 TPMS_TAGGED_PCR_SELECT *select
1102 )
1103 {
1104 UINT32 pcr;
1105 UINT32 groupIndex;
1106 select->tag = property;
1107 // Always set the bitmap to be the size of all PCR
1108 select->sizeofSelect = (IMPLEMENTATION_PCR + 7) / 8;
1109 // Initialize bitmap
1110 MemorySet(select->pcrSelect, 0, select->sizeofSelect);
1111 // Collecting properties
1112 for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++)
1113 {
1114 switch(property)
1115 {
1116 case TPM_PT_PCR_SAVE:
1117 if(s_initAttributes[pcr].stateSave == SET)
1118 PCRSetSelectBit(pcr, select->pcrSelect);
1119 break;
1120 case TPM_PT_PCR_EXTEND_L0:
1121 if((s_initAttributes[pcr].extendLocality & 0x01) != 0)
1122 PCRSetSelectBit(pcr, select->pcrSelect);
1123 break;
1124 case TPM_PT_PCR_RESET_L0:
1125 if((s_initAttributes[pcr].resetLocality & 0x01) != 0)
1126 PCRSetSelectBit(pcr, select->pcrSelect);
1127 break;
1128 case TPM_PT_PCR_EXTEND_L1:
1129 if((s_initAttributes[pcr].extendLocality & 0x02) != 0)
1130 PCRSetSelectBit(pcr, select->pcrSelect);
1131 break;
1132 case TPM_PT_PCR_RESET_L1:
1133 if((s_initAttributes[pcr].resetLocality & 0x02) != 0)
1134 PCRSetSelectBit(pcr, select->pcrSelect);
1135 break;
1136 case TPM_PT_PCR_EXTEND_L2:
1137 if((s_initAttributes[pcr].extendLocality & 0x04) != 0)
1138 PCRSetSelectBit(pcr, select->pcrSelect);
1139 //
1140 break;
1141 case TPM_PT_PCR_RESET_L2:
1142 if((s_initAttributes[pcr].resetLocality & 0x04) != 0)
1143 PCRSetSelectBit(pcr, select->pcrSelect);
1144 break;
1145 case TPM_PT_PCR_EXTEND_L3:
1146 if((s_initAttributes[pcr].extendLocality & 0x08) != 0)
1147 PCRSetSelectBit(pcr, select->pcrSelect);
1148 break;
1149 case TPM_PT_PCR_RESET_L3:
1150 if((s_initAttributes[pcr].resetLocality & 0x08) != 0)
1151 PCRSetSelectBit(pcr, select->pcrSelect);
1152 break;
1153 case TPM_PT_PCR_EXTEND_L4:
1154 if((s_initAttributes[pcr].extendLocality & 0x10) != 0)
1155 PCRSetSelectBit(pcr, select->pcrSelect);
1156 break;
1157 case TPM_PT_PCR_RESET_L4:
1158 if((s_initAttributes[pcr].resetLocality & 0x10) != 0)
1159 PCRSetSelectBit(pcr, select->pcrSelect);
1160 break;
1161 case TPM_PT_PCR_DRTM_RESET:
1162 // DRTM reset PCRs are the PCR reset by locality 4
1163 if((s_initAttributes[pcr].resetLocality & 0x10) != 0)
1164 PCRSetSelectBit(pcr, select->pcrSelect);
1165 break;
1166 #if NUM_POLICY_PCR_GROUP > 0
1167 case TPM_PT_PCR_POLICY:
1168 if(PCRBelongsPolicyGroup(pcr + PCR_FIRST, &groupIndex))
1169 PCRSetSelectBit(pcr, select->pcrSelect);
1170 break;
1171 #endif
1172 #if NUM_AUTHVALUE_PCR_GROUP > 0
1173 case TPM_PT_PCR_AUTH:
1174 if(PCRBelongsAuthGroup(pcr + PCR_FIRST, &groupIndex))
1175 PCRSetSelectBit(pcr, select->pcrSelect);
1176 break;
1177 #endif
1178 #if ENABLE_PCR_NO_INCREMENT == YES
1179 case TPM_PT_PCR_NO_INCREMENT:
1180 if(PCRBelongsTCBGroup(pcr + PCR_FIRST))
1181 PCRSetSelectBit(pcr, select->pcrSelect);
1182 break;
1183 #endif
1184 default:
1185 // If property is not supported, stop scanning PCR attributes
1186 // and return.
1187 return FALSE;
1188 break;
1189 }
1190 }
1191 return TRUE;
1192 }
1193 //
1194 //
1195 // PCRCapGetProperties()
1196 //
1197 // This function returns a list of PCR properties starting at property.
1198 //
1199 //
1200 //
1201 //
1202 // Return Value Meaning
1203 //
1204 // YES: if no more property is available
1205 // NO: if there are more properties not reported
1206 //
1207 TPMI_YES_NO
PCRCapGetProperties(TPM_PT_PCR property,UINT32 count,TPML_TAGGED_PCR_PROPERTY * select)1208 PCRCapGetProperties(
1209 TPM_PT_PCR property, // IN: the starting PCR property
1210 UINT32 count, // IN: count of returned propertie
1211 TPML_TAGGED_PCR_PROPERTY *select // OUT: PCR select
1212 )
1213 {
1214 TPMI_YES_NO more = NO;
1215 UINT32 i;
1216 // Initialize output property list
1217 select->count = 0;
1218 // The maximum count of properties we may return is MAX_PCR_PROPERTIES
1219 if(count > MAX_PCR_PROPERTIES) count = MAX_PCR_PROPERTIES;
1220 // TPM_PT_PCR_FIRST is defined as 0 in spec. It ensures that property
1221 // value would never be less than TPM_PT_PCR_FIRST
1222 pAssert(TPM_PT_PCR_FIRST == 0);
1223 // Iterate PCR properties. TPM_PT_PCR_LAST is the index of the last property
1224 // implemented on the TPM.
1225 for(i = property; i <= TPM_PT_PCR_LAST; i++)
1226 {
1227 if(select->count < count)
1228 {
1229 // If we have not filled up the return list, add more properties to it
1230 if(PCRGetProperty(i, &select->pcrProperty[select->count]))
1231 // only increment if the property is implemented
1232 select->count++;
1233 }
1234 else
1235 {
1236 // If the return list is full but we still have properties
1237 // available, report this and stop iterating.
1238 more = YES;
1239 break;
1240 }
1241 }
1242 return more;
1243 }
1244 //
1245 //
1246 // PCRCapGetHandles()
1247 //
1248 // This function is used to get a list of handles of PCR, started from handle. If handle exceeds the maximum
1249 // PCR handle range, an empty list will be returned and the return value will be NO.
1250 //
1251 // Return Value Meaning
1252 //
1253 // YES if there are more handles available
1254 // NO all the available handles has been returned
1255 //
1256 TPMI_YES_NO
PCRCapGetHandles(TPMI_DH_PCR handle,UINT32 count,TPML_HANDLE * handleList)1257 PCRCapGetHandles(
1258 TPMI_DH_PCR handle, // IN: start handle
1259 UINT32 count, // IN: count of returned handle
1260 TPML_HANDLE *handleList // OUT: list of handle
1261 )
1262 {
1263 TPMI_YES_NO more = NO;
1264 UINT32 i;
1265 pAssert(HandleGetType(handle) == TPM_HT_PCR);
1266 // Initialize output handle list
1267 handleList->count = 0;
1268 // The maximum count of handles we may return is MAX_CAP_HANDLES
1269 if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
1270 // Iterate PCR handle range
1271 for(i = handle & HR_HANDLE_MASK; i <= PCR_LAST; i++)
1272 {
1273 if(handleList->count < count)
1274 {
1275 // If we have not filled up the return list, add this PCR
1276 // handle to it
1277 handleList->handle[handleList->count] = i + PCR_FIRST;
1278 handleList->count++;
1279 }
1280 else
1281 {
1282 // If the return list is full but we still have PCR handle
1283 // available, report this and stop iterating
1284 more = YES;
1285 break;
1286 }
1287 }
1288 return more;
1289 }
1290