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