• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stefanberger / libtpms / #2063

11 Feb 2026 02:58PM UTC coverage: 77.18% (-0.02%) from 77.195%
#2063

push

travis-ci

web-flow
Merge c175b6f1e into c2a8109f8

1174 of 1370 new or added lines in 95 files covered. (85.69%)

2190 existing lines in 89 files now uncovered.

36347 of 47094 relevant lines covered (77.18%)

125164.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.95
/src/tpm2/IntegrityCommands.c
1
/********************************************************************************/
2
/*                                                                                */
3
/*                          Integrity Collection (PCR)                                   */
4
/*                             Written by Ken Goldman                                */
5
/*                       IBM Thomas J. Watson Research Center                        */
6
/*            $Id: IntegrityCommands.c 1490 2019-07-26 21:13:22Z 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 - 2021                                */
59
/*                                                                                */
60
/********************************************************************************/
61

62
#include "Tpm.h"
63
#include "PCR_Extend_fp.h"
64
#if CC_PCR_Extend  // Conditional expansion of this file
65
TPM_RC
66
TPM2_PCR_Extend(
68✔
67
                PCR_Extend_In   *in             // IN: input parameter list
68
                )
69
{
70
    UINT32              i;
68✔
71
    // Input Validation
72
    // NOTE: This function assumes that the unmarshaling function for 'digests' will
73
    // have validated that all of the indicated hash algorithms are valid. If the
74
    // hash algorithms are correct, the unmarshaling code will unmarshal a digest
75
    // of the size indicated by the hash algorithm. If the overall size is not
76
    // consistent, the unmarshaling code will run out of input data or have input
77
    // data left over. In either case, it will cause an unmarshaling error and this
78
    // function will not be called.
79
    // For NULL handle, do nothing and return success
80
    if(in->pcrHandle == TPM_RH_NULL)
68✔
81
        return TPM_RC_SUCCESS;
82
    // Check if the extend operation is allowed by the current command locality
83
    if(!PCRIsExtendAllowed(in->pcrHandle))
64✔
84
        return TPM_RC_LOCALITY;
85
    // If PCR is state saved and we need to update orderlyState, check NV
86
    // availability
87
    if(PCRIsStateSaved(in->pcrHandle))
60✔
88
        RETURN_IF_ORDERLY;
15✔
89
    // Internal Data Update
90
    // Iterate input digest list to extend
91
    for(i = 0; i < in->digests.count; i++)
137✔
92
        {
93
            PCRExtend(in->pcrHandle, in->digests.digests[i].hashAlg,
77✔
94
                      CryptHashGetDigestSize(in->digests.digests[i].hashAlg),
77✔
95
                      (BYTE *)&in->digests.digests[i].digest);
77✔
96
        }
97
    return TPM_RC_SUCCESS;
98
}
99
#endif // CC_PCR_Extend
100
#include "Tpm.h"
101
#include "PCR_Event_fp.h"
102
#if CC_PCR_Event  // Conditional expansion of this file
103
TPM_RC
104
TPM2_PCR_Event(
36✔
105
               PCR_Event_In    *in,            // IN: input parameter list
106
               PCR_Event_Out   *out            // OUT: output parameter list
107
               )
108
{
109
    HASH_STATE          hashState;
36✔
110
    UINT32              i;
36✔
111
    UINT16              size;
36✔
112
    // Input Validation
113
    // If a PCR extend is required
114
    if(in->pcrHandle != TPM_RH_NULL)
36✔
115
        {
116
            // If the PCR is not allow to extend, return error
117
            if(!PCRIsExtendAllowed(in->pcrHandle))
32✔
118
                return TPM_RC_LOCALITY;
119
            // If PCR is state saved and we need to update orderlyState, check NV
120
            // availability
121
            if(PCRIsStateSaved(in->pcrHandle))
28✔
122
                RETURN_IF_ORDERLY;
5✔
123
        }
124
    // Internal Data Update
125
    out->digests.count = HASH_COUNT;
32✔
126
    // Iterate supported PCR bank algorithms to extend
127
    for(i = 0; i < HASH_COUNT; i++)
160✔
128
        {
129
            TPM_ALG_ID  hash = CryptHashGetAlgByIndex(i);
128✔
130
            out->digests.digests[i].hashAlg = hash;
128✔
131
            size = CryptHashStart(&hashState, hash);
128✔
132
            CryptDigestUpdate2B(&hashState, &in->eventData.b);
128✔
133
            CryptHashEnd(&hashState, size,
128✔
134
                         (BYTE *)&out->digests.digests[i].digest);
128✔
135
            if(in->pcrHandle != TPM_RH_NULL)
128✔
136
                PCRExtend(in->pcrHandle, hash, size,
112✔
137
                          (BYTE *)&out->digests.digests[i].digest);
138
        }
139
    return TPM_RC_SUCCESS;
140
}
141
#endif // CC_PCR_Event
142
#include "Tpm.h"
143
#include "PCR_Allocate_fp.h"
144
#if CC_PCR_Allocate  // Conditional expansion of this file
145
TPM_RC
146
TPM2_PCR_Allocate(
137✔
147
                  PCR_Allocate_In     *in,            // IN: input parameter list
148
                  PCR_Allocate_Out    *out            // OUT: output parameter list
149
                  )
