Coverage Report

Created: 2023-06-07 06:46

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