Coverage Report

Created: 2025-10-28 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ibmswtpm2/src/HashCommands.c
Line
Count
Source
1
/********************************************************************************/
2
/*                    */
3
/*      Hash/HMAC/Event Sequences           */
4
/*           Written by Ken Goldman       */
5
/*           IBM Thomas J. Watson Research Center     */
6
/*            $Id: HashCommands.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 "HMAC_Start_fp.h"
64
#if CC_HMAC_Start  // Conditional expansion of this file
65
TPM_RC
66
TPM2_HMAC_Start(
67
    HMAC_Start_In   *in,            // IN: input parameter list
68
    HMAC_Start_Out  *out            // OUT: output parameter list
69
    )
70
{
71
    OBJECT                  *keyObject;
72
    TPMT_PUBLIC             *publicArea;
73
    TPM_ALG_ID               hashAlg;
74
    // Input Validation
75
    // Get HMAC key object and public area pointers
76
    keyObject = HandleToObject(in->handle);
77
    publicArea = &keyObject->publicArea;
78
    // Make sure that the key is an HMAC key
79
    if(publicArea->type != TPM_ALG_KEYEDHASH)
80
  return TPM_RCS_TYPE + RC_HMAC_Start_handle;
81
    // and that it is unrestricted
82
    if (IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
83
  return TPM_RCS_ATTRIBUTES + RC_HMAC_Start_handle;
84
    // and that it is a signing key
85
    if (!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
86
  return TPM_RCS_KEY + RC_HMAC_Start_handle;
87
    // See if the key has a default
88
    if(publicArea->parameters.keyedHashDetail.scheme.scheme == TPM_ALG_NULL)
89
  // it doesn't so use the input value
90
  hashAlg = in->hashAlg;
91
    else
92
  {
93
      // key has a default so use it
94
      hashAlg
95
    = publicArea->parameters.keyedHashDetail.scheme.details.hmac.hashAlg;
96
      // and verify that the input was either the  TPM_ALG_NULL or the default
97
      if(in->hashAlg != TPM_ALG_NULL && in->hashAlg != hashAlg)
98
    hashAlg = TPM_ALG_NULL;
99
  }
100
    // if we ended up without a hash algorithm then return an error
101
    if(hashAlg == TPM_ALG_NULL)
102
  return TPM_RCS_VALUE + RC_HMAC_Start_hashAlg;
103
    // Internal Data Update
104
    // Create a HMAC sequence object. A TPM_RC_OBJECT_MEMORY error may be
105
    // returned at this point
106
    return ObjectCreateHMACSequence(hashAlg,
107
            keyObject,
108
            &in->auth,
109
            &out->sequenceHandle);
110
}
111
#endif // CC_HMAC_Start
112
#include "Tpm.h"
113
#include "MAC_Start_fp.h"
114
#if CC_MAC_Start  // Conditional expansion of this file
115
/* Error Returns Meaning */
116
/* TPM_RC_ATTRIBUTES key referenced by handle is not a signing key or is restricted */
117
/* TPM_RC_OBJECT_MEMORY no space to create an internal object */
118
/* TPM_RC_KEY key referenced by handle is not an HMAC key */
119
/* TPM_RC_VALUE hashAlg is not compatible with the hash algorithm of the scheme of the object
120
   referenced by handle */
121
TPM_RC
122
TPM2_MAC_Start(
123
         MAC_Start_In   *in,            // IN: input parameter list
124
         MAC_Start_Out  *out            // OUT: output parameter list
125
         )
