Coverage Report

Created: 2026-07-16 06:51

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