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// 15static 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// 47BOOL 48PCRBelongsAuthGroup( 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{ 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 return FALSE; 61} 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// 79BOOL 80PCRBelongsPolicyGroup( 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{ 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 return FALSE; 92} 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// 104static BOOL 105PCRBelongsTCBGroup( 106 TPMI_DH_PCR handle // IN: handle of PCR 107 ) 108{ 109#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 if(handle == 16 || (handle >= 21 && handle <= 23)) 115 return TRUE; 116#endif 117 return FALSE; 118} 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// 133BOOL 134PCRPolicyIsAvailable( 135 TPMI_DH_PCR handle // IN: PCR handle 136 ) 137{ 138 UINT32 groupIndex; 139 return PCRBelongsPolicyGroup(handle, &groupIndex); 140} 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// 148void 149PCRGetAuthValue( 150 TPMI_DH_PCR handle, // IN: PCR handle 151 TPM2B_AUTH *auth // OUT: authValue of PCR 152 ) 153{ 154 UINT32 groupIndex; 155 if(PCRBelongsAuthGroup(handle, &groupIndex)) 156 { 157 *auth = gc.pcrAuthValues.auth[groupIndex]; 158 } 159 else 160 { 161 auth->t.size = 0; 162 } 163 return; 164} 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// 172TPMI_ALG_HASH 173PCRGetAuthPolicy( 174 TPMI_DH_PCR handle, // IN: PCR handle 175 TPM2B_DIGEST *policy // OUT: policy of PCR 176 ) 177{ 178 UINT32 groupIndex; 179 if(PCRBelongsPolicyGroup(handle, &groupIndex)) 180 { 181 *policy = gp.pcrPolicies.policy[groupIndex]; 182 return gp.pcrPolicies.hashAlg[groupIndex]; 183 } 184 else 185 { 186 policy->t.size = 0; 187 return TPM_ALG_NULL; 188 } 189} 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// 197void 198PCRSimStart( 199 void 200 ) 201{ 202 UINT32 i; 203 for(i = 0; i < NUM_POLICY_PCR_GROUP; i++) 204 { 205 gp.pcrPolicies.hashAlg[i] = TPM_ALG_NULL; 206 gp.pcrPolicies.policy[i].t.size = 0; 207 } 208 for(i = 0; i < NUM_AUTHVALUE_PCR_GROUP; i++) 209 { 210 gc.pcrAuthValues.auth[i].t.size = 0; 211 } 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 for(gp.pcrAllocated.count = 0; gp.pcrAllocated.count < HASH_COUNT; 216 gp.pcrAllocated.count++) 217 { 218 gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].hash 219 = CryptGetHashAlgByIndex(gp.pcrAllocated.count); 220 gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].sizeofSelect 221 = PCR_SELECT_MAX; 222 for(i = 0; i < PCR_SELECT_MAX; i++) 223 gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].pcrSelect[i] 224 = 0xFF; 225 } 226 // Store the initial configuration to NV 227 NvWriteReserved(NV_PCR_POLICIES, &gp.pcrPolicies); 228 NvWriteReserved(NV_PCR_ALLOCATED, &gp.pcrAllocated); 229 return; 230} 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// 242static BYTE * 243GetSavedPcrPointer ( 244 TPM_ALG_ID alg, // IN: algorithm for bank 245 UINT32 pcrIndex // IN: PCR index in PCR_SAVE 246 ) 247{ 248 switch(alg) 249 { 250#ifdef TPM_ALG_SHA1 251 case TPM_ALG_SHA1: 252 return gc.pcrSave.sha1[pcrIndex]; 253 break; 254#endif 255#ifdef TPM_ALG_SHA256 256 case TPM_ALG_SHA256: 257 return gc.pcrSave.sha256[pcrIndex]; 258 break; 259#endif 260#ifdef TPM_ALG_SHA384 261 case TPM_ALG_SHA384: 262 return gc.pcrSave.sha384[pcrIndex]; 263 break; 264#endif 265#ifdef TPM_ALG_SHA512 266 case TPM_ALG_SHA512: 267 return gc.pcrSave.sha512[pcrIndex]; 268 break; 269#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 default: 276 FAIL(FATAL_ERROR_INTERNAL); 277 } 278 return NULL; // Never reached. 279} 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// 291BOOL 292PcrIsAllocated ( 293 UINT32 pcr, // IN: The number of the PCR 294 TPMI_ALG_HASH hashAlg // IN: The PCR algorithm 295 ) 296{ 297 UINT32 i; 298 BOOL allocated = FALSE; 299 if(pcr < IMPLEMENTATION_PCR) 300 { 301 for(i = 0; i < gp.pcrAllocated.count; i++) 302 { 303 if(gp.pcrAllocated.pcrSelections[i].hash == hashAlg) 304 { 305 if(((gp.pcrAllocated.pcrSelections[i].pcrSelect[pcr/8]) 306 & (1 << (pcr % 8))) != 0) 307// 308 allocated = TRUE; 309 else 310 allocated = FALSE; 311 break; 312 } 313 } 314 } 315 return allocated; 316} 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// 328static BYTE * 329GetPcrPointer ( 330 TPM_ALG_ID alg, // IN: algorithm for bank 331 UINT32 pcrNumber // IN: PCR number 332 ) 333{ 334 static BYTE *pcr = NULL; 335 if(!PcrIsAllocated(pcrNumber, alg)) 336 return NULL; 337 switch(alg) 338 { 339#ifdef TPM_ALG_SHA1 340 case TPM_ALG_SHA1: 341 pcr = s_pcrs[pcrNumber].sha1Pcr; 342 break; 343#endif 344#ifdef TPM_ALG_SHA256 345 case TPM_ALG_SHA256: 346 pcr = s_pcrs[pcrNumber].sha256Pcr; 347 break; 348#endif 349#ifdef TPM_ALG_SHA384 350 case TPM_ALG_SHA384: 351 pcr = s_pcrs[pcrNumber].sha384Pcr; 352 break; 353#endif 354#ifdef TPM_ALG_SHA512 355 case TPM_ALG_SHA512: 356 pcr = s_pcrs[pcrNumber].sha512Pcr; 357 break; 358#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 default: 365 pAssert(FALSE); 366 break; 367 } 368 return pcr; 369// 370} 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// 382static BOOL 383IsPcrSelected ( 384 UINT32 pcr, // IN: The number of the PCR 385 TPMS_PCR_SELECTION *selection // IN: The selection structure 386 ) 387{ 388 BOOL selected = FALSE; 389 if( pcr < IMPLEMENTATION_PCR 390 && ((selection->pcrSelect[pcr/8]) & (1 << (pcr % 8))) != 0) 391 selected = TRUE; 392 return selected; 393} 394// 395// 396// FilterPcr() 397// 398// This function modifies a PCR selection array based on the implemented PCR. 399// 400static void 401FilterPcr( 402 TPMS_PCR_SELECTION *selection // IN: input PCR selection 403 ) 404{ 405 UINT32 i; 406 TPMS_PCR_SELECTION *allocated = NULL; 407 // If size of select is less than PCR_SELECT_MAX, zero the unspecified PCR 408 for(i = selection->sizeofSelect; i < PCR_SELECT_MAX; i++) 409 selection->pcrSelect[i] = 0; 410 // Find the internal configuration for the bank 411 for(i = 0; i < gp.pcrAllocated.count; i++) 412 { 413 if(gp.pcrAllocated.pcrSelections[i].hash == selection->hash) 414 { 415 allocated = &gp.pcrAllocated.pcrSelections[i]; 416 break; 417 } 418 } 419 for (i = 0; i < selection->sizeofSelect; i++) 420 { 421 if(allocated == NULL) 422 { 423 // If the required bank does not exist, clear input selection 424 selection->pcrSelect[i] = 0; 425 } 426 else 427 selection->pcrSelect[i] &= allocated->pcrSelect[i]; 428 } 429 return; 430} 431// 432// 433// PcrDrtm() 434// 435// This function does the DRTM and H-CRTM processing it is called from _TPM_Hash_End(). 436// 437void 438PcrDrtm( 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{ 445 BYTE *pcrData = GetPcrPointer(hash, pcrHandle); 446 if(pcrData != NULL) 447 { 448 // Rest the PCR to zeros 449 MemorySet(pcrData, 0, digest->t.size); 450 // if the TPM has not started, then set the PCR to 0...04 and then extend 451 if(!TPMIsStarted()) 452 { 453 pcrData[digest->t.size - 1] = 4; 454 } 455 // Now, extend the value 456 PCRExtend(pcrHandle, hash, digest->t.size, (BYTE *)digest->t.buffer); 457 } 458} 459// 460// 461// PCRStartup() 462// 463// This function initializes the PCR subsystem at TPM2_Startup(). 464// 465void 466PCRStartup( 467 STARTUP_TYPE type, // IN: startup type 468 BYTE locality // IN: startup locality 469 ) 470{ 471 UINT32 pcr, j; 472 UINT32 saveIndex = 0; 473 g_pcrReConfig = FALSE; 474 if(type != SU_RESUME) 475 { 476 // PCR generation counter is cleared at TPM_RESET and TPM_RESTART 477 gr.pcrCounter = 0; 478 } 479 // Initialize/Restore PCR values 480 for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) 481 { 482 // On resume, need to know if this PCR had its state saved or not 483 UINT32 stateSaved = 484 (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 if(pcr == HCRTM_PCR && type != SU_RESUME && g_DrtmPreStartup == TRUE) 488 continue; 489 // Iterate each hash algorithm bank 490 for(j = 0; j < gp.pcrAllocated.count; j++) 491 { 492 TPMI_ALG_HASH hash = gp.pcrAllocated.pcrSelections[j].hash; 493 BYTE *pcrData = GetPcrPointer(hash, pcr); 494 UINT16 pcrSize = CryptGetHashDigestSize(hash); 495 if(pcrData != NULL) 496 { 497 // if state was saved 498 if(stateSaved == 1) 499 { 500 // Restore saved PCR value 501 BYTE *pcrSavedData; 502 pcrSavedData = GetSavedPcrPointer( 503 gp.pcrAllocated.pcrSelections[j].hash, 504 saveIndex); 505 MemoryCopy(pcrData, pcrSavedData, pcrSize, pcrSize); 506 } 507 else 508 // PCR was not restored by state save 509 { 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 if((s_initAttributes[pcr].resetLocality & 0x10) != 0) 514 MemorySet(pcrData, 0xFF, pcrSize); 515 else 516 { 517 MemorySet(pcrData, 0, pcrSize); 518 if(pcr == HCRTM_PCR) 519 pcrData[pcrSize-1] = locality; 520 } 521 } 522 } 523 } 524 saveIndex += stateSaved; 525 } 526 // Reset authValues 527 if(type != SU_RESUME) 528 { 529 for(j = 0; j < NUM_AUTHVALUE_PCR_GROUP; j++) 530 { 531 gc.pcrAuthValues.auth[j].t.size = 0; 532 } 533 } 534} 535// 536// 537// PCRStateSave() 538// 539// This function is used to save the PCR values that will be restored on TPM Resume. 540// 541void 542PCRStateSave( 543 TPM_SU type // IN: startup type 544 ) 545{ 546 UINT32 pcr, j; 547 UINT32 saveIndex = 0; 548// 549 // if state save CLEAR, nothing to be done. Return here 550 if(type == TPM_SU_CLEAR) return; 551 // Copy PCR values to the structure that should be saved to NV 552 for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) 553 { 554 UINT32 stateSaved = (s_initAttributes[pcr].stateSave == SET) ? 1 : 0; 555 // Iterate each hash algorithm bank 556 for(j = 0; j < gp.pcrAllocated.count; j++) 557 { 558 BYTE *pcrData; 559 UINT32 pcrSize; 560 pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[j].hash, pcr); 561 if(pcrData != NULL) 562 { 563 pcrSize 564 = CryptGetHashDigestSize(gp.pcrAllocated.pcrSelections[j].hash); 565 if(stateSaved == 1) 566 { 567 // Restore saved PCR value 568 BYTE *pcrSavedData; 569 pcrSavedData 570 = GetSavedPcrPointer(gp.pcrAllocated.pcrSelections[j].hash, 571 saveIndex); 572 MemoryCopy(pcrSavedData, pcrData, pcrSize, pcrSize); 573 } 574 } 575 } 576 saveIndex += stateSaved; 577 } 578 return; 579} 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// 592BOOL 593PCRIsStateSaved( 594 TPMI_DH_PCR handle // IN: PCR handle to be extended 595 ) 596{ 597 UINT32 pcr = handle - PCR_FIRST; 598 if(s_initAttributes[pcr].stateSave == SET) 599 return TRUE; 600 else 601 return FALSE; 602} 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// 616BOOL 617PCRIsResetAllowed( 618 TPMI_DH_PCR handle // IN: PCR handle to be extended 619 ) 620{ 621 UINT8 commandLocality; 622 UINT8 localityBits = 1; 623 UINT32 pcr = handle - PCR_FIRST; 624 // Check for the locality 625 commandLocality = _plat__LocalityGet(); 626#ifdef DRTM_PCR 627 // For a TPM that does DRTM, Reset is not allowed at locality 4 628 if(commandLocality == 4) 629 return FALSE; 630#endif 631 localityBits = localityBits << commandLocality; 632 if((localityBits & s_initAttributes[pcr].resetLocality) == 0) 633 return FALSE; 634 else 635 return TRUE; 636} 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// 644void 645PCRChanged( 646 TPM_HANDLE pcrHandle // IN: the handle of the PCR that changed. 647 ) 648{ 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 if(!PCRBelongsTCBGroup(pcrHandle)) 652 gr.pcrCounter++; 653} 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// 669BOOL 670PCRIsExtendAllowed( 671 TPMI_DH_PCR handle // IN: PCR handle to be extended 672 ) 673{ 674 UINT8 commandLocality; 675 UINT8 localityBits = 1; 676 UINT32 pcr = handle - PCR_FIRST; 677 // Check for the locality 678 commandLocality = _plat__LocalityGet(); 679 localityBits = localityBits << commandLocality; 680 if((localityBits & s_initAttributes[pcr].extendLocality) == 0) 681 return FALSE; 682 else 683 return TRUE; 684} 685// 686// 687// PCRExtend() 688// 689// This function is used to extend a PCR in a specific bank. 690// 691void 692PCRExtend( 693 TPMI_DH_PCR handle, // IN: PCR handle to be extended 694 TPMI_ALG_HASH hash, // IN: hash algorithm of PCR 695 UINT32 size, // IN: size of data to be extended 696 BYTE *data // IN: data to be extended 697 ) 698{ 699 UINT32 pcr = handle - PCR_FIRST; 700 BYTE *pcrData; 701 HASH_STATE hashState; 702 UINT16 pcrSize; 703 pcrData = GetPcrPointer(hash, pcr); 704 // Extend PCR if it is allocated 705 if(pcrData != NULL) 706 { 707 pcrSize = CryptGetHashDigestSize(hash); 708 CryptStartHash(hash, &hashState); 709 CryptUpdateDigest(&hashState, pcrSize, pcrData); 710 CryptUpdateDigest(&hashState, size, data); 711 CryptCompleteHash(&hashState, pcrSize, pcrData); 712 // If PCR does not belong to TCB group, increment PCR counter 713 if(!PCRBelongsTCBGroup(handle)) 714 gr.pcrCounter++; 715 } 716 return; 717} 718// 719// 720// 721// PCRComputeCurrentDigest() 722// 723// This function computes the digest of the selected PCR. 724// As a side-effect, selection is modified so that only the implemented PCR will have their bits still set. 725// 726void 727PCRComputeCurrentDigest( 728 TPMI_ALG_HASH hashAlg, // IN: hash algorithm to compute digest 729 TPML_PCR_SELECTION *selection, // IN/OUT: PCR selection (filtered on 730 // output) 731 TPM2B_DIGEST *digest // OUT: digest 732 ) 733{ 734 HASH_STATE hashState; 735 TPMS_PCR_SELECTION *select; 736 BYTE *pcrData; // will point to a digest 737 UINT32 pcrSize; 738 UINT32 pcr; 739 UINT32 i; 740 // Initialize the hash 741 digest->t.size = CryptStartHash(hashAlg, &hashState); 742 pAssert(digest->t.size > 0 && digest->t.size < UINT16_MAX); 743 // Iterate through the list of PCR selection structures 744 for(i = 0; i < selection->count; i++) 745 { 746 // Point to the current selection 747 select = &selection->pcrSelections[i]; // Point to the current selection 748 FilterPcr(select); // Clear out the bits for unimplemented PCR 749 // Need the size of each digest 750 pcrSize = CryptGetHashDigestSize(selection->pcrSelections[i].hash); 751 // Iterate through the selection 752 for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) 753 { 754 if(IsPcrSelected(pcr, select)) // Is this PCR selected 755 { 756 // Get pointer to the digest data for the bank 757 pcrData = GetPcrPointer(selection->pcrSelections[i].hash, pcr); 758 pAssert(pcrData != NULL); 759 CryptUpdateDigest(&hashState, pcrSize, pcrData); // add to digest 760 } 761 } 762 } 763 // Complete hash stack 764 CryptCompleteHash2B(&hashState, &digest->b); 765 return; 766} 767// 768// 769// PCRRead() 770// 771// This function is used to read a list of selected PCR. If the requested PCR number exceeds the maximum 772// number that can be output, the selection is adjusted to reflect the actual output PCR. 773// 774void 775PCRRead( 776 TPML_PCR_SELECTION *selection, // IN/OUT: PCR selection (filtered on 777 // output) 778 TPML_DIGEST *digest, // OUT: digest 779 UINT32 *pcrCounter // OUT: the current value of PCR generation 780 // number 781 ) 782{ 783 TPMS_PCR_SELECTION *select; 784 BYTE *pcrData; // will point to a digest 785 UINT32 pcr; 786 UINT32 i; 787 digest->count = 0; 788 // Iterate through the list of PCR selection structures 789 for(i = 0; i < selection->count; i++) 790 { 791 // Point to the current selection 792 select = &selection->pcrSelections[i]; // Point to the current selection 793 FilterPcr(select); // Clear out the bits for unimplemented PCR 794 // Iterate through the selection 795 for (pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) 796 { 797 if(IsPcrSelected(pcr, select)) // Is this PCR selected 798 { 799 // Check if number of digest exceed upper bound 800 if(digest->count > 7) 801 { 802 // Clear rest of the current select bitmap 803 while( pcr < IMPLEMENTATION_PCR 804 // do not round up! 805 && (pcr / 8) < select->sizeofSelect) 806 { 807 // do not round up! 808 select->pcrSelect[pcr/8] &= (BYTE) ~(1 << (pcr % 8)); 809 pcr++; 810 } 811 // Exit inner loop 812 break;; 813 } 814 // Need the size of each digest 815 digest->digests[digest->count].t.size = 816 CryptGetHashDigestSize(selection->pcrSelections[i].hash); 817 // Get pointer to the digest data for the bank 818 pcrData = GetPcrPointer(selection->pcrSelections[i].hash, pcr); 819 pAssert(pcrData != NULL); 820 // Add to the data to digest 821 MemoryCopy(digest->digests[digest->count].t.buffer, 822 pcrData, 823 digest->digests[digest->count].t.size, 824 digest->digests[digest->count].t.size); 825 digest->count++; 826 } 827 } 828 // If we exit inner loop because we have exceed the output upper bound 829 if(digest->count > 7 && pcr < IMPLEMENTATION_PCR) 830 { 831 // Clear rest of the selection 832 while(i < selection->count) 833 { 834 MemorySet(selection->pcrSelections[i].pcrSelect, 0, 835 selection->pcrSelections[i].sizeofSelect); 836 i++; 837 } 838 // exit outer loop 839 break; 840 } 841 } 842 *pcrCounter = gr.pcrCounter; 843 return; 844} 845// 846// 847// PcrWrite() 848// 849// This function is used by _TPM_Hash_End() to set a PCR to the computed hash of the H-CRTM event. 850// 851void 852PcrWrite( 853 TPMI_DH_PCR handle, // IN: PCR handle to be extended 854 TPMI_ALG_HASH hash, // IN: hash algorithm of PCR 855 TPM2B_DIGEST *digest // IN: the new value 856 ) 857{ 858 UINT32 pcr = handle - PCR_FIRST; 859 BYTE *pcrData; 860 // Copy value to the PCR if it is allocated 861 pcrData = GetPcrPointer(hash, pcr); 862 if(pcrData != NULL) 863 { 864 MemoryCopy(pcrData, digest->t.buffer, digest->t.size, digest->t.size); ; 865 } 866 return; 867} 868// 869// 870// PCRAllocate() 871// 872// This function is used to change the PCR allocation. 873// 874// Error Returns Meaning 875// 876// TPM_RC_SUCCESS allocate success 877// TPM_RC_NO_RESULTS allocate failed 878// TPM_RC_PCR improper allocation 879// 880TPM_RC 881PCRAllocate( 882 TPML_PCR_SELECTION *allocate, // IN: required allocation 883 UINT32 *maxPCR, // OUT: Maximum number of PCR 884 UINT32 *sizeNeeded, // OUT: required space 885 UINT32 *sizeAvailable // OUT: available space 886 ) 887{ 888 UINT32 i, j, k; 889 TPML_PCR_SELECTION newAllocate; 890 // Initialize the flags to indicate if HCRTM PCR and DRTM PCR are allocated. 891 BOOL pcrHcrtm = FALSE; 892 BOOL pcrDrtm = FALSE; 893 // Create the expected new PCR allocation based on the existing allocation 894 // and the new input: 895 // 1. if a PCR bank does not appear in the new allocation, the existing 896 // allocation of this PCR bank will be preserved. 897 // 2. if a PCR bank appears multiple times in the new allocation, only the 898 // last one will be in effect. 899 newAllocate = gp.pcrAllocated; 900 for(i = 0; i < allocate->count; i++) 901 { 902 for(j = 0; j < newAllocate.count; j++) 903 { 904 // If hash matches, the new allocation covers the old allocation 905 // for this particular bank. 906 // The assumption is the initial PCR allocation (from manufacture) 907 // has all the supported hash algorithms with an assigned bank 908 // (possibly empty). So there must be a match for any new bank 909 // allocation from the input. 910 if(newAllocate.pcrSelections[j].hash == 911 allocate->pcrSelections[i].hash) 912 { 913 newAllocate.pcrSelections[j] = allocate->pcrSelections[i]; 914 break; 915 } 916 } 917 // The j loop must exit with a match. 918 pAssert(j < newAllocate.count); 919 } 920 // Max PCR in a bank is MIN(implemented PCR, PCR with attributes defined) 921 *maxPCR = sizeof(s_initAttributes) / sizeof(PCR_Attributes); 922 if(*maxPCR > IMPLEMENTATION_PCR) 923 *maxPCR = IMPLEMENTATION_PCR; 924 // Compute required size for allocation 925 *sizeNeeded = 0; 926 for(i = 0; i < newAllocate.count; i++) 927 { 928 UINT32 digestSize 929 = CryptGetHashDigestSize(newAllocate.pcrSelections[i].hash); 930#if defined(DRTM_PCR) 931 // Make sure that we end up with at least one DRTM PCR 932# define PCR_DRTM (PCR_FIRST + DRTM_PCR) // for cosmetics 933 pcrDrtm = pcrDrtm || TEST_BIT(PCR_DRTM, newAllocate.pcrSelections[i]); 934#else // if DRTM PCR is not required, indicate that the allocation is OK 935 pcrDrtm = TRUE; 936#endif 937#if defined(HCRTM_PCR) 938 // and one HCRTM PCR (since this is usually PCR 0...) 939# define PCR_HCRTM (PCR_FIRST + HCRTM_PCR) 940 pcrHcrtm = pcrDrtm || TEST_BIT(PCR_HCRTM, newAllocate.pcrSelections[i]); 941#else 942 pcrHcrtm = TRUE; 943#endif 944 for(j = 0; j < newAllocate.pcrSelections[i].sizeofSelect; j++) 945 { 946 BYTE mask = 1; 947 for(k = 0; k < 8; k++) 948 { 949 if((newAllocate.pcrSelections[i].pcrSelect[j] & mask) != 0) 950 *sizeNeeded += digestSize; 951 mask = mask << 1; 952 } 953 } 954 } 955 if(!pcrDrtm || !pcrHcrtm) 956 return TPM_RC_PCR; 957 // In this particular implementation, we always have enough space to 958 // allocate PCR. Different implementation may return a sizeAvailable less 959 // than the sizeNeed. 960 *sizeAvailable = sizeof(s_pcrs); 961 // Save the required allocation to NV. Note that after NV is written, the 962 // PCR allocation in NV is no longer consistent with the RAM data 963 // gp.pcrAllocated. The NV version reflect the allocate after next 964 // TPM_RESET, while the RAM version reflects the current allocation 965 NvWriteReserved(NV_PCR_ALLOCATED, &newAllocate); 966 return TPM_RC_SUCCESS; 967} 968// 969// 970// PCRSetValue() 971// 972// This function is used to set the designated PCR in all banks to an initial value. The initial value is signed 973// and will be sign extended into the entire PCR. 974// 975void 976PCRSetValue( 977 TPM_HANDLE handle, // IN: the handle of the PCR to set 978 INT8 initialValue // IN: the value to set 979 ) 980{ 981 int i; 982 UINT32 pcr = handle - PCR_FIRST; 983 TPMI_ALG_HASH hash; 984 UINT16 digestSize; 985 BYTE *pcrData; 986 // Iterate supported PCR bank algorithms to reset 987 for(i = 0; i < HASH_COUNT; i++) 988 { 989 hash = CryptGetHashAlgByIndex(i); 990 // Prevent runaway 991 if(hash == TPM_ALG_NULL) 992 break; 993 // Get a pointer to the data 994 pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr); 995 // If the PCR is allocated 996 if(pcrData != NULL) 997 { 998 // And the size of the digest 999 digestSize = CryptGetHashDigestSize(hash); 1000 // Set the LSO to the input value 1001 pcrData[digestSize - 1] = initialValue; 1002 // Sign extend 1003 if(initialValue >= 0) 1004 MemorySet(pcrData, 0, digestSize - 1); 1005 else 1006 MemorySet(pcrData, -1, digestSize - 1); 1007 } 1008 } 1009} 1010// 1011// 1012// PCRResetDynamics 1013// 1014// This function is used to reset a dynamic PCR to 0. This function is used in DRTM sequence. 1015// 1016void 1017PCRResetDynamics( 1018 void 1019 ) 1020{ 1021 UINT32 pcr, i; 1022 // Initialize PCR values 1023 for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) 1024 { 1025 // Iterate each hash algorithm bank 1026 for(i = 0; i < gp.pcrAllocated.count; i++) 1027 { 1028 BYTE *pcrData; 1029 UINT32 pcrSize; 1030 pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr); 1031 if(pcrData != NULL) 1032 { 1033 pcrSize = 1034 CryptGetHashDigestSize(gp.pcrAllocated.pcrSelections[i].hash); 1035 // Reset PCR 1036 // Any PCR can be reset by locality 4 should be reset to 0 1037 if((s_initAttributes[pcr].resetLocality & 0x10) != 0) 1038 MemorySet(pcrData, 0, pcrSize); 1039 } 1040 } 1041 } 1042 return; 1043} 1044// 1045// 1046// PCRCapGetAllocation() 1047// 1048// This function is used to get the current allocation of PCR banks. 1049// 1050// Return Value Meaning 1051// 1052// YES: if the return count is 0 1053// NO: if the return count is not 0 1054// 1055TPMI_YES_NO 1056PCRCapGetAllocation( 1057 UINT32 count, // IN: count of return 1058 TPML_PCR_SELECTION *pcrSelection // OUT: PCR allocation list 1059 ) 1060{ 1061 if(count == 0) 1062 { 1063 pcrSelection->count = 0; 1064 return YES; 1065 } 1066 else 1067 { 1068 *pcrSelection = gp.pcrAllocated; 1069 return NO; 1070 } 1071} 1072// 1073// 1074// PCRSetSelectBit() 1075// 1076// This function sets a bit in a bitmap array. 1077// 1078static void 1079PCRSetSelectBit( 1080 UINT32 pcr, // IN: PCR number 1081 BYTE *bitmap // OUT: bit map to be set 1082 ) 1083{ 1084 bitmap[pcr / 8] |= (1 << (pcr % 8)); 1085 return; 1086} 1087// 1088// 1089// PCRGetProperty() 1090// 1091// This function returns the selected PCR property. 1092// 1093// Return Value Meaning 1094// 1095// TRUE the property type is implemented 1096// FALSE the property type is not implemented 1097// 1098static BOOL 1099PCRGetProperty( 1100 TPM_PT_PCR property, 1101 TPMS_TAGGED_PCR_SELECT *select 1102 ) 1103{ 1104 UINT32 pcr; 1105 UINT32 groupIndex; 1106 select->tag = property; 1107 // Always set the bitmap to be the size of all PCR 1108 select->sizeofSelect = (IMPLEMENTATION_PCR + 7) / 8; 1109 // Initialize bitmap 1110 MemorySet(select->pcrSelect, 0, select->sizeofSelect); 1111 // Collecting properties 1112 for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) 1113 { 1114 switch(property) 1115 { 1116 case TPM_PT_PCR_SAVE: 1117 if(s_initAttributes[pcr].stateSave == SET) 1118 PCRSetSelectBit(pcr, select->pcrSelect); 1119 break; 1120 case TPM_PT_PCR_EXTEND_L0: 1121 if((s_initAttributes[pcr].extendLocality & 0x01) != 0) 1122 PCRSetSelectBit(pcr, select->pcrSelect); 1123 break; 1124 case TPM_PT_PCR_RESET_L0: 1125 if((s_initAttributes[pcr].resetLocality & 0x01) != 0) 1126 PCRSetSelectBit(pcr, select->pcrSelect); 1127 break; 1128 case TPM_PT_PCR_EXTEND_L1: 1129 if((s_initAttributes[pcr].extendLocality & 0x02) != 0) 1130 PCRSetSelectBit(pcr, select->pcrSelect); 1131 break; 1132 case TPM_PT_PCR_RESET_L1: 1133 if((s_initAttributes[pcr].resetLocality & 0x02) != 0) 1134 PCRSetSelectBit(pcr, select->pcrSelect); 1135 break; 1136 case TPM_PT_PCR_EXTEND_L2: 1137 if((s_initAttributes[pcr].extendLocality & 0x04) != 0) 1138 PCRSetSelectBit(pcr, select->pcrSelect); 1139// 1140 break; 1141 case TPM_PT_PCR_RESET_L2: 1142 if((s_initAttributes[pcr].resetLocality & 0x04) != 0) 1143 PCRSetSelectBit(pcr, select->pcrSelect); 1144 break; 1145 case TPM_PT_PCR_EXTEND_L3: 1146 if((s_initAttributes[pcr].extendLocality & 0x08) != 0) 1147 PCRSetSelectBit(pcr, select->pcrSelect); 1148 break; 1149 case TPM_PT_PCR_RESET_L3: 1150 if((s_initAttributes[pcr].resetLocality & 0x08) != 0) 1151 PCRSetSelectBit(pcr, select->pcrSelect); 1152 break; 1153 case TPM_PT_PCR_EXTEND_L4: 1154 if((s_initAttributes[pcr].extendLocality & 0x10) != 0) 1155 PCRSetSelectBit(pcr, select->pcrSelect); 1156 break; 1157 case TPM_PT_PCR_RESET_L4: 1158 if((s_initAttributes[pcr].resetLocality & 0x10) != 0) 1159 PCRSetSelectBit(pcr, select->pcrSelect); 1160 break; 1161 case TPM_PT_PCR_DRTM_RESET: 1162 // DRTM reset PCRs are the PCR reset by locality 4 1163 if((s_initAttributes[pcr].resetLocality & 0x10) != 0) 1164 PCRSetSelectBit(pcr, select->pcrSelect); 1165 break; 1166#if NUM_POLICY_PCR_GROUP > 0 1167 case TPM_PT_PCR_POLICY: 1168 if(PCRBelongsPolicyGroup(pcr + PCR_FIRST, &groupIndex)) 1169 PCRSetSelectBit(pcr, select->pcrSelect); 1170 break; 1171#endif 1172#if NUM_AUTHVALUE_PCR_GROUP > 0 1173 case TPM_PT_PCR_AUTH: 1174 if(PCRBelongsAuthGroup(pcr + PCR_FIRST, &groupIndex)) 1175 PCRSetSelectBit(pcr, select->pcrSelect); 1176 break; 1177#endif 1178#if ENABLE_PCR_NO_INCREMENT == YES 1179 case TPM_PT_PCR_NO_INCREMENT: 1180 if(PCRBelongsTCBGroup(pcr + PCR_FIRST)) 1181 PCRSetSelectBit(pcr, select->pcrSelect); 1182 break; 1183#endif 1184 default: 1185 // If property is not supported, stop scanning PCR attributes 1186 // and return. 1187 return FALSE; 1188 break; 1189 } 1190 } 1191 return TRUE; 1192} 1193// 1194// 1195// PCRCapGetProperties() 1196// 1197// This function returns a list of PCR properties starting at property. 1198// 1199// 1200// 1201// 1202// Return Value Meaning 1203// 1204// YES: if no more property is available 1205// NO: if there are more properties not reported 1206// 1207TPMI_YES_NO 1208PCRCapGetProperties( 1209 TPM_PT_PCR property, // IN: the starting PCR property 1210 UINT32 count, // IN: count of returned propertie 1211 TPML_TAGGED_PCR_PROPERTY *select // OUT: PCR select 1212 ) 1213{ 1214 TPMI_YES_NO more = NO; 1215 UINT32 i; 1216 // Initialize output property list 1217 select->count = 0; 1218 // The maximum count of properties we may return is MAX_PCR_PROPERTIES 1219 if(count > MAX_PCR_PROPERTIES) count = MAX_PCR_PROPERTIES; 1220 // TPM_PT_PCR_FIRST is defined as 0 in spec. It ensures that property 1221 // value would never be less than TPM_PT_PCR_FIRST 1222 pAssert(TPM_PT_PCR_FIRST == 0); 1223 // Iterate PCR properties. TPM_PT_PCR_LAST is the index of the last property 1224 // implemented on the TPM. 1225 for(i = property; i <= TPM_PT_PCR_LAST; i++) 1226 { 1227 if(select->count < count) 1228 { 1229 // If we have not filled up the return list, add more properties to it 1230 if(PCRGetProperty(i, &select->pcrProperty[select->count])) 1231 // only increment if the property is implemented 1232 select->count++; 1233 } 1234 else 1235 { 1236 // If the return list is full but we still have properties 1237 // available, report this and stop iterating. 1238 more = YES; 1239 break; 1240 } 1241 } 1242 return more; 1243} 1244// 1245// 1246// PCRCapGetHandles() 1247// 1248// This function is used to get a list of handles of PCR, started from handle. If handle exceeds the maximum 1249// PCR handle range, an empty list will be returned and the return value will be NO. 1250// 1251// Return Value Meaning 1252// 1253// YES if there are more handles available 1254// NO all the available handles has been returned 1255// 1256TPMI_YES_NO 1257PCRCapGetHandles( 1258 TPMI_DH_PCR handle, // IN: start handle 1259 UINT32 count, // IN: count of returned handle 1260 TPML_HANDLE *handleList // OUT: list of handle 1261 ) 1262{ 1263 TPMI_YES_NO more = NO; 1264 UINT32 i; 1265 pAssert(HandleGetType(handle) == TPM_HT_PCR); 1266 // Initialize output handle list 1267 handleList->count = 0; 1268 // The maximum count of handles we may return is MAX_CAP_HANDLES 1269 if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; 1270 // Iterate PCR handle range 1271 for(i = handle & HR_HANDLE_MASK; i <= PCR_LAST; i++) 1272 { 1273 if(handleList->count < count) 1274 { 1275 // If we have not filled up the return list, add this PCR 1276 // handle to it 1277 handleList->handle[handleList->count] = i + PCR_FIRST; 1278 handleList->count++; 1279 } 1280 else 1281 { 1282 // If the return list is full but we still have PCR handle 1283 // available, report this and stop iterating 1284 more = YES; 1285 break; 1286 } 1287 } 1288 return more; 1289} 1290