/src/ibmswtpm2/src/StartupCommands.c
Line | Count | Source (jump to first uncovered line) |
1 | | /********************************************************************************/ |
2 | | /* */ |
3 | | /* Startup Commands */ |
4 | | /* Written by Ken Goldman */ |
5 | | /* IBM Thomas J. Watson Research Center */ |
6 | | /* $Id: StartupCommands.c 1314 2018-08-28 14:25:12Z kgoldman $ */ |
7 | | /* */ |
8 | | /* Licenses and Notices */ |
9 | | /* */ |
10 | | /* 1. Copyright Licenses: */ |
11 | | /* */ |
12 | | /* - Trusted Computing Group (TCG) grants to the user of the source code in */ |
13 | | /* this specification (the "Source Code") a worldwide, irrevocable, */ |
14 | | /* nonexclusive, royalty free, copyright license to reproduce, create */ |
15 | | /* derivative works, distribute, display and perform the Source Code and */ |
16 | | /* derivative works thereof, and to grant others the rights granted herein. */ |
17 | | /* */ |
18 | | /* - The TCG grants to the user of the other parts of the specification */ |
19 | | /* (other than the Source Code) the rights to reproduce, distribute, */ |
20 | | /* display, and perform the specification solely for the purpose of */ |
21 | | /* developing products based on such documents. */ |
22 | | /* */ |
23 | | /* 2. Source Code Distribution Conditions: */ |
24 | | /* */ |
25 | | /* - Redistributions of Source Code must retain the above copyright licenses, */ |
26 | | /* this list of conditions and the following disclaimers. */ |
27 | | /* */ |
28 | | /* - Redistributions in binary form must reproduce the above copyright */ |
29 | | /* licenses, this list of conditions and the following disclaimers in the */ |
30 | | /* documentation and/or other materials provided with the distribution. */ |
31 | | /* */ |
32 | | /* 3. Disclaimers: */ |
33 | | /* */ |
34 | | /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ |
35 | | /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ |
36 | | /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ |
37 | | /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ |
38 | | /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ |
39 | | /* information on specification licensing rights available through TCG */ |
40 | | /* membership agreements. */ |
41 | | /* */ |
42 | | /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ |
43 | | /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ |
44 | | /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ |
45 | | /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ |
46 | | /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ |
47 | | /* */ |
48 | | /* - Without limitation, TCG and its members and licensors disclaim all */ |
49 | | /* liability, including liability for infringement of any proprietary */ |
50 | | /* rights, relating to use of information in this specification and to the */ |
51 | | /* implementation of this specification, and TCG disclaims all liability for */ |
52 | | /* cost of procurement of substitute goods or services, lost profits, loss */ |
53 | | /* of use, loss of data or any incidental, consequential, direct, indirect, */ |
54 | | /* or special damages, whether under contract, tort, warranty or otherwise, */ |
55 | | /* arising in any way out of use or reliance upon this specification or any */ |
56 | | /* information herein. */ |
57 | | /* */ |
58 | | /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ |
59 | | /* */ |
60 | | /********************************************************************************/ |
61 | | |
62 | | /* 9.2 _TPM_Init */ |
63 | | #include "Tpm.h" |
64 | | #include "_TPM_Init_fp.h" |
65 | | // This function is used to process a _TPM_Init indication. |
66 | | LIB_EXPORT void |
67 | | _TPM_Init( |
68 | | void |
69 | | ) |
70 | 1 | { |
71 | 1 | g_powerWasLost = g_powerWasLost | _plat__WasPowerLost(); |
72 | | #if SIMULATION && !NDEBUG |
73 | | // If power was lost and this was a simulation, put canary in RAM used by NV |
74 | | // so that uninitialized memory can be detected more easily |
75 | | if(g_powerWasLost) |
76 | | { |
77 | | memset(&gc, 0xbb, sizeof(gc)); |
78 | | memset(&gr, 0xbb, sizeof(gr)); |
79 | | memset(&gp, 0xbb, sizeof(gp)); |
80 | | memset(&go, 0xbb, sizeof(go)); |
81 | | } |
82 | | #endif |
83 | | #if SIMULATION |
84 | | // Clear the flag that forces failure on self-test |
85 | | g_forceFailureMode = FALSE; |
86 | | #endif |
87 | | // Set initialization state |
88 | 1 | TPMInit(); |
89 | | // Set g_DRTMHandle as unassigned |
90 | 1 | g_DRTMHandle = TPM_RH_UNASSIGNED; |
91 | | // No H-CRTM, yet. |
92 | 1 | g_DrtmPreStartup = FALSE; |
93 | | // Initialize the NvEnvironment. |
94 | 1 | g_nvOk = NvPowerOn(); |
95 | | // Initialize cryptographic functions |
96 | 1 | g_inFailureMode = (CryptInit() == FALSE); |
97 | 1 | if(!g_inFailureMode) |
98 | 1 | { |
99 | | // Load the persistent data |
100 | 1 | NvReadPersistent(); |
101 | | // Load the orderly data (clock and DRBG state). |
102 | | // If this is not done here, things break |
103 | 1 | NvRead(&go, NV_ORDERLY_DATA, sizeof(go)); |
104 | | // Start clock. Need to do this after NV has been restored. |
105 | 1 | TimePowerOn(); |
106 | 1 | } |
107 | 1 | return; |
108 | 1 | } |
109 | | #include "Tpm.h" |
110 | | #include "Startup_fp.h" |
111 | | #if CC_Startup // Conditional expansion of this file |
112 | | TPM_RC |
113 | | TPM2_Startup( |
114 | | Startup_In *in // IN: input parameter list |
115 | | ) |
116 | 914 | { |
117 | 914 | STARTUP_TYPE startup; |
118 | 914 | BYTE locality = _plat__LocalityGet(); |
119 | | // The command needs NV update. |
120 | 914 | RETURN_IF_NV_IS_NOT_AVAILABLE; |
121 | | // Get the flags for the current startup locality and the H-CRTM. |
122 | | // Rather than generalizing the locality setting, this code takes advantage |
123 | | // of the fact that the PC Client specification only allows Startup() |
124 | | // from locality 0 and 3. To generalize this probably would require a |
125 | | // redo of the NV space and since this is a feature that is hardly ever used |
126 | | // outside of the PC Client, this code just support the PC Client needs. |
127 | | // Input Validation |
128 | | // Check that the locality is a supported value |
129 | 0 | if(locality != 0 && locality != 3) |
130 | 0 | return TPM_RC_LOCALITY; |
131 | | // If there was a H-CRTM, then treat the locality as being 3 |
132 | | // regardless of what the Startup() was. This is done to preserve the |
133 | | // H-CRTM PCR so that they don't get overwritten with the normal |
134 | | // PCR startup initialization. This basically means that g_StartupLocality3 |
135 | | // and g_DrtmPreStartup can't both be SET at the same time. |
136 | 0 | if(g_DrtmPreStartup) |
137 | 0 | locality = 0; |
138 | 0 | g_StartupLocality3 = (locality == 3); |
139 | 0 | #if USE_DA_USED |
140 | | // If there was no orderly shutdown, then their might have been a write to |
141 | | // failedTries that didn't get recorded but only if g_daUsed was SET in the |
142 | | // shutdown state |
143 | 0 | g_daUsed = (gp.orderlyState == SU_DA_USED_VALUE); |
144 | 0 | if(g_daUsed) |
145 | 0 | gp.orderlyState = SU_NONE_VALUE; |
146 | 0 | #endif |
147 | 0 | g_prevOrderlyState = gp.orderlyState; |
148 | | // If there was a proper shutdown, then the startup modifiers are in the |
149 | | // orderlyState. Turn them off in the copy. |
150 | 0 | if(IS_ORDERLY(g_prevOrderlyState)) |
151 | 0 | g_prevOrderlyState &= ~(PRE_STARTUP_FLAG | STARTUP_LOCALITY_3); |
152 | | // If this is a Resume, |
153 | 0 | if(in->startupType == TPM_SU_STATE) |
154 | 0 | { |
155 | | // then there must have been a prior TPM2_ShutdownState(STATE) |
156 | 0 | if(g_prevOrderlyState != TPM_SU_STATE) |
157 | 0 | return TPM_RCS_VALUE + RC_Startup_startupType; |
158 | | // and the part of NV used for state save must have been recovered |
159 | | // correctly. |
160 | | // NOTE: if this fails, then the caller will need to do Startup(CLEAR). The |
161 | | // code for Startup(Clear) cannot fail if the NV can't be read correctly |
162 | | // because that would prevent the TPM from ever getting unstuck. |
163 | 0 | if(g_nvOk == FALSE) |
164 | 0 | return TPM_RC_NV_UNINITIALIZED; |
165 | | // For Resume, the H-CRTM has to be the same as the previous boot |
166 | 0 | if(g_DrtmPreStartup != ((gp.orderlyState & PRE_STARTUP_FLAG) != 0)) |
167 | 0 | return TPM_RCS_VALUE + RC_Startup_startupType; |
168 | 0 | if(g_StartupLocality3 != ((gp.orderlyState & STARTUP_LOCALITY_3) != 0)) |
169 | 0 | return TPM_RC_LOCALITY; |
170 | 0 | } |
171 | | // Clean up the gp state |
172 | 0 | gp.orderlyState = g_prevOrderlyState; |
173 | | |
174 | | // Internal Date Update |
175 | 0 | if((gp.orderlyState == TPM_SU_STATE) && (g_nvOk == TRUE)) |
176 | 0 | { |
177 | | // Always read the data that is only cleared on a Reset because this is not |
178 | | // a reset |
179 | 0 | NvRead(&gr, NV_STATE_RESET_DATA, sizeof(gr)); |
180 | 0 | if(in->startupType == TPM_SU_STATE) |
181 | 0 | { |
182 | | // If this is a startup STATE (a Resume) need to read the data |
183 | | // that is cleared on a startup CLEAR because this is not a Reset |
184 | | // or Restart. |
185 | 0 | NvRead(&gc, NV_STATE_CLEAR_DATA, sizeof(gc)); |
186 | 0 | startup = SU_RESUME; |
187 | 0 | } |
188 | 0 | else |
189 | 0 | startup = SU_RESTART; |
190 | 0 | } |
191 | 0 | else |
192 | | // Will do a TPM reset if Shutdown(CLEAR) and Startup(CLEAR) or no shutdown |
193 | | // or there was a failure reading the NV data. |
194 | 0 | startup = SU_RESET; |
195 | | // Startup for cryptographic library. Don't do this until after the orderly |
196 | | // state has been read in from NV. |
197 | 0 | CryptStartup(startup); |
198 | | // When the cryptographic library has been started, indicate that a TPM2_Startup |
199 | | // command has been received. |
200 | 0 | TPMRegisterStartup(); |
201 | | // Read the platform unique value that is used as VENDOR_PERMANENT |
202 | | // authorization value |
203 | 0 | g_platformUniqueDetails.t.size |
204 | 0 | = (UINT16)_plat__GetUnique(1, sizeof(g_platformUniqueDetails.t.buffer), |
205 | 0 | g_platformUniqueDetails.t.buffer); |
206 | | // Start up subsystems |
207 | | // Start set the safe flag |
208 | 0 | TimeStartup(startup); |
209 | | // Start dictionary attack subsystem |
210 | 0 | DAStartup(startup); |
211 | | // Enable hierarchies |
212 | 0 | HierarchyStartup(startup); |
213 | | // Restore/Initialize PCR |
214 | 0 | PCRStartup(startup, locality); |
215 | | // Restore/Initialize command audit information |
216 | 0 | CommandAuditStartup(startup); |
217 | | //// The following code was moved from Time.c where it made no sense |
218 | 0 | switch (startup) |
219 | 0 | { |
220 | 0 | case SU_RESUME: |
221 | | // Resume sequence |
222 | 0 | gr.restartCount++; |
223 | 0 | break; |
224 | 0 | case SU_RESTART: |
225 | | // Hibernate sequence |
226 | 0 | gr.clearCount++; |
227 | 0 | gr.restartCount++; |
228 | 0 | break; |
229 | 0 | default: |
230 | | // Reset object context ID to 0 |
231 | 0 | gr.objectContextID = 0; |
232 | | // Reset clearCount to 0 |
233 | 0 | gr.clearCount = 0; |
234 | | // Reset sequence |
235 | | // Increase resetCount |
236 | 0 | gp.resetCount++; |
237 | | // Write resetCount to NV |
238 | 0 | NV_SYNC_PERSISTENT(resetCount); |
239 | 0 | gp.totalResetCount++; |
240 | | // We do not expect the total reset counter overflow during the life |
241 | | // time of TPM. if it ever happens, TPM will be put to failure mode |
242 | | // and there is no way to recover it. |
243 | | // The reason that there is no recovery is that we don't increment |
244 | | // the NV totalResetCount when incrementing would make it 0. When the |
245 | | // TPM starts up again, the old value of totalResetCount will be read |
246 | | // and we will get right back to here with the increment failing. |
247 | 0 | if(gp.totalResetCount == 0) |
248 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
249 | | // Write total reset counter to NV |
250 | 0 | NV_SYNC_PERSISTENT(totalResetCount); |
251 | | // Reset restartCount |
252 | 0 | gr.restartCount = 0; |
253 | 0 | break; |
254 | 0 | } |
255 | | // Initialize session table |
256 | 0 | SessionStartup(startup); |
257 | | // Initialize object table |
258 | 0 | ObjectStartup(); |
259 | | // Initialize index/evict data. This function clears read/write locks |
260 | | // in NV index |
261 | 0 | NvEntityStartup(startup); |
262 | | // Initialize the orderly shut down flag for this cycle to SU_NONE_VALUE. |
263 | 0 | gp.orderlyState = SU_NONE_VALUE; |
264 | 0 | NV_SYNC_PERSISTENT(orderlyState); |
265 | | // This can be reset after the first completion of a TPM2_Startup() after |
266 | | // a power loss. It can probably be reset earlier but this is an OK place. |
267 | 0 | g_powerWasLost = FALSE; |
268 | 0 | return TPM_RC_SUCCESS; |
269 | 0 | } |
270 | | #endif // CC_Startup |
271 | | #include "Tpm.h" |
272 | | #include "Shutdown_fp.h" |
273 | | #if CC_Shutdown // Conditional expansion of this file |
274 | | TPM_RC |
275 | | TPM2_Shutdown( |
276 | | Shutdown_In *in // IN: input parameter list |
277 | | ) |
278 | 0 | { |
279 | | // The command needs NV update. Check if NV is available. |
280 | | // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at |
281 | | // this point |
282 | 0 | RETURN_IF_NV_IS_NOT_AVAILABLE; |
283 | | // Input Validation |
284 | | // If PCR bank has been reconfigured, a CLEAR state save is required |
285 | 0 | if(g_pcrReConfig && in->shutdownType == TPM_SU_STATE) |
286 | 0 | return TPM_RCS_TYPE + RC_Shutdown_shutdownType; |
287 | | // Internal Data Update |
288 | 0 | gp.orderlyState = in->shutdownType; |
289 | | // PCR private date state save |
290 | 0 | PCRStateSave(in->shutdownType); |
291 | | // Save RAM backed NV index data |
292 | 0 | NvUpdateIndexOrderlyData(); |
293 | 0 | #if ACCUMULATE_SELF_HEAL_TIMER |
294 | | // Save the current time value |
295 | 0 | go.time = g_time; |
296 | 0 | #endif |
297 | | // Save all orderly data |
298 | 0 | NvWrite(NV_ORDERLY_DATA, sizeof(ORDERLY_DATA), &go); |
299 | 0 | if(in->shutdownType == TPM_SU_STATE) |
300 | 0 | { |
301 | | // Save STATE_RESET and STATE_CLEAR data |
302 | 0 | NvWrite(NV_STATE_CLEAR_DATA, sizeof(STATE_CLEAR_DATA), &gc); |
303 | 0 | NvWrite(NV_STATE_RESET_DATA, sizeof(STATE_RESET_DATA), &gr); |
304 | | // Save the startup flags for resume |
305 | 0 | if(g_DrtmPreStartup) |
306 | 0 | gp.orderlyState = TPM_SU_STATE | PRE_STARTUP_FLAG; |
307 | 0 | else if(g_StartupLocality3) |
308 | 0 | gp.orderlyState = TPM_SU_STATE | STARTUP_LOCALITY_3; |
309 | 0 | } |
310 | 0 | else if(in->shutdownType == TPM_SU_CLEAR) |
311 | 0 | { |
312 | | // Save STATE_RESET data |
313 | 0 | NvWrite(NV_STATE_RESET_DATA, sizeof(STATE_RESET_DATA), &gr); |
314 | 0 | } |
315 | 0 | else |
316 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
317 | 0 | NV_SYNC_PERSISTENT(orderlyState); |
318 | 0 | return TPM_RC_SUCCESS; |
319 | 0 | } |
320 | | #endif // CC_Shutdown |