• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Microsoft Reference Implementation for TPM 2.0
2  *
3  *  The copyright in this software is being made available under the BSD License,
4  *  included below. This software may be subject to other third party and
5  *  contributor rights, including patent rights, and no such rights are granted
6  *  under this license.
7  *
8  *  Copyright (c) Microsoft Corporation
9  *
10  *  All rights reserved.
11  *
12  *  BSD License
13  *
14  *  Redistribution and use in source and binary forms, with or without modification,
15  *  are permitted provided that the following conditions are met:
16  *
17  *  Redistributions of source code must retain the above copyright notice, this list
18  *  of conditions and the following disclaimer.
19  *
20  *  Redistributions in binary form must reproduce the above copyright notice, this
21  *  list of conditions and the following disclaimer in the documentation and/or
22  *  other materials provided with the distribution.
23  *
24  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28  *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29  *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31  *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 //** Introduction
36 
37 // The NV memory is divided into two areas: dynamic space for user defined NV
38 // Indices and evict objects, and reserved space for TPM persistent and state save
39 // data.
40 //
41 // The entries in dynamic space are a linked list of entries. Each entry has, as its
42 // first field, a size. If the size field is zero, it marks the end of the
43 // list.
44 //
45 // An allocation of an Index or evict object may use almost all of the remaining
46 // NV space such that the size field will not fit. The functions that search the
47 // list are aware of this and will terminate the search if they either find a zero
48 // size or recognize that there is insufficient space for the size field.
49 //
50 // An Index allocation will contain an NV_INDEX structure. If the Index does not
51 // have the orderly attribute, the NV_INDEX is followed immediately by the NV data.
52 //
53 // An evict object entry contains a handle followed by an OBJECT structure. This
54 // results in both the Index and Evict Object having an identifying handle as the
55 // first field following the size field.
56 //
57 // When an Index has the orderly attribute, the data is kept in RAM. This RAM is
58 // saved to backing store in NV memory on any orderly shutdown. The entries in
59 // orderly memory are also a linked list using a size field as the first entry. As
60 // with the NV memory, the list is terminated by a zero size field or when the last
61 // entry leaves insufficient space for the terminating size field.
62 //
63 // The attributes of an orderly index are maintained in RAM memory in order to
64 // reduce the number of NV writes needed for orderly data. When an orderly index
65 // is created, an entry is made in the dynamic NV memory space that holds the Index
66 // authorizations (authPolicy and authValue) and the size of the data. This entry is
67 // only modified if the authValue  of the index is changed. The more volatile data
68 // of the index is kept in RAM. When an orderly Index is created or deleted, the
69 // RAM data is copied to NV backing store so that the image in the backing store
70 // matches the layout of RAM. In normal operation. The RAM data is also copied on
71 // any orderly shutdown. In normal operation, the only other reason for writing
72 // to the backing store for RAM is when a counter is first written (TPMA_NV_WRITTEN
73 // changes from CLEAR to SET) or when a counter "rolls over."
74 //
75 // Static space contains items that are individually modifiable. The values are in
76 // the 'gp' PERSISTENT_DATA structure in RAM and mapped to locations in NV.
77 //
78 
79 //** Includes, Defines
80 #define NV_C
81 #include    "Tpm.h"
82 
83 //************************************************
84 //** Functions
85 //************************************************
86 
87 
88 //*** NvInitStatic()
89 // This function initializes the static variables used in the NV subsystem.
90 static void
NvInitStatic(void)91 NvInitStatic(
92     void
93     )
94 {
95     // In some implementations, the end of NV is variable and is set at boot time.
96     // This value will be the same for each boot, but is not necessarily known
97     // at compile time.
98     s_evictNvEnd = (NV_REF)NV_MEMORY_SIZE;
99     return;
100 }
101 
102 //*** NvCheckState()
103 // Function to check the NV state by accessing the platform-specific function
104 // to get the NV state.  The result state is registered in s_NvIsAvailable
105 // that will be reported by NvIsAvailable.
106 //
107 // This function is called at the beginning of ExecuteCommand before any potential
108 // check of g_NvStatus.
109 void
NvCheckState(void)110 NvCheckState(
111     void
112     )
113 {
114     int     func_return;
115 //
116     func_return = _plat__IsNvAvailable();
117     if(func_return == 0)
118         g_NvStatus = TPM_RC_SUCCESS;
119     else if(func_return == 1)
120         g_NvStatus = TPM_RC_NV_UNAVAILABLE;
121     else
122         g_NvStatus = TPM_RC_NV_RATE;
123     return;
124 }
125 
126 //*** NvCommit
127 // This is a wrapper for the platform function to commit pending NV writes.
128 BOOL
NvCommit(void)129 NvCommit(
130     void
131     )
132 {
133     return (_plat__NvCommit() == 0);
134 }
135 
136 //*** NvPowerOn()
137 //  This function is called at _TPM_Init to initialize the NV environment.
138 //  Return Type: BOOL
139 //      TRUE(1)         all NV was initialized
140 //      FALSE(0)        the NV containing saved state had an error and
141 //                      TPM2_Startup(CLEAR) is required
142 BOOL
NvPowerOn(void)143 NvPowerOn(
144     void
145     )
146 {
147     int          nvError = 0;
148     // If power was lost, need to re-establish the RAM data that is loaded from
149     // NV and initialize the static variables
150     if(g_powerWasLost)
151     {
152         if((nvError = _plat__NVEnable(0)) < 0)
153             FAIL(FATAL_ERROR_NV_UNRECOVERABLE);
154         NvInitStatic();
155     }
156     return nvError == 0;
157 }
158 
159 //*** NvManufacture()
160 // This function initializes the NV system at pre-install time.
161 //
162 // This function should only be called in a manufacturing environment or in a
163 // simulation.
164 //
165 // The layout of NV memory space is an implementation choice.
166 void
NvManufacture(void)167 NvManufacture(
168     void
169     )
170 {
171 #if SIMULATION
172     // Simulate the NV memory being in the erased state.
173     _plat__NvMemoryClear(0, NV_MEMORY_SIZE);
174 #endif
175     // Initialize static variables
176     NvInitStatic();
177     // Clear the RAM used for Orderly Index data
178     MemorySet(s_indexOrderlyRam, 0, RAM_INDEX_SPACE);
179     // Write that Orderly Index data to NV
180     NvUpdateIndexOrderlyData();
181     // Initialize the next offset of the first entry in evict/index list to 0 (the
182     // end of list marker) and the initial s_maxCounterValue;
183     NvSetMaxCount(0);
184     // Put the end of list marker at the end of memory. This contains the MaxCount
185     // value as well as the end marker.
186     NvWriteNvListEnd(NV_USER_DYNAMIC);
187     return;
188 }
189 
190 //*** NvRead()
191 // This function is used to move reserved data from NV memory to RAM.
192 void
NvRead(void * outBuffer,UINT32 nvOffset,UINT32 size)193 NvRead(
194     void            *outBuffer,     // OUT: buffer to receive data
195     UINT32           nvOffset,      // IN: offset in NV of value
196     UINT32           size           // IN: size of the value to read
197     )
198 {
199     // Input type should be valid
200     pAssert(nvOffset + size < NV_MEMORY_SIZE);
201     _plat__NvMemoryRead(nvOffset, size, outBuffer);
202     return;
203 }
204 
205 //*** NvWrite()
206 // This function is used to post reserved data for writing to NV memory. Before
207 // the TPM completes the operation, the value will be written.
208 BOOL
NvWrite(UINT32 nvOffset,UINT32 size,void * inBuffer)209 NvWrite(
210     UINT32           nvOffset,      // IN: location in NV to receive data
211     UINT32           size,          // IN: size of the data to move
212     void            *inBuffer       // IN: location containing data to write
213     )
214 {
215     // Input type should be valid
216     if(nvOffset + size <= NV_MEMORY_SIZE)
217     {
218     // Set the flag that a NV write happened
219     SET_NV_UPDATE(UT_NV);
220         return _plat__NvMemoryWrite(nvOffset, size, inBuffer);
221     }
222     return FALSE;
223 }
224 
225 //*** NvUpdatePersistent()
226 // This function is used to update a value in the PERSISTENT_DATA structure and
227 // commits the value to NV.
228 void
NvUpdatePersistent(UINT32 offset,UINT32 size,void * buffer)229 NvUpdatePersistent(
230     UINT32           offset,        // IN: location in PERMANENT_DATA to be updated
231     UINT32           size,          // IN: size of the value
232     void            *buffer         // IN: the new data
233     )
234 {
235     pAssert(offset + size <= sizeof(gp));
236     MemoryCopy(&gp + offset, buffer, size);
237     NvWrite(offset, size, buffer);
238 }
239 
240 //*** NvClearPersistent()
241 // This function is used to clear a persistent data entry and commit it to NV
242 void
NvClearPersistent(UINT32 offset,UINT32 size)243 NvClearPersistent(
244     UINT32           offset,        // IN: the offset in the PERMANENT_DATA
245                                     //     structure to be cleared (zeroed)
246     UINT32           size           // IN: number of bytes to clear
247     )
248 {
249     pAssert(offset + size <= sizeof(gp));
250     MemorySet((&gp) + offset, 0, size);
251     NvWrite(offset, size, (&gp) + offset);
252 }
253 
254 //*** NvReadPersistent()
255 // This function reads persistent data to the RAM copy of the 'gp' structure.
256 void
NvReadPersistent(void)257 NvReadPersistent(
258     void
259     )
260 {
261     NvRead(&gp, NV_PERSISTENT_DATA, sizeof(gp));
262     return;
263 }