150
{
151
    TPM_RC      result;
137✔
152
    // The command needs NV update.  Check if NV is available.
153
    // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
154
    // this point.
155
    // Note: These codes are not listed in the return values above because it is
156
    // an implementation choice to check in this routine rather than in a common
157
    // function that is called before these actions are called. These return values
158
    // are described in the Response Code section of Part 3.
159
    RETURN_IF_NV_IS_NOT_AVAILABLE;
137✔
160
    // Command Output
161
    // Call PCR Allocation function.
162
    result = PCRAllocate(&in->pcrAllocation, &out->maxPCR,
137✔
163
                         &out->sizeNeeded, &out->sizeAvailable);
164
    if(result == TPM_RC_PCR)
137✔
165
        return result;
166
    //
167
    out->allocationSuccess = (result == TPM_RC_SUCCESS);
137✔
168
    // if re-configuration succeeds, set the flag to indicate PCR configuration is
169
    // going to be changed in next boot
170
    if(out->allocationSuccess == YES)
137✔
171
        g_pcrReConfig = TRUE;
137✔
172
    return TPM_RC_SUCCESS;
173
}
174
#endif // CC_PCR_Allocate
175
#include "Tpm.h"
176
#include "PCR_SetAuthPolicy_fp.h"
177
#if CC_PCR_SetAuthPolicy  // Conditional expansion of this file
178
TPM_RC
UNCOV
179
TPM2_PCR_SetAuthPolicy(
×
180
                       PCR_SetAuthPolicy_In    *in             // IN: input parameter list
181
                       )
182
{
183
    UINT32      groupIndex;
×
184
    // The command needs NV update.  Check if NV is available.
185
    // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
186
    // this point
UNCOV
187
    RETURN_IF_NV_IS_NOT_AVAILABLE;
×
188
    // Input Validation:
189
    // Check the authPolicy consistent with hash algorithm
UNCOV
190
    if(in->authPolicy.t.size != CryptHashGetDigestSize(in->hashAlg))
×
191
        return TPM_RCS_SIZE + RC_PCR_SetAuthPolicy_authPolicy;
192
    // If PCR does not belong to a policy group, return TPM_RC_VALUE
UNCOV
193
    if(!PCRBelongsPolicyGroup(in->pcrNum, &groupIndex))
×
194
        return TPM_RCS_VALUE + RC_PCR_SetAuthPolicy_pcrNum;
195
    // Internal Data Update
196
    // Set PCR policy
UNCOV
197
    gp.pcrPolicies.hashAlg[groupIndex] = in->hashAlg;
×
UNCOV
198
    gp.pcrPolicies.policy[groupIndex] = in->authPolicy;
×
199
    // Save new policy to NV
UNCOV
200
    NV_SYNC_PERSISTENT(pcrPolicies);
×
UNCOV
201
    return TPM_RC_SUCCESS;
×
202
}
203
#endif // CC_PCR_SetAuthPolicy
204
#include "Tpm.h"
205
#include "PCR_SetAuthValue_fp.h"
206
#if CC_PCR_SetAuthValue  // Conditional expansion of this file
207
// CC_PCR_SetAuthPolicy
208
TPM_RC
209
TPM2_PCR_SetAuthValue(
4✔
210
                      PCR_SetAuthValue_In     *in             // IN: input parameter list
211
                      )
212
{
213
    UINT32      groupIndex;
4✔
214
    // Input Validation:
215
    // If PCR does not belong to an auth group, return TPM_RC_VALUE
216
    if(!PCRBelongsAuthGroup(in->pcrHandle, &groupIndex))
4✔
217
        return TPM_RC_VALUE;
218
    // The command may cause the orderlyState to be cleared due to the update of
219
    // state clear data.  If this is the case, Check if NV is available.
220
    // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
221
    // this point
UNCOV
222
    RETURN_IF_ORDERLY;
×
223
    // Internal Data Update
224
    // Set PCR authValue
UNCOV
225
    MemoryRemoveTrailingZeros(&in->auth);
×
UNCOV
226
    gc.pcrAuthValues.auth[groupIndex] = in->auth;
×
UNCOV
227
    return TPM_RC_SUCCESS;
×
228
}
229
#endif // CC_PCR_SetAuthValue
230
#include "Tpm.h"
231
#include "PCR_Reset_fp.h"
232
#if CC_PCR_Reset  // Conditional expansion of this file
233
TPM_RC
234
TPM2_PCR_Reset(
85✔
235
               PCR_Reset_In    *in             // IN: input parameter list
236
               )
