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