blob: 37e91da1b708ae872b5c43d65c14eec299751eba [file] [log] [blame]
Vadim Bendebury56797522015-05-20 10:32:25 -07001// 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"
Vadim Bendebury6c73a9e2015-05-31 16:06:18 -070010#include "Platform.h"
Vadim Bendebury56797522015-05-20 10:32:25 -070011//
12// NV Index/evict object iterator value
13//
14typedef 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//
27void
28NvCheckState(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//
58TPM_RC
59NvIsAvailable(
60 void
61 )
62{
Bill Richardsonacc84192016-09-28 11:06:53 -070063 // Make sure that NV state is still good
64 if (s_NvStatus == TPM_RC_SUCCESS)
65 NvCheckState();
66
Vadim Bendebury56797522015-05-20 10:32:25 -070067 return s_NvStatus;
68}
69//
70//
71// NvCommit
72//
73// This is a wrapper for the platform function to commit pending NV writes.
74//
75BOOL
76NvCommit(
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//
89static UINT64
90NvReadMaxCount(
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//
104static void
105NvWriteMaxCount(
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//
134static UINT32
135NvNext(
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);
Vadim Bendeburyf6a820b2018-08-31 16:36:44 -0700154 if(!*iter || (*iter == NV_ITER_INIT)) return 0;
Vadim Bendebury56797522015-05-20 10:32:25 -0700155 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//
163static UINT32
164NvGetEnd(
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//
187static UINT32
188NvGetFreeByte(
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//
199static UINT32
200NvGetEvictObjectSize(
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//
212static UINT32
213NvGetCounterSize(
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//
232static BOOL
233NvTestSpace(
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//
276static void
277NvAdd(
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//
310static void
311NvDelete(
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//
373static BOOL
374NvTestRAMSpace(
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//
391static UINT32
392NvGetRAMIndexOffset(
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;
Jocelyn Bohr71e3b992015-08-14 12:05:59 -0700401 memcpy(&currHandle, &s_ramIndex[currAddr + sizeof(UINT32)],
402 sizeof(currHandle));
Vadim Bendebury56797522015-05-20 10:32:25 -0700403 // Found a match
404 if(currHandle == handle)
405 // data buffer follows the handle and size field
406 break;
Jocelyn Bohr71e3b992015-08-14 12:05:59 -0700407 memcpy(&currSize, &s_ramIndex[currAddr], sizeof(currSize));
Vadim Bendebury56797522015-05-20 10:32:25 -0700408 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//
421static void
422NvAddRAM(
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
Jocelyn Bohr71e3b992015-08-14 12:05:59 -0700428 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)]));
Vadim Bendebury56797522015-05-20 10:32:25 -0700433 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//
448static void
449NvDeleteRAM(
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
Jocelyn Bohr71e3b992015-08-14 12:05:59 -0700460 memcpy(&size, &s_ramIndex[nodeOffset], sizeof(size));
Vadim Bendebury56797522015-05-20 10:32:25 -0700461 // 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//
483static void
484NvInitStatic(
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//
555void
556NvInit(
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//
578void
579NvReadReserved(
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//
596void
597NvWriteReserved(
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//
615void
616NvReadPersistent(
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
Vadim Bendebury15d53c32016-10-25 14:14:38 -0700661#ifdef EMBEDDED_MODE
662 _plat__GetFwVersion(&gp.firmwareV1, &gp.firmwareV2);
663#else
Vadim Bendebury56797522015-05-20 10:32:25 -0700664 NvReadReserved(NV_FIRMWARE_V1, &gp.firmwareV1);
665 NvReadReserved(NV_FIRMWARE_V2, &gp.firmwareV2);
Vadim Bendebury15d53c32016-10-25 14:14:38 -0700666#endif
Vadim Bendebury56797522015-05-20 10:32:25 -0700667 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//
681BOOL
682NvIsPlatformPersistentHandle(
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//
700BOOL
701NvIsOwnerPersistentHandle(
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//
716static UINT32
717NvNextIndex(
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//
740static UINT32
741NvNextEvict(
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//
764static UINT32
765NvFindHandle(
766 TPM_HANDLE handle
767 )
768{
769 UINT32 addr;
770 NV_ITER iter = NV_ITER_INIT;
Louis Collard5cb743a2018-06-26 20:07:49 +0800771
772 if ((addr = _plat__NvGetHandleVirtualOffset(handle)) != 0) {
773 return addr;
774 }
775
Vadim Bendebury56797522015-05-20 10:32:25 -0700776 while((addr = NvNext(&iter)) != 0)
777 {
778 TPM_HANDLE entityHandle;
779 // Read handle
780//
781 _plat__NvMemoryRead(addr, sizeof(TPM_HANDLE), &entityHandle);
782 if(entityHandle == handle)
783 return addr;
784 }
785 pAssert(addr == 0);
786 return addr;
787}
Vadim Bendebury889c3dd2016-12-03 07:27:09 +0800788
789//
790// NvCheckAndMigrateIfNeeded()
791//
792// Supported only in EMBEDDED_MODE.
793//
794// Check if the NVRAM storage format changed, and if so - reinitialize the
795// NVRAM. No content migration yet, hopefully it will come one day.
796//
797// Note that the NV_FIRMWARE_V1 and NV_FIRMWARE_V2 values not used to store
798// TPM versoion when in embedded mode are used for NVRAM format version
799// instead.
800//
801//
802static void
803NvCheckAndMigrateIfNeeded(void)
804{
805#ifdef EMBEDDED_MODE
806 UINT32 nv_vers1;
807 UINT32 nv_vers2;
808
809 NvReadReserved(NV_FIRMWARE_V1, &nv_vers1);
810 NvReadReserved(NV_FIRMWARE_V2, &nv_vers2);
811
812 if ((nv_vers1 == ~nv_vers2) && (nv_vers1 == NV_FORMAT_VERSION))
813 return; // All is well.
814
815 // This will reinitialize NVRAM to empty. Migration code will come here
816 // later.
817 NvInit();
818
819 nv_vers1 = NV_FORMAT_VERSION;
820 nv_vers2 = ~NV_FORMAT_VERSION;
821
822 NvWriteReserved(NV_FIRMWARE_V1, &nv_vers1);
823 NvWriteReserved(NV_FIRMWARE_V2, &nv_vers2);
824
825 NvCommit();
826#endif
827}
828
829
Vadim Bendebury56797522015-05-20 10:32:25 -0700830//
831//
832// NvPowerOn()
833//
834// This function is called at _TPM_Init() to initialize the NV environment.
835//
836// Return Value Meaning
837//
838// TRUE all NV was initialized
839// FALSE the NV containing saved state had an error and
840// TPM2_Startup(CLEAR) is required
841//
842BOOL
843NvPowerOn(
844 void
845 )
846{
847 int nvError = 0;
848 // If power was lost, need to re-establish the RAM data that is loaded from
849 // NV and initialize the static variables
850 if(_plat__WasPowerLost(TRUE))
851 {
852 if((nvError = _plat__NVEnable(0)) < 0)
853 FAIL(FATAL_ERROR_NV_UNRECOVERABLE);
Vadim Bendebury889c3dd2016-12-03 07:27:09 +0800854 NvInitStatic();
855 NvCheckAndMigrateIfNeeded();
Vadim Bendebury56797522015-05-20 10:32:25 -0700856 }
857 return nvError == 0;
858}
859//
860//
861// NvStateSave()
862//
863// This function is used to cause the memory containing the RAM backed NV Indices to be written to NV.
864//
865void
866NvStateSave(
867 void
868 )
869{
870 // Write RAM backed NV Index info to NV
871 // No need to save s_ramIndexSize because we save it to NV whenever it is
872 // updated.
873 _plat__NvMemoryWrite(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex);
874 // Set the flag so that an NV write happens before the command completes.
875 g_updateNV = TRUE;
876 return;
877}
878//
879//
880//
881// NvEntityStartup()
882//
883// This function is called at TPM_Startup(). If the startup completes a TPM Resume cycle, no action is
884// taken. If the startup is a TPM Reset or a TPM Restart, then this function will:
885// a) clear read/write lock;
886// b) reset NV Index data that has TPMA_NV_CLEAR_STCLEAR SET; and
887// c) set the lower bits in orderly counters to 1 for a non-orderly startup
888// It is a prerequisite that NV be available for writing before this function is called.
889//
890void
891NvEntityStartup(
892 STARTUP_TYPE type // IN: start up type
893 )
894{
895 NV_ITER iter = NV_ITER_INIT;
896 UINT32 currentAddr; // offset points to the current entity
897 // Restore RAM index data
898 _plat__NvMemoryRead(s_ramIndexSizeAddr, sizeof(UINT32), &s_ramIndexSize);
899 _plat__NvMemoryRead(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex);
900 // If recovering from state save, do nothing
901 if(type == SU_RESUME)
902 return;
903 // Iterate all the NV Index to clear the locks
904 while((currentAddr = NvNextIndex(&iter)) != 0)
905 {
906 NV_INDEX nvIndex;
907 UINT32 indexAddr; // NV address points to index info
908 TPMA_NV attributes;
Jocelyn Bohr71e3b992015-08-14 12:05:59 -0700909 UINT32 attributesValue;
910 UINT32 publicAreaAttributesValue;
Vadim Bendebury56797522015-05-20 10:32:25 -0700911 indexAddr = currentAddr + sizeof(TPM_HANDLE);
912 // Read NV Index info structure
913 _plat__NvMemoryRead(indexAddr, sizeof(NV_INDEX), &nvIndex);
914 attributes = nvIndex.publicArea.attributes;
915 // Clear read/write lock
916 if(attributes.TPMA_NV_READLOCKED == SET)
917 attributes.TPMA_NV_READLOCKED = CLEAR;
918 if( attributes.TPMA_NV_WRITELOCKED == SET
919 && ( attributes.TPMA_NV_WRITTEN == CLEAR
920 || attributes.TPMA_NV_WRITEDEFINE == CLEAR
921 )
922 )
923 attributes.TPMA_NV_WRITELOCKED = CLEAR;
924 // Reset NV data for TPMA_NV_CLEAR_STCLEAR
925 if(attributes.TPMA_NV_CLEAR_STCLEAR == SET)
926 {
927 attributes.TPMA_NV_WRITTEN = CLEAR;
928 attributes.TPMA_NV_WRITELOCKED = CLEAR;
929 }
930 // Reset NV data for orderly values that are not counters
931 // NOTE: The function has already exited on a TPM Resume, so the only
932 // things being processed are TPM Restart and TPM Reset
933 if( type == SU_RESET
934 && attributes.TPMA_NV_ORDERLY == SET
935 && attributes.TPMA_NV_COUNTER == CLEAR
936 )
937 attributes.TPMA_NV_WRITTEN = CLEAR;
938 // Write NV Index info back if it has changed
Jocelyn Bohr71e3b992015-08-14 12:05:59 -0700939 memcpy(&attributesValue, &attributes, sizeof(attributesValue));
940 memcpy(&publicAreaAttributesValue, &nvIndex.publicArea.attributes,
941 sizeof(publicAreaAttributesValue));
942 if(attributesValue != publicAreaAttributesValue)
Vadim Bendebury56797522015-05-20 10:32:25 -0700943 {
944 nvIndex.publicArea.attributes = attributes;
945 _plat__NvMemoryWrite(indexAddr, sizeof(NV_INDEX), &nvIndex);
946 // Set the flag that a NV write happens
947 g_updateNV = TRUE;
948 }
949 // Set the lower bits in an orderly counter to 1 for a non-orderly startup
950 if( g_prevOrderlyState == SHUTDOWN_NONE
951 && attributes.TPMA_NV_WRITTEN == SET)
952 {
953 if( attributes.TPMA_NV_ORDERLY == SET
954 && attributes.TPMA_NV_COUNTER == SET)
955 {
956 TPMI_RH_NV_INDEX nvHandle;
957 UINT64 counter;
958 // Read NV handle
959 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &nvHandle);
960 // Read the counter value saved to NV upon the last roll over.
961 // Do not use RAM backed storage for this once.
962 nvIndex.publicArea.attributes.TPMA_NV_ORDERLY = CLEAR;
963 NvGetIntIndexData(nvHandle, &nvIndex, &counter);
964 nvIndex.publicArea.attributes.TPMA_NV_ORDERLY = SET;
965 // Set the lower bits of counter to 1's
966 counter |= MAX_ORDERLY_COUNT;
967 // Write back to RAM
968 NvWriteIndexData(nvHandle, &nvIndex, 0, sizeof(counter), &counter);
969 // No write to NV because an orderly shutdown will update the
970 // counters.
971 }
972 }
973 }
974 return;
975}
976//
977//
978// NV Access Functions
979//
980// Introduction
981//
982// This set of functions provide accessing NV Index and persistent objects based using a handle for
983// reference to the entity.
984//
985// NvIsUndefinedIndex()
986//
987// This function is used to verify that an NV Index is not defined. This is only used by
988// TPM2_NV_DefineSpace().
989//
990//
991//
992//
993// Return Value Meaning
994//
995// TRUE the handle points to an existing NV Index
996// FALSE the handle points to a non-existent Index
997//
998BOOL
999NvIsUndefinedIndex(
1000 TPMI_RH_NV_INDEX handle // IN: handle
1001 )
1002{
1003 UINT32 entityAddr; // offset points to the entity
1004 pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX);
1005 // Find the address of index
1006 entityAddr = NvFindHandle(handle);
1007 // If handle is not found, return TPM_RC_SUCCESS
1008 if(entityAddr == 0)
1009 return TPM_RC_SUCCESS;
1010 // NV Index is defined
1011 return TPM_RC_NV_DEFINED;
1012}
1013//
1014//
1015// NvIndexIsAccessible()
1016//
1017// This function validates that a handle references a defined NV Index and that the Index is currently
1018// accessible.
1019//
1020// Error Returns Meaning
1021//
1022// TPM_RC_HANDLE the handle points to an undefined NV Index If shEnable is CLEAR,
1023// this would include an index created using ownerAuth. If phEnableNV
1024// is CLEAR, this would include and index created using platform auth
1025// TPM_RC_NV_READLOCKED Index is present but locked for reading and command does not write
1026// to the index
1027// TPM_RC_NV_WRITELOCKED Index is present but locked for writing and command writes to the
1028// index
1029//
1030TPM_RC
1031NvIndexIsAccessible(
1032 TPMI_RH_NV_INDEX handle, // IN: handle
1033 TPM_CC commandCode // IN: the command
1034 )
1035{
1036 UINT32 entityAddr; // offset points to the entity
1037 NV_INDEX nvIndex; //
1038 pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX);
1039 // Find the address of index
1040 entityAddr = NvFindHandle(handle);
1041 // If handle is not found, return TPM_RC_HANDLE
1042 if(entityAddr == 0)
1043 return TPM_RC_HANDLE;
1044 // Read NV Index info structure
1045 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX),
1046 &nvIndex);
1047 if(gc.shEnable == FALSE || gc.phEnableNV == FALSE)
1048 {
1049 // if shEnable is CLEAR, an ownerCreate NV Index should not be
1050 // indicated as present
1051 if(nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == CLEAR)
1052 {
Vadim Bendeburyc4562252017-12-08 14:05:56 -08001053 /*
1054 * FWMP is a Chrome OS specific object saved at address 0x100a, it
1055 * needs to be available for reading even before TPM2_Startup
1056 * command is issued.
1057 */
1058 UINT32 isFwmpRead = (handle == 0x100100a) &&
1059 IsReadOperation(commandCode);
1060
1061 if((gc.shEnable == FALSE) && !isFwmpRead)
Vadim Bendebury56797522015-05-20 10:32:25 -07001062 return TPM_RC_HANDLE;
1063 }
1064 // if phEnableNV is CLEAR, a platform created Index should not
1065 // be visible
1066 else if(gc.phEnableNV == FALSE)
1067 return TPM_RC_HANDLE;
1068 }
1069 // If the Index is write locked and this is an NV Write operation...
1070 if( nvIndex.publicArea.attributes.TPMA_NV_WRITELOCKED
1071 && IsWriteOperation(commandCode))
1072 {
1073 // then return a locked indication unless the command is TPM2_NV_WriteLock
1074 if(commandCode != TPM_CC_NV_WriteLock)
1075 return TPM_RC_NV_LOCKED;
1076 return TPM_RC_SUCCESS;
1077 }
1078 // If the Index is read locked and this is an NV Read operation...
1079 if( nvIndex.publicArea.attributes.TPMA_NV_READLOCKED
1080 && IsReadOperation(commandCode))
1081 {
1082 // then return a locked indication unless the command is TPM2_NV_ReadLock
1083 if(commandCode != TPM_CC_NV_ReadLock)
1084 return TPM_RC_NV_LOCKED;
1085 return TPM_RC_SUCCESS;
1086 }
1087 // NV Index is accessible
1088 return TPM_RC_SUCCESS;
1089}
1090//
1091//
1092// NvIsUndefinedEvictHandle()
1093//
1094// This function indicates if a handle does not reference an existing persistent object. This function requires
1095// that the handle be in the proper range for persistent objects.
1096//
1097// Return Value Meaning
1098//
1099// TRUE handle does not reference an existing persistent object
1100// FALSE handle does reference an existing persistent object
1101//
1102static BOOL
1103NvIsUndefinedEvictHandle(
1104 TPM_HANDLE handle // IN: handle
1105 )
1106{
1107 UINT32 entityAddr; // offset points to the entity
1108 pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT);
1109 // Find the address of evict object
1110 entityAddr = NvFindHandle(handle);
1111 // If handle is not found, return TRUE
1112 if(entityAddr == 0)
1113 return TRUE;
1114 else
1115 return FALSE;
1116}
Vadim Bendebury21756122016-12-29 11:14:03 -08001117
1118//
1119//
1120// NvUnmarshalObject()
1121//
1122// This function accepts a buffer containing a marshaled OBJECT
1123// structure, a pointer to the area where the input data should be
1124// unmarshaled, and a pointer to the size of the output area.
1125//
1126// No error checking is performed, unmarshaled data is guaranteed not to
1127// spill over the allocated space.
1128//
1129static TPM_RC NvUnmarshalObject(OBJECT *o, BYTE **buf, INT32 *size)
1130{
1131 TPM_RC result;
1132
1133 // There is no generated function to unmarshal the attributes field, do it
1134 // by hand.
1135 MemoryCopy(&o->attributes, *buf, sizeof(o->attributes), *size);
1136 *buf += sizeof(o->attributes);
1137 *size -= sizeof(o->attributes);
1138
1139 result = TPMT_PUBLIC_Unmarshal(&o->publicArea, buf, size);
1140 if (result != TPM_RC_SUCCESS)
1141 return result;
1142
1143 result = TPMT_SENSITIVE_Unmarshal(&o->sensitive, buf, size);
1144 if (result != TPM_RC_SUCCESS)
1145 return result;
1146
1147#ifdef TPM_ALG_RSA
1148 result = TPM2B_PUBLIC_KEY_RSA_Unmarshal(&o->privateExponent, buf, size);
1149 if (result != TPM_RC_SUCCESS)
1150 return result;
1151#endif
1152
1153 result = TPM2B_NAME_Unmarshal(&o->qualifiedName, buf, size);
1154 if (result != TPM_RC_SUCCESS)
1155 return result;
1156
1157 result = TPMI_DH_OBJECT_Unmarshal(&o->evictHandle, buf, size, TRUE);
1158 if (result != TPM_RC_SUCCESS)
1159 return result;
1160
1161 return TPM2B_NAME_Unmarshal(&o->name, buf, size);
1162}
1163
Vadim Bendebury56797522015-05-20 10:32:25 -07001164//
1165//
1166// NvGetEvictObject()
1167//
1168// This function is used to dereference an evict object handle and get a pointer to the object.
1169//
1170// Error Returns Meaning
1171//
1172// TPM_RC_HANDLE the handle does not point to an existing persistent object
1173//
1174TPM_RC
1175NvGetEvictObject(
1176 TPM_HANDLE handle, // IN: handle
1177 OBJECT *object // OUT: object data
1178 )
1179{
1180 UINT32 entityAddr; // offset points to the entity
1181 TPM_RC result = TPM_RC_SUCCESS;
1182 pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT);
1183 // Find the address of evict object
1184 entityAddr = NvFindHandle(handle);
1185 // If handle is not found, return an error
Vadim Bendebury21756122016-12-29 11:14:03 -08001186 if(entityAddr == 0) {
Vadim Bendebury56797522015-05-20 10:32:25 -07001187 result = TPM_RC_HANDLE;
Vadim Bendebury21756122016-12-29 11:14:03 -08001188 } else {
1189 UINT32 storedSize;
1190 UINT32 nextEntryAddr;
1191
1192 // Let's calculate the size of object as stored in NVMEM.
1193 _plat__NvMemoryRead(entityAddr - sizeof(UINT32),
1194 sizeof(UINT32), &nextEntryAddr);
1195
1196 storedSize = nextEntryAddr - entityAddr;
1197
1198 if (storedSize == (sizeof(TPM_HANDLE) + sizeof(OBJECT))) {
1199 // Read evict object stored unmarshaled.
1200 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE),
1201 sizeof(OBJECT),
1202 object);
1203 } else {
1204 // Must be stored marshaled, let's unmarshal it.
1205 BYTE marshaled[sizeof(OBJECT)];
1206 INT32 max_size = sizeof(marshaled);
1207 BYTE *marshaledPtr = marshaled;
1208
1209 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE),
1210 storedSize, marshaled);
1211 result = NvUnmarshalObject(object, &marshaledPtr, &max_size);
1212 }
1213 }
Vadim Bendebury56797522015-05-20 10:32:25 -07001214 // whether there is an error or not, make sure that the evict
1215 // status of the object is set so that the slot will get freed on exit
1216 object->attributes.evict = SET;
1217 return result;
1218}
1219//
1220//
1221// NvGetIndexInfo()
1222//
1223// This function is used to retrieve the contents of an NV Index.
1224// An implementation is allowed to save the NV Index in a vendor-defined format. If the format is different
1225// from the default used by the reference code, then this function would be changed to reformat the data into
1226// the default format.
1227// A prerequisite to calling this function is that the handle must be known to reference a defined NV Index.
1228//
1229void
1230NvGetIndexInfo(
1231 TPMI_RH_NV_INDEX handle, // IN: handle
1232 NV_INDEX *nvIndex // OUT: NV index structure
1233 )
1234{
Namyoon Woo0be7f8d2020-02-04 16:43:47 -08001235 NvReadIndexInfo(handle, 0, nvIndex);
1236 return;
1237}
1238//
1239//
1240// NvReadIndexInfo()
1241//
1242// This function is used to retrieve the contents of an NV Index from the
1243// given address.
1244// A prerequisite to calling this function is that either handle or
1245// entityAddr must be valid value. If entityAddr is non-zero, then it will
1246// be regarded as a valid address of NV data. If it is zero, then "handle"
1247// shall be used to find its address.
1248//
1249void
1250NvReadIndexInfo(
1251 TPMI_RH_NV_INDEX handle, // IN: handle
1252 UINT32 entityAddr, // IN: Base address of NV data
1253 NV_INDEX *nvIndex // OUT: NV index structure
1254 )
1255{
1256 if (!entityAddr) {
1257 pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX);
1258 // Find the address of NV index
1259 entityAddr = NvFindHandle(handle);
1260 }
1261
Vadim Bendebury56797522015-05-20 10:32:25 -07001262 pAssert(entityAddr != 0);
1263 // This implementation uses the default format so just
1264 // read the data in
1265 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX),
1266 nvIndex);
1267 return;
1268}
1269//
1270//
1271// NvInitialCounter()
1272//
1273// This function returns the value to be used when a counter index is initialized. It will scan the NV counters
1274// and find the highest value in any active counter. It will use that value as the starting point. If there are no
1275// active counters, it will use the value of the previous largest counter.
1276//
1277UINT64
1278NvInitialCounter(
1279 void
1280 )
1281{
1282 UINT64 maxCount;
1283 NV_ITER iter = NV_ITER_INIT;
1284 UINT32 currentAddr;
1285 // Read the maxCount value
1286 maxCount = NvReadMaxCount();
1287 // Iterate all existing counters
1288 while((currentAddr = NvNextIndex(&iter)) != 0)
1289 {
1290 TPMI_RH_NV_INDEX nvHandle;
1291 NV_INDEX nvIndex;
1292 // Read NV handle
1293 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &nvHandle);
1294 // Get NV Index
1295 NvGetIndexInfo(nvHandle, &nvIndex);
1296 if( nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET
1297 && nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET)
1298 {
1299 UINT64 countValue;
1300 // Read counter value
1301 NvGetIntIndexData(nvHandle, &nvIndex, &countValue);
1302 if(countValue > maxCount)
1303 maxCount = countValue;
1304 }
1305 }
1306 // Initialize the new counter value to be maxCount + 1
1307 // A counter is only initialized the first time it is written. The
1308 // way to write a counter is with TPM2_NV_INCREMENT(). Since the
1309 // "initial" value of a defined counter is the largest count value that
1310 // may have existed in this index previously, then the first use would
1311 // add one to that value.
1312 return maxCount;
1313}
1314//
1315//
1316// NvGetIndexData()
1317//
1318// This function is used to access the data in an NV Index. The data is returned as a byte sequence. Since
1319// counter values are kept in native format, they are converted to canonical form before being returned.
1320// Family "2.0" TCG Published Page 139
1321// Level 00 Revision 01.16 Copyright © TCG 2006-2014 October 30, 2014
1322// Trusted Platform Module Library Part 4: Supporting Routines
1323//
1324//
1325// This function requires that the NV Index be defined, and that the required data is within the data range. It
1326// also requires that TPMA_NV_WRITTEN of the Index is SET.
1327//
1328void
1329NvGetIndexData(
1330 TPMI_RH_NV_INDEX handle, // IN: handle
1331 NV_INDEX *nvIndex, // IN: RAM image of index header
1332 UINT32 offset, // IN: offset of NV data
1333 UINT16 size, // IN: size of NV data
1334 void *data // OUT: data buffer
1335 )
1336{
Namyoon Woo0be7f8d2020-02-04 16:43:47 -08001337 NvReadIndexData(handle, nvIndex, 0, offset, size, data);
1338}
1339//
1340//
1341// NvReadIndexData()
1342//
1343// This function is used to read the data in an NV Index from the given address.
1344// This function requires that the NV Index be defined, and that the required
1345// data is within the data range. It also requires that TPMA_NV_WRITTEN of the
1346// Index is SET.
1347// entityAddr is optional. If the value is zero, then it will be retrieved
1348// by calling NvFindHandle() in this function.
1349//
1350void
1351NvReadIndexData(
1352 TPMI_RH_NV_INDEX handle, // IN: handle
1353 NV_INDEX *nvIndex, // IN: RAM image of index header
1354 UINT32 entityAddr, // IN: Base address of NV data
1355 UINT32 offset, // IN: offset of NV data
1356 UINT16 size, // IN: size of NV data
1357 void *data // OUT: data buffer
1358 )
1359{
Vadim Bendebury56797522015-05-20 10:32:25 -07001360 pAssert(nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == SET);
1361 if( nvIndex->publicArea.attributes.TPMA_NV_BITS == SET
1362 || nvIndex->publicArea.attributes.TPMA_NV_COUNTER == SET)
1363 {
1364 // Read bit or counter data in canonical form
1365 UINT64 dataInInt;
1366 NvGetIntIndexData(handle, nvIndex, &dataInInt);
1367 UINT64_TO_BYTE_ARRAY(dataInInt, (BYTE *)data);
1368 }
1369 else
1370 {
1371 if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET)
1372 {
1373 UINT32 ramAddr;
Namyoon Woo0be7f8d2020-02-04 16:43:47 -08001374 // Get data from RAM buffer
1375 ramAddr = NvGetRAMIndexOffset(handle);
1376 MemoryCopy(data, s_ramIndex + ramAddr + offset, size, size);
1377 }
1378 else
1379 {
1380 if (!entityAddr)
1381 entityAddr = NvFindHandle(handle);
1382 pAssert(entityAddr != 0);
1383 // Get data from NV
1384 // Skip NV Index info, read data buffer
1385 entityAddr += sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + offset;
1386 // Read the data
1387 _plat__NvMemoryRead(entityAddr, size, data);
Vadim Bendebury56797522015-05-20 10:32:25 -07001388 }
1389 }
1390 return;
1391}
1392//
1393//
1394// NvGetIntIndexData()
1395//
1396// Get data in integer format of a bit or counter NV Index.
1397// This function requires that the NV Index is defined and that the NV Index previously has been written.
1398//
1399void
1400NvGetIntIndexData(
1401 TPMI_RH_NV_INDEX handle, // IN: handle
1402 NV_INDEX *nvIndex, // IN: RAM image of NV Index header
1403 UINT64 *data // IN: UINT64 pointer for counter or bit
1404 )
1405{
1406 // Validate that index has been written and is the right type
1407 pAssert( nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == SET
1408 && ( nvIndex->publicArea.attributes.TPMA_NV_BITS == SET
1409 || nvIndex->publicArea.attributes.TPMA_NV_COUNTER == SET
1410 )
1411 );
1412 // bit and counter value is store in native format for TPM CPU. So we directly
1413 // copy the contents of NV to output data buffer
1414 if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET)
1415 {
1416 UINT32 ramAddr;
1417 // Get data from RAM buffer
1418 ramAddr = NvGetRAMIndexOffset(handle);
1419 MemoryCopy(data, s_ramIndex + ramAddr, sizeof(*data), sizeof(*data));
1420 }
1421 else
1422 {
1423 UINT32 entityAddr;
1424 entityAddr = NvFindHandle(handle);
1425 // Get data from NV
1426 // Skip NV Index info, read data buffer
1427 _plat__NvMemoryRead(
1428 entityAddr + sizeof(TPM_HANDLE) + sizeof(NV_INDEX),
1429 sizeof(UINT64), data);
1430 }
1431 return;
1432}
1433//
1434//
1435// NvWriteIndexInfo()
1436//
1437// This function is called to queue the write of NV Index data to persistent memory.
1438// This function requires that NV Index is defined.
1439//
1440// Error Returns Meaning
1441//
1442// TPM_RC_NV_RATE NV is rate limiting so retry
1443// TPM_RC_NV_UNAVAILABLE NV is not available
1444//
1445TPM_RC
1446NvWriteIndexInfo(
1447 TPMI_RH_NV_INDEX handle, // IN: handle
1448 NV_INDEX *nvIndex // IN: NV Index info to be written
1449 )
1450{
1451 UINT32 entryAddr;
1452 TPM_RC result;
1453 // Get the starting offset for the index in the RAM image of NV
1454 entryAddr = NvFindHandle(handle);
1455 pAssert(entryAddr != 0);
1456 // Step over the link value
1457 entryAddr = entryAddr + sizeof(TPM_HANDLE);
1458 // If the index data is actually changed, then a write to NV is required
1459 if(_plat__NvIsDifferent(entryAddr, sizeof(NV_INDEX),nvIndex))
1460 {
1461 // Make sure that NV is available
1462 result = NvIsAvailable();
1463 if(result != TPM_RC_SUCCESS)
1464 return result;
1465 _plat__NvMemoryWrite(entryAddr, sizeof(NV_INDEX), nvIndex);
1466 g_updateNV = TRUE;
1467 }
1468 return TPM_RC_SUCCESS;
1469}
1470//
1471//
1472// NvWriteIndexData()
1473//
1474// This function is used to write NV index data.
1475// This function requires that the NV Index is defined, and the data is within the defined data range for the
1476// index.
1477//
1478// Error Returns Meaning
1479//
1480// TPM_RC_NV_RATE NV is rate limiting so retry
1481// TPM_RC_NV_UNAVAILABLE NV is not available
1482//
1483TPM_RC
1484NvWriteIndexData(
1485 TPMI_RH_NV_INDEX handle, // IN: handle
1486 NV_INDEX *nvIndex, // IN: RAM copy of NV Index
1487 UINT32 offset, // IN: offset of NV data
1488 UINT32 size, // IN: size of NV data
1489 void *data // OUT: data buffer
1490 )
1491{
1492 TPM_RC result;
1493 // Validate that write falls within range of the index
1494 pAssert(nvIndex->publicArea.dataSize >= offset + size);
1495 // Update TPMA_NV_WRITTEN bit if necessary
1496 if(nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == CLEAR)
1497 {
1498 nvIndex->publicArea.attributes.TPMA_NV_WRITTEN = SET;
1499 result = NvWriteIndexInfo(handle, nvIndex);
1500 if(result != TPM_RC_SUCCESS)
1501 return result;
1502 }
1503 // Check to see if process for an orderly index is required.
1504 if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET)
1505 {
1506 UINT32 ramAddr;
1507 // Write data to RAM buffer
1508 ramAddr = NvGetRAMIndexOffset(handle);
1509 MemoryCopy(s_ramIndex + ramAddr + offset, data, size,
1510 sizeof(s_ramIndex) - ramAddr - offset);
1511 // NV update does not happen for orderly index. Have
1512 // to clear orderlyState to reflect that we have changed the
1513 // NV and an orderly shutdown is required. Only going to do this if we
1514 // are not processing a counter that has just rolled over
1515 if(g_updateNV == FALSE)
1516 g_clearOrderly = TRUE;
1517 }
1518 // Need to process this part if the Index isn't orderly or if it is
1519 // an orderly counter that just rolled over.
1520 if(g_updateNV || nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == CLEAR)
1521 {
1522 // Processing for an index with TPMA_NV_ORDERLY CLEAR
1523 UINT32 entryAddr = NvFindHandle(handle);
1524 pAssert(entryAddr != 0);
1525//
1526 // Offset into the index to the first byte of the data to be written
1527 entryAddr += sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + offset;
1528 // If the data is actually changed, then a write to NV is required
1529 if(_plat__NvIsDifferent(entryAddr, size, data))
1530 {
1531 // Make sure that NV is available
1532 result = NvIsAvailable();
1533 if(result != TPM_RC_SUCCESS)
1534 return result;
1535 _plat__NvMemoryWrite(entryAddr, size, data);
1536 g_updateNV = TRUE;
1537 }
1538 }
1539 return TPM_RC_SUCCESS;
1540}
1541//
1542//
1543// NvGetName()
1544//
1545// This function is used to compute the Name of an NV Index.
1546// The name buffer receives the bytes of the Name and the return value is the number of octets in the
1547// Name.
1548// This function requires that the NV Index is defined.
1549//
1550UINT16
1551NvGetName(
1552 TPMI_RH_NV_INDEX handle, // IN: handle of the index
1553 NAME *name // OUT: name of the index
1554 )
1555{
1556 UINT16 dataSize, digestSize;
1557 NV_INDEX nvIndex;
1558 BYTE marshalBuffer[sizeof(TPMS_NV_PUBLIC)];
1559 BYTE *buffer;
Jocelyn Bohr32be4042015-07-29 15:14:01 -07001560 INT32 bufferSize;
Vadim Bendebury56797522015-05-20 10:32:25 -07001561 HASH_STATE hashState;
1562 // Get NV public info
1563 NvGetIndexInfo(handle, &nvIndex);
1564 // Marshal public area
1565 buffer = marshalBuffer;
Jocelyn Bohr32be4042015-07-29 15:14:01 -07001566 bufferSize = sizeof(TPMS_NV_PUBLIC);
1567 dataSize = TPMS_NV_PUBLIC_Marshal(&nvIndex.publicArea, &buffer, &bufferSize);
Vadim Bendebury56797522015-05-20 10:32:25 -07001568 // hash public area
1569 digestSize = CryptStartHash(nvIndex.publicArea.nameAlg, &hashState);
1570 CryptUpdateDigest(&hashState, dataSize, marshalBuffer);
1571 // Complete digest leaving room for the nameAlg
1572 CryptCompleteHash(&hashState, digestSize, &((BYTE *)name)[2]);
1573 // Include the nameAlg
Vadim Bendebury99e88832015-06-04 20:32:54 -07001574 UINT16_TO_BYTE_ARRAY(nvIndex.publicArea.nameAlg, (BYTE *)name);
Vadim Bendebury56797522015-05-20 10:32:25 -07001575 return digestSize + 2;
1576}
1577//
1578//
1579// NvDefineIndex()
1580//
1581// This function is used to assign NV memory to an NV Index.
1582//
1583//
1584//
1585// Error Returns Meaning
1586//
1587// TPM_RC_NV_SPACE insufficient NV space
1588//
1589TPM_RC
1590NvDefineIndex(
1591 TPMS_NV_PUBLIC *publicArea, // IN: A template for an area to create.
1592 TPM2B_AUTH *authValue // IN: The initial authorization value
1593 )
1594{
1595 // The buffer to be written to NV memory
1596 BYTE nvBuffer[sizeof(TPM_HANDLE) + sizeof(NV_INDEX)];
1597 NV_INDEX *nvIndex; // a pointer to the NV_INDEX data in
1598 // nvBuffer
1599 UINT16 entrySize; // size of entry
1600 entrySize = sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + publicArea->dataSize;
1601 // Check if we have enough space to create the NV Index
1602 // In this implementation, the only resource limitation is the available NV
1603 // space. Other implementation may have other limitation on counter or on
1604 // NV slot
1605 if(!NvTestSpace(entrySize, TRUE)) return TPM_RC_NV_SPACE;
1606 // if the index to be defined is RAM backed, check RAM space availability
1607 // as well
1608 if(publicArea->attributes.TPMA_NV_ORDERLY == SET
1609 && !NvTestRAMSpace(publicArea->dataSize))
1610 return TPM_RC_NV_SPACE;
1611 // Copy input value to nvBuffer
1612 // Copy handle
Jocelyn Bohr71e3b992015-08-14 12:05:59 -07001613 memcpy(nvBuffer, &publicArea->nvIndex, sizeof(TPM_HANDLE));
Vadim Bendebury56797522015-05-20 10:32:25 -07001614 // Copy NV_INDEX
1615 nvIndex = (NV_INDEX *) (nvBuffer + sizeof(TPM_HANDLE));
1616 nvIndex->publicArea = *publicArea;
1617 nvIndex->authValue = *authValue;
1618 // Add index to NV memory
1619 NvAdd(entrySize, sizeof(TPM_HANDLE) + sizeof(NV_INDEX), nvBuffer);
1620 // If the data of NV Index is RAM backed, add the data area in RAM as well
1621 if(publicArea->attributes.TPMA_NV_ORDERLY == SET)
1622 NvAddRAM(publicArea->nvIndex, publicArea->dataSize);
1623 return TPM_RC_SUCCESS;
1624}
Vadim Bendebury21756122016-12-29 11:14:03 -08001625
1626//
1627//
1628// NvMarshalObject()
1629//
1630// This function marshals the passed in OBJECT structure into a buffer. A
1631// pointer to pointer to the buffer and a pointer to the size of the
1632// buffer are passed in for this function to update as appropriate.
1633//
1634// On top of marshaling the object, this function also modifies one of
1635// the object's properties and sets the evictHandle field of the
1636// marshaled object to the requested value.
1637//
1638// Returns
1639//
1640// Marshaled size of the object.
1641//
1642static UINT16 NvMarshalObject(OBJECT *o, TPMI_DH_OBJECT evictHandle,
1643 BYTE **buf, INT32 *size)
1644{
1645 UINT16 marshaledSize;
1646 OBJECT_ATTRIBUTES stored_attributes;
1647
1648 stored_attributes = o->attributes;
1649 stored_attributes.evict = SET;
1650 marshaledSize = sizeof(stored_attributes);
1651 MemoryCopy(*buf, &stored_attributes, marshaledSize, *size);
1652 *buf += marshaledSize;
1653 *size -= marshaledSize;
1654
1655 marshaledSize += TPMT_PUBLIC_Marshal(&o->publicArea, buf, size);
1656 marshaledSize += TPMT_SENSITIVE_Marshal(&o->sensitive, buf, size);
1657#ifdef TPM_ALG_RSA
1658 marshaledSize += TPM2B_PUBLIC_KEY_RSA_Marshal(&o->privateExponent,
1659 buf, size);
1660#endif
1661 marshaledSize += TPM2B_NAME_Marshal(&o->qualifiedName, buf, size);
1662
1663 // Use the supplied handle instead of the object contents.
1664 marshaledSize += TPMI_DH_OBJECT_Marshal(&evictHandle, buf, size);
1665 marshaledSize += TPM2B_NAME_Marshal(&o->name, buf, size);
1666
1667 return marshaledSize;
1668}
1669
Vadim Bendebury56797522015-05-20 10:32:25 -07001670//
1671//
1672// NvAddEvictObject()
1673//
1674// This function is used to assign NV memory to a persistent object.
1675//
1676// Error Returns Meaning
1677//
1678// TPM_RC_NV_HANDLE the requested handle is already in use
1679// TPM_RC_NV_SPACE insufficient NV space
1680//
1681TPM_RC
1682NvAddEvictObject(
1683 TPMI_DH_OBJECT evictHandle, // IN: new evict handle
1684//
1685 OBJECT *object // IN: object to be added
1686 )
1687{
1688 // The buffer to be written to NV memory
1689 BYTE nvBuffer[sizeof(TPM_HANDLE) + sizeof(OBJECT)];
Vadim Bendebury56797522015-05-20 10:32:25 -07001690 UINT16 entrySize; // size of entry
Vadim Bendebury21756122016-12-29 11:14:03 -08001691 BYTE *marshalSpace;
1692 INT32 marshalRoom;
1693
Vadim Bendebury56797522015-05-20 10:32:25 -07001694 // evict handle type should match the object hierarchy
1695 pAssert( ( NvIsPlatformPersistentHandle(evictHandle)
1696 && object->attributes.ppsHierarchy == SET)
1697 || ( NvIsOwnerPersistentHandle(evictHandle)
1698 && ( object->attributes.spsHierarchy == SET
1699 || object->attributes.epsHierarchy == SET)));
Vadim Bendebury21756122016-12-29 11:14:03 -08001700
1701 // Do not attemp storing a duplicate handle.
Vadim Bendebury56797522015-05-20 10:32:25 -07001702 if(!NvIsUndefinedEvictHandle(evictHandle))
1703 return TPM_RC_NV_DEFINED;
Vadim Bendebury21756122016-12-29 11:14:03 -08001704
Vadim Bendebury56797522015-05-20 10:32:25 -07001705 // Copy handle
Vadim Bendebury21756122016-12-29 11:14:03 -08001706 entrySize = sizeof(TPM_HANDLE);
1707 memcpy(nvBuffer, &evictHandle, entrySize);
1708
1709 // Let's serialize the object before storing it in NVMEM
1710 marshalSpace = nvBuffer + entrySize;
1711 marshalRoom = sizeof(nvBuffer) - entrySize;
1712 entrySize += NvMarshalObject(object, evictHandle,
1713 &marshalSpace, &marshalRoom);
1714
1715 // Check if we have enough space to add this evict object
1716 if(!NvTestSpace(entrySize, FALSE)) return TPM_RC_NV_SPACE;
1717
Vadim Bendebury56797522015-05-20 10:32:25 -07001718 // Add evict to NV memory
1719 NvAdd(entrySize, entrySize, nvBuffer);
1720 return TPM_RC_SUCCESS;
1721}
1722//
1723//
1724// NvDeleteEntity()
1725//
1726// This function will delete a NV Index or an evict object.
1727// This function requires that the index/evict object has been defined.
1728//
1729void
1730NvDeleteEntity(
1731 TPM_HANDLE handle // IN: handle of entity to be deleted
1732 )
1733{
1734 UINT32 entityAddr; // pointer to entity
Louis Collard5cb743a2018-06-26 20:07:49 +08001735
1736 // Deleting virtual NV indexes is not supported.
1737 if(_plat__NvGetHandleVirtualOffset(handle) != 0)
1738 {
1739 return;
1740 }
1741
Vadim Bendebury56797522015-05-20 10:32:25 -07001742 entityAddr = NvFindHandle(handle);
1743 pAssert(entityAddr != 0);
1744 if(HandleGetType(handle) == TPM_HT_NV_INDEX)
1745 {
1746 NV_INDEX nvIndex;
1747 // Read the NV Index info
1748 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX),
1749 &nvIndex);
1750 // If the entity to be deleted is a counter with the maximum counter
1751 // value, record it in NV memory
1752 if(nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET
1753 && nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET)
1754 {
1755 UINT64 countValue;
1756 UINT64 maxCount;
1757 NvGetIntIndexData(handle, &nvIndex, &countValue);
1758 maxCount = NvReadMaxCount();
1759 if(countValue > maxCount)
1760 NvWriteMaxCount(countValue);
1761 }
1762 // If the NV Index is RAM back, delete the RAM data as well
1763 if(nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == SET)
1764 NvDeleteRAM(handle);
1765 }
1766 NvDelete(entityAddr);
1767 return;
1768}
1769//
1770//
1771// NvFlushHierarchy()
1772//
1773// This function will delete persistent objects belonging to the indicated If the storage hierarchy is selected,
1774// the function will also delete any NV Index define using ownerAuth.
1775//
1776void
1777NvFlushHierarchy(
1778 TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flushed.
1779 )
1780{
1781 NV_ITER iter = NV_ITER_INIT;
1782 UINT32 currentAddr;
1783 while((currentAddr = NvNext(&iter)) != 0)
1784 {
1785 TPM_HANDLE entityHandle;
1786 // Read handle information.
1787 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle);
1788 if(HandleGetType(entityHandle) == TPM_HT_NV_INDEX)
1789 {
1790 // Handle NV Index
1791 NV_INDEX nvIndex;
1792 // If flush endorsement or platform hierarchy, no NV Index would be
1793 // flushed
1794 if(hierarchy == TPM_RH_ENDORSEMENT || hierarchy == TPM_RH_PLATFORM)
1795 continue;
1796 _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE),
1797 sizeof(NV_INDEX), &nvIndex);
1798 // For storage hierarchy, flush OwnerCreated index
1799 if( nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == CLEAR)
1800 {
Andrey Pronin45fa7902018-08-01 21:14:41 -07001801 if(_plat__ShallSurviveOwnerClear(nvIndex.publicArea.nvIndex))
1802 continue;
Vadim Bendebury56797522015-05-20 10:32:25 -07001803 // Delete the NV Index
1804 NvDelete(currentAddr);
1805 // Re-iterate from beginning after a delete
1806 iter = NV_ITER_INIT;
1807 // If the NV Index is RAM back, delete the RAM data as well
1808 if(nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == SET)
1809 NvDeleteRAM(entityHandle);
1810 }
1811 }
1812 else if(HandleGetType(entityHandle) == TPM_HT_PERSISTENT)
1813 {
1814 OBJECT object;
1815 // Get evict object
1816 NvGetEvictObject(entityHandle, &object);
1817 // If the evict object belongs to the hierarchy to be flushed
1818 if( ( hierarchy == TPM_RH_PLATFORM
1819 && object.attributes.ppsHierarchy == SET)
1820 || ( hierarchy == TPM_RH_OWNER
1821 && object.attributes.spsHierarchy == SET)
1822 || ( hierarchy == TPM_RH_ENDORSEMENT
1823 && object.attributes.epsHierarchy == SET)
1824 )
1825 {
1826 // Delete the evict object
1827 NvDelete(currentAddr);
1828 // Re-iterate from beginning after a delete
1829 iter = NV_ITER_INIT;
1830 }
1831 }
1832 else
1833 {
1834 pAssert(FALSE);
1835 }
1836 }
1837 return;
1838}
1839//
1840//
1841// NvSetGlobalLock()
1842//
1843// This function is used to SET the TPMA_NV_WRITELOCKED attribute for all NV Indices that have
1844// TPMA_NV_GLOBALLOCK SET. This function is use by TPM2_NV_GlobalWriteLock().
1845//
1846void
1847NvSetGlobalLock(
1848 void
1849 )
1850{
1851 NV_ITER iter = NV_ITER_INIT;
1852 UINT32 currentAddr;
1853 // Check all Indices
1854 while((currentAddr = NvNextIndex(&iter)) != 0)
1855 {
1856 NV_INDEX nvIndex;
1857 // Read the index data
1858 _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE),
1859 sizeof(NV_INDEX), &nvIndex);
1860 // See if it should be locked
1861 if(nvIndex.publicArea.attributes.TPMA_NV_GLOBALLOCK == SET)
1862 {
1863 // if so, lock it
1864 nvIndex.publicArea.attributes.TPMA_NV_WRITELOCKED = SET;
1865 _plat__NvMemoryWrite(currentAddr + sizeof(TPM_HANDLE),
1866 sizeof(NV_INDEX), &nvIndex);
1867 // Set the flag that a NV write happens
1868 g_updateNV = TRUE;
1869 }
1870 }
1871 return;
1872}
1873//
1874//
1875// InsertSort()
1876//
1877// Sort a handle into handle list in ascending order. The total handle number in the list should not exceed
1878// MAX_CAP_HANDLES
1879//
1880static void
1881InsertSort(
1882 TPML_HANDLE *handleList, // IN/OUT: sorted handle list
1883 UINT32 count, // IN: maximum count in the handle list
1884 TPM_HANDLE entityHandle // IN: handle to be inserted
1885 )
1886{
1887 UINT32 i, j;
1888 UINT32 originalCount;
1889 // For a corner case that the maximum count is 0, do nothing
1890 if(count == 0) return;
1891 // For empty list, add the handle at the beginning and return
1892 if(handleList->count == 0)
1893 {
1894 handleList->handle[0] = entityHandle;
1895 handleList->count++;
1896 return;
1897 }
1898 // Check if the maximum of the list has been reached
1899 originalCount = handleList->count;
1900 if(originalCount < count)
1901 handleList->count++;
1902 // Insert the handle to the list
1903 for(i = 0; i < originalCount; i++)
1904 {
1905 if(handleList->handle[i] > entityHandle)
1906 {
1907 for(j = handleList->count - 1; j > i; j--)
1908 {
1909 handleList->handle[j] = handleList->handle[j-1];
1910 }
1911 break;
1912 }
1913 }
1914 // If a slot was found, insert the handle in this position
1915 if(i < originalCount || handleList->count > originalCount)
1916 handleList->handle[i] = entityHandle;
1917 return;
1918}
1919//
1920//
1921// NvCapGetPersistent()
1922//
1923// This function is used to get a list of handles of the persistent objects, starting at handle.
1924// Handle must be in valid persistent object handle range, but does not have to reference an existing
1925// persistent object.
1926//
1927// Return Value Meaning
1928//
1929// YES if there are more handles available
1930// NO all the available handles has been returned
1931//
1932TPMI_YES_NO
1933NvCapGetPersistent(
1934 TPMI_DH_OBJECT handle, // IN: start handle
1935 UINT32 count, // IN: maximum number of returned handle
1936 TPML_HANDLE *handleList // OUT: list of handle
1937 )
1938{
1939 TPMI_YES_NO more = NO;
1940 NV_ITER iter = NV_ITER_INIT;
1941 UINT32 currentAddr;
1942 pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT);
1943 // Initialize output handle list
1944 handleList->count = 0;
1945 // The maximum count of handles we may return is MAX_CAP_HANDLES
1946 if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
1947 while((currentAddr = NvNextEvict(&iter)) != 0)
1948 {
1949 TPM_HANDLE entityHandle;
1950 // Read handle information.
1951 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle);
1952 // Ignore persistent handles that have values less than the input handle
1953 if(entityHandle < handle)
1954 continue;
1955 // if the handles in the list have reached the requested count, and there
1956 // are still handles need to be inserted, indicate that there are more.
1957 if(handleList->count == count)
1958 more = YES;
1959 // A handle with a value larger than start handle is a candidate
1960 // for return. Insert sort it to the return list. Insert sort algorithm
1961 // is chosen here for simplicity based on the assumption that the total
1962 // number of NV Indices is small. For an implementation that may allow
1963 // large number of NV Indices, a more efficient sorting algorithm may be
1964 // used here.
1965 InsertSort(handleList, count, entityHandle);
1966//
1967 }
1968 return more;
1969}
1970//
1971//
1972// NvCapGetIndex()
1973//
1974// This function returns a list of handles of NV Indices, starting from handle. Handle must be in the range of
1975// NV Indices, but does not have to reference an existing NV Index.
1976//
1977// Return Value Meaning
1978//
1979// YES if there are more handles to report
1980// NO all the available handles has been reported
1981//
1982TPMI_YES_NO
1983NvCapGetIndex(
1984 TPMI_DH_OBJECT handle, // IN: start handle
1985 UINT32 count, // IN: maximum number of returned handle
1986 TPML_HANDLE *handleList // OUT: list of handle
1987 )
1988{
1989 TPMI_YES_NO more = NO;
1990 NV_ITER iter = NV_ITER_INIT;
1991 UINT32 currentAddr;
1992 pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX);
1993 // Initialize output handle list
1994 handleList->count = 0;
1995 // The maximum count of handles we may return is MAX_CAP_HANDLES
1996 if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
1997 while((currentAddr = NvNextIndex(&iter)) != 0)
1998 {
1999 TPM_HANDLE entityHandle;
2000 // Read handle information.
2001 _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle);
2002 // Ignore index handles that have values less than the 'handle'
2003 if(entityHandle < handle)
2004 continue;
2005 // if the count of handles in the list has reached the requested count,
2006 // and there are still handles to report, set more.
2007 if(handleList->count == count)
2008 more = YES;
2009 // A handle with a value larger than start handle is a candidate
2010 // for return. Insert sort it to the return list. Insert sort algorithm
2011 // is chosen here for simplicity based on the assumption that the total
2012 // number of NV Indices is small. For an implementation that may allow
2013 // large number of NV Indices, a more efficient sorting algorithm may be
2014 // used here.
2015 InsertSort(handleList, count, entityHandle);
2016 }
2017 return more;
2018}
2019//
2020//
2021//
2022// NvCapGetIndexNumber()
2023//
2024// This function returns the count of NV Indexes currently defined.
2025//
2026UINT32
2027NvCapGetIndexNumber(
2028 void
2029 )
2030{
2031 UINT32 num = 0;
2032 NV_ITER iter = NV_ITER_INIT;
2033 while(NvNextIndex(&iter) != 0) num++;
2034 return num;
2035}
2036//
2037//
2038// NvCapGetPersistentNumber()
2039//
2040// Function returns the count of persistent objects currently in NV memory.
2041//
2042UINT32
2043NvCapGetPersistentNumber(
2044 void
2045 )
2046{
2047 UINT32 num = 0;
2048 NV_ITER iter = NV_ITER_INIT;
2049 while(NvNextEvict(&iter) != 0) num++;
2050 return num;
2051}
2052//
2053//
2054// NvCapGetPersistentAvail()
2055//
2056// This function returns an estimate of the number of additional persistent objects that could be loaded into
2057// NV memory.
2058//
2059UINT32
2060NvCapGetPersistentAvail(
2061 void
2062 )
2063{
2064 UINT32 availSpace;
2065 UINT32 objectSpace;
2066 // Compute the available space in NV storage
2067 availSpace = NvGetFreeByte();
2068 // Get the space needed to add a persistent object to NV storage
2069 objectSpace = NvGetEvictObjectSize();
2070 return availSpace / objectSpace;
2071}
2072//
2073//
2074// NvCapGetCounterNumber()
2075//
2076// Get the number of defined NV Indexes that have NV TPMA_NV_COUNTER attribute SET.
2077//
2078//
2079UINT32
2080NvCapGetCounterNumber(
2081 void
2082 )
2083{
2084 NV_ITER iter = NV_ITER_INIT;
2085 UINT32 currentAddr;
2086 UINT32 num = 0;
2087 while((currentAddr = NvNextIndex(&iter)) != 0)
2088 {
2089 NV_INDEX nvIndex;
2090 // Get NV Index info
2091 _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE),
2092 sizeof(NV_INDEX), &nvIndex);
2093 if(nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET) num++;
2094 }
2095 return num;
2096}
2097//
2098//
2099// NvCapGetCounterAvail()
2100//
2101// This function returns an estimate of the number of additional counter type NV Indices that can be defined.
2102//
2103UINT32
2104NvCapGetCounterAvail(
2105 void
2106 )
2107{
2108 UINT32 availNVSpace;
2109 UINT32 availRAMSpace;
2110 UINT32 counterNVSpace;
2111 UINT32 counterRAMSpace;
2112 UINT32 persistentNum = NvCapGetPersistentNumber();
2113 // Get the available space in NV storage
2114 availNVSpace = NvGetFreeByte();
2115 if (persistentNum < MIN_EVICT_OBJECTS)
2116 {
2117 // Some space have to be reserved for evict object. Adjust availNVSpace.
2118 UINT32 reserved = (MIN_EVICT_OBJECTS - persistentNum)
2119 * NvGetEvictObjectSize();
2120 if (reserved > availNVSpace)
2121 availNVSpace = 0;
2122 else
2123 availNVSpace -= reserved;
2124 }
2125 // Get the space needed to add a counter index to NV storage
2126 counterNVSpace = NvGetCounterSize();
2127 // Compute the available space in RAM
2128 availRAMSpace = RAM_INDEX_SPACE - s_ramIndexSize;
2129 // Compute the space needed to add a counter index to RAM storage
2130 // It takes an size field, a handle and sizeof(UINT64) for counter data
2131 counterRAMSpace = sizeof(UINT32) + sizeof(TPM_HANDLE) + sizeof(UINT64);
2132 // Return the min of counter number in NV and in RAM
2133 if(availNVSpace / counterNVSpace > availRAMSpace / counterRAMSpace)
2134 return availRAMSpace / counterRAMSpace;
2135 else
2136 return availNVSpace / counterNVSpace;
2137}
Vadim Bendeburyf5ddef52018-04-19 19:52:41 -07002138
2139//
2140// NvEarlyStageFindHandle
2141//
2142// This function checks if a certain handle is present in NVMEM, even before
2143// TPM_Startup was invoked.
2144//
2145// To facilitate NVMEM lookip this function initializes static variables if
2146// they are not yet initialized.
2147//
Namyoon Woo0be7f8d2020-02-04 16:43:47 -08002148// Returns Non-zero if handle was found. The value is the offset in NV memory of
2149// the entity associated with the input handle.
2150// Zero if handle does not exist.
2151
Vadim Bendeburyf5ddef52018-04-19 19:52:41 -07002152//
Namyoon Woo0be7f8d2020-02-04 16:43:47 -08002153UINT32
Vadim Bendeburyf5ddef52018-04-19 19:52:41 -07002154NvEarlyStageFindHandle(
2155 TPM_HANDLE handle
2156 )
2157
2158{
2159 if (!s_evictNvEnd)
2160 NvInitStatic();
2161
2162 return NvFindHandle(handle);
2163}
Louis Collardec333822018-10-05 16:04:28 +08002164//
2165// NvIsDefinedHiddenObject()
2166//
2167// This function indicates if a handle references an existing
2168// hidden object.
2169//
2170// Return Value Meaning
2171//
2172// TRUE handle references an
2173// existing hidden object
2174// FALSE handle does not reference an
2175// existing hidden object
2176//
2177BOOL
2178NvIsDefinedHiddenObject(
2179 TPM_HANDLE handle // IN: handle
2180 )
2181{
2182 return HandleGetType(handle) == TPM_HT_HIDDEN &&
2183 NvFindHandle(handle) != 0;
2184}
2185//
2186//
2187// NvAddHiddenObject()
2188//
2189// This function is used to assign NV memory to a new hidden object.
2190//
2191// Error Returns Meaning
2192//
2193// TPM_RC_NV_HANDLE the requested handle is already in use
2194// TPM_RC_NV_SPACE insufficient NV space
2195//
2196TPM_RC
2197NvAddHiddenObject(
2198 TPM_HANDLE handle, // IN: new handle
2199 UINT16 object_size,
2200 void *object // IN: data to be stored
2201 )
2202{
2203 // The buffer to be written to NV memory
2204 BYTE nvBuffer[sizeof(TPM_HANDLE) + object_size];
2205 BYTE *buf = nvBuffer;
2206
2207 if (HandleGetType(handle) != TPM_HT_HIDDEN)
2208 return TPM_RC_HANDLE;
2209
2210 // Do not attemp storing a duplicate handle.
2211 if(NvIsDefinedHiddenObject(handle))
2212 return TPM_RC_NV_DEFINED;
2213
2214 // Check if we have enough space to add this hidden object
2215 if(!NvTestSpace(sizeof(nvBuffer), FALSE))
2216 return TPM_RC_NV_SPACE;
2217
2218 memcpy(buf, &handle, sizeof(TPM_HANDLE));
2219 buf += sizeof(TPM_HANDLE);
2220
2221 memcpy(buf, object, object_size);
2222
2223 NvAdd(sizeof(nvBuffer), sizeof(nvBuffer), nvBuffer);
2224
2225 return TPM_RC_SUCCESS;
2226}
2227
2228//
2229//
Vadim Sukhomlinov6ab308b2020-07-02 18:14:15 -07002230// NvGetHiddenObjectAddrSize()
2231//
2232// This function returns address (internal to nvmem) and size of
2233// hidden object. It requires the index to be defined.
2234//
2235// Error Returns Meaning
2236//
2237// TPM_RC_HANDLE the requested handle could not be found
2238// TPM_RC_TYPE handle is not a hidden object
2239static TPM_RC NvGetHiddenObjectAddrSize(
2240 TPM_HANDLE handle, // IN: handle
2241 UINT32 *addr, // OUT: address of entity
2242 UINT16 *size // OUT: size of entity
2243 )
2244{
2245 UINT32 entityAddr;
2246 NV_ITER iter;
2247
2248 if (HandleGetType(handle) != TPM_HT_HIDDEN)
2249 return TPM_RC_TYPE;
2250
2251 entityAddr = NvFindHandle(handle);
2252 if (entityAddr == 0)
2253 return TPM_RC_HANDLE;
2254
2255 iter = entityAddr - sizeof(NV_ITER);
2256
2257 // This will return the same address we already have in NvFindHandle,
2258 // (we discard this return value), and advance iter to point to the
2259 // start of next item in the list (its next pointer).
2260 NvNext(&iter);
2261 // Calculate size of this entity using position of next item.
2262 *size =
2263 iter // Points to beginning of next entry.
2264 - entityAddr // Points to beginning of current item.
2265 - sizeof(TPM_HANDLE); // Current item includes a handle.
2266
2267 *addr = entityAddr;
2268 return TPM_RC_SUCCESS;
2269}
2270
2271//
2272//
Louis Collardec333822018-10-05 16:04:28 +08002273// NvWriteHiddenObject()
2274//
2275// This function is used to write new data to an existing hidden object.
2276//
2277// Error Returns Meaning
2278//
2279// TPM_RC_HANDLE the requested handle could not be found
2280// TPM_RC_NV_SPACE size does not match NV space
2281//
2282TPM_RC NvWriteHiddenObject(TPM_HANDLE handle, // IN: new evict handle
2283 UINT16 size,
2284 void *object // IN: object to be added
2285 ) {
2286 UINT32 entityAddr; // offset points to the entity
2287 UINT16 entitySize; // recorded size of the entity
Vadim Sukhomlinov6ab308b2020-07-02 18:14:15 -07002288 TPM_RC rc;
Louis Collardec333822018-10-05 16:04:28 +08002289
Vadim Sukhomlinov6ab308b2020-07-02 18:14:15 -07002290 rc = NvGetHiddenObjectAddrSize(handle, &entityAddr, &entitySize);
2291 if (TPM_RC_SUCCESS != rc)
2292 return rc;
2293 if (size != entitySize) {
2294 return TPM_RC_NV_SPACE;
Louis Collardec333822018-10-05 16:04:28 +08002295 }
Vadim Sukhomlinov6ab308b2020-07-02 18:14:15 -07002296 _plat__NvMemoryWrite(entityAddr + sizeof(TPM_HANDLE),
2297 size, object);
2298 g_updateNV = TRUE;
Louis Collardec333822018-10-05 16:04:28 +08002299 return TPM_RC_SUCCESS;
2300}
2301//
2302//
2303// NvGetHiddenObject()
2304//
2305// This function is used to access data stored as a hidden object.
2306//
2307// This function requires that the index be defined, and that the
2308// required data is within the data range.
2309//
2310// Error Returns Meaning
2311//
2312// TPM_RC_HANDLE the requested handle could not be found
2313TPM_RC
2314NvGetHiddenObject(
2315 TPM_HANDLE handle, // IN: handle
2316 UINT16 size, // IN: size of NV data
2317 void *data // OUT: data buffer
2318 )
2319{
2320 UINT32 entityAddr;
2321 UINT16 entitySize;
Vadim Sukhomlinov6ab308b2020-07-02 18:14:15 -07002322 TPM_RC rc;
Louis Collardec333822018-10-05 16:04:28 +08002323
Vadim Sukhomlinov6ab308b2020-07-02 18:14:15 -07002324 rc = NvGetHiddenObjectAddrSize(handle, &entityAddr, &entitySize);
2325 if (TPM_RC_SUCCESS != rc)
2326 return rc;
Louis Collardec333822018-10-05 16:04:28 +08002327
Vadim Sukhomlinov6ab308b2020-07-02 18:14:15 -07002328 if (size > entitySize) {
2329 return TPM_RC_NV_SPACE;
Louis Collardec333822018-10-05 16:04:28 +08002330 }
Vadim Bendebury15260c82018-12-04 12:08:59 -08002331
Vadim Sukhomlinov6ab308b2020-07-02 18:14:15 -07002332 _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), size, data);
2333 return TPM_RC_SUCCESS;
2334}
2335//
2336//
2337// NvGetHiddenObjectSize()
2338//
2339// This function is used to get size of data stored as a hidden object.
2340//
2341// This function requires that the index be defined.
2342//
2343// Error Returns Meaning
2344//
2345// TPM_RC_HANDLE the requested handle could not be found
2346TPM_RC
2347NvGetHiddenObjectSize(
2348 TPM_HANDLE handle, // IN: handle
2349 UINT16 *size // OUT: size of NV data
2350 )
2351{
2352 UINT32 entityAddr;
2353
2354 return NvGetHiddenObjectAddrSize(handle, &entityAddr, size);
2355}
Vadim Bendebury15260c82018-12-04 12:08:59 -08002356//
2357// NVWipeCache
2358//
2359// A function to call to wipe out SRAM cache of NVMEM. Most evictable objects'
2360// contents get overwritten with some random data. The passed in two element
2361// array communicates an inclusive range of NV indexes to preserve during
2362// wipeout.
2363//
2364void NvSelectivelyInvalidateCache(const UINT16 *keep_range)
2365{
2366 UINT32 addr;
2367 NV_ITER iter = NV_ITER_INIT;
2368 TPMI_RH_NV_INDEX bottom = NV_INDEX_FIRST + keep_range[0];
2369 TPMI_RH_NV_INDEX top = NV_INDEX_FIRST + keep_range[1];
2370
2371 if (!s_evictNvEnd)
2372 return; /* Cache not initialized, nothing to do here. */
2373
2374 while((addr = NvNext(&iter)) != 0)
2375 {
2376 TPM_HANDLE entityHandle;
2377 size_t space;
2378
2379 /*
2380 * Read the object's handle. Note that TPMI_RH_NV_INDEX is a handle of
2381 * a certain type, the same size as TPM_HANDLE.
2382 */
2383 _plat__NvMemoryRead(addr, sizeof(TPM_HANDLE), &entityHandle);
2384
2385 /* Skip it if it is in the range to preserve. */
2386 if((entityHandle >= bottom) && (entityHandle <= top))
2387 continue;
2388
2389 /*
2390 * Determine the space the object takes in the cache less the handle
2391 * size. Note that at this point 'iter' points at the location right
2392 * above the current object.
2393 */
2394 space = iter - addr - sizeof(TPMI_RH_NV_INDEX);
2395
2396 /* Overwrite the cache space with junk data coped from text segment. */
2397 _plat__NvMemoryWrite(addr + sizeof(TPMI_RH_NV_INDEX), space,
2398 NvCapGetCounterAvail);
2399 }
2400}
Vadim Bendeburyc9e573a2018-12-11 15:19:59 -08002401
2402/*
2403 * A helper function which allows the caller to find out NVMEM cache offset
2404 * and size of all reserved objects AND of the RAM index space AND of the
2405 * maxCount value. The last two items are technically not reserved objects,
2406 * but are always present in the NVMEM cache and need to be preserved in
2407 * non-volatile storage.
2408 *
2409 * From the caller's perspective these two items are considered reserved
2410 * objects at indices NV_RAM_INDEX_SPACE and NV_MAX_COUNTER.
2411 */
2412void NvGetReserved(UINT32 index, NV_RESERVED_ITEM *ri)
2413{
2414 UINT32 indexSize;
2415
2416 if (index < NV_RESERVE_LAST) {
2417 ri->size = s_reservedSize[index];
2418 ri->offset = s_reservedAddr[index];
2419 return;
2420 }
2421
2422 switch (index) {
2423 case NV_RAM_INDEX_SPACE:
2424 /*
2425 * This is a request for the RAM index space, which is a concatenation of
2426 * the 4 byte size field and the actual RAM index contents field. For the
2427 * purposes of this function both fields are considered as single space
2428 * with the size equal 4 + the value stored at s_ramIndexSize.
2429 */
2430 _plat__NvMemoryRead(s_ramIndexSizeAddr, sizeof(UINT32), &indexSize);
2431 if (indexSize == ~0)
2432 indexSize = 0; /* Must be starting with empty flash memeory. */
2433 ri->offset = s_ramIndexSizeAddr;
2434 ri->size = indexSize + sizeof(indexSize);
2435 return;
2436
2437 case NV_MAX_COUNTER:
2438 ri->size = sizeof(UINT64);
2439 ri->offset = s_maxCountAddr;
2440 return;
2441 }
2442
2443 ri->size = 0;
2444}
2445