Coverage Report

Created: 2023-09-25 06:15

/src/ibmswtpm2/src/IntegrityCommands.c
Line
Count
Source (jump to first uncovered line)
1
/********************************************************************************/
2
/*                    */
3
/*        Integrity Collection (PCR)          */
4
/*           Written by Ken Goldman       */
5
/*           IBM Thomas J. Watson Research Center     */
6
/*            $Id: IntegrityCommands.c 1272 2018-07-20 17:46:57Z 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
#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(
67
    PCR_Extend_In   *in             // IN: input parameter list
68
    )
69
0
{
70
0
    UINT32              i;
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
0
    if(in->pcrHandle == TPM_RH_NULL)
81
0
  return TPM_RC_SUCCESS;
82
    // Check if the extend operation is allowed by the current command locality
83
0
    if(!PCRIsExtendAllowed(in->pcrHandle))
84
0
  return TPM_RC_LOCALITY;
85
    // If PCR is state saved and we need to update orderlyState, check NV
86
    // availability
87
0
    if(PCRIsStateSaved(in->pcrHandle))
88
0
  RETURN_IF_ORDERLY;
89
    // Internal Data Update
90
    // Iterate input digest list to extend
91
0
    for(i = 0; i < in->digests.count; i++)
92
0
  {
93
0
      PCRExtend(in->pcrHandle, in->digests.digests[i].hashAlg,
94
0
          CryptHashGetDigestSize(in->digests.digests[i].hashAlg),
95
0
          (BYTE *)&in->digests.digests[i].digest);
96
0
  }
97
0
    return TPM_RC_SUCCESS;
98
0
}
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(
105
         PCR_Event_In    *in,            // IN: input parameter list
106
         PCR_Event_Out   *out            // OUT: output parameter list
107
         )
108
0
{
109
0
    HASH_STATE          hashState;
110
0
    UINT32              i;
111
0
    UINT16              size;
112
    // Input Validation
113
    // If a PCR extend is required
114
0
    if(in->pcrHandle != TPM_RH_NULL)
115
0
  {
116
      // If the PCR is not allow to extend, return error
117
0
      if(!PCRIsExtendAllowed(in->pcrHandle))
118
0
    return TPM_RC_LOCALITY;
119
      // If PCR is state saved and we need to update orderlyState, check NV
120
      // availability
121
0
      if(PCRIsStateSaved(in->pcrHandle))
122
0
    RETURN_IF_ORDERLY;
123
0
  }
124
    // Internal Data Update
125
0
    out->digests.count = HASH_COUNT;
126
    // Iterate supported PCR bank algorithms to extend
127
0
    for(i = 0; i < HASH_COUNT; i++)
128
0
  {
129
0
      TPM_ALG_ID  hash = CryptHashGetAlgByIndex(i);
130
0
      out->digests.digests[i].hashAlg = hash;
131
0
      size = CryptHashStart(&hashState, hash);
132
0
      CryptDigestUpdate2B(&hashState, &in->eventData.b);
133
0
      CryptHashEnd(&hashState, size,
134
0
       (BYTE *)&out->digests.digests[i].digest);
135
0
      if(in->pcrHandle != TPM_RH_NULL)
136
0
    PCRExtend(in->pcrHandle, hash, size,
137
0
        (BYTE *)&out->digests.digests[i].digest);
138
0
  }
139
0
    return TPM_RC_SUCCESS;
140
0
}
141
#endif // CC_PCR_Event
142
#include "Tpm.h"
143
#include "PCR_Read_fp.h"
144
#if CC_PCR_Read  // Conditional expansion of this file
145
TPM_RC
146
TPM2_PCR_Read(
147
        PCR_Read_In     *in,            // IN: input parameter list
148
        PCR_Read_Out    *out            // OUT: output parameter list
149
        )
150
0
{
151
    // Command Output
152
    // Call PCR read function.  input pcrSelectionIn parameter could be changed
153
    // to reflect the actual PCR being returned
154
0
    PCRRead(&in->pcrSelectionIn, &out->pcrValues, &out->pcrUpdateCounter);
155
0
    out->pcrSelectionOut = in->pcrSelectionIn;
156
0
    return TPM_RC_SUCCESS;
157
0
}
158
#endif // CC_PCR_Read
159
#include "Tpm.h"
160
#include "PCR_Allocate_fp.h"
161
#if CC_PCR_Allocate  // Conditional expansion of this file
162
TPM_RC
163
TPM2_PCR_Allocate(
164
      PCR_Allocate_In     *in,            // IN: input parameter list
165
      PCR_Allocate_Out    *out            // OUT: output parameter list
166
      )
167
0
{
168
0
    TPM_RC      result;
169
    // The command needs NV update.  Check if NV is available.
170
    // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
171
    // this point.
172
    // Note: These codes are not listed in the return values above because it is
173
    // an implementation choice to check in this routine rather than in a common
174
    // function that is called before these actions are called. These return values
175
    // are described in the Response Code section of Part 3.
176
0
    RETURN_IF_NV_IS_NOT_AVAILABLE;
177
    // Command Output
178
    // Call PCR Allocation function.
179
0
    result = PCRAllocate(&in->pcrAllocation, &out->maxPCR,
180
0
       &out->sizeNeeded, &out->sizeAvailable);
181
0
    if(result == TPM_RC_PCR)
182
0
  return result;
183
    //
184
0
    out->allocationSuccess = (result == TPM_RC_SUCCESS);
185
    // if re-configuration succeeds, set the flag to indicate PCR configuration is
186
    // going to be changed in next boot
187
0
    if(out->allocationSuccess == YES)
188
0
  g_pcrReConfig = TRUE;
189
0
    return TPM_RC_SUCCESS;
190
0
}
191
#endif // CC_PCR_Allocate
192
#include "Tpm.h"
193
#include "PCR_SetAuthPolicy_fp.h"
194
#if CC_PCR_SetAuthPolicy  // Conditional expansion of this file
195
TPM_RC
196
TPM2_PCR_SetAuthPolicy(
197
           PCR_SetAuthPolicy_In    *in             // IN: input parameter list
198
           )
199
0
{
200
0
    UINT32      groupIndex;
201
    // The command needs NV update.  Check if NV is available.
202
    // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
203
    // this point
204
0
    RETURN_IF_NV_IS_NOT_AVAILABLE;
205
    // Input Validation:
206
    // Check the authPolicy consistent with hash algorithm
207
0
    if(in->authPolicy.t.size != CryptHashGetDigestSize(in->hashAlg))
208
0
  return TPM_RCS_SIZE + RC_PCR_SetAuthPolicy_authPolicy;
209
    // If PCR does not belong to a policy group, return TPM_RC_VALUE
210
0
    if(!PCRBelongsPolicyGroup(in->pcrNum, &groupIndex))
211
0
  return TPM_RCS_VALUE + RC_PCR_SetAuthPolicy_pcrNum;
212
    // Internal Data Update
213
    // Set PCR policy
214
0
    gp.pcrPolicies.hashAlg[groupIndex] = in->hashAlg;
215
0
    gp.pcrPolicies.policy[groupIndex] = in->authPolicy;
216
    // Save new policy to NV
217
0
    NV_SYNC_PERSISTENT(pcrPolicies);
218
0
    return TPM_RC_SUCCESS;
219
0
}
220
#endif // CC_PCR_SetAuthPolicy
221
#include "Tpm.h"
222
#include "PCR_SetAuthValue_fp.h"
223
#if CC_PCR_SetAuthValue  // Conditional expansion of this file
224
// CC_PCR_SetAuthPolicy
225
TPM_RC
226
TPM2_PCR_SetAuthValue(
227
          PCR_SetAuthValue_In     *in             // IN: input parameter list
228
          )
229
0
{
230
0
    UINT32      groupIndex;
231
    // Input Validation:
232
    // If PCR does not belong to an auth group, return TPM_RC_VALUE
233
0
    if(!PCRBelongsAuthGroup(in->pcrHandle, &groupIndex))
234
0
  return TPM_RC_VALUE;
235
    // The command may cause the orderlyState to be cleared due to the update of
236
    // state clear data.  If this is the case, Check if NV is available.
237
    // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
238
    // this point
239
0
    RETURN_IF_ORDERLY;
240
    // Internal Data Update
241
    // Set PCR authValue
242
0
    MemoryRemoveTrailingZeros(&in->auth);
243
0
    gc.pcrAuthValues.auth[groupIndex] = in->auth;
244
0
    return TPM_RC_SUCCESS;
245
0
}
246
#endif // CC_PCR_SetAuthValue
247
#include "Tpm.h"
248
#include "PCR_Reset_fp.h"
249
#if CC_PCR_Reset  // Conditional expansion of this file
250
TPM_RC
251
TPM2_PCR_Reset(
252
         PCR_Reset_In    *in             // IN: input parameter list
253
         )
254
0
{
255
    // Input Validation
256
    // Check if the reset operation is allowed by the current command locality
257
0
    if(!PCRIsResetAllowed(in->pcrHandle))
258
0
  return TPM_RC_LOCALITY;
259
    // If PCR is state saved and we need to update orderlyState, check NV
260
    // availability
261
0
    if(PCRIsStateSaved(in->pcrHandle))
262
0
  RETURN_IF_ORDERLY;
263
    // Internal Data Update
264
    // Reset selected PCR in all banks to 0
265
0
    PCRSetValue(in->pcrHandle, 0);
266
    // Indicate that the PCR changed so that pcrCounter will be incremented if
267
    // necessary.
268
0
    PCRChanged(in->pcrHandle);
269
0
    return TPM_RC_SUCCESS;
270
0
}
271
#endif // CC_PCR_Reset
272
273
#include "Tpm.h"
274
/* This function is called to process a _TPM_Hash_Start() indication. */
275
LIB_EXPORT void
276
_TPM_Hash_Start(
277
    void
278
    )
