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 NV_C 9 #include "InternalRoutines.h" 10 #include "Platform.h" 11 // 12 // NV Index/evict object iterator value 13 // 14 typedef UINT32 NV_ITER; // type of a NV iterator 15 #define NV_ITER_INIT 0xFFFFFFFF // initial value to start an 16 // iterator 17 // 18 // 19 // NV Utility Functions 20 // 21 // NvCheckState() 22 // 23 // Function to check the NV state by accessing the platform-specific function to get the NV state. The result 24 // state is registered in s_NvIsAvailable that will be reported by NvIsAvailable(). 25 // This function is called at the beginning of ExecuteCommand() before any potential call to NvIsAvailable(). 26 // 27 void 28 NvCheckState(void) 29 { 30 int func_return; 31 func_return = _plat__IsNvAvailable(); 32 if(func_return == 0) 33 { 34 s_NvStatus = TPM_RC_SUCCESS; 35 } 36 else if(func_return == 1) 37 { 38 s_NvStatus = TPM_RC_NV_UNAVAILABLE; 39 } 40 else 41 { 42 s_NvStatus = TPM_RC_NV_RATE; 43 } 44 return; 45 } 46 // 47 // 48 // NvIsAvailable() 49 // 50 // This function returns the NV availability parameter. 51 // 52 // Error Returns Meaning 53 // 54 // TPM_RC_SUCCESS NV is available 55 // TPM_RC_NV_RATE NV is unavailable because of rate limit 56 // TPM_RC_NV_UNAVAILABLE NV is inaccessible 57 // 58 TPM_RC 59 NvIsAvailable( 60 void 61 ) 62 { 63 // Make sure that NV state is still good 64 if (s_NvStatus == TPM_RC_SUCCESS) 65 NvCheckState(); 66 67 return s_NvStatus; 68 } 69 // 70 // 71 // NvCommit 72 // 73 // This is a wrapper for the platform function to commit pending NV writes. 74 // 75 BOOL 76 NvCommit( 77 void 78 ) 79 { 80 BOOL success = (_plat__NvCommit() == 0); 81 return success; 82 } 83 // 84 // 85 // NvReadMaxCount() 86 // 87 // This function returns the max NV counter value. 88 // 89 static UINT64 90 NvReadMaxCount( 91 void 92 ) 93 { 94 UINT64 countValue; 95 _plat__NvMemoryRead(s_maxCountAddr, sizeof(UINT64), &countValue); 96 return countValue; 97 } 98 // 99 // 100 // NvWriteMaxCount() 101 // 102 // This function updates the max counter value to NV memory. 103 // 104 static void 105 NvWriteMaxCount( 106 UINT64 maxCount 107 ) 108 { 109 _plat__NvMemoryWrite(s_maxCountAddr, sizeof(UINT64), &maxCount); 110 return; 111 } 112 // 113 // 114 // NV Index and Persistent Object Access Functions 115 // 116 // Introduction 117 // 118 // These functions are used to access an NV Index and persistent object memory. In this implementation, 119 // the memory is simulated with RAM. The data in dynamic area is organized as a linked list, starting from 120 // address s_evictNvStart. The first 4 bytes of a node in this link list is the offset of next node, followed by 121 // the data entry. A 0-valued offset value indicates the end of the list. If the data entry area of the last node 122 // happens to reach the end of the dynamic area without space left for an additional 4 byte end marker, the 123 // end address, s_evictNvEnd, should serve as the mark of list end 124 // 125 // NvNext() 126 // 127 // This function provides a method to traverse every data entry in NV dynamic area. 128 // To begin with, parameter iter should be initialized to NV_ITER_INIT indicating the first element. Every 129 // time this function is called, the value in iter would be adjusted pointing to the next element in traversal. If 130 // there is no next element, iter value would be 0. This function returns the address of the 'data entry' 131 // pointed by the iter. If there is no more element in the set, a 0 value is returned indicating the end of 132 // traversal. 133 // 134 static UINT32 135 NvNext( 136 NV_ITER *iter 137 ) 138 { 139 NV_ITER currentIter; 140 // If iterator is at the beginning of list 141 if(*iter == NV_ITER_INIT) 142 { 143 // Initialize iterator 144 *iter = s_evictNvStart; 145 } 146 // If iterator reaches the end of NV space, or iterator indicates list end 147 if(*iter + sizeof(UINT32) > s_evictNvEnd || *iter == 0) 148 return 0; 149 // Save the current iter offset 150 currentIter = *iter; 151 // Adjust iter pointer pointing to next entity 152 // Read pointer value 153 _plat__NvMemoryRead(*iter, sizeof(UINT32), iter); 154 if(*iter == 0) return 0; 155 return currentIter + sizeof(UINT32); // entity stores after the pointer 156 } 157 // 158 // 159 // NvGetEnd() 160 // 161 // Function to find the end of the NV dynamic data list 162 // 163 static UINT32 164 NvGetEnd( 165 void 166 ) 167 { 168 NV_ITER iter = NV_ITER_INIT; 169 UINT32 endAddr = s_evictNvStart; 170 UINT32 currentAddr; 171 while((currentAddr = NvNext(&iter)) != 0) 172 endAddr = currentAddr; 173 if(endAddr != s_evictNvStart) 174 { 175 // Read offset 176 endAddr -= sizeof(UINT32); 177 _plat__NvMemoryRead(endAddr, sizeof(UINT32), &endAddr); 178 } 179 return endAddr; 180 } 181 // 182 // 183 // NvGetFreeByte 184 // 185 // This function returns the number of free octets in NV space. 186 // 187 static UINT32 188 NvGetFreeByte( 189 void 190 ) 191 { 192 return s_evictNvEnd - NvGetEnd(); 193 } 194 // 195 // NvGetEvictObjectSize 196 // 197 // This function returns the size of an evict object in NV space 198 // 199 static UINT32 200 NvGetEvictObjectSize( 201 void 202 ) 203 { 204 return sizeof(TPM_HANDLE) + sizeof(OBJECT) + sizeof(UINT32); 205 } 206 // 207 // 208 // NvGetCounterSize 209 // 210 // This function returns the size of a counter index in NV space. 211 // 212 static UINT32 213 NvGetCounterSize( 214 void 215 ) 216 { 217 // It takes an offset field, a handle and the sizeof(NV_INDEX) and 218 // sizeof(UINT64) for counter data 219 return sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + sizeof(UINT64) + sizeof(UINT32); 220 } 221 // 222 // 223 // NvTestSpace() 224 // 225 // This function will test if there is enough space to add a new entity. 226 // 227 // Return Value Meaning 228 // 229 // TRUE space available 230 // FALSE no enough space 231 // 232 static BOOL 233 NvTestSpace( 234 UINT32 size, // IN: size of the entity to be added 235 BOOL isIndex // IN: TRUE if the entity is an index 236 ) 237 { 238 UINT32 remainByte = NvGetFreeByte(); 239 // For NV Index, need to make sure that we do not allocate and Index if this 240 // would mean that the TPM cannot allocate the minimum number of evict 241 // objects. 242 if(isIndex) 243 { 244 // Get the number of persistent objects allocated 245 UINT32 persistentNum = NvCapGetPersistentNumber(); 246 // If we have not allocated the requisite number of evict objects, then we 247 // need to reserve space for them. 248 // NOTE: some of this is not written as simply as it might seem because 249 // the values are all unsigned and subtracting needs to be done carefully 250 // so that an underflow doesn't cause problems. 251 if(persistentNum < MIN_EVICT_OBJECTS) 252 { 253 UINT32 needed = (MIN_EVICT_OBJECTS - persistentNum) 254 * NvGetEvictObjectSize(); 255 if(needed > remainByte) 256 remainByte = 0; 257 else 258 remainByte -= needed; 259 } 260 // if the requisite number of evict objects have been allocated then 261 // no need to reserve additional space 262 } 263 // This checks for the size of the value being added plus the index value. 264 // NOTE: This does not check to see if the end marker can be placed in 265 // memory because the end marker will not be written if it will not fit. 266 return (size + sizeof(UINT32) <= remainByte); 267 } 268 // 269 // 270 // NvAdd() 271 // 272 // This function adds a new entity to NV. 273 // This function requires that there is enough space to add a new entity (i.e., that NvTestSpace() has been 274 // called and the available space is at least as large as the required space). 275 // 276 static void 277 NvAdd( 278 UINT32 totalSize, // IN: total size needed for this entity For 279 // evict object, totalSize is the same as 280 // bufferSize. For NV Index, totalSize is 281 // bufferSize plus index data size 282 UINT32 bufferSize, // IN: size of initial buffer 283 BYTE *entity // IN: initial buffer 284 ) 285 { 286 UINT32 endAddr; 287 UINT32 nextAddr; 288 UINT32 listEnd = 0; 289 // Get the end of data list 290 endAddr = NvGetEnd(); 291 // Calculate the value of next pointer, which is the size of a pointer + 292 // the entity data size 293 nextAddr = endAddr + sizeof(UINT32) + totalSize; 294 // Write next pointer 295 _plat__NvMemoryWrite(endAddr, sizeof(UINT32), &nextAddr); 296 // Write entity data 297 _plat__NvMemoryWrite(endAddr + sizeof(UINT32), bufferSize, entity); 298 // Write the end of list if it is not going to exceed the NV space 299 if(nextAddr + sizeof(UINT32) <= s_evictNvEnd) 300 _plat__NvMemoryWrite(nextAddr, sizeof(UINT32), &listEnd); 301 // Set the flag so that NV changes are committed before the command completes. 302 g_updateNV = TRUE; 303 } 304 // 305 // 306 // NvDelete() 307 // 308 // This function is used to delete an NV Index or persistent object from NV memory. 309 // 310 static void 311 NvDelete( 312 UINT32 entityAddr // IN: address of entity to be deleted 313 ) 314 { 315 UINT32 next; 316 UINT32 entrySize; 317 UINT32 entryAddr = entityAddr - sizeof(UINT32); 318 UINT32 listEnd = 0; 319 // Get the offset of the next entry. 320 _plat__NvMemoryRead(entryAddr, sizeof(UINT32), &next); 321 // The size of this entry is the difference between the current entry and the 322 // next entry. 323 entrySize = next - entryAddr; 324 // Move each entry after the current one to fill the freed space. 325 // Stop when we have reached the end of all the indexes. There are two 326 // ways to detect the end of the list. The first is to notice that there 327 // is no room for anything else because we are at the end of NV. The other 328 // indication is that we find an end marker. 329 // The loop condition checks for the end of NV. 330 while(next + sizeof(UINT32) <= s_evictNvEnd) 331 { 332 UINT32 size, oldAddr, newAddr; 333 // Now check for the end marker 334 _plat__NvMemoryRead(next, sizeof(UINT32), &oldAddr); 335 if(oldAddr == 0) 336 break; 337 size = oldAddr - next; 338 // Move entry 339 _plat__NvMemoryMove(next, next - entrySize, size); 340 // Update forward link 341 newAddr = oldAddr - entrySize; 342 _plat__NvMemoryWrite(next - entrySize, sizeof(UINT32), &newAddr); 343 next = oldAddr; 344 } 345 // Mark the end of list 346 _plat__NvMemoryWrite(next - entrySize, sizeof(UINT32), &listEnd); 347 // Set the flag so that NV changes are committed before the command completes. 348 g_updateNV = TRUE; 349 } 350 // 351 // 352 // RAM-based NV Index Data Access Functions 353 // 354 // Introduction 355 // 356 // The data layout in ram buffer is {size of(NV_handle() + data), NV_handle(), data} for each NV Index data 357 // stored in RAM. 358 // NV storage is updated when a NV Index is added or deleted. We do NOT updated NV storage when the 359 // data is updated/ 360 // 361 // NvTestRAMSpace() 362 // 363 // This function indicates if there is enough RAM space to add a data for a new NV Index. 364 // 365 // 366 // 367 // 368 // Return Value Meaning 369 // 370 // TRUE space available 371 // FALSE no enough space 372 // 373 static BOOL 374 NvTestRAMSpace( 375 UINT32 size // IN: size of the data to be added to RAM 376 ) 377 { 378 BOOL success = ( s_ramIndexSize 379 + size 380 + sizeof(TPM_HANDLE) + sizeof(UINT32) 381 <= RAM_INDEX_SPACE); 382 return success; 383 } 384 // 385 // 386 // NvGetRamIndexOffset 387 // 388 // This function returns the offset of NV data in the RAM buffer 389 // This function requires that NV Index is in RAM. That is, the index must be known to exist. 390 // 391 static UINT32 392 NvGetRAMIndexOffset( 393 TPMI_RH_NV_INDEX handle // IN: NV handle 394 ) 395 { 396 UINT32 currAddr = 0; 397 while(currAddr < s_ramIndexSize) 398 { 399 TPMI_RH_NV_INDEX currHandle; 400 UINT32 currSize; 401 memcpy(&currHandle, &s_ramIndex[currAddr + sizeof(UINT32)], 402 sizeof(currHandle)); 403 // Found a match 404 if(currHandle == handle) 405 // data buffer follows the handle and size field 406 break; 407 memcpy(&currSize, &s_ramIndex[currAddr], sizeof(currSize)); 408 currAddr += sizeof(UINT32) + currSize; 409 } 410 // We assume the index data is existing in RAM space 411 pAssert(currAddr < s_ramIndexSize); 412 return currAddr + sizeof(TPMI_RH_NV_INDEX) + sizeof(UINT32); 413 } 414 // 415 // 416 // NvAddRAM() 417 // 418 // This function adds a new data area to RAM. 419 // This function requires that enough free RAM space is available to add the new data. 420 // 421 static void 422 NvAddRAM( 423 TPMI_RH_NV_INDEX handle, // IN: NV handle 424 UINT32 size // IN: size of data 425 ) 426 { 427 // Add data space at the end of reserved RAM buffer 428 UINT32 value = size + sizeof(TPMI_RH_NV_INDEX); 429 memcpy(&s_ramIndex[s_ramIndexSize], &value, 430 sizeof(s_ramIndex[s_ramIndexSize])); 431 memcpy(&s_ramIndex[s_ramIndexSize + sizeof(UINT32)], &handle, 432 sizeof(s_ramIndex[s_ramIndexSize + sizeof(UINT32)])); 433 s_ramIndexSize += sizeof(UINT32) + sizeof(TPMI_RH_NV_INDEX) + size; 434 pAssert(s_ramIndexSize <= RAM_INDEX_SPACE); 435 // Update NV version of s_ramIndexSize 436 _plat__NvMemoryWrite(s_ramIndexSizeAddr, sizeof(UINT32), &s_ramIndexSize); 437 // Write reserved RAM space to NV to reflect the newly added NV Index 438 _plat__NvMemoryWrite(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex); 439 return; 440 } 441 // 442 // 443 // NvDeleteRAM() 444 // 445 // This function is used to delete a RAM-backed NV Index data area. 446 // This function assumes the data of NV Index exists in RAM 447 // 448 static void 449 NvDeleteRAM( 450 TPMI_RH_NV_INDEX handle // IN: NV handle 451 ) 452 { 453 UINT32 nodeOffset; 454 UINT32 nextNode; 455 UINT32 size; 456 nodeOffset = NvGetRAMIndexOffset(handle); 457 // Move the pointer back to get the size field of this node 458 nodeOffset -= sizeof(UINT32) + sizeof(TPMI_RH_NV_INDEX); 459 // Get node size 460 memcpy(&size, &s_ramIndex[nodeOffset], sizeof(size)); 461 // Get the offset of next node 462 nextNode = nodeOffset + sizeof(UINT32) + size; 463 // Move data 464 MemoryMove(s_ramIndex + nodeOffset, s_ramIndex + nextNode, 465 s_ramIndexSize - nextNode, s_ramIndexSize - nextNode); 466 // Update RAM size 467 s_ramIndexSize -= size + sizeof(UINT32); 468 // Update NV version of s_ramIndexSize 469 _plat__NvMemoryWrite(s_ramIndexSizeAddr, sizeof(UINT32), &s_ramIndexSize); 470 // Write reserved RAM space to NV to reflect the newly delete NV Index 471 _plat__NvMemoryWrite(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex); 472 return; 473 } 474 // 475 // 476 // 477 // Utility Functions 478 // 479 // NvInitStatic() 480 // 481 // This function initializes the static variables used in the NV subsystem. 482 // 483 static void 484 NvInitStatic( 485 void 486 ) 487 { 488 UINT16 i; 489 UINT32 reservedAddr; 490 s_reservedSize[NV_DISABLE_CLEAR] = sizeof(gp.disableClear); 491 s_reservedSize[NV_OWNER_ALG] = sizeof(gp.ownerAlg); 492 s_reservedSize[NV_ENDORSEMENT_ALG] = sizeof(gp.endorsementAlg); 493 s_reservedSize[NV_LOCKOUT_ALG] = sizeof(gp.lockoutAlg); 494 s_reservedSize[NV_OWNER_POLICY] = sizeof(gp.ownerPolicy); 495 s_reservedSize[NV_ENDORSEMENT_POLICY] = sizeof(gp.endorsementPolicy); 496 s_reservedSize[NV_LOCKOUT_POLICY] = sizeof(gp.lockoutPolicy); 497 s_reservedSize[NV_OWNER_AUTH] = sizeof(gp.ownerAuth); 498 s_reservedSize[NV_ENDORSEMENT_AUTH] = sizeof(gp.endorsementAuth); 499 s_reservedSize[NV_LOCKOUT_AUTH] = sizeof(gp.lockoutAuth); 500 s_reservedSize[NV_EP_SEED] = sizeof(gp.EPSeed); 501 s_reservedSize[NV_SP_SEED] = sizeof(gp.SPSeed); 502 s_reservedSize[NV_PP_SEED] = sizeof(gp.PPSeed); 503 s_reservedSize[NV_PH_PROOF] = sizeof(gp.phProof); 504 s_reservedSize[NV_SH_PROOF] = sizeof(gp.shProof); 505 s_reservedSize[NV_EH_PROOF] = sizeof(gp.ehProof); 506 s_reservedSize[NV_TOTAL_RESET_COUNT] = sizeof(gp.totalResetCount); 507 s_reservedSize[NV_RESET_COUNT] = sizeof(gp.resetCount); 508 s_reservedSize[NV_PCR_POLICIES] = sizeof(gp.pcrPolicies); 509 s_reservedSize[NV_PCR_ALLOCATED] = sizeof(gp.pcrAllocated); 510 s_reservedSize[NV_PP_LIST] = sizeof(gp.ppList); 511 s_reservedSize[NV_FAILED_TRIES] = sizeof(gp.failedTries); 512 s_reservedSize[NV_MAX_TRIES] = sizeof(gp.maxTries); 513 s_reservedSize[NV_RECOVERY_TIME] = sizeof(gp.recoveryTime); 514 s_reservedSize[NV_LOCKOUT_RECOVERY] = sizeof(gp.lockoutRecovery); 515 s_reservedSize[NV_LOCKOUT_AUTH_ENABLED] = sizeof(gp.lockOutAuthEnabled); 516 s_reservedSize[NV_ORDERLY] = sizeof(gp.orderlyState); 517 s_reservedSize[NV_AUDIT_COMMANDS] = sizeof(gp.auditComands); 518 s_reservedSize[NV_AUDIT_HASH_ALG] = sizeof(gp.auditHashAlg); 519 s_reservedSize[NV_AUDIT_COUNTER] = sizeof(gp.auditCounter); 520 s_reservedSize[NV_ALGORITHM_SET] = sizeof(gp.algorithmSet); 521 s_reservedSize[NV_FIRMWARE_V1] = sizeof(gp.firmwareV1); 522 s_reservedSize[NV_FIRMWARE_V2] = sizeof(gp.firmwareV2); 523 s_reservedSize[NV_ORDERLY_DATA] = sizeof(go); 524 s_reservedSize[NV_STATE_CLEAR] = sizeof(gc); 525 s_reservedSize[NV_STATE_RESET] = sizeof(gr); 526 // Initialize reserved data address. In this implementation, reserved data 527 // is stored at the start of NV memory 528 reservedAddr = 0; 529 for(i = 0; i < NV_RESERVE_LAST; i++) 530 { 531 s_reservedAddr[i] = reservedAddr; 532 reservedAddr += s_reservedSize[i]; 533 } 534 // Initialize auxiliary variable space for index/evict implementation. 535 // Auxiliary variables are stored after reserved data area 536 // RAM index copy starts at the beginning 537 s_ramIndexSizeAddr = reservedAddr; 538 s_ramIndexAddr = s_ramIndexSizeAddr + sizeof(UINT32); 539 // Maximum counter value 540 s_maxCountAddr = s_ramIndexAddr + RAM_INDEX_SPACE; 541 // dynamic memory start 542 s_evictNvStart = s_maxCountAddr + sizeof(UINT64); 543 // dynamic memory ends at the end of NV memory 544 s_evictNvEnd = NV_MEMORY_SIZE; 545 return; 546 } 547 // 548 // 549 // NvInit() 550 // 551 // This function initializes the NV system at pre-install time. 552 // This function should only be called in a manufacturing environment or in a simulation. 553 // The layout of NV memory space is an implementation choice. 554 // 555 void 556 NvInit( 557 void 558 ) 559 { 560 UINT32 nullPointer = 0; 561 UINT64 zeroCounter = 0; 562 // Initialize static variables 563 NvInitStatic(); 564 // Initialize RAM index space as unused 565 _plat__NvMemoryWrite(s_ramIndexSizeAddr, sizeof(UINT32), &nullPointer); 566 // Initialize max counter value to 0 567 _plat__NvMemoryWrite(s_maxCountAddr, sizeof(UINT64), &zeroCounter); 568 // Initialize the next offset of the first entry in evict/index list to 0 569 _plat__NvMemoryWrite(s_evictNvStart, sizeof(TPM_HANDLE), &nullPointer); 570 return; 571 } 572 // 573 // 574 // NvReadReserved() 575 // 576 // This function is used to move reserved data from NV memory to RAM. 577 // 578 void 579 NvReadReserved( 580 NV_RESERVE type, // IN: type of reserved data 581 void *buffer // OUT: buffer receives the data. 582 ) 583 { 584 // Input type should be valid 585 pAssert(type >= 0 && type < NV_RESERVE_LAST); 586 _plat__NvMemoryRead(s_reservedAddr[type], s_reservedSize[type], buffer); 587 return; 588 } 589 // 590 // 591 // NvWriteReserved() 592 // 593 // This function is used to post a reserved data for writing to NV memory. Before the TPM completes the 594 // operation, the value will be written. 595 // 596 void 597 NvWriteReserved( 598 NV_RESERVE type, // IN: type of reserved data 599 void *buffer // IN: data buffer 600 ) 601 { 602 // Input type should be valid 603 pAssert(type >= 0 && type < NV_RESERVE_LAST); 604 _plat__NvMemoryWrite(s_reservedAddr[type], s_reservedSize[type], buffer); 605 // Set the flag that a NV write happens 606 g_updateNV = TRUE; 607 return; 608 } 609 // 610 // 611 // NvReadPersistent() 612 // 613 // This function reads persistent data to the RAM copy of the gp structure. 614 // 615 void 616 NvReadPersistent( 617 void 618 ) 619 { 620 // Hierarchy persistent data 621 NvReadReserved(NV_DISABLE_CLEAR, &gp.disableClear); 622 NvReadReserved(NV_OWNER_ALG, &gp.ownerAlg); 623 NvReadReserved(NV_ENDORSEMENT_ALG, &gp.endorsementAlg); 624 NvReadReserved(NV_LOCKOUT_ALG, &gp.lockoutAlg); 625 NvReadReserved(NV_OWNER_POLICY, &gp.ownerPolicy); 626 NvReadReserved(NV_ENDORSEMENT_POLICY, &gp.endorsementPolicy); 627 NvReadReserved(NV_LOCKOUT_POLICY, &gp.lockoutPolicy); 628 NvReadReserved(NV_OWNER_AUTH, &gp.ownerAuth); 629 NvReadReserved(NV_ENDORSEMENT_AUTH, &gp.endorsementAuth); 630 NvReadReserved(NV_LOCKOUT_AUTH, &gp.lockoutAuth); 631 NvReadReserved(NV_EP_SEED, &gp.EPSeed); 632 NvReadReserved(NV_SP_SEED, &gp.SPSeed); 633 NvReadReserved(NV_PP_SEED, &gp.PPSeed); 634 NvReadReserved(NV_PH_PROOF, &gp.phProof); 635 NvReadReserved(NV_SH_PROOF, &gp.shProof); 636 NvReadReserved(NV_EH_PROOF, &gp.ehProof); 637 // Time persistent data 638 NvReadReserved(NV_TOTAL_RESET_COUNT, &gp.totalResetCount); 639 NvReadReserved(NV_RESET_COUNT, &gp.resetCount); 640 // PCR persistent data 641 NvReadReserved(NV_PCR_POLICIES, &gp.pcrPolicies); 642 NvReadReserved(NV_PCR_ALLOCATED, &gp.pcrAllocated); 643 // Physical Presence persistent data 644 NvReadReserved(NV_PP_LIST, &gp.ppList); 645 // Dictionary attack values persistent data 646 NvReadReserved(NV_FAILED_TRIES, &gp.failedTries); 647 NvReadReserved(NV_MAX_TRIES, &gp.maxTries); 648 NvReadReserved(NV_RECOVERY_TIME, &gp.recoveryTime); 649 // 650 NvReadReserved(NV_LOCKOUT_RECOVERY, &gp.lockoutRecovery); 651 NvReadReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled); 652 // Orderly State persistent data 653 NvReadReserved(NV_ORDERLY, &gp.orderlyState); 654 // Command audit values persistent data 655 NvReadReserved(NV_AUDIT_COMMANDS, &gp.auditComands); 656 NvReadReserved(NV_AUDIT_HASH_ALG, &gp.auditHashAlg); 657 NvReadReserved(NV_AUDIT_COUNTER, &gp.auditCounter); 658 // Algorithm selection persistent data 659 NvReadReserved(NV_ALGORITHM_SET, &gp.algorithmSet); 660 // Firmware version persistent data 661 #ifdef EMBEDDED_MODE 662 _plat__GetFwVersion(&gp.firmwareV1, &gp.firmwareV2); 663 #else 664 NvReadReserved(NV_FIRMWARE_V1, &gp.firmwareV1); 665 NvReadReserved(NV_FIRMWARE_V2, &gp.firmwareV2); 666 #endif 667 return; 668 } 669 // 670 // 671 // NvIsPlatformPersistentHandle() 672 // 673 // This function indicates if a handle references a persistent object in the range belonging to the platform. 674 // 675 // Return Value Meaning 676 // 677 // TRUE handle references a platform persistent object 678 // FALSE handle does not reference platform persistent object and may 679 // reference an owner persistent object either 680 // 681 BOOL 682 NvIsPlatformPersistentHandle( 683 TPM_HANDLE handle // IN: handle 684 ) 685 { 686 return (handle >= PLATFORM_PERSISTENT && handle <= PERSISTENT_LAST); 687 } 688 // 689 // 690 // NvIsOwnerPersistentHandle() 691 // 692 // This function indicates if a handle references a persistent object in the range belonging to the owner. 693 // 694 // Return Value Meaning 695 // 696 // TRUE handle is owner persistent handle 697 // FALSE handle is not owner persistent handle and may not be a persistent 698 // handle at all 699 // 700 BOOL 701 NvIsOwnerPersistentHandle( 702 TPM_HANDLE handle // IN: handle 703 ) 704 { 705 return (handle >= PERSISTENT_FIRST && handle < PLATFORM_PERSISTENT); 706 } 707 // 708 // 709 // NvNextIndex() 710 // 711 // This function returns the offset in NV of the next NV Index entry. A value of 0 indicates the end of the list. 712 // Family "2.0" TCG Published Page 131 713 // Level 00 Revision 01.16 Copyright TCG 2006-2014 October 30, 2014 714 // Trusted Platform Module Library Part 4: Supporting Routines 716 // 717 static UINT32 718 NvNextIndex( 719 NV_ITER *iter 720 ) 721 { 722 UINT32 addr; 723 TPM_HANDLE handle; 724 while((addr = NvNext(iter)) != 0) 725 { 726 // Read handle 727 _plat__NvMemoryRead(addr, sizeof(TPM_HANDLE), &handle); 728 if(HandleGetType(handle) == TPM_HT_NV_INDEX) 729 return addr; 730 } 731 pAssert(addr == 0); 732 return addr; 733 } 734 // 735 // 736 // NvNextEvict() 737 // 738 // This function returns the offset in NV of the next evict object entry. A value of 0 indicates the end of the 739 // list. 740 // 741 static UINT32 742 NvNextEvict( 743 NV_ITER *iter 744 ) 745 { 746 UINT32 addr; 747 TPM_HANDLE handle; 748 while((addr = NvNext(iter)) != 0) 749 { 750 // Read handle 751 _plat__NvMemoryRead(addr, sizeof(TPM_HANDLE), &handle); 752 if(HandleGetType(handle) == TPM_HT_PERSISTENT) 753 return addr; 754 } 755 pAssert(addr == 0); 756 return addr; 757 } 758 // 759 // 760 // NvFindHandle() 761 // 762 // this function returns the offset in NV memory of the entity associated with the input handle. A value of 763 // zero indicates that handle does not exist reference an existing persistent object or defined NV Index. 764 // 765 static UINT32 766 NvFindHandle( 767 TPM_HANDLE handle 768 ) 769 { 770 UINT32 addr; 771 NV_ITER iter = NV_ITER_INIT; 772 while((addr = NvNext(&iter)) != 0) 773 { 774 TPM_HANDLE entityHandle; 775 // Read handle 776 // 777 _plat__NvMemoryRead(addr, sizeof(TPM_HANDLE), &entityHandle); 778 if(entityHandle == handle) 779 return addr; 780 } 781 pAssert(addr == 0); 782 return addr; 783 } 784 785 // 786 // NvCheckAndMigrateIfNeeded() 787 // 788 // Supported only in EMBEDDED_MODE. 789 // 790 // Check if the NVRAM storage format changed, and if so - reinitialize the 791 // NVRAM. No content migration yet, hopefully it will come one day. 792 // 793 // Note that the NV_FIRMWARE_V1 and NV_FIRMWARE_V2 values not used to store 794 // TPM versoion when in embedded mode are used for NVRAM format version 795 // instead. 796 // 797 // 798 static void 799 NvCheckAndMigrateIfNeeded(void) 800 { 801 #ifdef EMBEDDED_MODE 802 UINT32 nv_vers1; 803 UINT32 nv_vers2; 804 805 NvReadReserved(NV_FIRMWARE_V1, &nv_vers1); 806 NvReadReserved(NV_FIRMWARE_V2, &nv_vers2); 807 808 if ((nv_vers1 == ~nv_vers2) && (nv_vers1 == NV_FORMAT_VERSION)) 809 return; // All is well. 810 811 // This will reinitialize NVRAM to empty. Migration code will come here 812 // later. 813 NvInit(); 814 815 nv_vers1 = NV_FORMAT_VERSION; 816 nv_vers2 = ~NV_FORMAT_VERSION; 817 818 NvWriteReserved(NV_FIRMWARE_V1, &nv_vers1); 819 NvWriteReserved(NV_FIRMWARE_V2, &nv_vers2); 820 821 NvCommit(); 822 #endif 823 } 824 825 826 // 827 // 828 // NvPowerOn() 829 // 830 // This function is called at _TPM_Init() to initialize the NV environment. 831 // 832 // Return Value Meaning 833 // 834 // TRUE all NV was initialized 835 // FALSE the NV containing saved state had an error and 836 // TPM2_Startup(CLEAR) is required 837 // 838 BOOL 839 NvPowerOn( 840 void 841 ) 842 { 843 int nvError = 0; 844 // If power was lost, need to re-establish the RAM data that is loaded from 845 // NV and initialize the static variables 846 if(_plat__WasPowerLost(TRUE)) 847 { 848 if((nvError = _plat__NVEnable(0)) < 0) 849 FAIL(FATAL_ERROR_NV_UNRECOVERABLE); 850 NvInitStatic(); 851 NvCheckAndMigrateIfNeeded(); 852 } 853 return nvError == 0; 854 } 855 // 856 // 857 // NvStateSave() 858 // 859 // This function is used to cause the memory containing the RAM backed NV Indices to be written to NV. 860 // 861 void 862 NvStateSave( 863 void 864 ) 865 { 866 // Write RAM backed NV Index info to NV 867 // No need to save s_ramIndexSize because we save it to NV whenever it is 868 // updated. 869 _plat__NvMemoryWrite(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex); 870 // Set the flag so that an NV write happens before the command completes. 871 g_updateNV = TRUE; 872 return; 873 } 874 // 875 // 876 // 877 // NvEntityStartup() 878 // 879 // This function is called at TPM_Startup(). If the startup completes a TPM Resume cycle, no action is 880 // taken. If the startup is a TPM Reset or a TPM Restart, then this function will: 881 // a) clear read/write lock; 882 // b) reset NV Index data that has TPMA_NV_CLEAR_STCLEAR SET; and 883 // c) set the lower bits in orderly counters to 1 for a non-orderly startup 884 // It is a prerequisite that NV be available for writing before this function is called. 885 // 886 void 887 NvEntityStartup( 888 STARTUP_TYPE type // IN: start up type 889 ) 890 { 891 NV_ITER iter = NV_ITER_INIT; 892 UINT32 currentAddr; // offset points to the current entity 893 // Restore RAM index data 894 _plat__NvMemoryRead(s_ramIndexSizeAddr, sizeof(UINT32), &s_ramIndexSize); 895 _plat__NvMemoryRead(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex); 896 // If recovering from state save, do nothing 897 if(type == SU_RESUME) 898 return; 899 // Iterate all the NV Index to clear the locks 900 while((currentAddr = NvNextIndex(&iter)) != 0) 901 { 902 NV_INDEX nvIndex; 903 UINT32 indexAddr; // NV address points to index info 904 TPMA_NV attributes; 905 UINT32 attributesValue; 906 UINT32 publicAreaAttributesValue; 907 indexAddr = currentAddr + sizeof(TPM_HANDLE); 908 // Read NV Index info structure 909 _plat__NvMemoryRead(indexAddr, sizeof(NV_INDEX), &nvIndex); 910 attributes = nvIndex.publicArea.attributes; 911 // Clear read/write lock 912 if(attributes.TPMA_NV_READLOCKED == SET) 913 attributes.TPMA_NV_READLOCKED = CLEAR; 914 if( attributes.TPMA_NV_WRITELOCKED == SET 915 && ( attributes.TPMA_NV_WRITTEN == CLEAR 916 || attributes.TPMA_NV_WRITEDEFINE == CLEAR 917 ) 918 ) 919 attributes.TPMA_NV_WRITELOCKED = CLEAR; 920 // Reset NV data for TPMA_NV_CLEAR_STCLEAR 921 if(attributes.TPMA_NV_CLEAR_STCLEAR == SET) 922 { 923 attributes.TPMA_NV_WRITTEN = CLEAR; 924 attributes.TPMA_NV_WRITELOCKED = CLEAR; 925 } 926 // Reset NV data for orderly values that are not counters 927 // NOTE: The function has already exited on a TPM Resume, so the only 928 // things being processed are TPM Restart and TPM Reset 929 if( type == SU_RESET 930 && attributes.TPMA_NV_ORDERLY == SET 931 && attributes.TPMA_NV_COUNTER == CLEAR 932 ) 933 attributes.TPMA_NV_WRITTEN = CLEAR; 934 // Write NV Index info back if it has changed 935 memcpy(&attributesValue, &attributes, sizeof(attributesValue)); 936 memcpy(&publicAreaAttributesValue, &nvIndex.publicArea.attributes, 937 sizeof(publicAreaAttributesValue)); 938 if(attributesValue != publicAreaAttributesValue) 939 { 940 nvIndex.publicArea.attributes = attributes; 941 _plat__NvMemoryWrite(indexAddr, sizeof(NV_INDEX), &nvIndex); 942 // Set the flag that a NV write happens 943 g_updateNV = TRUE; 944 } 945 // Set the lower bits in an orderly counter to 1 for a non-orderly startup 946 if( g_prevOrderlyState == SHUTDOWN_NONE 947 && attributes.TPMA_NV_WRITTEN == SET) 948 { 949 if( attributes.TPMA_NV_ORDERLY == SET 950 && attributes.TPMA_NV_COUNTER == SET) 951 { 952 TPMI_RH_NV_INDEX nvHandle; 953 UINT64 counter; 954 // Read NV handle 955 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &nvHandle); 956 // Read the counter value saved to NV upon the last roll over. 957 // Do not use RAM backed storage for this once. 958 nvIndex.publicArea.attributes.TPMA_NV_ORDERLY = CLEAR; 959 NvGetIntIndexData(nvHandle, &nvIndex, &counter); 960 nvIndex.publicArea.attributes.TPMA_NV_ORDERLY = SET; 961 // Set the lower bits of counter to 1's 962 counter |= MAX_ORDERLY_COUNT; 963 // Write back to RAM 964 NvWriteIndexData(nvHandle, &nvIndex, 0, sizeof(counter), &counter); 965 // No write to NV because an orderly shutdown will update the 966 // counters. 967 } 968 } 969 } 970 return; 971 } 972 // 973 // 974 // NV Access Functions 975 // 976 // Introduction 977 // 978 // This set of functions provide accessing NV Index and persistent objects based using a handle for 979 // reference to the entity. 980 // 981 // NvIsUndefinedIndex() 982 // 983 // This function is used to verify that an NV Index is not defined. This is only used by 984 // TPM2_NV_DefineSpace(). 985 // 986 // 987 // 988 // 989 // Return Value Meaning 990 // 991 // TRUE the handle points to an existing NV Index 992 // FALSE the handle points to a non-existent Index 993 // 994 BOOL 995 NvIsUndefinedIndex( 996 TPMI_RH_NV_INDEX handle // IN: handle 997 ) 998 { 999 UINT32 entityAddr; // offset points to the entity 1000 pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX); 1001 // Find the address of index 1002 entityAddr = NvFindHandle(handle); 1003 // If handle is not found, return TPM_RC_SUCCESS 1004 if(entityAddr == 0) 1005 return TPM_RC_SUCCESS; 1006 // NV Index is defined 1007 return TPM_RC_NV_DEFINED; 1008 } 1009 // 1010 // 1011 // NvIndexIsAccessible() 1012 // 1013 // This function validates that a handle references a defined NV Index and that the Index is currently 1014 // accessible. 1015 // 1016 // Error Returns Meaning 1017 // 1018 // TPM_RC_HANDLE the handle points to an undefined NV Index If shEnable is CLEAR, 1019 // this would include an index created using ownerAuth. If phEnableNV 1020 // is CLEAR, this would include and index created using platform auth 1021 // TPM_RC_NV_READLOCKED Index is present but locked for reading and command does not write 1022 // to the index 1023 // TPM_RC_NV_WRITELOCKED Index is present but locked for writing and command writes to the 1024 // index 1025 // 1026 TPM_RC 1027 NvIndexIsAccessible( 1028 TPMI_RH_NV_INDEX handle, // IN: handle 1029 TPM_CC commandCode // IN: the command 1030 ) 1031 { 1032 UINT32 entityAddr; // offset points to the entity 1033 NV_INDEX nvIndex; // 1034 pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX); 1035 // Find the address of index 1036 entityAddr = NvFindHandle(handle); 1037 // If handle is not found, return TPM_RC_HANDLE 1038 if(entityAddr == 0) 1039 return TPM_RC_HANDLE; 1040 // Read NV Index info structure 1041 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX), 1042 &nvIndex); 1043 if(gc.shEnable == FALSE || gc.phEnableNV == FALSE) 1044 { 1045 // if shEnable is CLEAR, an ownerCreate NV Index should not be 1046 // indicated as present 1047 if(nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == CLEAR) 1048 { 1049 /* 1050 * FWMP is a Chrome OS specific object saved at address 0x100a, it 1051 * needs to be available for reading even before TPM2_Startup 1052 * command is issued. 1053 */ 1054 UINT32 isFwmpRead = (handle == 0x100100a) && 1055 IsReadOperation(commandCode); 1056 1057 if((gc.shEnable == FALSE) && !isFwmpRead) 1058 return TPM_RC_HANDLE; 1059 } 1060 // if phEnableNV is CLEAR, a platform created Index should not 1061 // be visible 1062 else if(gc.phEnableNV == FALSE) 1063 return TPM_RC_HANDLE; 1064 } 1065 // If the Index is write locked and this is an NV Write operation... 1066 if( nvIndex.publicArea.attributes.TPMA_NV_WRITELOCKED 1067 && IsWriteOperation(commandCode)) 1068 { 1069 // then return a locked indication unless the command is TPM2_NV_WriteLock 1070 if(commandCode != TPM_CC_NV_WriteLock) 1071 return TPM_RC_NV_LOCKED; 1072 return TPM_RC_SUCCESS; 1073 } 1074 // If the Index is read locked and this is an NV Read operation... 1075 if( nvIndex.publicArea.attributes.TPMA_NV_READLOCKED 1076 && IsReadOperation(commandCode)) 1077 { 1078 // then return a locked indication unless the command is TPM2_NV_ReadLock 1079 if(commandCode != TPM_CC_NV_ReadLock) 1080 return TPM_RC_NV_LOCKED; 1081 return TPM_RC_SUCCESS; 1082 } 1083 // NV Index is accessible 1084 return TPM_RC_SUCCESS; 1085 } 1086 // 1087 // 1088 // NvIsUndefinedEvictHandle() 1089 // 1090 // This function indicates if a handle does not reference an existing persistent object. This function requires 1091 // that the handle be in the proper range for persistent objects. 1092 // 1093 // Return Value Meaning 1094 // 1095 // TRUE handle does not reference an existing persistent object 1096 // FALSE handle does reference an existing persistent object 1097 // 1098 static BOOL 1099 NvIsUndefinedEvictHandle( 1100 TPM_HANDLE handle // IN: handle 1101 ) 1102 { 1103 UINT32 entityAddr; // offset points to the entity 1104 pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT); 1105 // Find the address of evict object 1106 entityAddr = NvFindHandle(handle); 1107 // If handle is not found, return TRUE 1108 if(entityAddr == 0) 1109 return TRUE; 1110 else 1111 return FALSE; 1112 } 1113 1114 // 1115 // 1116 // NvUnmarshalObject() 1117 // 1118 // This function accepts a buffer containing a marshaled OBJECT 1119 // structure, a pointer to the area where the input data should be 1120 // unmarshaled, and a pointer to the size of the output area. 1121 // 1122 // No error checking is performed, unmarshaled data is guaranteed not to 1123 // spill over the allocated space. 1124 // 1125 static TPM_RC NvUnmarshalObject(OBJECT *o, BYTE **buf, INT32 *size) 1126 { 1127 TPM_RC result; 1128 1129 // There is no generated function to unmarshal the attributes field, do it 1130 // by hand. 1131 MemoryCopy(&o->attributes, *buf, sizeof(o->attributes), *size); 1132 *buf += sizeof(o->attributes); 1133 *size -= sizeof(o->attributes); 1134 1135 result = TPMT_PUBLIC_Unmarshal(&o->publicArea, buf, size); 1136 if (result != TPM_RC_SUCCESS) 1137 return result; 1138 1139 result = TPMT_SENSITIVE_Unmarshal(&o->sensitive, buf, size); 1140 if (result != TPM_RC_SUCCESS) 1141 return result; 1142 1143 #ifdef TPM_ALG_RSA 1144 result = TPM2B_PUBLIC_KEY_RSA_Unmarshal(&o->privateExponent, buf, size); 1145 if (result != TPM_RC_SUCCESS) 1146 return result; 1147 #endif 1148 1149 result = TPM2B_NAME_Unmarshal(&o->qualifiedName, buf, size); 1150 if (result != TPM_RC_SUCCESS) 1151 return result; 1152 1153 result = TPMI_DH_OBJECT_Unmarshal(&o->evictHandle, buf, size, TRUE); 1154 if (result != TPM_RC_SUCCESS) 1155 return result; 1156 1157 return TPM2B_NAME_Unmarshal(&o->name, buf, size); 1158 } 1159 1160 // 1161 // 1162 // NvGetEvictObject() 1163 // 1164 // This function is used to dereference an evict object handle and get a pointer to the object. 1165 // 1166 // Error Returns Meaning 1167 // 1168 // TPM_RC_HANDLE the handle does not point to an existing persistent object 1169 // 1170 TPM_RC 1171 NvGetEvictObject( 1172 TPM_HANDLE handle, // IN: handle 1173 OBJECT *object // OUT: object data 1174 ) 1175 { 1176 UINT32 entityAddr; // offset points to the entity 1177 TPM_RC result = TPM_RC_SUCCESS; 1178 pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT); 1179 // Find the address of evict object 1180 entityAddr = NvFindHandle(handle); 1181 // If handle is not found, return an error 1182 if(entityAddr == 0) { 1183 result = TPM_RC_HANDLE; 1184 } else { 1185 UINT32 storedSize; 1186 UINT32 nextEntryAddr; 1187 1188 // Let's calculate the size of object as stored in NVMEM. 1189 _plat__NvMemoryRead(entityAddr - sizeof(UINT32), 1190 sizeof(UINT32), &nextEntryAddr); 1191 1192 storedSize = nextEntryAddr - entityAddr; 1193 1194 if (storedSize == (sizeof(TPM_HANDLE) + sizeof(OBJECT))) { 1195 // Read evict object stored unmarshaled. 1196 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), 1197 sizeof(OBJECT), 1198 object); 1199 } else { 1200 // Must be stored marshaled, let's unmarshal it. 1201 BYTE marshaled[sizeof(OBJECT)]; 1202 INT32 max_size = sizeof(marshaled); 1203 BYTE *marshaledPtr = marshaled; 1204 1205 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), 1206 storedSize, marshaled); 1207 result = NvUnmarshalObject(object, &marshaledPtr, &max_size); 1208 } 1209 } 1210 // whether there is an error or not, make sure that the evict 1211 // status of the object is set so that the slot will get freed on exit 1212 object->attributes.evict = SET; 1213 return result; 1214 } 1215 // 1216 // 1217 // NvGetIndexInfo() 1218 // 1219 // This function is used to retrieve the contents of an NV Index. 1220 // An implementation is allowed to save the NV Index in a vendor-defined format. If the format is different 1221 // from the default used by the reference code, then this function would be changed to reformat the data into 1222 // the default format. 1223 // A prerequisite to calling this function is that the handle must be known to reference a defined NV Index. 1224 // 1225 void 1226 NvGetIndexInfo( 1227 TPMI_RH_NV_INDEX handle, // IN: handle 1228 NV_INDEX *nvIndex // OUT: NV index structure 1229 ) 1230 { 1231 UINT32 entityAddr; // offset points to the entity 1232 pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX); 1233 // Find the address of NV index 1234 entityAddr = NvFindHandle(handle); 1235 pAssert(entityAddr != 0); 1236 // This implementation uses the default format so just 1237 // read the data in 1238 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX), 1239 nvIndex); 1240 return; 1241 } 1242 // 1243 // 1244 // NvInitialCounter() 1245 // 1246 // This function returns the value to be used when a counter index is initialized. It will scan the NV counters 1247 // and find the highest value in any active counter. It will use that value as the starting point. If there are no 1248 // active counters, it will use the value of the previous largest counter. 1249 // 1250 UINT64 1251 NvInitialCounter( 1252 void 1253 ) 1254 { 1255 UINT64 maxCount; 1256 NV_ITER iter = NV_ITER_INIT; 1257 UINT32 currentAddr; 1258 // Read the maxCount value 1259 maxCount = NvReadMaxCount(); 1260 // Iterate all existing counters 1261 while((currentAddr = NvNextIndex(&iter)) != 0) 1262 { 1263 TPMI_RH_NV_INDEX nvHandle; 1264 NV_INDEX nvIndex; 1265 // Read NV handle 1266 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &nvHandle); 1267 // Get NV Index 1268 NvGetIndexInfo(nvHandle, &nvIndex); 1269 if( nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET 1270 && nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET) 1271 { 1272 UINT64 countValue; 1273 // Read counter value 1274 NvGetIntIndexData(nvHandle, &nvIndex, &countValue); 1275 if(countValue > maxCount) 1276 maxCount = countValue; 1277 } 1278 } 1279 // Initialize the new counter value to be maxCount + 1 1280 // A counter is only initialized the first time it is written. The 1281 // way to write a counter is with TPM2_NV_INCREMENT(). Since the 1282 // "initial" value of a defined counter is the largest count value that 1283 // may have existed in this index previously, then the first use would 1284 // add one to that value. 1285 return maxCount; 1286 } 1287 // 1288 // 1289 // NvGetIndexData() 1290 // 1291 // This function is used to access the data in an NV Index. The data is returned as a byte sequence. Since 1292 // counter values are kept in native format, they are converted to canonical form before being returned. 1293 // Family "2.0" TCG Published Page 139 1294 // Level 00 Revision 01.16 Copyright TCG 2006-2014 October 30, 2014 1295 // Trusted Platform Module Library Part 4: Supporting Routines 1297 // 1298 // 1299 // This function requires that the NV Index be defined, and that the required data is within the data range. It 1300 // also requires that TPMA_NV_WRITTEN of the Index is SET. 1301 // 1302 void 1303 NvGetIndexData( 1304 TPMI_RH_NV_INDEX handle, // IN: handle 1305 NV_INDEX *nvIndex, // IN: RAM image of index header 1306 UINT32 offset, // IN: offset of NV data 1307 UINT16 size, // IN: size of NV data 1308 void *data // OUT: data buffer 1309 ) 1310 { 1311 pAssert(nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == SET); 1312 if( nvIndex->publicArea.attributes.TPMA_NV_BITS == SET 1313 || nvIndex->publicArea.attributes.TPMA_NV_COUNTER == SET) 1314 { 1315 // Read bit or counter data in canonical form 1316 UINT64 dataInInt; 1317 NvGetIntIndexData(handle, nvIndex, &dataInInt); 1318 UINT64_TO_BYTE_ARRAY(dataInInt, (BYTE *)data); 1319 } 1320 else 1321 { 1322 if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET) 1323 { 1324 UINT32 ramAddr; 1325 // Get data from RAM buffer 1326 ramAddr = NvGetRAMIndexOffset(handle); 1327 MemoryCopy(data, s_ramIndex + ramAddr + offset, size, size); 1328 } 1329 else 1330 { 1331 UINT32 entityAddr; 1332 entityAddr = NvFindHandle(handle); 1333 // Get data from NV 1334 // Skip NV Index info, read data buffer 1335 entityAddr += sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + offset; 1336 // Read the data 1337 _plat__NvMemoryRead(entityAddr, size, data); 1338 } 1339 } 1340 return; 1341 } 1342 // 1343 // 1344 // NvGetIntIndexData() 1345 // 1346 // Get data in integer format of a bit or counter NV Index. 1347 // This function requires that the NV Index is defined and that the NV Index previously has been written. 1348 // 1349 void 1350 NvGetIntIndexData( 1351 TPMI_RH_NV_INDEX handle, // IN: handle 1352 NV_INDEX *nvIndex, // IN: RAM image of NV Index header 1353 UINT64 *data // IN: UINT64 pointer for counter or bit 1354 ) 1355 { 1356 // Validate that index has been written and is the right type 1357 pAssert( nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == SET 1358 && ( nvIndex->publicArea.attributes.TPMA_NV_BITS == SET 1359 || nvIndex->publicArea.attributes.TPMA_NV_COUNTER == SET 1360 ) 1361 ); 1362 // bit and counter value is store in native format for TPM CPU. So we directly 1363 // copy the contents of NV to output data buffer 1364 if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET) 1365 { 1366 UINT32 ramAddr; 1367 // Get data from RAM buffer 1368 ramAddr = NvGetRAMIndexOffset(handle); 1369 MemoryCopy(data, s_ramIndex + ramAddr, sizeof(*data), sizeof(*data)); 1370 } 1371 else 1372 { 1373 UINT32 entityAddr; 1374 entityAddr = NvFindHandle(handle); 1375 // Get data from NV 1376 // Skip NV Index info, read data buffer 1377 _plat__NvMemoryRead( 1378 entityAddr + sizeof(TPM_HANDLE) + sizeof(NV_INDEX), 1379 sizeof(UINT64), data); 1380 } 1381 return; 1382 } 1383 // 1384 // 1385 // NvWriteIndexInfo() 1386 // 1387 // This function is called to queue the write of NV Index data to persistent memory. 1388 // This function requires that NV Index is defined. 1389 // 1390 // Error Returns Meaning 1391 // 1392 // TPM_RC_NV_RATE NV is rate limiting so retry 1393 // TPM_RC_NV_UNAVAILABLE NV is not available 1394 // 1395 TPM_RC 1396 NvWriteIndexInfo( 1397 TPMI_RH_NV_INDEX handle, // IN: handle 1398 NV_INDEX *nvIndex // IN: NV Index info to be written 1399 ) 1400 { 1401 UINT32 entryAddr; 1402 TPM_RC result; 1403 // Get the starting offset for the index in the RAM image of NV 1404 entryAddr = NvFindHandle(handle); 1405 pAssert(entryAddr != 0); 1406 // Step over the link value 1407 entryAddr = entryAddr + sizeof(TPM_HANDLE); 1408 // If the index data is actually changed, then a write to NV is required 1409 if(_plat__NvIsDifferent(entryAddr, sizeof(NV_INDEX),nvIndex)) 1410 { 1411 // Make sure that NV is available 1412 result = NvIsAvailable(); 1413 if(result != TPM_RC_SUCCESS) 1414 return result; 1415 _plat__NvMemoryWrite(entryAddr, sizeof(NV_INDEX), nvIndex); 1416 g_updateNV = TRUE; 1417 } 1418 return TPM_RC_SUCCESS; 1419 } 1420 // 1421 // 1422 // NvWriteIndexData() 1423 // 1424 // This function is used to write NV index data. 1425 // This function requires that the NV Index is defined, and the data is within the defined data range for the 1426 // index. 1427 // 1428 // Error Returns Meaning 1429 // 1430 // TPM_RC_NV_RATE NV is rate limiting so retry 1431 // TPM_RC_NV_UNAVAILABLE NV is not available 1432 // 1433 TPM_RC 1434 NvWriteIndexData( 1435 TPMI_RH_NV_INDEX handle, // IN: handle 1436 NV_INDEX *nvIndex, // IN: RAM copy of NV Index 1437 UINT32 offset, // IN: offset of NV data 1438 UINT32 size, // IN: size of NV data 1439 void *data // OUT: data buffer 1440 ) 1441 { 1442 TPM_RC result; 1443 // Validate that write falls within range of the index 1444 pAssert(nvIndex->publicArea.dataSize >= offset + size); 1445 // Update TPMA_NV_WRITTEN bit if necessary 1446 if(nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == CLEAR) 1447 { 1448 nvIndex->publicArea.attributes.TPMA_NV_WRITTEN = SET; 1449 result = NvWriteIndexInfo(handle, nvIndex); 1450 if(result != TPM_RC_SUCCESS) 1451 return result; 1452 } 1453 // Check to see if process for an orderly index is required. 1454 if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET) 1455 { 1456 UINT32 ramAddr; 1457 // Write data to RAM buffer 1458 ramAddr = NvGetRAMIndexOffset(handle); 1459 MemoryCopy(s_ramIndex + ramAddr + offset, data, size, 1460 sizeof(s_ramIndex) - ramAddr - offset); 1461 // NV update does not happen for orderly index. Have 1462 // to clear orderlyState to reflect that we have changed the 1463 // NV and an orderly shutdown is required. Only going to do this if we 1464 // are not processing a counter that has just rolled over 1465 if(g_updateNV == FALSE) 1466 g_clearOrderly = TRUE; 1467 } 1468 // Need to process this part if the Index isn't orderly or if it is 1469 // an orderly counter that just rolled over. 1470 if(g_updateNV || nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == CLEAR) 1471 { 1472 // Processing for an index with TPMA_NV_ORDERLY CLEAR 1473 UINT32 entryAddr = NvFindHandle(handle); 1474 pAssert(entryAddr != 0); 1475 // 1476 // Offset into the index to the first byte of the data to be written 1477 entryAddr += sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + offset; 1478 // If the data is actually changed, then a write to NV is required 1479 if(_plat__NvIsDifferent(entryAddr, size, data)) 1480 { 1481 // Make sure that NV is available 1482 result = NvIsAvailable(); 1483 if(result != TPM_RC_SUCCESS) 1484 return result; 1485 _plat__NvMemoryWrite(entryAddr, size, data); 1486 g_updateNV = TRUE; 1487 } 1488 } 1489 return TPM_RC_SUCCESS; 1490 } 1491 // 1492 // 1493 // NvGetName() 1494 // 1495 // This function is used to compute the Name of an NV Index. 1496 // The name buffer receives the bytes of the Name and the return value is the number of octets in the 1497 // Name. 1498 // This function requires that the NV Index is defined. 1499 // 1500 UINT16 1501 NvGetName( 1502 TPMI_RH_NV_INDEX handle, // IN: handle of the index 1503 NAME *name // OUT: name of the index 1504 ) 1505 { 1506 UINT16 dataSize, digestSize; 1507 NV_INDEX nvIndex; 1508 BYTE marshalBuffer[sizeof(TPMS_NV_PUBLIC)]; 1509 BYTE *buffer; 1510 INT32 bufferSize; 1511 HASH_STATE hashState; 1512 // Get NV public info 1513 NvGetIndexInfo(handle, &nvIndex); 1514 // Marshal public area 1515 buffer = marshalBuffer; 1516 bufferSize = sizeof(TPMS_NV_PUBLIC); 1517 dataSize = TPMS_NV_PUBLIC_Marshal(&nvIndex.publicArea, &buffer, &bufferSize); 1518 // hash public area 1519 digestSize = CryptStartHash(nvIndex.publicArea.nameAlg, &hashState); 1520 CryptUpdateDigest(&hashState, dataSize, marshalBuffer); 1521 // Complete digest leaving room for the nameAlg 1522 CryptCompleteHash(&hashState, digestSize, &((BYTE *)name)[2]); 1523 // Include the nameAlg 1524 UINT16_TO_BYTE_ARRAY(nvIndex.publicArea.nameAlg, (BYTE *)name); 1525 return digestSize + 2; 1526 } 1527 // 1528 // 1529 // NvDefineIndex() 1530 // 1531 // This function is used to assign NV memory to an NV Index. 1532 // 1533 // 1534 // 1535 // Error Returns Meaning 1536 // 1537 // TPM_RC_NV_SPACE insufficient NV space 1538 // 1539 TPM_RC 1540 NvDefineIndex( 1541 TPMS_NV_PUBLIC *publicArea, // IN: A template for an area to create. 1542 TPM2B_AUTH *authValue // IN: The initial authorization value 1543 ) 1544 { 1545 // The buffer to be written to NV memory 1546 BYTE nvBuffer[sizeof(TPM_HANDLE) + sizeof(NV_INDEX)]; 1547 NV_INDEX *nvIndex; // a pointer to the NV_INDEX data in 1548 // nvBuffer 1549 UINT16 entrySize; // size of entry 1550 entrySize = sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + publicArea->dataSize; 1551 // Check if we have enough space to create the NV Index 1552 // In this implementation, the only resource limitation is the available NV 1553 // space. Other implementation may have other limitation on counter or on 1554 // NV slot 1555 if(!NvTestSpace(entrySize, TRUE)) return TPM_RC_NV_SPACE; 1556 // if the index to be defined is RAM backed, check RAM space availability 1557 // as well 1558 if(publicArea->attributes.TPMA_NV_ORDERLY == SET 1559 && !NvTestRAMSpace(publicArea->dataSize)) 1560 return TPM_RC_NV_SPACE; 1561 // Copy input value to nvBuffer 1562 // Copy handle 1563 memcpy(nvBuffer, &publicArea->nvIndex, sizeof(TPM_HANDLE)); 1564 // Copy NV_INDEX 1565 nvIndex = (NV_INDEX *) (nvBuffer + sizeof(TPM_HANDLE)); 1566 nvIndex->publicArea = *publicArea; 1567 nvIndex->authValue = *authValue; 1568 // Add index to NV memory 1569 NvAdd(entrySize, sizeof(TPM_HANDLE) + sizeof(NV_INDEX), nvBuffer); 1570 // If the data of NV Index is RAM backed, add the data area in RAM as well 1571 if(publicArea->attributes.TPMA_NV_ORDERLY == SET) 1572 NvAddRAM(publicArea->nvIndex, publicArea->dataSize); 1573 return TPM_RC_SUCCESS; 1574 } 1575 1576 // 1577 // 1578 // NvMarshalObject() 1579 // 1580 // This function marshals the passed in OBJECT structure into a buffer. A 1581 // pointer to pointer to the buffer and a pointer to the size of the 1582 // buffer are passed in for this function to update as appropriate. 1583 // 1584 // On top of marshaling the object, this function also modifies one of 1585 // the object's properties and sets the evictHandle field of the 1586 // marshaled object to the requested value. 1587 // 1588 // Returns 1589 // 1590 // Marshaled size of the object. 1591 // 1592 static UINT16 NvMarshalObject(OBJECT *o, TPMI_DH_OBJECT evictHandle, 1593 BYTE **buf, INT32 *size) 1594 { 1595 UINT16 marshaledSize; 1596 OBJECT_ATTRIBUTES stored_attributes; 1597 1598 stored_attributes = o->attributes; 1599 stored_attributes.evict = SET; 1600 marshaledSize = sizeof(stored_attributes); 1601 MemoryCopy(*buf, &stored_attributes, marshaledSize, *size); 1602 *buf += marshaledSize; 1603 *size -= marshaledSize; 1604 1605 marshaledSize += TPMT_PUBLIC_Marshal(&o->publicArea, buf, size); 1606 marshaledSize += TPMT_SENSITIVE_Marshal(&o->sensitive, buf, size); 1607 #ifdef TPM_ALG_RSA 1608 marshaledSize += TPM2B_PUBLIC_KEY_RSA_Marshal(&o->privateExponent, 1609 buf, size); 1610 #endif 1611 marshaledSize += TPM2B_NAME_Marshal(&o->qualifiedName, buf, size); 1612 1613 // Use the supplied handle instead of the object contents. 1614 marshaledSize += TPMI_DH_OBJECT_Marshal(&evictHandle, buf, size); 1615 marshaledSize += TPM2B_NAME_Marshal(&o->name, buf, size); 1616 1617 return marshaledSize; 1618 } 1619 1620 // 1621 // 1622 // NvAddEvictObject() 1623 // 1624 // This function is used to assign NV memory to a persistent object. 1625 // 1626 // Error Returns Meaning 1627 // 1628 // TPM_RC_NV_HANDLE the requested handle is already in use 1629 // TPM_RC_NV_SPACE insufficient NV space 1630 // 1631 TPM_RC 1632 NvAddEvictObject( 1633 TPMI_DH_OBJECT evictHandle, // IN: new evict handle 1634 // 1635 OBJECT *object // IN: object to be added 1636 ) 1637 { 1638 // The buffer to be written to NV memory 1639 BYTE nvBuffer[sizeof(TPM_HANDLE) + sizeof(OBJECT)]; 1640 UINT16 entrySize; // size of entry 1641 BYTE *marshalSpace; 1642 INT32 marshalRoom; 1643 1644 // evict handle type should match the object hierarchy 1645 pAssert( ( NvIsPlatformPersistentHandle(evictHandle) 1646 && object->attributes.ppsHierarchy == SET) 1647 || ( NvIsOwnerPersistentHandle(evictHandle) 1648 && ( object->attributes.spsHierarchy == SET 1649 || object->attributes.epsHierarchy == SET))); 1650 1651 // Do not attemp storing a duplicate handle. 1652 if(!NvIsUndefinedEvictHandle(evictHandle)) 1653 return TPM_RC_NV_DEFINED; 1654 1655 // Copy handle 1656 entrySize = sizeof(TPM_HANDLE); 1657 memcpy(nvBuffer, &evictHandle, entrySize); 1658 1659 // Let's serialize the object before storing it in NVMEM 1660 marshalSpace = nvBuffer + entrySize; 1661 marshalRoom = sizeof(nvBuffer) - entrySize; 1662 entrySize += NvMarshalObject(object, evictHandle, 1663 &marshalSpace, &marshalRoom); 1664 1665 // Check if we have enough space to add this evict object 1666 if(!NvTestSpace(entrySize, FALSE)) return TPM_RC_NV_SPACE; 1667 1668 // Add evict to NV memory 1669 NvAdd(entrySize, entrySize, nvBuffer); 1670 return TPM_RC_SUCCESS; 1671 } 1672 // 1673 // 1674 // NvDeleteEntity() 1675 // 1676 // This function will delete a NV Index or an evict object. 1677 // This function requires that the index/evict object has been defined. 1678 // 1679 void 1680 NvDeleteEntity( 1681 TPM_HANDLE handle // IN: handle of entity to be deleted 1682 ) 1683 { 1684 UINT32 entityAddr; // pointer to entity 1685 entityAddr = NvFindHandle(handle); 1686 pAssert(entityAddr != 0); 1687 if(HandleGetType(handle) == TPM_HT_NV_INDEX) 1688 { 1689 NV_INDEX nvIndex; 1690 // Read the NV Index info 1691 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX), 1692 &nvIndex); 1693 // If the entity to be deleted is a counter with the maximum counter 1694 // value, record it in NV memory 1695 if(nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET 1696 && nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET) 1697 { 1698 UINT64 countValue; 1699 UINT64 maxCount; 1700 NvGetIntIndexData(handle, &nvIndex, &countValue); 1701 maxCount = NvReadMaxCount(); 1702 if(countValue > maxCount) 1703 NvWriteMaxCount(countValue); 1704 } 1705 // If the NV Index is RAM back, delete the RAM data as well 1706 if(nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == SET) 1707 NvDeleteRAM(handle); 1708 } 1709 NvDelete(entityAddr); 1710 return; 1711 } 1712 // 1713 // 1714 // NvFlushHierarchy() 1715 // 1716 // This function will delete persistent objects belonging to the indicated If the storage hierarchy is selected, 1717 // the function will also delete any NV Index define using ownerAuth. 1718 // 1719 void 1720 NvFlushHierarchy( 1721 TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flushed. 1722 ) 1723 { 1724 NV_ITER iter = NV_ITER_INIT; 1725 UINT32 currentAddr; 1726 while((currentAddr = NvNext(&iter)) != 0) 1727 { 1728 TPM_HANDLE entityHandle; 1729 // Read handle information. 1730 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle); 1731 if(HandleGetType(entityHandle) == TPM_HT_NV_INDEX) 1732 { 1733 // Handle NV Index 1734 NV_INDEX nvIndex; 1735 // If flush endorsement or platform hierarchy, no NV Index would be 1736 // flushed 1737 if(hierarchy == TPM_RH_ENDORSEMENT || hierarchy == TPM_RH_PLATFORM) 1738 continue; 1739 _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE), 1740 sizeof(NV_INDEX), &nvIndex); 1741 // For storage hierarchy, flush OwnerCreated index 1742 if( nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == CLEAR) 1743 { 1744 // Delete the NV Index 1745 NvDelete(currentAddr); 1746 // Re-iterate from beginning after a delete 1747 iter = NV_ITER_INIT; 1748 // If the NV Index is RAM back, delete the RAM data as well 1749 if(nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == SET) 1750 NvDeleteRAM(entityHandle); 1751 } 1752 } 1753 else if(HandleGetType(entityHandle) == TPM_HT_PERSISTENT) 1754 { 1755 OBJECT object; 1756 // Get evict object 1757 NvGetEvictObject(entityHandle, &object); 1758 // If the evict object belongs to the hierarchy to be flushed 1759 if( ( hierarchy == TPM_RH_PLATFORM 1760 && object.attributes.ppsHierarchy == SET) 1761 || ( hierarchy == TPM_RH_OWNER 1762 && object.attributes.spsHierarchy == SET) 1763 || ( hierarchy == TPM_RH_ENDORSEMENT 1764 && object.attributes.epsHierarchy == SET) 1765 ) 1766 { 1767 // Delete the evict object 1768 NvDelete(currentAddr); 1769 // Re-iterate from beginning after a delete 1770 iter = NV_ITER_INIT; 1771 } 1772 } 1773 else 1774 { 1775 pAssert(FALSE); 1776 } 1777 } 1778 return; 1779 } 1780 // 1781 // 1782 // NvSetGlobalLock() 1783 // 1784 // This function is used to SET the TPMA_NV_WRITELOCKED attribute for all NV Indices that have 1785 // TPMA_NV_GLOBALLOCK SET. This function is use by TPM2_NV_GlobalWriteLock(). 1786 // 1787 void 1788 NvSetGlobalLock( 1789 void 1790 ) 1791 { 1792 NV_ITER iter = NV_ITER_INIT; 1793 UINT32 currentAddr; 1794 // Check all Indices 1795 while((currentAddr = NvNextIndex(&iter)) != 0) 1796 { 1797 NV_INDEX nvIndex; 1798 // Read the index data 1799 _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE), 1800 sizeof(NV_INDEX), &nvIndex); 1801 // See if it should be locked 1802 if(nvIndex.publicArea.attributes.TPMA_NV_GLOBALLOCK == SET) 1803 { 1804 // if so, lock it 1805 nvIndex.publicArea.attributes.TPMA_NV_WRITELOCKED = SET; 1806 _plat__NvMemoryWrite(currentAddr + sizeof(TPM_HANDLE), 1807 sizeof(NV_INDEX), &nvIndex); 1808 // Set the flag that a NV write happens 1809 g_updateNV = TRUE; 1810 } 1811 } 1812 return; 1813 } 1814 // 1815 // 1816 // InsertSort() 1817 // 1818 // Sort a handle into handle list in ascending order. The total handle number in the list should not exceed 1819 // MAX_CAP_HANDLES 1820 // 1821 static void 1822 InsertSort( 1823 TPML_HANDLE *handleList, // IN/OUT: sorted handle list 1824 UINT32 count, // IN: maximum count in the handle list 1825 TPM_HANDLE entityHandle // IN: handle to be inserted 1826 ) 1827 { 1828 UINT32 i, j; 1829 UINT32 originalCount; 1830 // For a corner case that the maximum count is 0, do nothing 1831 if(count == 0) return; 1832 // For empty list, add the handle at the beginning and return 1833 if(handleList->count == 0) 1834 { 1835 handleList->handle[0] = entityHandle; 1836 handleList->count++; 1837 return; 1838 } 1839 // Check if the maximum of the list has been reached 1840 originalCount = handleList->count; 1841 if(originalCount < count) 1842 handleList->count++; 1843 // Insert the handle to the list 1844 for(i = 0; i < originalCount; i++) 1845 { 1846 if(handleList->handle[i] > entityHandle) 1847 { 1848 for(j = handleList->count - 1; j > i; j--) 1849 { 1850 handleList->handle[j] = handleList->handle[j-1]; 1851 } 1852 break; 1853 } 1854 } 1855 // If a slot was found, insert the handle in this position 1856 if(i < originalCount || handleList->count > originalCount) 1857 handleList->handle[i] = entityHandle; 1858 return; 1859 } 1860 // 1861 // 1862 // NvCapGetPersistent() 1863 // 1864 // This function is used to get a list of handles of the persistent objects, starting at handle. 1865 // Handle must be in valid persistent object handle range, but does not have to reference an existing 1866 // persistent object. 1867 // 1868 // Return Value Meaning 1869 // 1870 // YES if there are more handles available 1871 // NO all the available handles has been returned 1872 // 1873 TPMI_YES_NO 1874 NvCapGetPersistent( 1875 TPMI_DH_OBJECT handle, // IN: start handle 1876 UINT32 count, // IN: maximum number of returned handle 1877 TPML_HANDLE *handleList // OUT: list of handle 1878 ) 1879 { 1880 TPMI_YES_NO more = NO; 1881 NV_ITER iter = NV_ITER_INIT; 1882 UINT32 currentAddr; 1883 pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT); 1884 // Initialize output handle list 1885 handleList->count = 0; 1886 // The maximum count of handles we may return is MAX_CAP_HANDLES 1887 if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; 1888 while((currentAddr = NvNextEvict(&iter)) != 0) 1889 { 1890 TPM_HANDLE entityHandle; 1891 // Read handle information. 1892 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle); 1893 // Ignore persistent handles that have values less than the input handle 1894 if(entityHandle < handle) 1895 continue; 1896 // if the handles in the list have reached the requested count, and there 1897 // are still handles need to be inserted, indicate that there are more. 1898 if(handleList->count == count) 1899 more = YES; 1900 // A handle with a value larger than start handle is a candidate 1901 // for return. Insert sort it to the return list. Insert sort algorithm 1902 // is chosen here for simplicity based on the assumption that the total 1903 // number of NV Indices is small. For an implementation that may allow 1904 // large number of NV Indices, a more efficient sorting algorithm may be 1905 // used here. 1906 InsertSort(handleList, count, entityHandle); 1907 // 1908 } 1909 return more; 1910 } 1911 // 1912 // 1913 // NvCapGetIndex() 1914 // 1915 // This function returns a list of handles of NV Indices, starting from handle. Handle must be in the range of 1916 // NV Indices, but does not have to reference an existing NV Index. 1917 // 1918 // Return Value Meaning 1919 // 1920 // YES if there are more handles to report 1921 // NO all the available handles has been reported 1922 // 1923 TPMI_YES_NO 1924 NvCapGetIndex( 1925 TPMI_DH_OBJECT handle, // IN: start handle 1926 UINT32 count, // IN: maximum number of returned handle 1927 TPML_HANDLE *handleList // OUT: list of handle 1928 ) 1929 { 1930 TPMI_YES_NO more = NO; 1931 NV_ITER iter = NV_ITER_INIT; 1932 UINT32 currentAddr; 1933 pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX); 1934 // Initialize output handle list 1935 handleList->count = 0; 1936 // The maximum count of handles we may return is MAX_CAP_HANDLES 1937 if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; 1938 while((currentAddr = NvNextIndex(&iter)) != 0) 1939 { 1940 TPM_HANDLE entityHandle; 1941 // Read handle information. 1942 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle); 1943 // Ignore index handles that have values less than the 'handle' 1944 if(entityHandle < handle) 1945 continue; 1946 // if the count of handles in the list has reached the requested count, 1947 // and there are still handles to report, set more. 1948 if(handleList->count == count) 1949 more = YES; 1950 // A handle with a value larger than start handle is a candidate 1951 // for return. Insert sort it to the return list. Insert sort algorithm 1952 // is chosen here for simplicity based on the assumption that the total 1953 // number of NV Indices is small. For an implementation that may allow 1954 // large number of NV Indices, a more efficient sorting algorithm may be 1955 // used here. 1956 InsertSort(handleList, count, entityHandle); 1957 } 1958 return more; 1959 } 1960 // 1961 // 1962 // 1963 // NvCapGetIndexNumber() 1964 // 1965 // This function returns the count of NV Indexes currently defined. 1966 // 1967 UINT32 1968 NvCapGetIndexNumber( 1969 void 1970 ) 1971 { 1972 UINT32 num = 0; 1973 NV_ITER iter = NV_ITER_INIT; 1974 while(NvNextIndex(&iter) != 0) num++; 1975 return num; 1976 } 1977 // 1978 // 1979 // NvCapGetPersistentNumber() 1980 // 1981 // Function returns the count of persistent objects currently in NV memory. 1982 // 1983 UINT32 1984 NvCapGetPersistentNumber( 1985 void 1986 ) 1987 { 1988 UINT32 num = 0; 1989 NV_ITER iter = NV_ITER_INIT; 1990 while(NvNextEvict(&iter) != 0) num++; 1991 return num; 1992 } 1993 // 1994 // 1995 // NvCapGetPersistentAvail() 1996 // 1997 // This function returns an estimate of the number of additional persistent objects that could be loaded into 1998 // NV memory. 1999 // 2000 UINT32 2001 NvCapGetPersistentAvail( 2002 void 2003 ) 2004 { 2005 UINT32 availSpace; 2006 UINT32 objectSpace; 2007 // Compute the available space in NV storage 2008 availSpace = NvGetFreeByte(); 2009 // Get the space needed to add a persistent object to NV storage 2010 objectSpace = NvGetEvictObjectSize(); 2011 return availSpace / objectSpace; 2012 } 2013 // 2014 // 2015 // NvCapGetCounterNumber() 2016 // 2017 // Get the number of defined NV Indexes that have NV TPMA_NV_COUNTER attribute SET. 2018 // 2019 // 2020 UINT32 2021 NvCapGetCounterNumber( 2022 void 2023 ) 2024 { 2025 NV_ITER iter = NV_ITER_INIT; 2026 UINT32 currentAddr; 2027 UINT32 num = 0; 2028 while((currentAddr = NvNextIndex(&iter)) != 0) 2029 { 2030 NV_INDEX nvIndex; 2031 // Get NV Index info 2032 _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE), 2033 sizeof(NV_INDEX), &nvIndex); 2034 if(nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET) num++; 2035 } 2036 return num; 2037 } 2038 // 2039 // 2040 // NvCapGetCounterAvail() 2041 // 2042 // This function returns an estimate of the number of additional counter type NV Indices that can be defined. 2043 // 2044 UINT32 2045 NvCapGetCounterAvail( 2046 void 2047 ) 2048 { 2049 UINT32 availNVSpace; 2050 UINT32 availRAMSpace; 2051 UINT32 counterNVSpace; 2052 UINT32 counterRAMSpace; 2053 UINT32 persistentNum = NvCapGetPersistentNumber(); 2054 // Get the available space in NV storage 2055 availNVSpace = NvGetFreeByte(); 2056 if (persistentNum < MIN_EVICT_OBJECTS) 2057 { 2058 // Some space have to be reserved for evict object. Adjust availNVSpace. 2059 UINT32 reserved = (MIN_EVICT_OBJECTS - persistentNum) 2060 * NvGetEvictObjectSize(); 2061 if (reserved > availNVSpace) 2062 availNVSpace = 0; 2063 else 2064 availNVSpace -= reserved; 2065 } 2066 // Get the space needed to add a counter index to NV storage 2067 counterNVSpace = NvGetCounterSize(); 2068 // Compute the available space in RAM 2069 availRAMSpace = RAM_INDEX_SPACE - s_ramIndexSize; 2070 // Compute the space needed to add a counter index to RAM storage 2071 // It takes an size field, a handle and sizeof(UINT64) for counter data 2072 counterRAMSpace = sizeof(UINT32) + sizeof(TPM_HANDLE) + sizeof(UINT64); 2073 // Return the min of counter number in NV and in RAM 2074 if(availNVSpace / counterNVSpace > availRAMSpace / counterRAMSpace) 2075 return availRAMSpace / counterRAMSpace; 2076 else 2077 return availNVSpace / counterNVSpace; 2078 } 2079