Coverage Report

Created: 2023-06-07 06:46

/src/tpm2/NVMem.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
#include     <memory.h>
9
#include     <stdio.h>
10
#include     <string.h>
11
12
#include     "PlatformData.h"
13
#include     "TpmError.h"
14
#include     "assert.h"
15
16
#ifndef EMBEDDED_MODE
17
#define FILE_BACKED_NV
18
#endif
19
20
#if defined FILE_BACKED_NV
21
static   FILE*                  s_NVFile;
22
#endif
23
static   unsigned char          s_NV[NV_MEMORY_SIZE];
24
static   BOOL                   s_NvIsAvailable;
25
static   BOOL                   s_NV_unrecoverable;
26
static   BOOL                   s_NV_recoverable;
27
//
28
//
29
//          Functions
30
//
31
//          _plat__NvErrors()
32
//
33
//     This function is used by the simulator to set the error flags in the NV subsystem to simulate an error in the
34
//     NV loading process
35
//
36
LIB_EXPORT void
37
_plat__NvErrors(
38
     BOOL                 recoverable,
39
     BOOL                 unrecoverable
40
     )
41
0
{
42
0
     s_NV_unrecoverable = unrecoverable;
43
0
     s_NV_recoverable = recoverable;
44
0
}
45
//
46
//
47
//          _plat__NVEnable()
48
//
49
//     Enable NV memory.
50
//     This version just pulls in data from a file. In a real TPM, with NV on chip, this function would verify the
51
//     integrity of the saved context. If the NV memory was not on chip but was in something like RPMB, the NV
52
//     state would be read in, decrypted and integrity checked.
53
//     The recovery from an integrity failure depends on where the error occurred. It it was in the state that is
54
//     discarded by TPM Reset, then the error is recoverable if the TPM is reset. Otherwise, the TPM must go
55
//     into failure mode.
56
//
57
//     Return Value                      Meaning
58
//
59
//     0                                 if success
60
//     >0                                if receive recoverable error
61
//     <0                                if unrecoverable error
62
//
63
LIB_EXPORT int
64
_plat__NVEnable(
65
     void                *platParameter       // IN: platform specific parameter
66
     )
67
11.2k
{
68
     // Start assuming everything is OK
69
11.2k
   s_NV_unrecoverable = FALSE;
70
11.2k
   s_NV_recoverable = FALSE;
71
11.2k
#ifdef FILE_BACKED_NV
72
11.2k
   if(s_NVFile != NULL) return 0;
73
   // Try to open an exist NVChip file for read/write
74
5.63k
   s_NVFile = fopen("NVChip", "r+b");
75
5.63k
   if(NULL != s_NVFile)
76
5.63k
   {
77
       // See if the NVChip file is empty
78
5.63k
       fseek(s_NVFile, 0, SEEK_END);
79
5.63k
       if(0 == ftell(s_NVFile))
80
0
           s_NVFile = NULL;
81
5.63k
   }
82
5.63k
   if(s_NVFile == NULL)
83
1
   {
84
       // Initialize all the byte in the new file to 0
85
1
       memset(s_NV, 0, NV_MEMORY_SIZE);
86
          // If NVChip file does not exist, try to create it for read/write
87
1
          s_NVFile = fopen("NVChip", "w+b");
88
          // Start initialize at the end of new file
89
1
          fseek(s_NVFile, 0, SEEK_END);
90
          // Write 0s to NVChip file
91
1
          fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NVFile);
92
1
   }
93
5.63k
   else
94
5.63k
   {
95
       // If NVChip file exist, assume the size is correct
96
5.63k
       fseek(s_NVFile, 0, SEEK_END);
97
5.63k
       assert(ftell(s_NVFile) == NV_MEMORY_SIZE);
98
       // read NV file data to memory
99
5.63k
       fseek(s_NVFile, 0, SEEK_SET);
100
5.63k
       assert(1 == fread(s_NV, NV_MEMORY_SIZE, 1, s_NVFile));
101
5.63k
   }
102
5.63k
#endif
103
   // NV contents have been read and the error checks have been performed. For