279
4.12k
{
280
4.12k
    TPM_RC              result;
281
4.12k
    TPMI_DH_OBJECT      handle;
282
    // If a DRTM sequence object exists, free it up
283
4.12k
    if(g_DRTMHandle != TPM_RH_UNASSIGNED)
284
908
  {
285
908
      FlushObject(g_DRTMHandle);
286
908
      g_DRTMHandle = TPM_RH_UNASSIGNED;
287
908
  }
288
    // Create an event sequence object and store the handle in global
289
    // g_DRTMHandle. A TPM_RC_OBJECT_MEMORY error may be returned at this point
290
    // The NULL value for the first parameter will cause the sequence structure to
291
    // be allocated without being set as present. This keeps the sequence from
292
    // being left behind if the sequence is terminated early.
293
4.12k
    result = ObjectCreateEventSequence(NULL, &g_DRTMHandle);
294
    // If a free slot was not available, then free up a slot.
295
4.12k
    if(result != TPM_RC_SUCCESS)
296
0
  {
297
      // An implementation does not need to have a fixed relationship between
298
      // slot numbers and handle numbers. To handle the general case, scan for
299
      // a handle that is assigned and free it for the DRTM sequence.
300
      // In the reference implementation, the relationship between handles and
301
      // slots is fixed. So, if the call to ObjectCreateEvenSequence()
302
      // failed indicating that all slots are occupied, then the first handle we
303
      // are going to check (TRANSIENT_FIRST) will be occupied. It will be freed
304
      // so that it can be assigned for use as the DRTM sequence object.
305
0
      for(handle = TRANSIENT_FIRST; handle < TRANSIENT_LAST; handle++)
306
0
    {
307
        // try to flush the first object
308
0
        if(IsObjectPresent(handle))
309
0
      break;
310
0
    }
311
      // If the first call to find a slot fails but none of the slots is occupied
312
      // then there's a big problem
313
0
      pAssert(handle < TRANSIENT_LAST);
314
      // Free the slot
315
0
      FlushObject(handle);
316
      // Try to create an event sequence object again.  This time, we must
317
      // succeed.
318
0
      result = ObjectCreateEventSequence(NULL, &g_DRTMHandle);
319
0
      if(result != TPM_RC_SUCCESS)
320
0
    FAIL(FATAL_ERROR_INTERNAL);
321
0
  }
322
4.12k
    return;
323
4.12k
}
324
325
#include "Tpm.h"
326
/* This function is called to process a _TPM_Hash_Data() indication. */
327
LIB_EXPORT void
328
_TPM_Hash_Data(
329
         uint32_t         dataSize,      // IN: size of data to be extend
330
         unsigned char   *data           // IN: data buffer
331
         )