126
0
{
127
0
    OBJECT                  *keyObject;
128
0
    TPMT_PUBLIC             *publicArea;
129
0
    TPM_RC                   result;
130
    // Input Validation
131
    // Get HMAC key object and public area pointers
132
0
    keyObject = HandleToObject(in->handle);
133
0
    publicArea = &keyObject->publicArea;
134
    // Make sure that the key can do what is required
135
0
    result = CryptSelectMac(publicArea, &in->inScheme);
136
    // If the key is not able to do a MAC, indicate that the handle selects an
137
    // object that can't do a MAC
138
0
    if(result == TPM_RCS_TYPE)
139
0
  return TPM_RCS_TYPE + RC_MAC_Start_handle;
140
    // If there is another error type, indicate that the scheme and key are not
141
    // compatible
142
0
    if(result != TPM_RC_SUCCESS)
143
0
  return RcSafeAddToResult(result, RC_MAC_Start_inScheme);
144
    // Make sure that the key is not restricted
145
0
    if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
146
0
  return TPM_RCS_ATTRIBUTES + RC_MAC_Start_handle;
147
    // and that it is a signing key
148
0
    if(!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
149
0
  return TPM_RCS_KEY + RC_MAC_Start_handle;
150
    // Internal Data Update
151
    // Create a HMAC sequence object. A TPM_RC_OBJECT_MEMORY error may be
152
    // returned at this point
153
0
    return ObjectCreateHMACSequence(in->inScheme,
154
0
            keyObject,
155
0
            &in->auth,
156
0
            &out->sequenceHandle);
157
0
}
158
#endif // CC_MAC_Start
159
#include "Tpm.h"
160
#include "HashSequenceStart_fp.h"
161
#if CC_HashSequenceStart  // Conditional expansion of this file
162
TPM_RC
163
TPM2_HashSequenceStart(
164
           HashSequenceStart_In    *in,            // IN: input parameter list
165
           HashSequenceStart_Out   *out            // OUT: output parameter list
166
           )
167
0
{
168
    // Internal Data Update
169
0
    if(in->hashAlg == TPM_ALG_NULL)
170
  // Start a event sequence.  A TPM_RC_OBJECT_MEMORY error may be
171
  // returned at this point
172
0
  return ObjectCreateEventSequence(&in->auth, &out->sequenceHandle);
173
    // Start a hash sequence.  A TPM_RC_OBJECT_MEMORY error may be
174
    // returned at this point
175
0
    return ObjectCreateHashSequence(in->hashAlg, &in->auth, &out->sequenceHandle);
176
0
}
177
#endif // CC_HashSequenceStart
178
#include "Tpm.h"
179
#include "SequenceUpdate_fp.h"
180
#if CC_SequenceUpdate  // Conditional expansion of this file
181
TPM_RC
182
TPM2_SequenceUpdate(
183
        SequenceUpdate_In   *in             // IN: input parameter list
184
        )
185
0
{
186
0
    OBJECT                  *object;
187
0
    HASH_OBJECT             *hashObject;
188
    // Input Validation
189
    // Get sequence object pointer
190
0
    object = HandleToObject(in->sequenceHandle);
191
0
    hashObject = (HASH_OBJECT *)object;
192
    // Check that referenced object is a sequence object.
193
0
    if(!ObjectIsSequence(object))
194
0
  return TPM_RCS_MODE + RC_SequenceUpdate_sequenceHandle;
195
    // Internal Data Update
196
0
    if(object->attributes.eventSeq == SET)
197
0
  {
198
      // Update event sequence object
199
0
      UINT32           i;
200
0
      for(i = 0; i < HASH_COUNT; i++)
201
0
          {
202
              // Update sequence object
203
0
              CryptDigestUpdate2B(&hashObject->state.hashState[i], &in->buffer.b);
204
0
          }
205
0
  }
206
0
    else
207
0
  {
208
      // Update hash/HMAC sequence object
209
0
      if(hashObject->attributes.hashSeq == SET)
210
0
          {
211
              // Is this the first block of the sequence
212
0
              if(hashObject->attributes.firstBlock == CLEAR)
213
0
      {
214
          // If so, indicate that first block was received
215
0
          hashObject->attributes.firstBlock = SET;
216
          // Check the first block to see if the first block can contain
217
          // the TPM_GENERATED_VALUE.  If it does, it is not safe for
218
          // a ticket.
219
0
          if(TicketIsSafe(&in->buffer.b))
220
0
        hashObject->attributes.ticketSafe = SET;
221
0
      }
222
              // Update sequence object hash/HMAC stack
223
0
              CryptDigestUpdate2B(&hashObject->state.hashState[0], &in->buffer.b);
224
0
          }
225
0
      else if(object->attributes.hmacSeq == SET)
226
0
          {
227
              // Update sequence object HMAC stack
228
0
              CryptDigestUpdate2B(&hashObject->state.hmacState.hashState,
229
0
                                  &in->buffer.b);
230
0
          }
231
0
  }
232
0
    return TPM_RC_SUCCESS;
233
0
}
234
#endif // CC_SequenceUpdate
235
#include "Tpm.h"
236
#include "SequenceComplete_fp.h"
237
#if CC_SequenceComplete  // Conditional expansion of this file
238
/* Error Returns Meaning */
239
/* TPM_RC_MODE sequenceHandle does not reference a hash or HMAC sequence object */
240
TPM_RC
241
TPM2_SequenceComplete(
242
          SequenceComplete_In     *in,            // IN: input parameter list
243
          SequenceComplete_Out    *out            // OUT: output parameter list
244
          )
245
0
{
246
0
    HASH_OBJECT                      *hashObject;
247
    // Input validation
248
    // Get hash object pointer
249
0
    hashObject = (HASH_OBJECT *)HandleToObject(in->sequenceHandle);
250
    // input handle must be a hash or HMAC sequence object.
251
0
    if(hashObject->attributes.hashSeq == CLEAR
252
0
       && hashObject->attributes.hmacSeq == CLEAR)
253
0
  return TPM_RCS_MODE + RC_SequenceComplete_sequenceHandle;
254
    // Command Output
255
0
    if(hashObject->attributes.hashSeq == SET)           // sequence object for hash
256
0
  {
257
      // Get the hash algorithm before the algorithm is lost in CryptHashEnd
258
0
      TPM_ALG_ID       hashAlg = hashObject->state.hashState[0].hashAlg;
259
      // Update last piece of the data
260
0
      CryptDigestUpdate2B(&hashObject->state.hashState[0], &in->buffer.b);
261
      // Complete hash
262
0
      out->result.t.size = CryptHashEnd(&hashObject->state.hashState[0],
263
0
                sizeof(out->result.t.buffer),
264
0
                out->result.t.buffer);
265
      // Check if the first block of the sequence has been received
266
0
      if(hashObject->attributes.firstBlock == CLEAR)
267
0
    {
268
        // If not, then this is the first block so see if it is 'safe'
269
        // to sign.
270
0
        if(TicketIsSafe(&in->buffer.b))
271
0
      hashObject->attributes.ticketSafe = SET;
272
0
    }
273
      // Output ticket
274
0
      out->validation.tag = TPM_ST_HASHCHECK;
275
0
      out->validation.hierarchy = in->hierarchy;
276
0
      if(in->hierarchy == TPM_RH_NULL)
277
0
    {
278
        // Ticket is not required
279
0
        out->validation.digest.t.size = 0;
280
0
    }
281
0
      else if(hashObject->attributes.ticketSafe == CLEAR)
282
0
    {
283
        // Ticket is not safe to generate
284
0
        out->validation.hierarchy = TPM_RH_NULL;
285
0
        out->validation.digest.t.size = 0;
286
0
    }
287
0
      else
288
0
    {
289
        // Compute ticket
290
0
        TicketComputeHashCheck(out->validation.hierarchy, hashAlg,
291
0
             &out->result, &out->validation);
292
0
    }
293
0
  }
294
0
    else
295
0
  {
296
      //   Update last piece of data
297
0
      CryptDigestUpdate2B(&hashObject->state.hmacState.hashState, &in->buffer.b);
298
#if !SMAC_IMPLEMENTED
299
      // Complete HMAC
300
      out->result.t.size = CryptHmacEnd(&(hashObject->state.hmacState),
301
                sizeof(out->result.t.buffer),
302
                out->result.t.buffer);
303
#else
304
      // Complete the MAC
305
0
      out->result.t.size = CryptMacEnd(&hashObject->state.hmacState,
306
0
               sizeof(out->result.t.buffer),
307
0
               out->result.t.buffer);
308
0
#endif
309
      // No ticket is generated for HMAC sequence
310
0
      out->validation.tag = TPM_ST_HASHCHECK;
311
0
      out->validation.hierarchy = TPM_RH_NULL;
312
0
      out->validation.digest.t.size = 0;
313
0
  }
314
    // Internal Data Update
315
    // mark sequence object as evict so it will be flushed on the way out
316
0
    hashObject->attributes.evict = SET;
317
0
    return TPM_RC_SUCCESS;
318
0
}
319
#endif // CC_SequenceComplete
320
#include "Tpm.h"
321
#include "EventSequenceComplete_fp.h"
322
#if CC_EventSequenceComplete  // Conditional expansion of this file
323
TPM_RC
324
TPM2_EventSequenceComplete(
325
         EventSequenceComplete_In    *in,            // IN: input parameter list
326
         EventSequenceComplete_Out   *out            // OUT: output parameter list
327
         )
328
0
{
329
0
    HASH_OBJECT         *hashObject;
330
0
    UINT32               i;
331
0
    TPM_ALG_ID           hashAlg;
332
    // Input validation
333
    // get the event sequence object pointer
334
0
    hashObject = (HASH_OBJECT *)HandleToObject(in->sequenceHandle);
335
    // input handle must reference an event sequence object
336
0
    if(hashObject->attributes.eventSeq != SET)
337
0
  return TPM_RCS_MODE + RC_EventSequenceComplete_sequenceHandle;
338
    // see if a PCR extend is requested in call
339
0
    if(in->pcrHandle != TPM_RH_NULL)
340
0
  {
341
      // see if extend of the PCR is allowed at the locality of the command,
342
0
      if(!PCRIsExtendAllowed(in->pcrHandle))
343
0
    return TPM_RC_LOCALITY;
344
      // if an extend is going to take place, then check to see if there has
345
      // been an orderly shutdown. If so, and the selected PCR is one of the
346
      // state saved PCR, then the orderly state has to change. The orderly state
347
      // does not change for PCR that are not preserved.
348
      // NOTE: This doesn't just check for Shutdown(STATE) because the orderly
349
      // state will have to change if this is a state-saved PCR regardless
350
      // of the current state. This is because a subsequent Shutdown(STATE) will
351
      // check to see if there was an orderly shutdown and not do anything if
352
      // there was. So, this must indicate that a future Shutdown(STATE) has
353
      // something to do.
354
0
      if(PCRIsStateSaved(in->pcrHandle))
355
0
    RETURN_IF_ORDERLY;
356
0
  }
357
    // Command Output
358
0
    out->results.count = 0;
359
0
    for(i = 0; i < HASH_COUNT; i++)
360
0
  {
361
0
      hashAlg = CryptHashGetAlgByIndex(i);
362
      // Update last piece of data
363
0
      CryptDigestUpdate2B(&hashObject->state.hashState[i], &in->buffer.b);
364
      // Complete hash
365
0
      out->results.digests[out->results.count].hashAlg = hashAlg;
366
0
      CryptHashEnd(&hashObject->state.hashState[i],
367
0
       CryptHashGetDigestSize(hashAlg),
368
0
       (BYTE *)&out->results.digests[out->results.count].digest);
369
      // Extend PCR
370
0
      if(in->pcrHandle != TPM_RH_NULL)
371
0
    PCRExtend(in->pcrHandle, hashAlg,
372
0
        CryptHashGetDigestSize(hashAlg),
373
0
        (BYTE *)&out->results.digests[out->results.count].digest);
374
0
      out->results.count++;
375
0
  }
376
    // Internal Data Update
377
    // mark sequence object as evict so it will be flushed on the way out
378
0
    hashObject->attributes.evict = SET;
379
0
    return TPM_RC_SUCCESS;
380
0
}
381
#endif // CC_EventSequenceComplete