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