332
450
{
333
450
    UINT32           i;
334
450
    HASH_OBJECT     *hashObject;
335
450
    TPMI_DH_PCR      pcrHandle = TPMIsStarted()
336
450
         ? PCR_FIRST + DRTM_PCR : PCR_FIRST + HCRTM_PCR;
337
    // If there is no DRTM sequence object, then _TPM_Hash_Start
338
    // was not called so this function returns without doing
339
    // anything.
340
450
    if(g_DRTMHandle == TPM_RH_UNASSIGNED)
341
290
  return;
342
160
    hashObject = (HASH_OBJECT *)HandleToObject(g_DRTMHandle);
343
160
    pAssert(hashObject->attributes.eventSeq);
344
    // For each of the implemented hash algorithms, update the digest with the
345
    // data provided.
346
800
    for(i = 0; i < HASH_COUNT; i++)
347
640
  {
348
      // make sure that the PCR is implemented for this algorithm
349
640
      if(PcrIsAllocated(pcrHandle,
350
640
            hashObject->state.hashState[i].hashAlg))
351
    // Update sequence object
352
640
    CryptDigestUpdate(&hashObject->state.hashState[i], dataSize, data);
353
640
  }
354
160
    return;
355
160
}
356
357
#include "Tpm.h"
358
/* This function is called to process a _TPM_Hash_End() indication. */
359
LIB_EXPORT void
360
_TPM_Hash_End(
361
        void
362
        )
