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
NvCheckState(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
NvIsAvailable(void)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
NvCommit(void)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
NvReadMaxCount(void)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
NvWriteMaxCount(UINT64 maxCount)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
NvNext(NV_ITER * iter)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
NvGetEnd(void)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
NvGetFreeByte(void)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
NvGetEvictObjectSize(void)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
NvGetCounterSize(void)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
NvTestSpace(UINT32 size,BOOL isIndex)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
NvAdd(UINT32 totalSize,UINT32 bufferSize,BYTE * entity)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
NvDelete(UINT32 entityAddr)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
NvTestRAMSpace(UINT32 size)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
NvGetRAMIndexOffset(TPMI_RH_NV_INDEX handle)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
NvAddRAM(TPMI_RH_NV_INDEX handle,UINT32 size)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
NvDeleteRAM(TPMI_RH_NV_INDEX handle)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
NvInitStatic(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
NvInit(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
NvReadReserved(NV_RESERVE type,void * buffer)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
NvWriteReserved(NV_RESERVE type,void * buffer)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
NvReadPersistent(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
NvIsPlatformPersistentHandle(TPM_HANDLE handle)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
NvIsOwnerPersistentHandle(TPM_HANDLE handle)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
715 //
716 static UINT32
NvNextIndex(NV_ITER * iter)717 NvNextIndex(
718 NV_ITER *iter
719 )
720 {
721 UINT32 addr;
722 TPM_HANDLE handle;
723 while((addr = NvNext(iter)) != 0)
724 {
725 // Read handle
726 _plat__NvMemoryRead(addr, sizeof(TPM_HANDLE), &handle);
727 if(HandleGetType(handle) == TPM_HT_NV_INDEX)
728 return addr;
729 }
730 pAssert(addr == 0);
731 return addr;
732 }
733 //
734 //
735 // NvNextEvict()
736 //
737 // This function returns the offset in NV of the next evict object entry. A value of 0 indicates the end of the
738 // list.
739 //
740 static UINT32
NvNextEvict(NV_ITER * iter)741 NvNextEvict(
742 NV_ITER *iter
743 )
744 {
745 UINT32 addr;
746 TPM_HANDLE handle;
747 while((addr = NvNext(iter)) != 0)
748 {
749 // Read handle
750 _plat__NvMemoryRead(addr, sizeof(TPM_HANDLE), &handle);
751 if(HandleGetType(handle) == TPM_HT_PERSISTENT)
752 return addr;
753 }
754 pAssert(addr == 0);
755 return addr;
756 }
757 //
758 //
759 // NvFindHandle()
760 //
761 // this function returns the offset in NV memory of the entity associated with the input handle. A value of
762 // zero indicates that handle does not exist reference an existing persistent object or defined NV Index.
763 //
764 static UINT32
NvFindHandle(TPM_HANDLE handle)765 NvFindHandle(
766 TPM_HANDLE handle
767 )
768 {
769 UINT32 addr;
770 NV_ITER iter = NV_ITER_INIT;
771 while((addr = NvNext(&iter)) != 0)
772 {
773 TPM_HANDLE entityHandle;
774 // Read handle
775 //
776 _plat__NvMemoryRead(addr, sizeof(TPM_HANDLE), &entityHandle);
777 if(entityHandle == handle)
778 return addr;
779 }
780 pAssert(addr == 0);
781 return addr;
782 }
783
784 //
785 // NvCheckAndMigrateIfNeeded()
786 //
787 // Supported only in EMBEDDED_MODE.
788 //
789 // Check if the NVRAM storage format changed, and if so - reinitialize the
790 // NVRAM. No content migration yet, hopefully it will come one day.
791 //
792 // Note that the NV_FIRMWARE_V1 and NV_FIRMWARE_V2 values not used to store
793 // TPM versoion when in embedded mode are used for NVRAM format version
794 // instead.
795 //
796 //
797 static void
NvCheckAndMigrateIfNeeded(void)798 NvCheckAndMigrateIfNeeded(void)
799 {
800 #ifdef EMBEDDED_MODE
801 UINT32 nv_vers1;
802 UINT32 nv_vers2;
803
804 NvReadReserved(NV_FIRMWARE_V1, &nv_vers1);
805 NvReadReserved(NV_FIRMWARE_V2, &nv_vers2);
806
807 if ((nv_vers1 == ~nv_vers2) && (nv_vers1 == NV_FORMAT_VERSION))
808 return; // All is well.
809
810 // This will reinitialize NVRAM to empty. Migration code will come here
811 // later.
812 NvInit();
813
814 nv_vers1 = NV_FORMAT_VERSION;
815 nv_vers2 = ~NV_FORMAT_VERSION;
816
817 NvWriteReserved(NV_FIRMWARE_V1, &nv_vers1);
818 NvWriteReserved(NV_FIRMWARE_V2, &nv_vers2);
819
820 NvCommit();
821 #endif
822 }
823
824
825 //
826 //
827 // NvPowerOn()
828 //
829 // This function is called at _TPM_Init() to initialize the NV environment.
830 //
831 // Return Value Meaning
832 //
833 // TRUE all NV was initialized
834 // FALSE the NV containing saved state had an error and
835 // TPM2_Startup(CLEAR) is required
836 //
837 BOOL
NvPowerOn(void)838 NvPowerOn(
839 void
840 )
841 {
842 int nvError = 0;
843 // If power was lost, need to re-establish the RAM data that is loaded from
844 // NV and initialize the static variables
845 if(_plat__WasPowerLost(TRUE))
846 {
847 if((nvError = _plat__NVEnable(0)) < 0)
848 FAIL(FATAL_ERROR_NV_UNRECOVERABLE);
849 NvInitStatic();
850 NvCheckAndMigrateIfNeeded();
851 }
852 return nvError == 0;
853 }
854 //
855 //
856 // NvStateSave()
857 //
858 // This function is used to cause the memory containing the RAM backed NV Indices to be written to NV.
859 //
860 void
NvStateSave(void)861 NvStateSave(
862 void
863 )
864 {
865 // Write RAM backed NV Index info to NV
866 // No need to save s_ramIndexSize because we save it to NV whenever it is
867 // updated.
868 _plat__NvMemoryWrite(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex);
869 // Set the flag so that an NV write happens before the command completes.
870 g_updateNV = TRUE;
871 return;
872 }
873 //
874 //
875 //
876 // NvEntityStartup()
877 //
878 // This function is called at TPM_Startup(). If the startup completes a TPM Resume cycle, no action is
879 // taken. If the startup is a TPM Reset or a TPM Restart, then this function will:
880 // a) clear read/write lock;
881 // b) reset NV Index data that has TPMA_NV_CLEAR_STCLEAR SET; and
882 // c) set the lower bits in orderly counters to 1 for a non-orderly startup
883 // It is a prerequisite that NV be available for writing before this function is called.
884 //
885 void
NvEntityStartup(STARTUP_TYPE type)886 NvEntityStartup(
887 STARTUP_TYPE type // IN: start up type
888 )
889 {
890 NV_ITER iter = NV_ITER_INIT;
891 UINT32 currentAddr; // offset points to the current entity
892 // Restore RAM index data
893 _plat__NvMemoryRead(s_ramIndexSizeAddr, sizeof(UINT32), &s_ramIndexSize);
894 _plat__NvMemoryRead(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex);
895 // If recovering from state save, do nothing
896 if(type == SU_RESUME)
897 return;
898 // Iterate all the NV Index to clear the locks
899 while((currentAddr = NvNextIndex(&iter)) != 0)
900 {
901 NV_INDEX nvIndex;
902 UINT32 indexAddr; // NV address points to index info
903 TPMA_NV attributes;
904 UINT32 attributesValue;
905 UINT32 publicAreaAttributesValue;
906 indexAddr = currentAddr + sizeof(TPM_HANDLE);
907 // Read NV Index info structure
908 _plat__NvMemoryRead(indexAddr, sizeof(NV_INDEX), &nvIndex);
909 attributes = nvIndex.publicArea.attributes;
910 // Clear read/write lock
911 if(attributes.TPMA_NV_READLOCKED == SET)
912 attributes.TPMA_NV_READLOCKED = CLEAR;
913 if( attributes.TPMA_NV_WRITELOCKED == SET
914 && ( attributes.TPMA_NV_WRITTEN == CLEAR
915 || attributes.TPMA_NV_WRITEDEFINE == CLEAR
916 )
917 )
918 attributes.TPMA_NV_WRITELOCKED = CLEAR;
919 // Reset NV data for TPMA_NV_CLEAR_STCLEAR
920 if(attributes.TPMA_NV_CLEAR_STCLEAR == SET)
921 {
922 attributes.TPMA_NV_WRITTEN = CLEAR;
923 attributes.TPMA_NV_WRITELOCKED = CLEAR;
924 }
925 // Reset NV data for orderly values that are not counters
926 // NOTE: The function has already exited on a TPM Resume, so the only
927 // things being processed are TPM Restart and TPM Reset
928 if( type == SU_RESET
929 && attributes.TPMA_NV_ORDERLY == SET
930 && attributes.TPMA_NV_COUNTER == CLEAR
931 )
932 attributes.TPMA_NV_WRITTEN = CLEAR;
933 // Write NV Index info back if it has changed
934 memcpy(&attributesValue, &attributes, sizeof(attributesValue));
935 memcpy(&publicAreaAttributesValue, &nvIndex.publicArea.attributes,
936 sizeof(publicAreaAttributesValue));
937 if(attributesValue != publicAreaAttributesValue)
938 {
939 nvIndex.publicArea.attributes = attributes;
940 _plat__NvMemoryWrite(indexAddr, sizeof(NV_INDEX), &nvIndex);
941 // Set the flag that a NV write happens
942 g_updateNV = TRUE;
943 }
944 // Set the lower bits in an orderly counter to 1 for a non-orderly startup
945 if( g_prevOrderlyState == SHUTDOWN_NONE
946 && attributes.TPMA_NV_WRITTEN == SET)
947 {
948 if( attributes.TPMA_NV_ORDERLY == SET
949 && attributes.TPMA_NV_COUNTER == SET)
950 {
951 TPMI_RH_NV_INDEX nvHandle;
952 UINT64 counter;
953 // Read NV handle
954 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &nvHandle);
955 // Read the counter value saved to NV upon the last roll over.
956 // Do not use RAM backed storage for this once.
957 nvIndex.publicArea.attributes.TPMA_NV_ORDERLY = CLEAR;
958 NvGetIntIndexData(nvHandle, &nvIndex, &counter);
959 nvIndex.publicArea.attributes.TPMA_NV_ORDERLY = SET;
960 // Set the lower bits of counter to 1's
961 counter |= MAX_ORDERLY_COUNT;
962 // Write back to RAM
963 NvWriteIndexData(nvHandle, &nvIndex, 0, sizeof(counter), &counter);
964 // No write to NV because an orderly shutdown will update the
965 // counters.
966 }
967 }
968 }
969 return;
970 }
971 //
972 //
973 // NV Access Functions
974 //
975 // Introduction
976 //
977 // This set of functions provide accessing NV Index and persistent objects based using a handle for
978 // reference to the entity.
979 //
980 // NvIsUndefinedIndex()
981 //
982 // This function is used to verify that an NV Index is not defined. This is only used by
983 // TPM2_NV_DefineSpace().
984 //
985 //
986 //
987 //
988 // Return Value Meaning
989 //
990 // TRUE the handle points to an existing NV Index
991 // FALSE the handle points to a non-existent Index
992 //
993 BOOL
NvIsUndefinedIndex(TPMI_RH_NV_INDEX handle)994 NvIsUndefinedIndex(
995 TPMI_RH_NV_INDEX handle // IN: handle
996 )
997 {
998 UINT32 entityAddr; // offset points to the entity
999 pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX);
1000 // Find the address of index
1001 entityAddr = NvFindHandle(handle);
1002 // If handle is not found, return TPM_RC_SUCCESS
1003 if(entityAddr == 0)
1004 return TPM_RC_SUCCESS;
1005 // NV Index is defined
1006 return TPM_RC_NV_DEFINED;
1007 }
1008 //
1009 //
1010 // NvIndexIsAccessible()
1011 //
1012 // This function validates that a handle references a defined NV Index and that the Index is currently
1013 // accessible.
1014 //
1015 // Error Returns Meaning
1016 //
1017 // TPM_RC_HANDLE the handle points to an undefined NV Index If shEnable is CLEAR,
1018 // this would include an index created using ownerAuth. If phEnableNV
1019 // is CLEAR, this would include and index created using platform auth
1020 // TPM_RC_NV_READLOCKED Index is present but locked for reading and command does not write
1021 // to the index
1022 // TPM_RC_NV_WRITELOCKED Index is present but locked for writing and command writes to the
1023 // index
1024 //
1025 TPM_RC
NvIndexIsAccessible(TPMI_RH_NV_INDEX handle,TPM_CC commandCode)1026 NvIndexIsAccessible(
1027 TPMI_RH_NV_INDEX handle, // IN: handle
1028 TPM_CC commandCode // IN: the command
1029 )
1030 {
1031 UINT32 entityAddr; // offset points to the entity
1032 NV_INDEX nvIndex; //
1033 pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX);
1034 // Find the address of index
1035 entityAddr = NvFindHandle(handle);
1036 // If handle is not found, return TPM_RC_HANDLE
1037 if(entityAddr == 0)
1038 return TPM_RC_HANDLE;
1039 // Read NV Index info structure
1040 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX),
1041 &nvIndex);
1042 if(gc.shEnable == FALSE || gc.phEnableNV == FALSE)
1043 {
1044 // if shEnable is CLEAR, an ownerCreate NV Index should not be
1045 // indicated as present
1046 if(nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == CLEAR)
1047 {
1048 if(gc.shEnable == FALSE)
1049 return TPM_RC_HANDLE;
1050 }
1051 // if phEnableNV is CLEAR, a platform created Index should not
1052 // be visible
1053 else if(gc.phEnableNV == FALSE)
1054 return TPM_RC_HANDLE;
1055 }
1056 // If the Index is write locked and this is an NV Write operation...
1057 if( nvIndex.publicArea.attributes.TPMA_NV_WRITELOCKED
1058 && IsWriteOperation(commandCode))
1059 {
1060 // then return a locked indication unless the command is TPM2_NV_WriteLock
1061 if(commandCode != TPM_CC_NV_WriteLock)
1062 return TPM_RC_NV_LOCKED;
1063 return TPM_RC_SUCCESS;
1064 }
1065 // If the Index is read locked and this is an NV Read operation...
1066 if( nvIndex.publicArea.attributes.TPMA_NV_READLOCKED
1067 && IsReadOperation(commandCode))
1068 {
1069 // then return a locked indication unless the command is TPM2_NV_ReadLock
1070 if(commandCode != TPM_CC_NV_ReadLock)
1071 return TPM_RC_NV_LOCKED;
1072 return TPM_RC_SUCCESS;
1073 }
1074 // NV Index is accessible
1075 return TPM_RC_SUCCESS;
1076 }
1077 //
1078 //
1079 // NvIsUndefinedEvictHandle()
1080 //
1081 // This function indicates if a handle does not reference an existing persistent object. This function requires
1082 // that the handle be in the proper range for persistent objects.
1083 //
1084 // Return Value Meaning
1085 //
1086 // TRUE handle does not reference an existing persistent object
1087 // FALSE handle does reference an existing persistent object
1088 //
1089 static BOOL
NvIsUndefinedEvictHandle(TPM_HANDLE handle)1090 NvIsUndefinedEvictHandle(
1091 TPM_HANDLE handle // IN: handle
1092 )
1093 {
1094 UINT32 entityAddr; // offset points to the entity
1095 pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT);
1096 // Find the address of evict object
1097 entityAddr = NvFindHandle(handle);
1098 // If handle is not found, return TRUE
1099 if(entityAddr == 0)
1100 return TRUE;
1101 else
1102 return FALSE;
1103 }
1104
1105 //
1106 //
1107 // NvUnmarshalObject()
1108 //
1109 // This function accepts a buffer containing a marshaled OBJECT
1110 // structure, a pointer to the area where the input data should be
1111 // unmarshaled, and a pointer to the size of the output area.
1112 //
1113 // No error checking is performed, unmarshaled data is guaranteed not to
1114 // spill over the allocated space.
1115 //
NvUnmarshalObject(OBJECT * o,BYTE ** buf,INT32 * size)1116 static TPM_RC NvUnmarshalObject(OBJECT *o, BYTE **buf, INT32 *size)
1117 {
1118 TPM_RC result;
1119
1120 // There is no generated function to unmarshal the attributes field, do it
1121 // by hand.
1122 MemoryCopy(&o->attributes, *buf, sizeof(o->attributes), *size);
1123 *buf += sizeof(o->attributes);
1124 *size -= sizeof(o->attributes);
1125
1126 result = TPMT_PUBLIC_Unmarshal(&o->publicArea, buf, size);
1127 if (result != TPM_RC_SUCCESS)
1128 return result;
1129
1130 result = TPMT_SENSITIVE_Unmarshal(&o->sensitive, buf, size);
1131 if (result != TPM_RC_SUCCESS)
1132 return result;
1133
1134 #ifdef TPM_ALG_RSA
1135 result = TPM2B_PUBLIC_KEY_RSA_Unmarshal(&o->privateExponent, buf, size);
1136 if (result != TPM_RC_SUCCESS)
1137 return result;
1138 #endif
1139
1140 result = TPM2B_NAME_Unmarshal(&o->qualifiedName, buf, size);
1141 if (result != TPM_RC_SUCCESS)
1142 return result;
1143
1144 result = TPMI_DH_OBJECT_Unmarshal(&o->evictHandle, buf, size, TRUE);
1145 if (result != TPM_RC_SUCCESS)
1146 return result;
1147
1148 return TPM2B_NAME_Unmarshal(&o->name, buf, size);
1149 }
1150
1151 //
1152 //
1153 // NvGetEvictObject()
1154 //
1155 // This function is used to dereference an evict object handle and get a pointer to the object.
1156 //
1157 // Error Returns Meaning
1158 //
1159 // TPM_RC_HANDLE the handle does not point to an existing persistent object
1160 //
1161 TPM_RC
NvGetEvictObject(TPM_HANDLE handle,OBJECT * object)1162 NvGetEvictObject(
1163 TPM_HANDLE handle, // IN: handle
1164 OBJECT *object // OUT: object data
1165 )
1166 {
1167 UINT32 entityAddr; // offset points to the entity
1168 TPM_RC result = TPM_RC_SUCCESS;
1169 pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT);
1170 // Find the address of evict object
1171 entityAddr = NvFindHandle(handle);
1172 // If handle is not found, return an error
1173 if(entityAddr == 0) {
1174 result = TPM_RC_HANDLE;
1175 } else {
1176 UINT32 storedSize;
1177 UINT32 nextEntryAddr;
1178
1179 // Let's calculate the size of object as stored in NVMEM.
1180 _plat__NvMemoryRead(entityAddr - sizeof(UINT32),
1181 sizeof(UINT32), &nextEntryAddr);
1182
1183 storedSize = nextEntryAddr - entityAddr;
1184
1185 if (storedSize == (sizeof(TPM_HANDLE) + sizeof(OBJECT))) {
1186 // Read evict object stored unmarshaled.
1187 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE),
1188 sizeof(OBJECT),
1189 object);
1190 } else {
1191 // Must be stored marshaled, let's unmarshal it.
1192 BYTE marshaled[sizeof(OBJECT)];
1193 INT32 max_size = sizeof(marshaled);
1194 BYTE *marshaledPtr = marshaled;
1195
1196 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE),
1197 storedSize, marshaled);
1198 result = NvUnmarshalObject(object, &marshaledPtr, &max_size);
1199 }
1200 }
1201 // whether there is an error or not, make sure that the evict
1202 // status of the object is set so that the slot will get freed on exit
1203 object->attributes.evict = SET;
1204 return result;
1205 }
1206 //
1207 //
1208 // NvGetIndexInfo()
1209 //
1210 // This function is used to retrieve the contents of an NV Index.
1211 // An implementation is allowed to save the NV Index in a vendor-defined format. If the format is different
1212 // from the default used by the reference code, then this function would be changed to reformat the data into
1213 // the default format.
1214 // A prerequisite to calling this function is that the handle must be known to reference a defined NV Index.
1215 //
1216 void
NvGetIndexInfo(TPMI_RH_NV_INDEX handle,NV_INDEX * nvIndex)1217 NvGetIndexInfo(
1218 TPMI_RH_NV_INDEX handle, // IN: handle
1219 NV_INDEX *nvIndex // OUT: NV index structure
1220 )
1221 {
1222 UINT32 entityAddr; // offset points to the entity
1223 pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX);
1224 // Find the address of NV index
1225 entityAddr = NvFindHandle(handle);
1226 pAssert(entityAddr != 0);
1227 // This implementation uses the default format so just
1228 // read the data in
1229 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX),
1230 nvIndex);
1231 return;
1232 }
1233 //
1234 //
1235 // NvInitialCounter()
1236 //
1237 // This function returns the value to be used when a counter index is initialized. It will scan the NV counters
1238 // and find the highest value in any active counter. It will use that value as the starting point. If there are no
1239 // active counters, it will use the value of the previous largest counter.
1240 //
1241 UINT64
NvInitialCounter(void)1242 NvInitialCounter(
1243 void
1244 )
1245 {
1246 UINT64 maxCount;
1247 NV_ITER iter = NV_ITER_INIT;
1248 UINT32 currentAddr;
1249 // Read the maxCount value
1250 maxCount = NvReadMaxCount();
1251 // Iterate all existing counters
1252 while((currentAddr = NvNextIndex(&iter)) != 0)
1253 {
1254 TPMI_RH_NV_INDEX nvHandle;
1255 NV_INDEX nvIndex;
1256 // Read NV handle
1257 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &nvHandle);
1258 // Get NV Index
1259 NvGetIndexInfo(nvHandle, &nvIndex);
1260 if( nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET
1261 && nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET)
1262 {
1263 UINT64 countValue;
1264 // Read counter value
1265 NvGetIntIndexData(nvHandle, &nvIndex, &countValue);
1266 if(countValue > maxCount)
1267 maxCount = countValue;
1268 }
1269 }
1270 // Initialize the new counter value to be maxCount + 1
1271 // A counter is only initialized the first time it is written. The
1272 // way to write a counter is with TPM2_NV_INCREMENT(). Since the
1273 // "initial" value of a defined counter is the largest count value that
1274 // may have existed in this index previously, then the first use would
1275 // add one to that value.
1276 return maxCount;
1277 }
1278 //
1279 //
1280 // NvGetIndexData()
1281 //
1282 // This function is used to access the data in an NV Index. The data is returned as a byte sequence. Since
1283 // counter values are kept in native format, they are converted to canonical form before being returned.
1284 // Family "2.0" TCG Published Page 139
1285 // Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014
1286 // Trusted Platform Module Library Part 4: Supporting Routines
1287 //
1288 //
1289 // This function requires that the NV Index be defined, and that the required data is within the data range. It
1290 // also requires that TPMA_NV_WRITTEN of the Index is SET.
1291 //
1292 void
NvGetIndexData(TPMI_RH_NV_INDEX handle,NV_INDEX * nvIndex,UINT32 offset,UINT16 size,void * data)1293 NvGetIndexData(
1294 TPMI_RH_NV_INDEX handle, // IN: handle
1295 NV_INDEX *nvIndex, // IN: RAM image of index header
1296 UINT32 offset, // IN: offset of NV data
1297 UINT16 size, // IN: size of NV data
1298 void *data // OUT: data buffer
1299 )
1300 {
1301 pAssert(nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == SET);
1302 if( nvIndex->publicArea.attributes.TPMA_NV_BITS == SET
1303 || nvIndex->publicArea.attributes.TPMA_NV_COUNTER == SET)
1304 {
1305 // Read bit or counter data in canonical form
1306 UINT64 dataInInt;
1307 NvGetIntIndexData(handle, nvIndex, &dataInInt);
1308 UINT64_TO_BYTE_ARRAY(dataInInt, (BYTE *)data);
1309 }
1310 else
1311 {
1312 if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET)
1313 {
1314 UINT32 ramAddr;
1315 // Get data from RAM buffer
1316 ramAddr = NvGetRAMIndexOffset(handle);
1317 MemoryCopy(data, s_ramIndex + ramAddr + offset, size, size);
1318 }
1319 else
1320 {
1321 UINT32 entityAddr;
1322 entityAddr = NvFindHandle(handle);
1323 // Get data from NV
1324 // Skip NV Index info, read data buffer
1325 entityAddr += sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + offset;
1326 // Read the data
1327 _plat__NvMemoryRead(entityAddr, size, data);
1328 }
1329 }
1330 return;
1331 }
1332 //
1333 //
1334 // NvGetIntIndexData()
1335 //
1336 // Get data in integer format of a bit or counter NV Index.
1337 // This function requires that the NV Index is defined and that the NV Index previously has been written.
1338 //
1339 void
NvGetIntIndexData(TPMI_RH_NV_INDEX handle,NV_INDEX * nvIndex,UINT64 * data)1340 NvGetIntIndexData(
1341 TPMI_RH_NV_INDEX handle, // IN: handle
1342 NV_INDEX *nvIndex, // IN: RAM image of NV Index header
1343 UINT64 *data // IN: UINT64 pointer for counter or bit
1344 )
1345 {
1346 // Validate that index has been written and is the right type
1347 pAssert( nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == SET
1348 && ( nvIndex->publicArea.attributes.TPMA_NV_BITS == SET
1349 || nvIndex->publicArea.attributes.TPMA_NV_COUNTER == SET
1350 )
1351 );
1352 // bit and counter value is store in native format for TPM CPU. So we directly
1353 // copy the contents of NV to output data buffer
1354 if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET)
1355 {
1356 UINT32 ramAddr;
1357 // Get data from RAM buffer
1358 ramAddr = NvGetRAMIndexOffset(handle);
1359 MemoryCopy(data, s_ramIndex + ramAddr, sizeof(*data), sizeof(*data));
1360 }
1361 else
1362 {
1363 UINT32 entityAddr;
1364 entityAddr = NvFindHandle(handle);
1365 // Get data from NV
1366 // Skip NV Index info, read data buffer
1367 _plat__NvMemoryRead(
1368 entityAddr + sizeof(TPM_HANDLE) + sizeof(NV_INDEX),
1369 sizeof(UINT64), data);
1370 }
1371 return;
1372 }
1373 //
1374 //
1375 // NvWriteIndexInfo()
1376 //
1377 // This function is called to queue the write of NV Index data to persistent memory.
1378 // This function requires that NV Index is defined.
1379 //
1380 // Error Returns Meaning
1381 //
1382 // TPM_RC_NV_RATE NV is rate limiting so retry
1383 // TPM_RC_NV_UNAVAILABLE NV is not available
1384 //
1385 TPM_RC
NvWriteIndexInfo(TPMI_RH_NV_INDEX handle,NV_INDEX * nvIndex)1386 NvWriteIndexInfo(
1387 TPMI_RH_NV_INDEX handle, // IN: handle
1388 NV_INDEX *nvIndex // IN: NV Index info to be written
1389 )
1390 {
1391 UINT32 entryAddr;
1392 TPM_RC result;
1393 // Get the starting offset for the index in the RAM image of NV
1394 entryAddr = NvFindHandle(handle);
1395 pAssert(entryAddr != 0);
1396 // Step over the link value
1397 entryAddr = entryAddr + sizeof(TPM_HANDLE);
1398 // If the index data is actually changed, then a write to NV is required
1399 if(_plat__NvIsDifferent(entryAddr, sizeof(NV_INDEX),nvIndex))
1400 {
1401 // Make sure that NV is available
1402 result = NvIsAvailable();
1403 if(result != TPM_RC_SUCCESS)
1404 return result;
1405 _plat__NvMemoryWrite(entryAddr, sizeof(NV_INDEX), nvIndex);
1406 g_updateNV = TRUE;
1407 }
1408 return TPM_RC_SUCCESS;
1409 }
1410 //
1411 //
1412 // NvWriteIndexData()
1413 //
1414 // This function is used to write NV index data.
1415 // This function requires that the NV Index is defined, and the data is within the defined data range for the
1416 // index.
1417 //
1418 // Error Returns Meaning
1419 //
1420 // TPM_RC_NV_RATE NV is rate limiting so retry
1421 // TPM_RC_NV_UNAVAILABLE NV is not available
1422 //
1423 TPM_RC
NvWriteIndexData(TPMI_RH_NV_INDEX handle,NV_INDEX * nvIndex,UINT32 offset,UINT32 size,void * data)1424 NvWriteIndexData(
1425 TPMI_RH_NV_INDEX handle, // IN: handle
1426 NV_INDEX *nvIndex, // IN: RAM copy of NV Index
1427 UINT32 offset, // IN: offset of NV data
1428 UINT32 size, // IN: size of NV data
1429 void *data // OUT: data buffer
1430 )
1431 {
1432 TPM_RC result;
1433 // Validate that write falls within range of the index
1434 pAssert(nvIndex->publicArea.dataSize >= offset + size);
1435 // Update TPMA_NV_WRITTEN bit if necessary
1436 if(nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == CLEAR)
1437 {
1438 nvIndex->publicArea.attributes.TPMA_NV_WRITTEN = SET;
1439 result = NvWriteIndexInfo(handle, nvIndex);
1440 if(result != TPM_RC_SUCCESS)
1441 return result;
1442 }
1443 // Check to see if process for an orderly index is required.
1444 if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET)
1445 {
1446 UINT32 ramAddr;
1447 // Write data to RAM buffer
1448 ramAddr = NvGetRAMIndexOffset(handle);
1449 MemoryCopy(s_ramIndex + ramAddr + offset, data, size,
1450 sizeof(s_ramIndex) - ramAddr - offset);
1451 // NV update does not happen for orderly index. Have
1452 // to clear orderlyState to reflect that we have changed the
1453 // NV and an orderly shutdown is required. Only going to do this if we
1454 // are not processing a counter that has just rolled over
1455 if(g_updateNV == FALSE)
1456 g_clearOrderly = TRUE;
1457 }
1458 // Need to process this part if the Index isn't orderly or if it is
1459 // an orderly counter that just rolled over.
1460 if(g_updateNV || nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == CLEAR)
1461 {
1462 // Processing for an index with TPMA_NV_ORDERLY CLEAR
1463 UINT32 entryAddr = NvFindHandle(handle);
1464 pAssert(entryAddr != 0);
1465 //
1466 // Offset into the index to the first byte of the data to be written
1467 entryAddr += sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + offset;
1468 // If the data is actually changed, then a write to NV is required
1469 if(_plat__NvIsDifferent(entryAddr, size, data))
1470 {
1471 // Make sure that NV is available
1472 result = NvIsAvailable();
1473 if(result != TPM_RC_SUCCESS)
1474 return result;
1475 _plat__NvMemoryWrite(entryAddr, size, data);
1476 g_updateNV = TRUE;
1477 }
1478 }
1479 return TPM_RC_SUCCESS;
1480 }
1481 //
1482 //
1483 // NvGetName()
1484 //
1485 // This function is used to compute the Name of an NV Index.
1486 // The name buffer receives the bytes of the Name and the return value is the number of octets in the
1487 // Name.
1488 // This function requires that the NV Index is defined.
1489 //
1490 UINT16
NvGetName(TPMI_RH_NV_INDEX handle,NAME * name)1491 NvGetName(
1492 TPMI_RH_NV_INDEX handle, // IN: handle of the index
1493 NAME *name // OUT: name of the index
1494 )
1495 {
1496 UINT16 dataSize, digestSize;
1497 NV_INDEX nvIndex;
1498 BYTE marshalBuffer[sizeof(TPMS_NV_PUBLIC)];
1499 BYTE *buffer;
1500 INT32 bufferSize;
1501 HASH_STATE hashState;
1502 // Get NV public info
1503 NvGetIndexInfo(handle, &nvIndex);
1504 // Marshal public area
1505 buffer = marshalBuffer;
1506 bufferSize = sizeof(TPMS_NV_PUBLIC);
1507 dataSize = TPMS_NV_PUBLIC_Marshal(&nvIndex.publicArea, &buffer, &bufferSize);
1508 // hash public area
1509 digestSize = CryptStartHash(nvIndex.publicArea.nameAlg, &hashState);
1510 CryptUpdateDigest(&hashState, dataSize, marshalBuffer);
1511 // Complete digest leaving room for the nameAlg
1512 CryptCompleteHash(&hashState, digestSize, &((BYTE *)name)[2]);
1513 // Include the nameAlg
1514 UINT16_TO_BYTE_ARRAY(nvIndex.publicArea.nameAlg, (BYTE *)name);
1515 return digestSize + 2;
1516 }
1517 //
1518 //
1519 // NvDefineIndex()
1520 //
1521 // This function is used to assign NV memory to an NV Index.
1522 //
1523 //
1524 //
1525 // Error Returns Meaning
1526 //
1527 // TPM_RC_NV_SPACE insufficient NV space
1528 //
1529 TPM_RC
NvDefineIndex(TPMS_NV_PUBLIC * publicArea,TPM2B_AUTH * authValue)1530 NvDefineIndex(
1531 TPMS_NV_PUBLIC *publicArea, // IN: A template for an area to create.
1532 TPM2B_AUTH *authValue // IN: The initial authorization value
1533 )
1534 {
1535 // The buffer to be written to NV memory
1536 BYTE nvBuffer[sizeof(TPM_HANDLE) + sizeof(NV_INDEX)];
1537 NV_INDEX *nvIndex; // a pointer to the NV_INDEX data in
1538 // nvBuffer
1539 UINT16 entrySize; // size of entry
1540 entrySize = sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + publicArea->dataSize;
1541 // Check if we have enough space to create the NV Index
1542 // In this implementation, the only resource limitation is the available NV
1543 // space. Other implementation may have other limitation on counter or on
1544 // NV slot
1545 if(!NvTestSpace(entrySize, TRUE)) return TPM_RC_NV_SPACE;
1546 // if the index to be defined is RAM backed, check RAM space availability
1547 // as well
1548 if(publicArea->attributes.TPMA_NV_ORDERLY == SET
1549 && !NvTestRAMSpace(publicArea->dataSize))
1550 return TPM_RC_NV_SPACE;
1551 // Copy input value to nvBuffer
1552 // Copy handle
1553 memcpy(nvBuffer, &publicArea->nvIndex, sizeof(TPM_HANDLE));
1554 // Copy NV_INDEX
1555 nvIndex = (NV_INDEX *) (nvBuffer + sizeof(TPM_HANDLE));
1556 nvIndex->publicArea = *publicArea;
1557 nvIndex->authValue = *authValue;
1558 // Add index to NV memory
1559 NvAdd(entrySize, sizeof(TPM_HANDLE) + sizeof(NV_INDEX), nvBuffer);
1560 // If the data of NV Index is RAM backed, add the data area in RAM as well
1561 if(publicArea->attributes.TPMA_NV_ORDERLY == SET)
1562 NvAddRAM(publicArea->nvIndex, publicArea->dataSize);
1563 return TPM_RC_SUCCESS;
1564 }
1565
1566 //
1567 //
1568 // NvMarshalObject()
1569 //
1570 // This function marshals the passed in OBJECT structure into a buffer. A
1571 // pointer to pointer to the buffer and a pointer to the size of the
1572 // buffer are passed in for this function to update as appropriate.
1573 //
1574 // On top of marshaling the object, this function also modifies one of
1575 // the object's properties and sets the evictHandle field of the
1576 // marshaled object to the requested value.
1577 //
1578 // Returns
1579 //
1580 // Marshaled size of the object.
1581 //
NvMarshalObject(OBJECT * o,TPMI_DH_OBJECT evictHandle,BYTE ** buf,INT32 * size)1582 static UINT16 NvMarshalObject(OBJECT *o, TPMI_DH_OBJECT evictHandle,
1583 BYTE **buf, INT32 *size)
1584 {
1585 UINT16 marshaledSize;
1586 OBJECT_ATTRIBUTES stored_attributes;
1587
1588 stored_attributes = o->attributes;
1589 stored_attributes.evict = SET;
1590 marshaledSize = sizeof(stored_attributes);
1591 MemoryCopy(*buf, &stored_attributes, marshaledSize, *size);
1592 *buf += marshaledSize;
1593 *size -= marshaledSize;
1594
1595 marshaledSize += TPMT_PUBLIC_Marshal(&o->publicArea, buf, size);
1596 marshaledSize += TPMT_SENSITIVE_Marshal(&o->sensitive, buf, size);
1597 #ifdef TPM_ALG_RSA
1598 marshaledSize += TPM2B_PUBLIC_KEY_RSA_Marshal(&o->privateExponent,
1599 buf, size);
1600 #endif
1601 marshaledSize += TPM2B_NAME_Marshal(&o->qualifiedName, buf, size);
1602
1603 // Use the supplied handle instead of the object contents.
1604 marshaledSize += TPMI_DH_OBJECT_Marshal(&evictHandle, buf, size);
1605 marshaledSize += TPM2B_NAME_Marshal(&o->name, buf, size);
1606
1607 return marshaledSize;
1608 }
1609
1610 //
1611 //
1612 // NvAddEvictObject()
1613 //
1614 // This function is used to assign NV memory to a persistent object.
1615 //
1616 // Error Returns Meaning
1617 //
1618 // TPM_RC_NV_HANDLE the requested handle is already in use
1619 // TPM_RC_NV_SPACE insufficient NV space
1620 //
1621 TPM_RC
NvAddEvictObject(TPMI_DH_OBJECT evictHandle,OBJECT * object)1622 NvAddEvictObject(
1623 TPMI_DH_OBJECT evictHandle, // IN: new evict handle
1624 //
1625 OBJECT *object // IN: object to be added
1626 )
1627 {
1628 // The buffer to be written to NV memory
1629 BYTE nvBuffer[sizeof(TPM_HANDLE) + sizeof(OBJECT)];
1630 UINT16 entrySize; // size of entry
1631 BYTE *marshalSpace;
1632 INT32 marshalRoom;
1633
1634 // evict handle type should match the object hierarchy
1635 pAssert( ( NvIsPlatformPersistentHandle(evictHandle)
1636 && object->attributes.ppsHierarchy == SET)
1637 || ( NvIsOwnerPersistentHandle(evictHandle)
1638 && ( object->attributes.spsHierarchy == SET
1639 || object->attributes.epsHierarchy == SET)));
1640
1641 // Do not attemp storing a duplicate handle.
1642 if(!NvIsUndefinedEvictHandle(evictHandle))
1643 return TPM_RC_NV_DEFINED;
1644
1645 // Copy handle
1646 entrySize = sizeof(TPM_HANDLE);
1647 memcpy(nvBuffer, &evictHandle, entrySize);
1648
1649 // Let's serialize the object before storing it in NVMEM
1650 marshalSpace = nvBuffer + entrySize;
1651 marshalRoom = sizeof(nvBuffer) - entrySize;
1652 entrySize += NvMarshalObject(object, evictHandle,
1653 &marshalSpace, &marshalRoom);
1654
1655 // Check if we have enough space to add this evict object
1656 if(!NvTestSpace(entrySize, FALSE)) return TPM_RC_NV_SPACE;
1657
1658 // Add evict to NV memory
1659 NvAdd(entrySize, entrySize, nvBuffer);
1660 return TPM_RC_SUCCESS;
1661 }
1662 //
1663 //
1664 // NvDeleteEntity()
1665 //
1666 // This function will delete a NV Index or an evict object.
1667 // This function requires that the index/evict object has been defined.
1668 //
1669 void
NvDeleteEntity(TPM_HANDLE handle)1670 NvDeleteEntity(
1671 TPM_HANDLE handle // IN: handle of entity to be deleted
1672 )
1673 {
1674 UINT32 entityAddr; // pointer to entity
1675 entityAddr = NvFindHandle(handle);
1676 pAssert(entityAddr != 0);
1677 if(HandleGetType(handle) == TPM_HT_NV_INDEX)
1678 {
1679 NV_INDEX nvIndex;
1680 // Read the NV Index info
1681 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX),
1682 &nvIndex);
1683 // If the entity to be deleted is a counter with the maximum counter
1684 // value, record it in NV memory
1685 if(nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET
1686 && nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET)
1687 {
1688 UINT64 countValue;
1689 UINT64 maxCount;
1690 NvGetIntIndexData(handle, &nvIndex, &countValue);
1691 maxCount = NvReadMaxCount();
1692 if(countValue > maxCount)
1693 NvWriteMaxCount(countValue);
1694 }
1695 // If the NV Index is RAM back, delete the RAM data as well
1696 if(nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == SET)
1697 NvDeleteRAM(handle);
1698 }
1699 NvDelete(entityAddr);
1700 return;
1701 }
1702 //
1703 //
1704 // NvFlushHierarchy()
1705 //
1706 // This function will delete persistent objects belonging to the indicated If the storage hierarchy is selected,
1707 // the function will also delete any NV Index define using ownerAuth.
1708 //
1709 void
NvFlushHierarchy(TPMI_RH_HIERARCHY hierarchy)1710 NvFlushHierarchy(
1711 TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flushed.
1712 )
1713 {
1714 NV_ITER iter = NV_ITER_INIT;
1715 UINT32 currentAddr;
1716 while((currentAddr = NvNext(&iter)) != 0)
1717 {
1718 TPM_HANDLE entityHandle;
1719 // Read handle information.
1720 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle);
1721 if(HandleGetType(entityHandle) == TPM_HT_NV_INDEX)
1722 {
1723 // Handle NV Index
1724 NV_INDEX nvIndex;
1725 // If flush endorsement or platform hierarchy, no NV Index would be
1726 // flushed
1727 if(hierarchy == TPM_RH_ENDORSEMENT || hierarchy == TPM_RH_PLATFORM)
1728 continue;
1729 _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE),
1730 sizeof(NV_INDEX), &nvIndex);
1731 // For storage hierarchy, flush OwnerCreated index
1732 if( nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == CLEAR)
1733 {
1734 // Delete the NV Index
1735 NvDelete(currentAddr);
1736 // Re-iterate from beginning after a delete
1737 iter = NV_ITER_INIT;
1738 // If the NV Index is RAM back, delete the RAM data as well
1739 if(nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == SET)
1740 NvDeleteRAM(entityHandle);
1741 }
1742 }
1743 else if(HandleGetType(entityHandle) == TPM_HT_PERSISTENT)
1744 {
1745 OBJECT object;
1746 // Get evict object
1747 NvGetEvictObject(entityHandle, &object);
1748 // If the evict object belongs to the hierarchy to be flushed
1749 if( ( hierarchy == TPM_RH_PLATFORM
1750 && object.attributes.ppsHierarchy == SET)
1751 || ( hierarchy == TPM_RH_OWNER
1752 && object.attributes.spsHierarchy == SET)
1753 || ( hierarchy == TPM_RH_ENDORSEMENT
1754 && object.attributes.epsHierarchy == SET)
1755 )
1756 {
1757 // Delete the evict object
1758 NvDelete(currentAddr);
1759 // Re-iterate from beginning after a delete
1760 iter = NV_ITER_INIT;
1761 }
1762 }
1763 else
1764 {
1765 pAssert(FALSE);
1766 }
1767 }
1768 return;
1769 }
1770 //
1771 //
1772 // NvSetGlobalLock()
1773 //
1774 // This function is used to SET the TPMA_NV_WRITELOCKED attribute for all NV Indices that have
1775 // TPMA_NV_GLOBALLOCK SET. This function is use by TPM2_NV_GlobalWriteLock().
1776 //
1777 void
NvSetGlobalLock(void)1778 NvSetGlobalLock(
1779 void
1780 )
1781 {
1782 NV_ITER iter = NV_ITER_INIT;
1783 UINT32 currentAddr;
1784 // Check all Indices
1785 while((currentAddr = NvNextIndex(&iter)) != 0)
1786 {
1787 NV_INDEX nvIndex;
1788 // Read the index data
1789 _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE),
1790 sizeof(NV_INDEX), &nvIndex);
1791 // See if it should be locked
1792 if(nvIndex.publicArea.attributes.TPMA_NV_GLOBALLOCK == SET)
1793 {
1794 // if so, lock it
1795 nvIndex.publicArea.attributes.TPMA_NV_WRITELOCKED = SET;
1796 _plat__NvMemoryWrite(currentAddr + sizeof(TPM_HANDLE),
1797 sizeof(NV_INDEX), &nvIndex);
1798 // Set the flag that a NV write happens
1799 g_updateNV = TRUE;
1800 }
1801 }
1802 return;
1803 }
1804 //
1805 //
1806 // InsertSort()
1807 //
1808 // Sort a handle into handle list in ascending order. The total handle number in the list should not exceed
1809 // MAX_CAP_HANDLES
1810 //
1811 static void
InsertSort(TPML_HANDLE * handleList,UINT32 count,TPM_HANDLE entityHandle)1812 InsertSort(
1813 TPML_HANDLE *handleList, // IN/OUT: sorted handle list
1814 UINT32 count, // IN: maximum count in the handle list
1815 TPM_HANDLE entityHandle // IN: handle to be inserted
1816 )
1817 {
1818 UINT32 i, j;
1819 UINT32 originalCount;
1820 // For a corner case that the maximum count is 0, do nothing
1821 if(count == 0) return;
1822 // For empty list, add the handle at the beginning and return
1823 if(handleList->count == 0)
1824 {
1825 handleList->handle[0] = entityHandle;
1826 handleList->count++;
1827 return;
1828 }
1829 // Check if the maximum of the list has been reached
1830 originalCount = handleList->count;
1831 if(originalCount < count)
1832 handleList->count++;
1833 // Insert the handle to the list
1834 for(i = 0; i < originalCount; i++)
1835 {
1836 if(handleList->handle[i] > entityHandle)
1837 {
1838 for(j = handleList->count - 1; j > i; j--)
1839 {
1840 handleList->handle[j] = handleList->handle[j-1];
1841 }
1842 break;
1843 }
1844 }
1845 // If a slot was found, insert the handle in this position
1846 if(i < originalCount || handleList->count > originalCount)
1847 handleList->handle[i] = entityHandle;
1848 return;
1849 }
1850 //
1851 //
1852 // NvCapGetPersistent()
1853 //
1854 // This function is used to get a list of handles of the persistent objects, starting at handle.
1855 // Handle must be in valid persistent object handle range, but does not have to reference an existing
1856 // persistent object.
1857 //
1858 // Return Value Meaning
1859 //
1860 // YES if there are more handles available
1861 // NO all the available handles has been returned
1862 //
1863 TPMI_YES_NO
NvCapGetPersistent(TPMI_DH_OBJECT handle,UINT32 count,TPML_HANDLE * handleList)1864 NvCapGetPersistent(
1865 TPMI_DH_OBJECT handle, // IN: start handle
1866 UINT32 count, // IN: maximum number of returned handle
1867 TPML_HANDLE *handleList // OUT: list of handle
1868 )
1869 {
1870 TPMI_YES_NO more = NO;
1871 NV_ITER iter = NV_ITER_INIT;
1872 UINT32 currentAddr;
1873 pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT);
1874 // Initialize output handle list
1875 handleList->count = 0;
1876 // The maximum count of handles we may return is MAX_CAP_HANDLES
1877 if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
1878 while((currentAddr = NvNextEvict(&iter)) != 0)
1879 {
1880 TPM_HANDLE entityHandle;
1881 // Read handle information.
1882 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle);
1883 // Ignore persistent handles that have values less than the input handle
1884 if(entityHandle < handle)
1885 continue;
1886 // if the handles in the list have reached the requested count, and there
1887 // are still handles need to be inserted, indicate that there are more.
1888 if(handleList->count == count)
1889 more = YES;
1890 // A handle with a value larger than start handle is a candidate
1891 // for return. Insert sort it to the return list. Insert sort algorithm
1892 // is chosen here for simplicity based on the assumption that the total
1893 // number of NV Indices is small. For an implementation that may allow
1894 // large number of NV Indices, a more efficient sorting algorithm may be
1895 // used here.
1896 InsertSort(handleList, count, entityHandle);
1897 //
1898 }
1899 return more;
1900 }
1901 //
1902 //
1903 // NvCapGetIndex()
1904 //
1905 // This function returns a list of handles of NV Indices, starting from handle. Handle must be in the range of
1906 // NV Indices, but does not have to reference an existing NV Index.
1907 //
1908 // Return Value Meaning
1909 //
1910 // YES if there are more handles to report
1911 // NO all the available handles has been reported
1912 //
1913 TPMI_YES_NO
NvCapGetIndex(TPMI_DH_OBJECT handle,UINT32 count,TPML_HANDLE * handleList)1914 NvCapGetIndex(
1915 TPMI_DH_OBJECT handle, // IN: start handle
1916 UINT32 count, // IN: maximum number of returned handle
1917 TPML_HANDLE *handleList // OUT: list of handle
1918 )
1919 {
1920 TPMI_YES_NO more = NO;
1921 NV_ITER iter = NV_ITER_INIT;
1922 UINT32 currentAddr;
1923 pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX);
1924 // Initialize output handle list
1925 handleList->count = 0;
1926 // The maximum count of handles we may return is MAX_CAP_HANDLES
1927 if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
1928 while((currentAddr = NvNextIndex(&iter)) != 0)
1929 {
1930 TPM_HANDLE entityHandle;
1931 // Read handle information.
1932 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle);
1933 // Ignore index handles that have values less than the 'handle'
1934 if(entityHandle < handle)
1935 continue;
1936 // if the count of handles in the list has reached the requested count,
1937 // and there are still handles to report, set more.
1938 if(handleList->count == count)
1939 more = YES;
1940 // A handle with a value larger than start handle is a candidate
1941 // for return. Insert sort it to the return list. Insert sort algorithm
1942 // is chosen here for simplicity based on the assumption that the total
1943 // number of NV Indices is small. For an implementation that may allow
1944 // large number of NV Indices, a more efficient sorting algorithm may be
1945 // used here.
1946 InsertSort(handleList, count, entityHandle);
1947 }
1948 return more;
1949 }
1950 //
1951 //
1952 //
1953 // NvCapGetIndexNumber()
1954 //
1955 // This function returns the count of NV Indexes currently defined.
1956 //
1957 UINT32
NvCapGetIndexNumber(void)1958 NvCapGetIndexNumber(
1959 void
1960 )
1961 {
1962 UINT32 num = 0;
1963 NV_ITER iter = NV_ITER_INIT;
1964 while(NvNextIndex(&iter) != 0) num++;
1965 return num;
1966 }
1967 //
1968 //
1969 // NvCapGetPersistentNumber()
1970 //
1971 // Function returns the count of persistent objects currently in NV memory.
1972 //
1973 UINT32
NvCapGetPersistentNumber(void)1974 NvCapGetPersistentNumber(
1975 void
1976 )
1977 {
1978 UINT32 num = 0;
1979 NV_ITER iter = NV_ITER_INIT;
1980 while(NvNextEvict(&iter) != 0) num++;
1981 return num;
1982 }
1983 //
1984 //
1985 // NvCapGetPersistentAvail()
1986 //
1987 // This function returns an estimate of the number of additional persistent objects that could be loaded into
1988 // NV memory.
1989 //
1990 UINT32
NvCapGetPersistentAvail(void)1991 NvCapGetPersistentAvail(
1992 void
1993 )
1994 {
1995 UINT32 availSpace;
1996 UINT32 objectSpace;
1997 // Compute the available space in NV storage
1998 availSpace = NvGetFreeByte();
1999 // Get the space needed to add a persistent object to NV storage
2000 objectSpace = NvGetEvictObjectSize();
2001 return availSpace / objectSpace;
2002 }
2003 //
2004 //
2005 // NvCapGetCounterNumber()
2006 //
2007 // Get the number of defined NV Indexes that have NV TPMA_NV_COUNTER attribute SET.
2008 //
2009 //
2010 UINT32
NvCapGetCounterNumber(void)2011 NvCapGetCounterNumber(
2012 void
2013 )
2014 {
2015 NV_ITER iter = NV_ITER_INIT;
2016 UINT32 currentAddr;
2017 UINT32 num = 0;
2018 while((currentAddr = NvNextIndex(&iter)) != 0)
2019 {
2020 NV_INDEX nvIndex;
2021 // Get NV Index info
2022 _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE),
2023 sizeof(NV_INDEX), &nvIndex);
2024 if(nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET) num++;
2025 }
2026 return num;
2027 }
2028 //
2029 //
2030 // NvCapGetCounterAvail()
2031 //
2032 // This function returns an estimate of the number of additional counter type NV Indices that can be defined.
2033 //
2034 UINT32
NvCapGetCounterAvail(void)2035 NvCapGetCounterAvail(
2036 void
2037 )
2038 {
2039 UINT32 availNVSpace;
2040 UINT32 availRAMSpace;
2041 UINT32 counterNVSpace;
2042 UINT32 counterRAMSpace;
2043 UINT32 persistentNum = NvCapGetPersistentNumber();
2044 // Get the available space in NV storage
2045 availNVSpace = NvGetFreeByte();
2046 if (persistentNum < MIN_EVICT_OBJECTS)
2047 {
2048 // Some space have to be reserved for evict object. Adjust availNVSpace.
2049 UINT32 reserved = (MIN_EVICT_OBJECTS - persistentNum)
2050 * NvGetEvictObjectSize();
2051 if (reserved > availNVSpace)
2052 availNVSpace = 0;
2053 else
2054 availNVSpace -= reserved;
2055 }
2056 // Get the space needed to add a counter index to NV storage
2057 counterNVSpace = NvGetCounterSize();
2058 // Compute the available space in RAM
2059 availRAMSpace = RAM_INDEX_SPACE - s_ramIndexSize;
2060 // Compute the space needed to add a counter index to RAM storage
2061 // It takes an size field, a handle and sizeof(UINT64) for counter data
2062 counterRAMSpace = sizeof(UINT32) + sizeof(TPM_HANDLE) + sizeof(UINT64);
2063 // Return the min of counter number in NV and in RAM
2064 if(availNVSpace / counterNVSpace > availRAMSpace / counterRAMSpace)
2065 return availRAMSpace / counterRAMSpace;
2066 else
2067 return availNVSpace / counterNVSpace;
2068 }
2069