104
   // simulation purposes, use the signaling interface to indicate if an error is
105
   // to be simulated and the type of the error.
106
5.63k
   if(s_NV_unrecoverable)
107
0
       return -1;
108
5.63k
   return s_NV_recoverable;
109
5.63k
}
110
//
111
//
112
//         _plat__NVDisable()
113
//
114
//     Disable NV memory
115
//
116
LIB_EXPORT void
117
_plat__NVDisable(
118
   void
119
   )
120
5.63k
{
121
5.63k
#ifdef     FILE_BACKED_NV
122
5.63k
   assert(s_NVFile != NULL);
123
   // Close NV file
124
5.63k
   fclose(s_NVFile);
125
   // Set file handle to NULL
126
//
127
5.63k
    s_NVFile = NULL;
128
5.63k
#endif
129
5.63k
    return;
130
5.63k
}
131
//
132
//
133
//          _plat__IsNvAvailable()
134
//
135
//      Check if NV is available
136
//
137
//      Return Value                      Meaning
138
//
139
//      0                                 NV is available
140
//      1                                 NV is not available due to write failure
141
//      2                                 NV is not available due to rate limit
142
//
143
LIB_EXPORT int
144
_plat__IsNvAvailable(
145
    void
146
    )
147
33.9k
{
148
    // NV is not available if the TPM is in failure mode
149
33.9k
    if(!s_NvIsAvailable)
150
0
        return 1;
151
33.9k
#ifdef FILE_BACKED_NV
152
33.9k
   if(s_NVFile == NULL)
153
0
       return 1;
154
33.9k
#endif
155
33.9k
    return 0;
156
33.9k
}
157
//
158
//
159
//          _plat__NvMemoryRead()
160
//
161
//      Function: Read a chunk of NV memory
162
//
163
LIB_EXPORT void
164
_plat__NvMemoryRead(
165
    unsigned int           startOffset,       // IN: read start
166
    unsigned int           size,              // IN: size of bytes to read
167
    void                  *data               // OUT: data buffer
168
    )
169
220k
{
170
220k
    assert(startOffset + size <= NV_MEMORY_SIZE);
171
    // Copy data from RAM
172
220k
    memcpy(data, &s_NV[startOffset], size);
173
220k
    return;
174
220k
}
175
//
176
//
177
//          _plat__NvIsDifferent()
178
//
179
//      This function checks to see if the NV is different from the test value. This is so that NV will not be written if
180
//      it has not changed.
181
//
182
//
183
//
184
//
185
//      Return Value                  Meaning
186
//
187
//      TRUE                          the NV location is different from the test value
188
//      FALSE                         the NV location is the same as the test value
189
//
190
LIB_EXPORT BOOL
191
_plat__NvIsDifferent(
192
   unsigned int        startOffset,       // IN: read start
193
   unsigned int        size,              // IN: size of bytes to read
194
   void               *data               // IN: data buffer
195
   )
196
0
{
197
0
   return (memcmp(&s_NV[startOffset], data, size) != 0);
198
0
}
199
//
200
//
201
//         _plat__NvMemoryWrite()
202
//
203
//      This function is used to update NV memory. The write is to a memory copy of NV. At the end of the
204
//      current command, any changes are written to the actual NV memory.
205
//
206
LIB_EXPORT void
207
_plat__NvMemoryWrite(
208
   unsigned int        startOffset,       // IN: write start
209
   unsigned int        size,              // IN: size of bytes to write
210
   void               *data               // OUT: data buffer
211
   )
212
220k
{
213
220k
   assert(startOffset + size <= NV_MEMORY_SIZE);
214
   // Copy the data to the NV image
215
220k
   memcpy(&s_NV[startOffset], data, size);
216
220k
}
217
//
218
//
219
//         _plat__NvMemoryMove()
220
//
221
//      Function: Move a chunk of NV memory from source to destination This function should ensure that if
222
//      there overlap, the original data is copied before it is written
223
//
224
LIB_EXPORT void
225
_plat__NvMemoryMove(
226
   unsigned int        sourceOffset,      // IN: source offset
227
   unsigned int        destOffset,        // IN: destination offset
228
   unsigned int        size               // IN: size of data being moved
229
   )