237
{
238
    // Input Validation
239
    // Check if the reset operation is allowed by the current command locality
240
    if(!PCRIsResetAllowed(in->pcrHandle))
85✔
241
        return TPM_RC_LOCALITY;
242
    // If PCR is state saved and we need to update orderlyState, check NV
243
    // availability
244
    if(PCRIsStateSaved(in->pcrHandle))
76✔
UNCOV
245
        RETURN_IF_ORDERLY;
×
246
    // Internal Data Update
247
    // Reset selected PCR in all banks to 0
248
    PCRSetValue(in->pcrHandle, 0);
76✔
249
    // Indicate that the PCR changed so that pcrCounter will be incremented if
250
    // necessary.
251
    PCRChanged(in->pcrHandle);
76✔
252
    return TPM_RC_SUCCESS;
76✔
253
}
254
#endif // CC_PCR_Reset
255

256
#include "Tpm.h"
257
/* This function is called to process a _TPM_Hash_Start() indication. */
258
LIB_EXPORT BOOL _TPM_Hash_Start(void)
31✔
259
{
260
    TPM_RC              result;
31✔
261
    TPMI_DH_OBJECT      handle;
31✔
262
    // If a DRTM sequence object exists, free it up
263
    if(g_DRTMHandle != TPM_RH_UNASSIGNED)
31✔
264
    {
265
        // ensure g_DRTMHandle is cleared
266
        // and Flush sequence object
NEW
267
        TPMI_DH_OBJECT oldHandle = g_DRTMHandle;
×
NEW
268
        g_DRTMHandle             = TPM_RH_UNASSIGNED;
×
NEW
269
        VERIFY(FlushObject(oldHandle), FATAL_ERROR_INTERNAL, FALSE);
×
270
    }
271
    // Create an event sequence object and store the handle in global
272
    // g_DRTMHandle. A TPM_RC_OBJECT_MEMORY error may be returned at this point
273
    // The NULL value for the first parameter will cause the sequence structure to
274
    // be allocated without being set as present. This keeps the sequence from
275
    // being left behind if the sequence is terminated early.
276
    result = ObjectCreateEventSequence(NULL, &g_DRTMHandle);
31✔
277
    // If a free slot was not available, then free up a slot.
278
    if(result != TPM_RC_SUCCESS)
31✔
279
        {
280
            // An implementation does not need to have a fixed relationship between
281
            // slot numbers and handle numbers. To handle the general case, scan for
282
            // a handle that is assigned and free it for the DRTM sequence.
283
            // In the reference implementation, the relationship between handles and
284
            // slots is fixed. So, if the call to ObjectCreateEvenSequence()
285
            // failed indicating that all slots are occupied, then the first handle we
286
            // are going to check (TRANSIENT_FIRST) will be occupied. It will be freed
287
            // so that it can be assigned for use as the DRTM sequence object.
UNCOV
288
            for(handle = TRANSIENT_FIRST; handle < TRANSIENT_LAST; handle++)
×
289
                {
290
                    // try to flush the first object
UNCOV
291
                    if(IsObjectPresent(handle))
×
292
                        break;
293
                }
294
            // If the first call to find a slot fails but none of the slots is occupied
295
            // then there's a big problem
UNCOV
296
            pAssert(handle < TRANSIENT_LAST);
×
297
            // Free the slot
NEW
298
            VERIFY(FlushObject(handle), FATAL_ERROR_INTERNAL, FALSE);
×
299
            // Try to create an event sequence object again.  This time, we must
300
            // succeed.
UNCOV
301
            result = ObjectCreateEventSequence(NULL, &g_DRTMHandle);
×
UNCOV
302
            if(result != TPM_RC_SUCCESS)
×
UNCOV
303
                FAIL(FATAL_ERROR_INTERNAL);
×
304
        }
305
    return TRUE;
31✔
306
}
307

