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