Coverage Report

Created: 2025-08-29 06:04

/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