308
#include "Tpm.h"
309
/* This function is called to process a _TPM_Hash_Data() indication. */
310
LIB_EXPORT BOOL _TPM_Hash_Data(uint32_t dataSize,   // IN: size of data to be extend
1,568✔
311
                               unsigned char* data  // IN: data buffer
312
)
313
{
314
    UINT32           i;
1,568✔
315
    HASH_OBJECT     *hashObject;
1,568✔
316
    TPMI_DH_PCR      pcrHandle = TPMIsStarted()
1,568✔
317
                                 ? PCR_FIRST + DRTM_PCR : PCR_FIRST + HCRTM_PCR;
1,568✔
318
    // If there is no DRTM sequence object, then _TPM_Hash_Start
319
    // was not called so this function returns without doing
320
    // anything.
321
    if(g_DRTMHandle == TPM_RH_UNASSIGNED)
1,568✔
322
    {
323
        // do not enter failure mode because this is an ordering issue that
324
        // can be triggered by a BIOS issue, not an internal failure.
325
        return FALSE;
326
    }
327

328
    hashObject = (HASH_OBJECT *)HandleToObject(g_DRTMHandle);
1,568✔
329
    pAssert_BOOL(hashObject != NULL);
1,568✔
330
    pAssert(hashObject->attributes.eventSeq);
1,568✔
331

332
    // For each of the implemented hash algorithms, update the digest with the
333
    // data provided.
334
    for(i = 0; i < HASH_COUNT; i++)
7,840✔
335
        {
336
            // make sure that the PCR is implemented for this algorithm
337
            if(PcrIsAllocated(pcrHandle,
6,272✔
338
                              hashObject->state.hashState[i].hashAlg))
6,272✔
339
                // Update sequence object
340
                CryptDigestUpdate(&hashObject->state.hashState[i], dataSize, data);
6,272✔
341
        }
342
    return TRUE;
343
}
344

345
#include "Tpm.h"
346
/* This function is called to process a _TPM_Hash_End() indication. */
347
LIB_EXPORT BOOL _TPM_Hash_End(void)
31✔
348
{
349
    UINT32          i;
31✔
350
    TPM2B_DIGEST    digest;
31✔
351
    HASH_OBJECT    *hashObject;
31✔
352
    TPMI_DH_PCR     pcrHandle;
31✔
353
    // If the DRTM handle is not being used, then either _TPM_Hash_Start has not
354
    // been called, _TPM_Hash_End was previously called, or some other command
355
    // was executed and the sequence was aborted.
356
    if(g_DRTMHandle == TPM_RH_UNASSIGNED)
31✔
357
    {
358
        // do not enter failure mode because this is an ordering issue that
359
        // can be triggered by a BIOS issue, not an internal failure.
360
        return FALSE;
361
    }
362

363
    // Get DRTM sequence object
364
    hashObject = (HASH_OBJECT *)HandleToObject(g_DRTMHandle);
31✔
365
    pAssert_BOOL(hashObject != NULL);
31✔
366
    pAssert_BOOL(hashObject->attributes.eventSeq);
31✔
367

368
    // Is this _TPM_Hash_End after Startup or before
369
    if(TPMIsStarted())
31✔
370
        {
371
            // After
372
            // Reset the DRTM PCR
373
            PCRResetDynamics();
28✔
374
            // Extend the DRTM_PCR.
375
            pcrHandle = PCR_FIRST + DRTM_PCR;
28✔
376
            // DRTM sequence increments restartCount
377
            gr.restartCount++;
28✔
378
        }
379
    else
380
        {
381
            pcrHandle = PCR_FIRST + HCRTM_PCR;
3✔
382
            g_DrtmPreStartup = TRUE;
3✔
383
        }
384
    // Complete hash and extend PCR, or if this is an HCRTM, complete
385
    // the hash, reset the H-CRTM register (PCR[0]) to 0...04, and then
386
    // extend the H-CRTM data
387
    for(i = 0; i < HASH_COUNT; i++)
155✔
388
        {
389
            TPMI_ALG_HASH       hash = CryptHashGetAlgByIndex(i);
124✔
390
            // make sure that the PCR is implemented for this algorithm
391
            if(PcrIsAllocated(pcrHandle,
124✔
392
                              hashObject->state.hashState[i].hashAlg))
124✔
393
                {
394
                    // Complete hash
395
                    digest.t.size = CryptHashGetDigestSize(hash);
124✔
396
                    CryptHashEnd2B(&hashObject->state.hashState[i], &digest.b);
124✔
397
                    PcrDrtm(pcrHandle, hash, &digest);
124✔
398
                }
399
        }
400

401
    // ensure g_DRTMHandle is cleared
402
    // and Flush sequence object
403
    TPMI_DH_OBJECT oldHandle = g_DRTMHandle;
31✔
404
    g_DRTMHandle             = TPM_RH_UNASSIGNED;
31✔
405
    return FlushObject(oldHandle);
31✔
406
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc