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 }