363
3.28k
{
364
3.28k
    UINT32          i;
365
3.28k
    TPM2B_DIGEST    digest;
366
3.28k
    HASH_OBJECT    *hashObject;
367
3.28k
    TPMI_DH_PCR     pcrHandle;
368
    // If the DRTM handle is not being used, then either _TPM_Hash_Start has not
369
    // been called, _TPM_Hash_End was previously called, or some other command
370
    // was executed and the sequence was aborted.
371
3.28k
    if(g_DRTMHandle == TPM_RH_UNASSIGNED)
372
226
  return;
373
    // Get DRTM sequence object
374
3.05k
    hashObject = (HASH_OBJECT *)HandleToObject(g_DRTMHandle);
375
    // Is this _TPM_Hash_End after Startup or before
376
3.05k
    if(TPMIsStarted())
377
0
  {
378
      // After
379
      // Reset the DRTM PCR
380
0
      PCRResetDynamics();
381
      // Extend the DRTM_PCR.
382
0
      pcrHandle = PCR_FIRST + DRTM_PCR;
383
      // DRTM sequence increments restartCount
384
0
      gr.restartCount++;
385
0
  }
386
3.05k
    else
387
3.05k
  {
388
3.05k
      pcrHandle = PCR_FIRST + HCRTM_PCR;
389
3.05k
      g_DrtmPreStartup = TRUE;
390
3.05k
  }
391
    // Complete hash and extend PCR, or if this is an HCRTM, complete
392
    // the hash, reset the H-CRTM register (PCR[0]) to 0...04, and then
393
    // extend the H-CRTM data
394
15.2k
    for(i = 0; i < HASH_COUNT; i++)
395
12.2k
  {
396
12.2k
      TPMI_ALG_HASH       hash = CryptHashGetAlgByIndex(i);
397
      // make sure that the PCR is implemented for this algorithm
398
12.2k
      if(PcrIsAllocated(pcrHandle,
399
12.2k
            hashObject->state.hashState[i].hashAlg))
400
12.2k
    {
401
        // Complete hash
402
12.2k
        digest.t.size = CryptHashGetDigestSize(hash);
403
12.2k
        CryptHashEnd2B(&hashObject->state.hashState[i], &digest.b);
404
12.2k
        PcrDrtm(pcrHandle, hash, &digest);
405
12.2k
    }
406
12.2k
  }
407
    // Flush sequence object.
408
3.05k
    FlushObject(g_DRTMHandle);
409
3.05k
    g_DRTMHandle = TPM_RH_UNASSIGNED;
410
3.05k
    return;
411
3.28k
}