230
0
{
231
0
   assert(sourceOffset + size <= NV_MEMORY_SIZE);
232
0
   assert(destOffset + size <= NV_MEMORY_SIZE);
233
   // Move data in RAM
234
0
   memmove(&s_NV[destOffset], &s_NV[sourceOffset], size);
235
0
   return;
236
0
}
237
//
238
//
239
//         _plat__NvCommit()
240
//
241
//      Update NV chip
242
//
243
//
244
//
245
//      Return Value                      Meaning
246
//
247
//      0                                 NV write success
248
//      non-0                             NV write fail
249
//
250
LIB_EXPORT int
251
_plat__NvCommit(
252
   void
253
   )
254
11.3k
{
255
11.3k
#ifdef FILE_BACKED_NV
256
   // If NV file is not available, return failure
257
11.3k
   if(s_NVFile == NULL)
258
0
       return 1;
259
   // Write RAM data to NV
260
11.3k
   fseek(s_NVFile, 0, SEEK_SET);
261
11.3k
   fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NVFile);
262
11.3k
   return 0;
263
#else
264
   return 0;
265
#endif
266
11.3k
}
267
//
268
//
269
//       _plat__SetNvAvail()
270
//
271
//      Set the current NV state to available. This function is for testing purpose only. It is not part of the
272
//      platform NV logic
273
//
274
LIB_EXPORT void
275
_plat__SetNvAvail(
276
   void
277
   )
278
5.63k
{
279
5.63k
   s_NvIsAvailable = TRUE;
280
5.63k
   return;
281
5.63k
}
282
//
283
//
284
//       _plat__ClearNvAvail()
285
//
286
//      Set the current NV state to unavailable. This function is for testing purpose only. It is not part of the
287
//      platform NV logic
288
//
289
LIB_EXPORT void
290
_plat__ClearNvAvail(
291
   void
292
   )
293
0
{
294
0
   s_NvIsAvailable = FALSE;
295
0
   return;
296
0
}
297
//
298
//
299
//      _plat__NvGetHandleVirtualOffset()
300
//
301
// Dummy implementation that effectively disables vNVRAM.
302
//
303
LIB_EXPORT uint32_t
304
_plat__NvGetHandleVirtualOffset(uint32_t handle)
305
183
{
306
183
   return 0;
307
183
}
308
//
309
//
310
//      _plat__NvOffsetIsVirtual()
311
//
312
// Always returns false, as vNVRAM is not supported so no offsets are virtual.
313
//
314
LIB_EXPORT BOOL
315
_plat__NvOffsetIsVirtual(unsigned int startOffset)
316
0
{
317
0
   return FALSE;
318
0
}
319
//
320
//
321
//      _plat__NvVirtualMemoryRead()
322
//
323
// The above functions have effectively disabled vNVRAM, so this function should
324
// never be called; sets memory to dummy value to highlight errors if it is
325
// called by accident, and to ensure no information is leaked.
326
//
327
LIB_EXPORT void
328
_plat__NvVirtualMemoryRead(
329
    unsigned int startOffset,
330
    unsigned int size,
331
    void *data)
332
0
{
333
0
   memset((BYTE *)data, 0xab, size);
334
0
}
335
//
336
// Check if a non-PLATFORMCREATE index shall nevertheless be retained when
337
// performing TPM2_Clear.
338
//
339
LIB_EXPORT BOOL
340
_plat__ShallSurviveOwnerClear(
341
    uint32_t  index
342
    )
343
0
{
344
0
    return FALSE;
345
0
}
346
347
LIB_EXPORT void
348
_plat__NvInformIndexDataChanged(uint32_t handle)
349
0
{
350
  /* Do nothing */
351
0
  return;
352
0
}
353
354
//
355
//
356
//      _plat__NvUpdateAllowed()
357
//
358
// Always returns TRUE. No platform-specific reasons to prevent updates.
359
//
360
LIB_EXPORT BOOL
361
_plat__NvUpdateAllowed(uint32_t handle)
362
72
{
363
72
   return TRUE;
364
72
}