Coverage Report

Created: 2025-08-03 07:04

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