Coverage Report

Created: 2025-08-29 06:04

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