blob: cdc6c0c8d3d9374c6b9adc24073e33f60f62d92a [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
Vadim Bendebury0820d9a2015-10-13 13:23:02 -070026 {0, 0x1C, 0x0E}, // PCR 20, Locality 1
27 {0, 0x1C, 0x04}, // PCR 21, Dynamic OS
28 {0, 0x1C, 0x04}, // PCR 22, Dynamic OS
Vadim Bendebury56797522015-05-20 10:32:25 -070029 {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{
Vadim Bendebury0820d9a2015-10-13 13:23:02 -070057 // 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;
Vadim Bendebury56797522015-05-20 10:32:25 -070061}
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//
79BOOL
80PCRBelongsPolicyGroup(
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{
Vadim Bendebury0820d9a2015-10-13 13:23:02 -070088 // 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;
Vadim Bendebury56797522015-05-20 10:32:25 -070092}
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//
104static BOOL
105PCRBelongsTCBGroup(
106 TPMI_DH_PCR handle // IN: handle of PCR
107 )
108{
109#if ENABLE_PCR_NO_INCREMENT == YES
Vadim Bendebury0820d9a2015-10-13 13:23:02 -0700110 // 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;
Vadim Bendebury56797522015-05-20 10:32:25 -0700116#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//
133BOOL
134PCRPolicyIsAvailable(
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//
148void
149PCRGetAuthValue(
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//
172TPMI_ALG_HASH
173PCRGetAuthPolicy(
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//
197void
198PCRSimStart(
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//
242static BYTE *
243GetSavedPcrPointer (
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 }
Vadim Bendebury761fbc62015-06-01 11:09:02 -0700278 return NULL; // Never reached.
Vadim Bendebury56797522015-05-20 10:32:25 -0700279}
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//
291BOOL
292PcrIsAllocated (
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//
328static BYTE *
329GetPcrPointer (
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//
382static BOOL
383IsPcrSelected (
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//
400static void
401FilterPcr(
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//
437void
438PcrDrtm(
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//
465void
466PCRStartup(
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//
541void
542PCRStateSave(
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//
592BOOL
593PCRIsStateSaved(
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//
616BOOL
617PCRIsResetAllowed(
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//
644void
645PCRChanged(
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//
669BOOL
670PCRIsExtendAllowed(
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//
691void
692PCRExtend(
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//
726void
727PCRComputeCurrentDigest(
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//
774void
775PCRRead(
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//
851void
852PcrWrite(
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//
880TPM_RC
881PCRAllocate(
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//
975void
976PCRSetValue(
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//
1016void
1017PCRResetDynamics(
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//
1055TPMI_YES_NO
1056PCRCapGetAllocation(
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//
1078static void
1079PCRSetSelectBit(
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//
1098static BOOL
1099PCRGetProperty(
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//
1207TPMI_YES_NO
1208PCRCapGetProperties(
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//
1256TPMI_YES_NO
1257PCRCapGetHandles(
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}