Coverage Report

Created: 2026-04-12 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libtpms/src/tpm2/HierarchyCommands.c
Line
Count
Source
1
/********************************************************************************/
2
/*                    */
3
/*           Hierarchy 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 "HierarchyControl_fp.h"
63
#if CC_HierarchyControl  // Conditional expansion of this file
64
TPM_RC
65
TPM2_HierarchyControl(
66
          HierarchyControl_In     *in             // IN: input parameter list
67
          )
68
11
{
69
11
    BOOL        select = (in->state == YES);
70
11
    BOOL        *selected = NULL;
71
    // Input Validation
72
11
    switch(in->enable)
73
11
  {
74
      // Platform hierarchy has to be disabled by PlatformAuth
75
      // If the platform hierarchy has already been disabled, only a reboot
76
      // can enable it again
77
3
    case TPM_RH_PLATFORM:
78
4
    case TPM_RH_PLATFORM_NV:
79
4
      if(in->authHandle != TPM_RH_PLATFORM)
80
2
    return TPM_RC_AUTH_TYPE;
81
2
      break;
82
      // ShEnable may be disabled if PlatformAuth/PlatformPolicy or
83
      // OwnerAuth/OwnerPolicy is provided.  If ShEnable is disabled, then it
84
      // may only be enabled if PlatformAuth/PlatformPolicy is provided.
85
4
    case TPM_RH_OWNER:
86
4
      if(in->authHandle != TPM_RH_PLATFORM
87
2
         && in->authHandle != TPM_RH_OWNER)
88
1
    return TPM_RC_AUTH_TYPE;
89
3
      if(gc.shEnable == FALSE && in->state == YES
90
0
         && in->authHandle != TPM_RH_PLATFORM)
91
0
    return TPM_RC_AUTH_TYPE;
92
3
      break;
93
      // EhEnable may be disabled if either PlatformAuth/PlatformPolicy or
94
      // EndosementAuth/EndorsementPolicy is provided.  If EhEnable is disabled,
95
      // then it may only be enabled if PlatformAuth/PlatformPolicy is
96
      // provided.
97
3
    case TPM_RH_ENDORSEMENT:
98
3
      if(in->authHandle != TPM_RH_PLATFORM
99
2
         && in->authHandle != TPM_RH_ENDORSEMENT)
100
1
    return TPM_RC_AUTH_TYPE;
101
2
      if(gc.ehEnable == FALSE && in->state == YES
102
0
         && in->authHandle != TPM_RH_PLATFORM)
103
0
    return TPM_RC_AUTH_TYPE;
104
2
      break;
105
2
    default:
106
0
      FAIL(FATAL_ERROR_INTERNAL);
107
0
      break;
108
11
  }
109
    // Internal Data Update
110
    // Enable or disable the selected hierarchy
111
    // Note: the authorization processing for this command may keep these
112
    // command actions from being executed. For example, if phEnable is
113
    // CLEAR, then platformAuth cannot be used for authorization. This
114
    // means that would not be possible to use platformAuth to change the
115
    // state of phEnable from CLEAR to SET.
116
    // If it is decided that platformPolicy can still be used when phEnable
117
    // is CLEAR, then this code could SET phEnable when proper platform
118
    // policy is provided.
119
7
    switch(in->enable)
120
7
  {
121
3
    case TPM_RH_OWNER:
122
3
      selected = &gc.shEnable;
123
3
      break;
124
2
    case TPM_RH_ENDORSEMENT:
125
2
      selected = &gc.ehEnable;
126
2
      break;
127
1
    case TPM_RH_PLATFORM:
128
1
      selected = &g_phEnable;
129
1
      break;
130
1
    case TPM_RH_PLATFORM_NV:
131
1
      selected = &gc.phEnableNV;
132
1
      break;
133
0
    default:
134
0
      FAIL(FATAL_ERROR_INTERNAL);
135
0
      break;
136
7
  }
137
7
    if(selected != NULL && *selected != select)
138
5
  {
139
      // Before changing the internal state, make sure that NV is available.
140
      // Only need to update NV if changing the orderly state
141
5
      RETURN_IF_ORDERLY;
142
      // state is changing and NV is available so modify
143
5
      *selected = select;
144
      // If a hierarchy was just disabled, flush it
145
5
      if(select == CLEAR && in->enable != TPM_RH_PLATFORM_NV)
146
          // Flush hierarchy
147
4
    ObjectFlushHierarchy(in->enable);
148
      // orderly state should be cleared because of the update to state clear data
149
      // This gets processed in ExecuteCommand() on the way out.
150
5
      g_clearOrderly = TRUE;
151
5
  }
152
7
    return TPM_RC_SUCCESS;
153
7
}
154
#endif // CC_HierarchyControl
155
#include "Tpm.h"
156
#include "SetPrimaryPolicy_fp.h"
157
#if CC_SetPrimaryPolicy  // Conditional expansion of this file
158
TPM_RC
159
TPM2_SetPrimaryPolicy(
160
          SetPrimaryPolicy_In     *in             // IN: input parameter list
161
          )
162
5
{
163
    // Input Validation
164
    // Check the authPolicy consistent with hash algorithm. If the policy size is
165
    // zero, then the algorithm is required to be TPM_ALG_NULL
166
5
    if(in->authPolicy.t.size != CryptHashGetDigestSize(in->hashAlg))
167
1
  return TPM_RCS_SIZE + RC_SetPrimaryPolicy_authPolicy;
168
    // The command need NV update for OWNER and ENDORSEMENT hierarchy, and
169
    // might need orderlyState update for PLATFROM hierarchy.
170
    // Check if NV is available.  A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE
171
    // error may be returned at this point
172
8
    RETURN_IF_NV_IS_NOT_AVAILABLE;
173
    // Internal Data Update
174
    // Set hierarchy policy
175
8
    switch(in->authHandle)
176
8
  {
177
1
    case TPM_RH_OWNER:
178
1
      gp.ownerAlg = in->hashAlg;
179
1
      gp.ownerPolicy = in->authPolicy;
180
1
      NV_SYNC_PERSISTENT(ownerAlg);
181
1
      NV_SYNC_PERSISTENT(ownerPolicy);
182
1
      break;
183
1
    case TPM_RH_ENDORSEMENT:
184
1
      gp.endorsementAlg = in->hashAlg;
185
1
      gp.endorsementPolicy = in->authPolicy;
186
1
      NV_SYNC_PERSISTENT(endorsementAlg);
187
1
      NV_SYNC_PERSISTENT(endorsementPolicy);
188
1
      break;
189
1
    case TPM_RH_PLATFORM:
190
1
      gc.platformAlg = in->hashAlg;
191
1
      gc.platformPolicy = in->authPolicy;
192
      // need to update orderly state
193
1
      g_clearOrderly = TRUE;
194
1
      break;
195
1
    case TPM_RH_LOCKOUT:
196
1
      gp.lockoutAlg = in->hashAlg;
197
1
      gp.lockoutPolicy = in->authPolicy;
198
1
      NV_SYNC_PERSISTENT(lockoutAlg);
199
1
      NV_SYNC_PERSISTENT(lockoutPolicy);
200
1
      break;
201
202
0
#define SET_ACT_POLICY(N)           \
203
0
      case TPM_RH_ACT_##N:          \
204
0
        go.ACT_##N.hashAlg = in->hashAlg;       \
205
0
        go.ACT_##N.authPolicy = in->authPolicy;     \
206
0
        g_clearOrderly = TRUE;          \
207
0
        break;
208
209
0
      FOR_EACH_ACT(SET_ACT_POLICY)
210
211
0
    default:
212
0
      FAIL(FATAL_ERROR_INTERNAL);
213
0
      break;
214
8
  }
215
4
    return TPM_RC_SUCCESS;
216
8
}
217
#endif // CC_SetPrimaryPolicy
218
#include "Tpm.h"
219
#include "ChangePPS_fp.h"
220
#if CC_ChangePPS  // Conditional expansion of this file
221
TPM_RC
222
TPM2_ChangePPS(
223
         ChangePPS_In    *in             // IN: input parameter list
224
         )
225
1
{
226
1
    UINT32          i;
227
    // Check if NV is available.  A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE
228
    // error may be returned at this point
229
1
    RETURN_IF_NV_IS_NOT_AVAILABLE;
230
    // Input parameter is not reference in command action
231
1
    NOT_REFERENCED(in);
232
    // Internal Data Update
233
    // Reset platform hierarchy seed from RNG
234
1
    CryptRandomGenerate(sizeof(gp.PPSeed.t.buffer), gp.PPSeed.t.buffer);
235
1
    gp.PPSeedCompatLevel = RuntimeProfileGetSeedCompatLevel(); // libtpms added
236
    // Create a new phProof value from RNG to prevent the saved platform
237
    // hierarchy contexts being loaded
238
1
    CryptRandomGenerate(sizeof(gp.phProof.t.buffer), gp.phProof.t.buffer);
239
    // Set platform authPolicy to null
240
1
    gc.platformAlg = TPM_ALG_NULL;
241
1
    gc.platformPolicy.t.size = 0;
242
    // Flush loaded object in platform hierarchy
243
1
    ObjectFlushHierarchy(TPM_RH_PLATFORM);
244
    // Flush platform evict object and index in NV
245
1
    NvFlushHierarchy(TPM_RH_PLATFORM);
246
    // Save hierarchy changes to NV
247
1
    NV_SYNC_PERSISTENT(PPSeed);
248
1
    NV_SYNC_PERSISTENT(PPSeedCompatLevel); // libtpms added
249
1
    NV_SYNC_PERSISTENT(phProof);
250
    // Re-initialize PCR policies
251
1
#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0
252
2
    for(i = 0; i < NUM_POLICY_PCR_GROUP; i++)
253
1
  {
254
1
      gp.pcrPolicies.hashAlg[i] = TPM_ALG_NULL;
255
1
      gp.pcrPolicies.policy[i].t.size = 0;
256
1
  }
257
1
    NV_SYNC_PERSISTENT(pcrPolicies);
258
1
#endif
259
    // orderly state should be cleared because of the update to state clear data
260
1
    g_clearOrderly = TRUE;
261
1
    return TPM_RC_SUCCESS;
262
1
}
263
#endif // CC_ChangePPS
264
#include "Tpm.h"
265
#include "ChangeEPS_fp.h"
266
#if CC_ChangeEPS  // Conditional expansion of this file
267
TPM_RC
268
TPM2_ChangeEPS(
269
         ChangeEPS_In    *in             // IN: input parameter list
270
         )
271
1
{
272
    // The command needs NV update.  Check if NV is available.
273
    // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
274
    // this point
275
1
    RETURN_IF_NV_IS_NOT_AVAILABLE;
276
    // Input parameter is not reference in command action
277
1
    NOT_REFERENCED(in);
278
    // Internal Data Update
279
    // Reset endorsement hierarchy seed from RNG
280
1
    CryptRandomGenerate(sizeof(gp.EPSeed.t.buffer), gp.EPSeed.t.buffer);
281
1
    gp.EPSeedCompatLevel = RuntimeProfileGetSeedCompatLevel(); // libtpms added
282
    // Create new ehProof value from RNG
283
1
    CryptRandomGenerate(sizeof(gp.ehProof.t.buffer), gp.ehProof.t.buffer);
284
    // Enable endorsement hierarchy
285
1
    gc.ehEnable = TRUE;
286
    // set authValue buffer to zeros
287
1
    MemorySet(gp.endorsementAuth.t.buffer, 0, gp.endorsementAuth.t.size);
288
    // Set endorsement authValue to null
289
1
    gp.endorsementAuth.t.size = 0;
290
    // Set endorsement authPolicy to null
291
1
    gp.endorsementAlg = TPM_ALG_NULL;
292
1
    gp.endorsementPolicy.t.size = 0;
293
    // Flush loaded object in endorsement hierarchy
294
1
    ObjectFlushHierarchy(TPM_RH_ENDORSEMENT);
295
    // Flush evict object of endorsement hierarchy stored in NV
296
1
    NvFlushHierarchy(TPM_RH_ENDORSEMENT);
297
    // Save hierarchy changes to NV
298
1
    NV_SYNC_PERSISTENT(EPSeed);
299
1
    NV_SYNC_PERSISTENT(EPSeedCompatLevel); // libtpms added
300
1
    NV_SYNC_PERSISTENT(ehProof);
301
1
    NV_SYNC_PERSISTENT(endorsementAuth);
302
1
    NV_SYNC_PERSISTENT(endorsementAlg);
303
1
    NV_SYNC_PERSISTENT(endorsementPolicy);
304
    // orderly state should be cleared because of the update to state clear data
305
1
    g_clearOrderly = TRUE;
306
1
    return TPM_RC_SUCCESS;
307
1
}
308
#endif // CC_ChangeEPS
309
#include "Tpm.h"
310
#include "Clear_fp.h"
311
#if CC_Clear  // Conditional expansion of this file
312
TPM_RC
313
TPM2_Clear(
314
     Clear_In        *in             // IN: input parameter list
315
     )
316
1
{
317
    // Input parameter is not reference in command action
318
1
    NOT_REFERENCED(in);
319
    // The command needs NV update.  Check if NV is available.
320
    // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
321
    // this point
322
1
    RETURN_IF_NV_IS_NOT_AVAILABLE;
323
    // Input Validation
324
    // If Clear command is disabled, return an error
325
1
    if(gp.disableClear)
326
0
  return TPM_RC_DISABLED;
327
    // Internal Data Update
328
    // Reset storage hierarchy seed from RNG
329
1
    CryptRandomGenerate(sizeof(gp.SPSeed.t.buffer), gp.SPSeed.t.buffer);
330
1
    gp.SPSeedCompatLevel = RuntimeProfileGetSeedCompatLevel(); // libtpms added
331
    // Create new shProof and ehProof value from RNG
332
1
    CryptRandomGenerate(sizeof(gp.shProof.t.buffer), gp.shProof.t.buffer);
333
1
    CryptRandomGenerate(sizeof(gp.ehProof.t.buffer), gp.ehProof.t.buffer);
334
    // Enable storage and endorsement hierarchy
335
1
    gc.shEnable = gc.ehEnable = TRUE;
336
    // set the authValue buffers to zero
337
1
    MemorySet(&gp.ownerAuth, 0, sizeof(gp.ownerAuth));
338
1
    MemorySet(&gp.endorsementAuth, 0, sizeof(gp.endorsementAuth));
339
1
    MemorySet(&gp.lockoutAuth, 0, sizeof(gp.lockoutAuth));
340
    // Set storage, endorsement, and lockout authPolicy to null
341
1
    gp.ownerAlg = gp.endorsementAlg = gp.lockoutAlg = TPM_ALG_NULL;
342
1
    MemorySet(&gp.ownerPolicy, 0, sizeof(gp.ownerPolicy));
343
1
    MemorySet(&gp.endorsementPolicy, 0, sizeof(gp.endorsementPolicy));
344
1
    MemorySet(&gp.lockoutPolicy, 0, sizeof(gp.lockoutPolicy));
345
    // Flush loaded object in storage and endorsement hierarchy
346
1
    ObjectFlushHierarchy(TPM_RH_OWNER);
347
1
    ObjectFlushHierarchy(TPM_RH_ENDORSEMENT);
348
    // Flush owner and endorsement object and owner index in NV
349
1
    NvFlushHierarchy(TPM_RH_OWNER);
350
1
    NvFlushHierarchy(TPM_RH_ENDORSEMENT);
351
    // Initialize dictionary attack parameters
352
1
    DAPreInstall_Init();
353
    // Reset clock
354
1
    go.clock = 0;
355
1
    go.clockSafe = YES;
356
1
    NvWrite(NV_ORDERLY_DATA, sizeof(ORDERLY_DATA), &go);
357
    // Reset counters
358
1
    gp.resetCount = gr.restartCount = gr.clearCount = 0;
359
1
    gp.auditCounter = 0;
360
    // Save persistent data changes to NV
361
    // Note: since there are so many changes to the persistent data structure, the
362
    // entire PERSISTENT_DATA structure is written as a unit
363
1
    NvWrite(NV_PERSISTENT_DATA, sizeof(PERSISTENT_DATA), &gp);
364
    // Reset the PCR authValues (this does not change the PCRs)
365
1
    PCR_ClearAuth();
366
    // Bump the PCR counter
367
1
    PCRChanged(0);
368
    // orderly state should be cleared because of the update to state clear data
369
1
    g_clearOrderly = TRUE;
370
1
    return TPM_RC_SUCCESS;
371
1
}
372
#endif // CC_Clear
373
#include "Tpm.h"
374
#include "ClearControl_fp.h"
375
#if CC_ClearControl  // Conditional expansion of this file
376
TPM_RC
377
TPM2_ClearControl(
378
      ClearControl_In     *in             // IN: input parameter list
379
      )
380
4
{
381
    // The command needs NV update.
382
4
    RETURN_IF_NV_IS_NOT_AVAILABLE;
383
    // Input Validation
384
    // LockoutAuth may be used to set disableLockoutClear to TRUE but not to FALSE
385
4
    if(in->auth == TPM_RH_LOCKOUT && in->disable == NO)
386
1
  return TPM_RC_AUTH_FAIL;
387
    // Internal Data Update
388
3
    if(in->disable == YES)
389
2
  gp.disableClear = TRUE;
390
1
    else
391
1
  gp.disableClear = FALSE;
392
    // Record the change to NV
393
3
    NV_SYNC_PERSISTENT(disableClear);
394
3
    return TPM_RC_SUCCESS;
395
4
}
396
#endif // CC_ClearControl
397
#include "Tpm.h"
398
#include "HierarchyChangeAuth_fp.h"
399
#if CC_HierarchyChangeAuth  // Conditional expansion of this file
400
#include "Object_spt_fp.h"
401
TPM_RC
402
TPM2_HierarchyChangeAuth(
403
       HierarchyChangeAuth_In  *in             // IN: input parameter list
404
       )
405
11
{
406
    // The command needs NV update.
407
11
    RETURN_IF_NV_IS_NOT_AVAILABLE;
408
    // Make sure that the authorization value is a reasonable size (not larger than
409
    // the size of the digest produced by the integrity hash. The integrity
410
    // hash is assumed to produce the longest digest of any hash implemented
411
    // on the TPM. This will also remove trailing zeros from the authValue.
412
11
    if(MemoryRemoveTrailingZeros(&in->newAuth) > CONTEXT_INTEGRITY_HASH_SIZE)
413
0
  return TPM_RCS_SIZE + RC_HierarchyChangeAuth_newAuth;
414
    // Set hierarchy authValue
415
11
    switch(in->authHandle)
416
11
  {
417
3
    case TPM_RH_OWNER:
418
3
      gp.ownerAuth = in->newAuth;
419
3
      NV_SYNC_PERSISTENT(ownerAuth);
420
3
      break;
421
2
    case TPM_RH_ENDORSEMENT:
422
2
      gp.endorsementAuth = in->newAuth;
423
2
      NV_SYNC_PERSISTENT(endorsementAuth);
424
2
      break;
425
4
    case TPM_RH_PLATFORM:
426
4
      gc.platformAuth = in->newAuth;
427
      // orderly state should be cleared
428
4
      g_clearOrderly = TRUE;
429
4
      break;
430
2
    case TPM_RH_LOCKOUT:
431
2
      gp.lockoutAuth = in->newAuth;
432
2
      NV_SYNC_PERSISTENT(lockoutAuth);
433
2
      break;
434
0
    default:
435
0
      FAIL(FATAL_ERROR_INTERNAL);
436
0
      break;
437
11
  }
438
11
    return TPM_RC_SUCCESS;
439
11
}
440
#endif // CC_HierarchyChangeAuth