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 if(gc.shEnable == FALSE) 1050 return TPM_RC_HANDLE; 1051 } 1052 // if phEnableNV is CLEAR, a platform created Index should not 1053 // be visible 1054 else if(gc.phEnableNV == FALSE) 1055 return TPM_RC_HANDLE; 1056 } 1057 // If the Index is write locked and this is an NV Write operation... 1058 if( nvIndex.publicArea.attributes.TPMA_NV_WRITELOCKED 1059 && IsWriteOperation(commandCode)) 1060 { 1061 // then return a locked indication unless the command is TPM2_NV_WriteLock 1062 if(commandCode != TPM_CC_NV_WriteLock) 1063 return TPM_RC_NV_LOCKED; 1064 return TPM_RC_SUCCESS; 1065 } 1066 // If the Index is read locked and this is an NV Read operation... 1067 if( nvIndex.publicArea.attributes.TPMA_NV_READLOCKED 1068 && IsReadOperation(commandCode)) 1069 { 1070 // then return a locked indication unless the command is TPM2_NV_ReadLock 1071 if(commandCode != TPM_CC_NV_ReadLock) 1072 return TPM_RC_NV_LOCKED; 1073 return TPM_RC_SUCCESS; 1074 } 1075 // NV Index is accessible 1076 return TPM_RC_SUCCESS; 1077 } 1078 // 1079 // 1080 // NvIsUndefinedEvictHandle() 1081 // 1082 // This function indicates if a handle does not reference an existing persistent object. This function requires 1083 // that the handle be in the proper range for persistent objects. 1084 // 1085 // Return Value Meaning 1086 // 1087 // TRUE handle does not reference an existing persistent object 1088 // FALSE handle does reference an existing persistent object 1089 // 1090 static BOOL 1091 NvIsUndefinedEvictHandle( 1092 TPM_HANDLE handle // IN: handle 1093 ) 1094 { 1095 UINT32 entityAddr; // offset points to the entity 1096 pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT); 1097 // Find the address of evict object 1098 entityAddr = NvFindHandle(handle); 1099 // If handle is not found, return TRUE 1100 if(entityAddr == 0) 1101 return TRUE; 1102 else 1103 return FALSE; 1104 } 1105 1106 // 1107 // 1108 // NvUnmarshalObject() 1109 // 1110 // This function accepts a buffer containing a marshaled OBJECT 1111 // structure, a pointer to the area where the input data should be 1112 // unmarshaled, and a pointer to the size of the output area. 1113 // 1114 // No error checking is performed, unmarshaled data is guaranteed not to 1115 // spill over the allocated space. 1116 // 1117 static TPM_RC NvUnmarshalObject(OBJECT *o, BYTE **buf, INT32 *size) 1118 { 1119 TPM_RC result; 1120 1121 // There is no generated function to unmarshal the attributes field, do it 1122 // by hand. 1123 MemoryCopy(&o->attributes, *buf, sizeof(o->attributes), *size); 1124 *buf += sizeof(o->attributes); 1125 *size -= sizeof(o->attributes); 1126 1127 result = TPMT_PUBLIC_Unmarshal(&o->publicArea, buf, size); 1128 if (result != TPM_RC_SUCCESS) 1129 return result; 1130 1131 result = TPMT_SENSITIVE_Unmarshal(&o->sensitive, buf, size); 1132 if (result != TPM_RC_SUCCESS) 1133 return result; 1134 1135 #ifdef TPM_ALG_RSA 1136 result = TPM2B_PUBLIC_KEY_RSA_Unmarshal(&o->privateExponent, buf, size); 1137 if (result != TPM_RC_SUCCESS) 1138 return result; 1139 #endif 1140 1141 result = TPM2B_NAME_Unmarshal(&o->qualifiedName, buf, size); 1142 if (result != TPM_RC_SUCCESS) 1143 return result; 1144 1145 result = TPMI_DH_OBJECT_Unmarshal(&o->evictHandle, buf, size, TRUE); 1146 if (result != TPM_RC_SUCCESS) 1147 return result; 1148 1149 return TPM2B_NAME_Unmarshal(&o->name, buf, size); 1150 } 1151 1152 // 1153 // 1154 // NvGetEvictObject() 1155 // 1156 // This function is used to dereference an evict object handle and get a pointer to the object. 1157 // 1158 // Error Returns Meaning 1159 // 1160 // TPM_RC_HANDLE the handle does not point to an existing persistent object 1161 // 1162 TPM_RC 1163 NvGetEvictObject( 1164 TPM_HANDLE handle, // IN: handle 1165 OBJECT *object // OUT: object data 1166 ) 1167 { 1168 UINT32 entityAddr; // offset points to the entity 1169 TPM_RC result = TPM_RC_SUCCESS; 1170 pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT); 1171 // Find the address of evict object 1172 entityAddr = NvFindHandle(handle); 1173 // If handle is not found, return an error 1174 if(entityAddr == 0) { 1175 result = TPM_RC_HANDLE; 1176 } else { 1177 UINT32 storedSize; 1178 UINT32 nextEntryAddr; 1179 1180 // Let's calculate the size of object as stored in NVMEM. 1181 _plat__NvMemoryRead(entityAddr - sizeof(UINT32), 1182 sizeof(UINT32), &nextEntryAddr); 1183 1184 storedSize = nextEntryAddr - entityAddr; 1185 1186 if (storedSize == (sizeof(TPM_HANDLE) + sizeof(OBJECT))) { 1187 // Read evict object stored unmarshaled. 1188 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), 1189 sizeof(OBJECT), 1190 object); 1191 } else { 1192 // Must be stored marshaled, let's unmarshal it. 1193 BYTE marshaled[sizeof(OBJECT)]; 1194 INT32 max_size = sizeof(marshaled); 1195 BYTE *marshaledPtr = marshaled; 1196 1197 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), 1198 storedSize, marshaled); 1199 result = NvUnmarshalObject(object, &marshaledPtr, &max_size); 1200 } 1201 } 1202 // whether there is an error or not, make sure that the evict 1203 // status of the object is set so that the slot will get freed on exit 1204 object->attributes.evict = SET; 1205 return result; 1206 } 1207 // 1208 // 1209 // NvGetIndexInfo() 1210 // 1211 // This function is used to retrieve the contents of an NV Index. 1212 // An implementation is allowed to save the NV Index in a vendor-defined format. If the format is different 1213 // from the default used by the reference code, then this function would be changed to reformat the data into 1214 // the default format. 1215 // A prerequisite to calling this function is that the handle must be known to reference a defined NV Index. 1216 // 1217 void 1218 NvGetIndexInfo( 1219 TPMI_RH_NV_INDEX handle, // IN: handle 1220 NV_INDEX *nvIndex // OUT: NV index structure 1221 ) 1222 { 1223 UINT32 entityAddr; // offset points to the entity 1224 pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX); 1225 // Find the address of NV index 1226 entityAddr = NvFindHandle(handle); 1227 pAssert(entityAddr != 0); 1228 // This implementation uses the default format so just 1229 // read the data in 1230 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX), 1231 nvIndex); 1232 return; 1233 } 1234 // 1235 // 1236 // NvInitialCounter() 1237 // 1238 // This function returns the value to be used when a counter index is initialized. It will scan the NV counters 1239 // and find the highest value in any active counter. It will use that value as the starting point. If there are no 1240 // active counters, it will use the value of the previous largest counter. 1241 // 1242 UINT64 1243 NvInitialCounter( 1244 void 1245 ) 1246 { 1247 UINT64 maxCount; 1248 NV_ITER iter = NV_ITER_INIT; 1249 UINT32 currentAddr; 1250 // Read the maxCount value 1251 maxCount = NvReadMaxCount(); 1252 // Iterate all existing counters 1253 while((currentAddr = NvNextIndex(&iter)) != 0) 1254 { 1255 TPMI_RH_NV_INDEX nvHandle; 1256 NV_INDEX nvIndex; 1257 // Read NV handle 1258 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &nvHandle); 1259 // Get NV Index 1260 NvGetIndexInfo(nvHandle, &nvIndex); 1261 if( nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET 1262 && nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET) 1263 { 1264 UINT64 countValue; 1265 // Read counter value 1266 NvGetIntIndexData(nvHandle, &nvIndex, &countValue); 1267 if(countValue > maxCount) 1268 maxCount = countValue; 1269 } 1270 } 1271 // Initialize the new counter value to be maxCount + 1 1272 // A counter is only initialized the first time it is written. The 1273 // way to write a counter is with TPM2_NV_INCREMENT(). Since the 1274 // "initial" value of a defined counter is the largest count value that 1275 // may have existed in this index previously, then the first use would 1276 // add one to that value. 1277 return maxCount; 1278 } 1279 // 1280 // 1281 // NvGetIndexData() 1282 // 1283 // This function is used to access the data in an NV Index. The data is returned as a byte sequence. Since 1284 // counter values are kept in native format, they are converted to canonical form before being returned. 1285 // Family "2.0" TCG Published Page 139 1286 // Level 00 Revision 01.16 Copyright TCG 2006-2014 October 30, 2014 1287 // Trusted Platform Module Library Part 4: Supporting Routines 1289 // 1290 // 1291 // This function requires that the NV Index be defined, and that the required data is within the data range. It 1292 // also requires that TPMA_NV_WRITTEN of the Index is SET. 1293 // 1294 void 1295 NvGetIndexData( 1296 TPMI_RH_NV_INDEX handle, // IN: handle 1297 NV_INDEX *nvIndex, // IN: RAM image of index header 1298 UINT32 offset, // IN: offset of NV data 1299 UINT16 size, // IN: size of NV data 1300 void *data // OUT: data buffer 1301 ) 1302 { 1303 pAssert(nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == SET); 1304 if( nvIndex->publicArea.attributes.TPMA_NV_BITS == SET 1305 || nvIndex->publicArea.attributes.TPMA_NV_COUNTER == SET) 1306 { 1307 // Read bit or counter data in canonical form 1308 UINT64 dataInInt; 1309 NvGetIntIndexData(handle, nvIndex, &dataInInt); 1310 UINT64_TO_BYTE_ARRAY(dataInInt, (BYTE *)data); 1311 } 1312 else 1313 { 1314 if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET) 1315 { 1316 UINT32 ramAddr; 1317 // Get data from RAM buffer 1318 ramAddr = NvGetRAMIndexOffset(handle); 1319 MemoryCopy(data, s_ramIndex + ramAddr + offset, size, size); 1320 } 1321 else 1322 { 1323 UINT32 entityAddr; 1324 entityAddr = NvFindHandle(handle); 1325 // Get data from NV 1326 // Skip NV Index info, read data buffer 1327 entityAddr += sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + offset; 1328 // Read the data 1329 _plat__NvMemoryRead(entityAddr, size, data); 1330 } 1331 } 1332 return; 1333 } 1334 // 1335 // 1336 // NvGetIntIndexData() 1337 // 1338 // Get data in integer format of a bit or counter NV Index. 1339 // This function requires that the NV Index is defined and that the NV Index previously has been written. 1340 // 1341 void 1342 NvGetIntIndexData( 1343 TPMI_RH_NV_INDEX handle, // IN: handle 1344 NV_INDEX *nvIndex, // IN: RAM image of NV Index header 1345 UINT64 *data // IN: UINT64 pointer for counter or bit 1346 ) 1347 { 1348 // Validate that index has been written and is the right type 1349 pAssert( nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == SET 1350 && ( nvIndex->publicArea.attributes.TPMA_NV_BITS == SET 1351 || nvIndex->publicArea.attributes.TPMA_NV_COUNTER == SET 1352 ) 1353 ); 1354 // bit and counter value is store in native format for TPM CPU. So we directly 1355 // copy the contents of NV to output data buffer 1356 if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET) 1357 { 1358 UINT32 ramAddr; 1359 // Get data from RAM buffer 1360 ramAddr = NvGetRAMIndexOffset(handle); 1361 MemoryCopy(data, s_ramIndex + ramAddr, sizeof(*data), sizeof(*data)); 1362 } 1363 else 1364 { 1365 UINT32 entityAddr; 1366 entityAddr = NvFindHandle(handle); 1367 // Get data from NV 1368 // Skip NV Index info, read data buffer 1369 _plat__NvMemoryRead( 1370 entityAddr + sizeof(TPM_HANDLE) + sizeof(NV_INDEX), 1371 sizeof(UINT64), data); 1372 } 1373 return; 1374 } 1375 // 1376 // 1377 // NvWriteIndexInfo() 1378 // 1379 // This function is called to queue the write of NV Index data to persistent memory. 1380 // This function requires that NV Index is defined. 1381 // 1382 // Error Returns Meaning 1383 // 1384 // TPM_RC_NV_RATE NV is rate limiting so retry 1385 // TPM_RC_NV_UNAVAILABLE NV is not available 1386 // 1387 TPM_RC 1388 NvWriteIndexInfo( 1389 TPMI_RH_NV_INDEX handle, // IN: handle 1390 NV_INDEX *nvIndex // IN: NV Index info to be written 1391 ) 1392 { 1393 UINT32 entryAddr; 1394 TPM_RC result; 1395 // Get the starting offset for the index in the RAM image of NV 1396 entryAddr = NvFindHandle(handle); 1397 pAssert(entryAddr != 0); 1398 // Step over the link value 1399 entryAddr = entryAddr + sizeof(TPM_HANDLE); 1400 // If the index data is actually changed, then a write to NV is required 1401 if(_plat__NvIsDifferent(entryAddr, sizeof(NV_INDEX),nvIndex)) 1402 { 1403 // Make sure that NV is available 1404 result = NvIsAvailable(); 1405 if(result != TPM_RC_SUCCESS) 1406 return result; 1407 _plat__NvMemoryWrite(entryAddr, sizeof(NV_INDEX), nvIndex); 1408 g_updateNV = TRUE; 1409 } 1410 return TPM_RC_SUCCESS; 1411 } 1412 // 1413 // 1414 // NvWriteIndexData() 1415 // 1416 // This function is used to write NV index data. 1417 // This function requires that the NV Index is defined, and the data is within the defined data range for the 1418 // index. 1419 // 1420 // Error Returns Meaning 1421 // 1422 // TPM_RC_NV_RATE NV is rate limiting so retry 1423 // TPM_RC_NV_UNAVAILABLE NV is not available 1424 // 1425 TPM_RC 1426 NvWriteIndexData( 1427 TPMI_RH_NV_INDEX handle, // IN: handle 1428 NV_INDEX *nvIndex, // IN: RAM copy of NV Index 1429 UINT32 offset, // IN: offset of NV data 1430 UINT32 size, // IN: size of NV data 1431 void *data // OUT: data buffer 1432 ) 1433 { 1434 TPM_RC result; 1435 // Validate that write falls within range of the index 1436 pAssert(nvIndex->publicArea.dataSize >= offset + size); 1437 // Update TPMA_NV_WRITTEN bit if necessary 1438 if(nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == CLEAR) 1439 { 1440 nvIndex->publicArea.attributes.TPMA_NV_WRITTEN = SET; 1441 result = NvWriteIndexInfo(handle, nvIndex); 1442 if(result != TPM_RC_SUCCESS) 1443 return result; 1444 } 1445 // Check to see if process for an orderly index is required. 1446 if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET) 1447 { 1448 UINT32 ramAddr; 1449 // Write data to RAM buffer 1450 ramAddr = NvGetRAMIndexOffset(handle); 1451 MemoryCopy(s_ramIndex + ramAddr + offset, data, size, 1452 sizeof(s_ramIndex) - ramAddr - offset); 1453 // NV update does not happen for orderly index. Have 1454 // to clear orderlyState to reflect that we have changed the 1455 // NV and an orderly shutdown is required. Only going to do this if we 1456 // are not processing a counter that has just rolled over 1457 if(g_updateNV == FALSE) 1458 g_clearOrderly = TRUE; 1459 } 1460 // Need to process this part if the Index isn't orderly or if it is 1461 // an orderly counter that just rolled over. 1462 if(g_updateNV || nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == CLEAR) 1463 { 1464 // Processing for an index with TPMA_NV_ORDERLY CLEAR 1465 UINT32 entryAddr = NvFindHandle(handle); 1466 pAssert(entryAddr != 0); 1467 // 1468 // Offset into the index to the first byte of the data to be written 1469 entryAddr += sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + offset; 1470 // If the data is actually changed, then a write to NV is required 1471 if(_plat__NvIsDifferent(entryAddr, size, data)) 1472 { 1473 // Make sure that NV is available 1474 result = NvIsAvailable(); 1475 if(result != TPM_RC_SUCCESS) 1476 return result; 1477 _plat__NvMemoryWrite(entryAddr, size, data); 1478 g_updateNV = TRUE; 1479 } 1480 } 1481 return TPM_RC_SUCCESS; 1482 } 1483 // 1484 // 1485 // NvGetName() 1486 // 1487 // This function is used to compute the Name of an NV Index. 1488 // The name buffer receives the bytes of the Name and the return value is the number of octets in the 1489 // Name. 1490 // This function requires that the NV Index is defined. 1491 // 1492 UINT16 1493 NvGetName( 1494 TPMI_RH_NV_INDEX handle, // IN: handle of the index 1495 NAME *name // OUT: name of the index 1496 ) 1497 { 1498 UINT16 dataSize, digestSize; 1499 NV_INDEX nvIndex; 1500 BYTE marshalBuffer[sizeof(TPMS_NV_PUBLIC)]; 1501 BYTE *buffer; 1502 INT32 bufferSize; 1503 HASH_STATE hashState; 1504 // Get NV public info 1505 NvGetIndexInfo(handle, &nvIndex); 1506 // Marshal public area 1507 buffer = marshalBuffer; 1508 bufferSize = sizeof(TPMS_NV_PUBLIC); 1509 dataSize = TPMS_NV_PUBLIC_Marshal(&nvIndex.publicArea, &buffer, &bufferSize); 1510 // hash public area 1511 digestSize = CryptStartHash(nvIndex.publicArea.nameAlg, &hashState); 1512 CryptUpdateDigest(&hashState, dataSize, marshalBuffer); 1513 // Complete digest leaving room for the nameAlg 1514 CryptCompleteHash(&hashState, digestSize, &((BYTE *)name)[2]); 1515 // Include the nameAlg 1516 UINT16_TO_BYTE_ARRAY(nvIndex.publicArea.nameAlg, (BYTE *)name); 1517 return digestSize + 2; 1518 } 1519 // 1520 // 1521 // NvDefineIndex() 1522 // 1523 // This function is used to assign NV memory to an NV Index. 1524 // 1525 // 1526 // 1527 // Error Returns Meaning 1528 // 1529 // TPM_RC_NV_SPACE insufficient NV space 1530 // 1531 TPM_RC 1532 NvDefineIndex( 1533 TPMS_NV_PUBLIC *publicArea, // IN: A template for an area to create. 1534 TPM2B_AUTH *authValue // IN: The initial authorization value 1535 ) 1536 { 1537 // The buffer to be written to NV memory 1538 BYTE nvBuffer[sizeof(TPM_HANDLE) + sizeof(NV_INDEX)]; 1539 NV_INDEX *nvIndex; // a pointer to the NV_INDEX data in 1540 // nvBuffer 1541 UINT16 entrySize; // size of entry 1542 entrySize = sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + publicArea->dataSize; 1543 // Check if we have enough space to create the NV Index 1544 // In this implementation, the only resource limitation is the available NV 1545 // space. Other implementation may have other limitation on counter or on 1546 // NV slot 1547 if(!NvTestSpace(entrySize, TRUE)) return TPM_RC_NV_SPACE; 1548 // if the index to be defined is RAM backed, check RAM space availability 1549 // as well 1550 if(publicArea->attributes.TPMA_NV_ORDERLY == SET 1551 && !NvTestRAMSpace(publicArea->dataSize)) 1552 return TPM_RC_NV_SPACE; 1553 // Copy input value to nvBuffer 1554 // Copy handle 1555 memcpy(nvBuffer, &publicArea->nvIndex, sizeof(TPM_HANDLE)); 1556 // Copy NV_INDEX 1557 nvIndex = (NV_INDEX *) (nvBuffer + sizeof(TPM_HANDLE)); 1558 nvIndex->publicArea = *publicArea; 1559 nvIndex->authValue = *authValue; 1560 // Add index to NV memory 1561 NvAdd(entrySize, sizeof(TPM_HANDLE) + sizeof(NV_INDEX), nvBuffer); 1562 // If the data of NV Index is RAM backed, add the data area in RAM as well 1563 if(publicArea->attributes.TPMA_NV_ORDERLY == SET) 1564 NvAddRAM(publicArea->nvIndex, publicArea->dataSize); 1565 return TPM_RC_SUCCESS; 1566 } 1567 1568 // 1569 // 1570 // NvMarshalObject() 1571 // 1572 // This function marshals the passed in OBJECT structure into a buffer. A 1573 // pointer to pointer to the buffer and a pointer to the size of the 1574 // buffer are passed in for this function to update as appropriate. 1575 // 1576 // On top of marshaling the object, this function also modifies one of 1577 // the object's properties and sets the evictHandle field of the 1578 // marshaled object to the requested value. 1579 // 1580 // Returns 1581 // 1582 // Marshaled size of the object. 1583 // 1584 static UINT16 NvMarshalObject(OBJECT *o, TPMI_DH_OBJECT evictHandle, 1585 BYTE **buf, INT32 *size) 1586 { 1587 UINT16 marshaledSize; 1588 OBJECT_ATTRIBUTES stored_attributes; 1589 1590 stored_attributes = o->attributes; 1591 stored_attributes.evict = SET; 1592 marshaledSize = sizeof(stored_attributes); 1593 MemoryCopy(*buf, &stored_attributes, marshaledSize, *size); 1594 *buf += marshaledSize; 1595 *size -= marshaledSize; 1596 1597 marshaledSize += TPMT_PUBLIC_Marshal(&o->publicArea, buf, size); 1598 marshaledSize += TPMT_SENSITIVE_Marshal(&o->sensitive, buf, size); 1599 #ifdef TPM_ALG_RSA 1600 marshaledSize += TPM2B_PUBLIC_KEY_RSA_Marshal(&o->privateExponent, 1601 buf, size); 1602 #endif 1603 marshaledSize += TPM2B_NAME_Marshal(&o->qualifiedName, buf, size); 1604 1605 // Use the supplied handle instead of the object contents. 1606 marshaledSize += TPMI_DH_OBJECT_Marshal(&evictHandle, buf, size); 1607 marshaledSize += TPM2B_NAME_Marshal(&o->name, buf, size); 1608 1609 return marshaledSize; 1610 } 1611 1612 // 1613 // 1614 // NvAddEvictObject() 1615 // 1616 // This function is used to assign NV memory to a persistent object. 1617 // 1618 // Error Returns Meaning 1619 // 1620 // TPM_RC_NV_HANDLE the requested handle is already in use 1621 // TPM_RC_NV_SPACE insufficient NV space 1622 // 1623 TPM_RC 1624 NvAddEvictObject( 1625 TPMI_DH_OBJECT evictHandle, // IN: new evict handle 1626 // 1627 OBJECT *object // IN: object to be added 1628 ) 1629 { 1630 // The buffer to be written to NV memory 1631 BYTE nvBuffer[sizeof(TPM_HANDLE) + sizeof(OBJECT)]; 1632 UINT16 entrySize; // size of entry 1633 BYTE *marshalSpace; 1634 INT32 marshalRoom; 1635 1636 // evict handle type should match the object hierarchy 1637 pAssert( ( NvIsPlatformPersistentHandle(evictHandle) 1638 && object->attributes.ppsHierarchy == SET) 1639 || ( NvIsOwnerPersistentHandle(evictHandle) 1640 && ( object->attributes.spsHierarchy == SET 1641 || object->attributes.epsHierarchy == SET))); 1642 1643 // Do not attemp storing a duplicate handle. 1644 if(!NvIsUndefinedEvictHandle(evictHandle)) 1645 return TPM_RC_NV_DEFINED; 1646 1647 // Copy handle 1648 entrySize = sizeof(TPM_HANDLE); 1649 memcpy(nvBuffer, &evictHandle, entrySize); 1650 1651 // Let's serialize the object before storing it in NVMEM 1652 marshalSpace = nvBuffer + entrySize; 1653 marshalRoom = sizeof(nvBuffer) - entrySize; 1654 entrySize += NvMarshalObject(object, evictHandle, 1655 &marshalSpace, &marshalRoom); 1656 1657 // Check if we have enough space to add this evict object 1658 if(!NvTestSpace(entrySize, FALSE)) return TPM_RC_NV_SPACE; 1659 1660 // Add evict to NV memory 1661 NvAdd(entrySize, entrySize, nvBuffer); 1662 return TPM_RC_SUCCESS; 1663 } 1664 // 1665 // 1666 // NvDeleteEntity() 1667 // 1668 // This function will delete a NV Index or an evict object. 1669 // This function requires that the index/evict object has been defined. 1670 // 1671 void 1672 NvDeleteEntity( 1673 TPM_HANDLE handle // IN: handle of entity to be deleted 1674 ) 1675 { 1676 UINT32 entityAddr; // pointer to entity 1677 entityAddr = NvFindHandle(handle); 1678 pAssert(entityAddr != 0); 1679 if(HandleGetType(handle) == TPM_HT_NV_INDEX) 1680 { 1681 NV_INDEX nvIndex; 1682 // Read the NV Index info 1683 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX), 1684 &nvIndex); 1685 // If the entity to be deleted is a counter with the maximum counter 1686 // value, record it in NV memory 1687 if(nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET 1688 && nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET) 1689 { 1690 UINT64 countValue; 1691 UINT64 maxCount; 1692 NvGetIntIndexData(handle, &nvIndex, &countValue); 1693 maxCount = NvReadMaxCount(); 1694 if(countValue > maxCount) 1695 NvWriteMaxCount(countValue); 1696 } 1697 // If the NV Index is RAM back, delete the RAM data as well 1698 if(nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == SET) 1699 NvDeleteRAM(handle); 1700 } 1701 NvDelete(entityAddr); 1702 return; 1703 } 1704 // 1705 // 1706 // NvFlushHierarchy() 1707 // 1708 // This function will delete persistent objects belonging to the indicated If the storage hierarchy is selected, 1709 // the function will also delete any NV Index define using ownerAuth. 1710 // 1711 void 1712 NvFlushHierarchy( 1713 TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flushed. 1714 ) 1715 { 1716 NV_ITER iter = NV_ITER_INIT; 1717 UINT32 currentAddr; 1718 while((currentAddr = NvNext(&iter)) != 0) 1719 { 1720 TPM_HANDLE entityHandle; 1721 // Read handle information. 1722 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle); 1723 if(HandleGetType(entityHandle) == TPM_HT_NV_INDEX) 1724 { 1725 // Handle NV Index 1726 NV_INDEX nvIndex; 1727 // If flush endorsement or platform hierarchy, no NV Index would be 1728 // flushed 1729 if(hierarchy == TPM_RH_ENDORSEMENT || hierarchy == TPM_RH_PLATFORM) 1730 continue; 1731 _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE), 1732 sizeof(NV_INDEX), &nvIndex); 1733 // For storage hierarchy, flush OwnerCreated index 1734 if( nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == CLEAR) 1735 { 1736 // Delete the NV Index 1737 NvDelete(currentAddr); 1738 // Re-iterate from beginning after a delete 1739 iter = NV_ITER_INIT; 1740 // If the NV Index is RAM back, delete the RAM data as well 1741 if(nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == SET) 1742 NvDeleteRAM(entityHandle); 1743 } 1744 } 1745 else if(HandleGetType(entityHandle) == TPM_HT_PERSISTENT) 1746 { 1747 OBJECT object; 1748 // Get evict object 1749 NvGetEvictObject(entityHandle, &object); 1750 // If the evict object belongs to the hierarchy to be flushed 1751 if( ( hierarchy == TPM_RH_PLATFORM 1752 && object.attributes.ppsHierarchy == SET) 1753 || ( hierarchy == TPM_RH_OWNER 1754 && object.attributes.spsHierarchy == SET) 1755 || ( hierarchy == TPM_RH_ENDORSEMENT 1756 && object.attributes.epsHierarchy == SET) 1757 ) 1758 { 1759 // Delete the evict object 1760 NvDelete(currentAddr); 1761 // Re-iterate from beginning after a delete 1762 iter = NV_ITER_INIT; 1763 } 1764 } 1765 else 1766 { 1767 pAssert(FALSE); 1768 } 1769 } 1770 return; 1771 } 1772 // 1773 // 1774 // NvSetGlobalLock() 1775 // 1776 // This function is used to SET the TPMA_NV_WRITELOCKED attribute for all NV Indices that have 1777 // TPMA_NV_GLOBALLOCK SET. This function is use by TPM2_NV_GlobalWriteLock(). 1778 // 1779 void 1780 NvSetGlobalLock( 1781 void 1782 ) 1783 { 1784 NV_ITER iter = NV_ITER_INIT; 1785 UINT32 currentAddr; 1786 // Check all Indices 1787 while((currentAddr = NvNextIndex(&iter)) != 0) 1788 { 1789 NV_INDEX nvIndex; 1790 // Read the index data 1791 _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE), 1792 sizeof(NV_INDEX), &nvIndex); 1793 // See if it should be locked 1794 if(nvIndex.publicArea.attributes.TPMA_NV_GLOBALLOCK == SET) 1795 { 1796 // if so, lock it 1797 nvIndex.publicArea.attributes.TPMA_NV_WRITELOCKED = SET; 1798 _plat__NvMemoryWrite(currentAddr + sizeof(TPM_HANDLE), 1799 sizeof(NV_INDEX), &nvIndex); 1800 // Set the flag that a NV write happens 1801 g_updateNV = TRUE; 1802 } 1803 } 1804 return; 1805 } 1806 // 1807 // 1808 // InsertSort() 1809 // 1810 // Sort a handle into handle list in ascending order. The total handle number in the list should not exceed 1811 // MAX_CAP_HANDLES 1812 // 1813 static void 1814 InsertSort( 1815 TPML_HANDLE *handleList, // IN/OUT: sorted handle list 1816 UINT32 count, // IN: maximum count in the handle list 1817 TPM_HANDLE entityHandle // IN: handle to be inserted 1818 ) 1819 { 1820 UINT32 i, j; 1821 UINT32 originalCount; 1822 // For a corner case that the maximum count is 0, do nothing 1823 if(count == 0) return; 1824 // For empty list, add the handle at the beginning and return 1825 if(handleList->count == 0) 1826 { 1827 handleList->handle[0] = entityHandle; 1828 handleList->count++; 1829 return; 1830 } 1831 // Check if the maximum of the list has been reached 1832 originalCount = handleList->count; 1833 if(originalCount < count) 1834 handleList->count++; 1835 // Insert the handle to the list 1836 for(i = 0; i < originalCount; i++) 1837 { 1838 if(handleList->handle[i] > entityHandle) 1839 { 1840 for(j = handleList->count - 1; j > i; j--) 1841 { 1842 handleList->handle[j] = handleList->handle[j-1]; 1843 } 1844 break; 1845 } 1846 } 1847 // If a slot was found, insert the handle in this position 1848 if(i < originalCount || handleList->count > originalCount) 1849 handleList->handle[i] = entityHandle; 1850 return; 1851 } 1852 // 1853 // 1854 // NvCapGetPersistent() 1855 // 1856 // This function is used to get a list of handles of the persistent objects, starting at handle. 1857 // Handle must be in valid persistent object handle range, but does not have to reference an existing 1858 // persistent object. 1859 // 1860 // Return Value Meaning 1861 // 1862 // YES if there are more handles available 1863 // NO all the available handles has been returned 1864 // 1865 TPMI_YES_NO 1866 NvCapGetPersistent( 1867 TPMI_DH_OBJECT handle, // IN: start handle 1868 UINT32 count, // IN: maximum number of returned handle 1869 TPML_HANDLE *handleList // OUT: list of handle 1870 ) 1871 { 1872 TPMI_YES_NO more = NO; 1873 NV_ITER iter = NV_ITER_INIT; 1874 UINT32 currentAddr; 1875 pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT); 1876 // Initialize output handle list 1877 handleList->count = 0; 1878 // The maximum count of handles we may return is MAX_CAP_HANDLES 1879 if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; 1880 while((currentAddr = NvNextEvict(&iter)) != 0) 1881 { 1882 TPM_HANDLE entityHandle; 1883 // Read handle information. 1884 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle); 1885 // Ignore persistent handles that have values less than the input handle 1886 if(entityHandle < handle) 1887 continue; 1888 // if the handles in the list have reached the requested count, and there 1889 // are still handles need to be inserted, indicate that there are more. 1890 if(handleList->count == count) 1891 more = YES; 1892 // A handle with a value larger than start handle is a candidate 1893 // for return. Insert sort it to the return list. Insert sort algorithm 1894 // is chosen here for simplicity based on the assumption that the total 1895 // number of NV Indices is small. For an implementation that may allow 1896 // large number of NV Indices, a more efficient sorting algorithm may be 1897 // used here. 1898 InsertSort(handleList, count, entityHandle); 1899 // 1900 } 1901 return more; 1902 } 1903 // 1904 // 1905 // NvCapGetIndex() 1906 // 1907 // This function returns a list of handles of NV Indices, starting from handle. Handle must be in the range of 1908 // NV Indices, but does not have to reference an existing NV Index. 1909 // 1910 // Return Value Meaning 1911 // 1912 // YES if there are more handles to report 1913 // NO all the available handles has been reported 1914 // 1915 TPMI_YES_NO 1916 NvCapGetIndex( 1917 TPMI_DH_OBJECT handle, // IN: start handle 1918 UINT32 count, // IN: maximum number of returned handle 1919 TPML_HANDLE *handleList // OUT: list of handle 1920 ) 1921 { 1922 TPMI_YES_NO more = NO; 1923 NV_ITER iter = NV_ITER_INIT; 1924 UINT32 currentAddr; 1925 pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX); 1926 // Initialize output handle list 1927 handleList->count = 0; 1928 // The maximum count of handles we may return is MAX_CAP_HANDLES 1929 if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; 1930 while((currentAddr = NvNextIndex(&iter)) != 0) 1931 { 1932 TPM_HANDLE entityHandle; 1933 // Read handle information. 1934 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle); 1935 // Ignore index handles that have values less than the 'handle' 1936 if(entityHandle < handle) 1937 continue; 1938 // if the count of handles in the list has reached the requested count, 1939 // and there are still handles to report, set more. 1940 if(handleList->count == count) 1941 more = YES; 1942 // A handle with a value larger than start handle is a candidate 1943 // for return. Insert sort it to the return list. Insert sort algorithm 1944 // is chosen here for simplicity based on the assumption that the total 1945 // number of NV Indices is small. For an implementation that may allow 1946 // large number of NV Indices, a more efficient sorting algorithm may be 1947 // used here. 1948 InsertSort(handleList, count, entityHandle); 1949 } 1950 return more; 1951 } 1952 // 1953 // 1954 // 1955 // NvCapGetIndexNumber() 1956 // 1957 // This function returns the count of NV Indexes currently defined. 1958 // 1959 UINT32 1960 NvCapGetIndexNumber( 1961 void 1962 ) 1963 { 1964 UINT32 num = 0; 1965 NV_ITER iter = NV_ITER_INIT; 1966 while(NvNextIndex(&iter) != 0) num++; 1967 return num; 1968 } 1969 // 1970 // 1971 // NvCapGetPersistentNumber() 1972 // 1973 // Function returns the count of persistent objects currently in NV memory. 1974 // 1975 UINT32 1976 NvCapGetPersistentNumber( 1977 void 1978 ) 1979 { 1980 UINT32 num = 0; 1981 NV_ITER iter = NV_ITER_INIT; 1982 while(NvNextEvict(&iter) != 0) num++; 1983 return num; 1984 } 1985 // 1986 // 1987 // NvCapGetPersistentAvail() 1988 // 1989 // This function returns an estimate of the number of additional persistent objects that could be loaded into 1990 // NV memory. 1991 // 1992 UINT32 1993 NvCapGetPersistentAvail( 1994 void 1995 ) 1996 { 1997 UINT32 availSpace; 1998 UINT32 objectSpace; 1999 // Compute the available space in NV storage 2000 availSpace = NvGetFreeByte(); 2001 // Get the space needed to add a persistent object to NV storage 2002 objectSpace = NvGetEvictObjectSize(); 2003 return availSpace / objectSpace; 2004 } 2005 // 2006 // 2007 // NvCapGetCounterNumber() 2008 // 2009 // Get the number of defined NV Indexes that have NV TPMA_NV_COUNTER attribute SET. 2010 // 2011 // 2012 UINT32 2013 NvCapGetCounterNumber( 2014 void 2015 ) 2016 { 2017 NV_ITER iter = NV_ITER_INIT; 2018 UINT32 currentAddr; 2019 UINT32 num = 0; 2020 while((currentAddr = NvNextIndex(&iter)) != 0) 2021 { 2022 NV_INDEX nvIndex; 2023 // Get NV Index info 2024 _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE), 2025 sizeof(NV_INDEX), &nvIndex); 2026 if(nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET) num++; 2027 } 2028 return num; 2029 } 2030 // 2031 // 2032 // NvCapGetCounterAvail() 2033 // 2034 // This function returns an estimate of the number of additional counter type NV Indices that can be defined. 2035 // 2036 UINT32 2037 NvCapGetCounterAvail( 2038 void 2039 ) 2040 { 2041 UINT32 availNVSpace; 2042 UINT32 availRAMSpace; 2043 UINT32 counterNVSpace; 2044 UINT32 counterRAMSpace; 2045 UINT32 persistentNum = NvCapGetPersistentNumber(); 2046 // Get the available space in NV storage 2047 availNVSpace = NvGetFreeByte(); 2048 if (persistentNum < MIN_EVICT_OBJECTS) 2049 { 2050 // Some space have to be reserved for evict object. Adjust availNVSpace. 2051 UINT32 reserved = (MIN_EVICT_OBJECTS - persistentNum) 2052 * NvGetEvictObjectSize(); 2053 if (reserved > availNVSpace) 2054 availNVSpace = 0; 2055 else 2056 availNVSpace -= reserved; 2057 } 2058 // Get the space needed to add a counter index to NV storage 2059 counterNVSpace = NvGetCounterSize(); 2060 // Compute the available space in RAM 2061 availRAMSpace = RAM_INDEX_SPACE - s_ramIndexSize; 2062 // Compute the space needed to add a counter index to RAM storage 2063 // It takes an size field, a handle and sizeof(UINT64) for counter data 2064 counterRAMSpace = sizeof(UINT32) + sizeof(TPM_HANDLE) + sizeof(UINT64); 2065 // Return the min of counter number in NV and in RAM 2066 if(availNVSpace / counterNVSpace > availRAMSpace / counterRAMSpace) 2067 return availRAMSpace / counterRAMSpace; 2068 else 2069 return availNVSpace / counterNVSpace; 2070 } 2071