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

stefanberger / libtpms / #2039

06 Dec 2025 06:17PM UTC coverage: 77.176%. Remained the same
#2039

push

travis-ci

web-flow
Merge fce5f14a4 into 4f71e9b45

1062 of 1261 new or added lines in 87 files covered. (84.22%)

1807 existing lines in 63 files now uncovered.

36353 of 47104 relevant lines covered (77.18%)

125322.86 hits per line

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

93.62
/src/tpm2/HashCommands.c
1
/********************************************************************************/
2
/*                                                                                */
3
/*                        Hash/HMAC/Event Sequences                                     */
4
/*                             Written by Ken Goldman                                */
5
/*                       IBM Thomas J. Watson Research Center                        */
6
/*            $Id: HashCommands.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 "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
    pAssert_RC(keyObject != NULL);
78

79
    publicArea = &keyObject->publicArea;
80
    pAssert_RC(publicArea != NULL);
81

82
    // Make sure that the key is an HMAC key
83
    if(publicArea->type != TPM_ALG_KEYEDHASH)
84
        return TPM_RCS_TYPE + RC_HMAC_Start_handle;
85
    // and that it is unrestricted
86
    if (IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
87
        return TPM_RCS_ATTRIBUTES + RC_HMAC_Start_handle;
88
    // and that it is a signing key
89
    if (!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
90
        return TPM_RCS_KEY + RC_HMAC_Start_handle;
91
    // See if the key has a default
92
    if(publicArea->parameters.keyedHashDetail.scheme.scheme == TPM_ALG_NULL)
93
        // it doesn't so use the input value
94
        hashAlg = in->hashAlg;
95
    else
96
        {
97
            // key has a default so use it
98
            hashAlg
99
                = publicArea->parameters.keyedHashDetail.scheme.details.hmac.hashAlg;
100
            // and verify that the input was either the  TPM_ALG_NULL or the default
101
            if(in->hashAlg != TPM_ALG_NULL && in->hashAlg != hashAlg)
102
                hashAlg = TPM_ALG_NULL;
103
        }
104
    // if we ended up without a hash algorithm then return an error
105
    if(hashAlg == TPM_ALG_NULL)
106
        return TPM_RCS_VALUE + RC_HMAC_Start_hashAlg;
107
    // Internal Data Update
108
    // Create a HMAC sequence object. A TPM_RC_OBJECT_MEMORY error may be
109
    // returned at this point
110
    return ObjectCreateHMACSequence(hashAlg,
111
                                    keyObject,
112
                                    &in->auth,
113
                                    &out->sequenceHandle);
114
}
115
#endif // CC_HMAC_Start
116
#include "Tpm.h"
117
#include "MAC_Start_fp.h"
118
#if CC_MAC_Start  // Conditional expansion of this file
119
/* Error Returns Meaning */
120
/* TPM_RC_ATTRIBUTES key referenced by handle is not a signing key or is restricted */
121
/* TPM_RC_OBJECT_MEMORY no space to create an internal object */
122
/* TPM_RC_KEY key referenced by handle is not an HMAC key */
123
/* TPM_RC_VALUE hashAlg is not compatible with the hash algorithm of the scheme of the object
124
   referenced by handle */
125
TPM_RC
126
TPM2_MAC_Start(
16✔
127
               MAC_Start_In   *in,            // IN: input parameter list
128
               MAC_Start_Out  *out            // OUT: output parameter list
129
               )
130
{
131
    OBJECT                  *keyObject;
16✔
132
    TPMT_PUBLIC             *publicArea;
16✔
133
    TPM_RC                   result;
16✔
134
    // Input Validation
135
    // Get HMAC key object and public area pointers
136
    keyObject = HandleToObject(in->handle);
16✔
137
    pAssert_RC(keyObject != NULL);
16✔
138
    publicArea = &keyObject->publicArea;
16✔
139
    pAssert_RC(publicArea != NULL);
16✔
140

141
    // Make sure that the key can do what is required
142
    result = CryptSelectMac(publicArea, &in->inScheme);
16✔
143
    // If the key is not able to do a MAC, indicate that the handle selects an
144
    // object that can't do a MAC
145
    if(result == TPM_RCS_TYPE)
16✔
146
        return TPM_RCS_TYPE + RC_MAC_Start_handle;
147
    // If there is another error type, indicate that the scheme and key are not
148
    // compatible
149
    if(result != TPM_RC_SUCCESS)
16✔
UNCOV
150
        return RcSafeAddToResult(result, RC_MAC_Start_inScheme);
×
151
    // Make sure that the key is not restricted
152
    if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
16✔
153
        return TPM_RCS_ATTRIBUTES + RC_MAC_Start_handle;
154
    // and that it is a signing key
155
    if(!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
16✔
156
        return TPM_RCS_KEY + RC_MAC_Start_handle;
157
    // Internal Data Update
158
    // Create a HMAC sequence object. A TPM_RC_OBJECT_MEMORY error may be
159
    // returned at this point
160
    return ObjectCreateHMACSequence(in->inScheme,
16✔
161
                                    keyObject,
162
                                    &in->auth,
163
                                    &out->sequenceHandle);
164
}
165
#endif // CC_MAC_Start
166
#include "Tpm.h"
167
#include "HashSequenceStart_fp.h"
168
#if CC_HashSequenceStart  // Conditional expansion of this file
169
TPM_RC
170
TPM2_HashSequenceStart(
56✔
171
                       HashSequenceStart_In    *in,            // IN: input parameter list
172
                       HashSequenceStart_Out   *out            // OUT: output parameter list
173
                       )
174
{
175
    // Internal Data Update
176
    if(in->hashAlg == TPM_ALG_NULL)
56✔
177
        // Start a event sequence.  A TPM_RC_OBJECT_MEMORY error may be
178
        // returned at this point
179
        return ObjectCreateEventSequence(&in->auth, &out->sequenceHandle);
19✔
180
    // Start a hash sequence.  A TPM_RC_OBJECT_MEMORY error may be
181
    // returned at this point
182
    return ObjectCreateHashSequence(in->hashAlg, &in->auth, &out->sequenceHandle);
37✔
183
}
184
#endif // CC_HashSequenceStart
185
#include "Tpm.h"
186
#include "SequenceUpdate_fp.h"
187
#if CC_SequenceUpdate  // Conditional expansion of this file
188
TPM_RC
189
TPM2_SequenceUpdate(
45✔
190
                    SequenceUpdate_In   *in             // IN: input parameter list
191
                    )
192
{
193
    OBJECT                  *object;
45✔
194
    HASH_OBJECT             *hashObject;
45✔
195
    // Input Validation
196
    // Get sequence object pointer
197
    object = HandleToObject(in->sequenceHandle);
45✔
198
    hashObject = (HASH_OBJECT *)object;
45✔
199
    // Check that referenced object is a sequence object.
200
    if(!ObjectIsSequence(object))
45✔
201
        return TPM_RCS_MODE + RC_SequenceUpdate_sequenceHandle;
202

203
    pAssert_RC(object != NULL);
45✔
204
    // Internal Data Update
205
    if(object->attributes.eventSeq == SET)
45✔
206
        {
207
            // Update event sequence object
208
            UINT32           i;
UNCOV
209
            for(i = 0; i < HASH_COUNT; i++)
×
210
                {
211
                    // Update sequence object
UNCOV
212
                    CryptDigestUpdate2B(&hashObject->state.hashState[i], &in->buffer.b);
×
213
                }
214
        }
215
    else
216
        {
217
            // Update hash/HMAC sequence object
218
            if(hashObject->attributes.hashSeq == SET)
45✔
219
                {
220
                    // Is this the first block of the sequence
221
                    if(hashObject->attributes.firstBlock == CLEAR)
29✔
222
                        {
223
                            // If so, indicate that first block was received
224
                            hashObject->attributes.firstBlock = SET;
29✔
225
                            // Check the first block to see if the first block can contain
226
                            // the TPM_GENERATED_VALUE.  If it does, it is not safe for
227
                            // a ticket.
228
                            if(TicketIsSafe(&in->buffer.b))
29✔
229
                                hashObject->attributes.ticketSafe = SET;
1✔
230
                        }
231
                    // Update sequence object hash/HMAC stack
232
                    CryptDigestUpdate2B(&hashObject->state.hashState[0], &in->buffer.b);
29✔
233
                }
234
            else if(object->attributes.hmacSeq == SET)
16✔
235
                {
236
                    // Update sequence object HMAC stack
237
                    CryptDigestUpdate2B(&hashObject->state.hmacState.hashState,
16✔
238
                                        &in->buffer.b);
16✔
239
                }
240
        }
241
    return TPM_RC_SUCCESS;
242
}
243
#endif // CC_SequenceUpdate
244
#include "Tpm.h"
245
#include "SequenceComplete_fp.h"
246
#if CC_SequenceComplete  // Conditional expansion of this file
247
/* Error Returns Meaning */
248
/* TPM_RC_MODE sequenceHandle does not reference a hash or HMAC sequence object */
249
TPM_RC
250
TPM2_SequenceComplete(
49✔
251
                      SequenceComplete_In     *in,            // IN: input parameter list
252
                      SequenceComplete_Out    *out            // OUT: output parameter list
253
                      )
254
{
255
    HASH_OBJECT                      *hashObject;
49✔
256
    // Input validation
257
    // Get hash object pointer
258
    hashObject = (HASH_OBJECT *)HandleToObject(in->sequenceHandle);
49✔
259
    pAssert_RC(hashObject != NULL);
49✔
260

261
    // input handle must be a hash or HMAC sequence object.
262
    if(hashObject->attributes.hashSeq == CLEAR
49✔
263
       && hashObject->attributes.hmacSeq == CLEAR)
49✔
264
        return TPM_RCS_MODE + RC_SequenceComplete_sequenceHandle;
265
    // Command Output
266
    if(hashObject->attributes.hashSeq == SET)           // sequence object for hash
49✔
267
        {
268
            // Get the hash algorithm before the algorithm is lost in CryptHashEnd
269
            TPM_ALG_ID       hashAlg = hashObject->state.hashState[0].hashAlg;
32✔
270
            // Update last piece of the data
271
            CryptDigestUpdate2B(&hashObject->state.hashState[0], &in->buffer.b);
32✔
272
            // Complete hash
273
            out->result.t.size = CryptHashEnd(&hashObject->state.hashState[0],
64✔
274
                                              sizeof(out->result.t.buffer),
275
                                              out->result.t.buffer);
32✔
276
            // Check if the first block of the sequence has been received
277
            if(hashObject->attributes.firstBlock == CLEAR)
32✔
278
                {
279
                    // If not, then this is the first block so see if it is 'safe'
280
                    // to sign.
UNCOV
281
                    if(TicketIsSafe(&in->buffer.b))
×
UNCOV
282
                        hashObject->attributes.ticketSafe = SET;
×
283
                }
284
            // Output ticket
285
            out->validation.tag = TPM_ST_HASHCHECK;
32✔
286
            out->validation.hierarchy = in->hierarchy;
32✔
287
            if(in->hierarchy == TPM_RH_NULL)
32✔
288
                {
289
                    // Ticket is not required
290
                    out->validation.digest.t.size = 0;
6✔
291
                }
292
            else if(hashObject->attributes.ticketSafe == CLEAR)
26✔
293
                {
294
                    // Ticket is not safe to generate
295
                    out->validation.hierarchy = TPM_RH_NULL;
25✔
296
                    out->validation.digest.t.size = 0;
25✔
297
                }
298
            else
299
                {
300
                    // Compute ticket
301
                    TicketComputeHashCheck(out->validation.hierarchy, hashAlg,
1✔
302
                                           &out->result, &out->validation);
303
                }
304
        }
305
    else
306
        {
307
            //   Update last piece of data
308
            CryptDigestUpdate2B(&hashObject->state.hmacState.hashState, &in->buffer.b);
17✔
309
#if !SMAC_IMPLEMENTED
310
            // Complete HMAC
311
            out->result.t.size = CryptHmacEnd(&(hashObject->state.hmacState),
312
                                              sizeof(out->result.t.buffer),
313
                                              out->result.t.buffer);
314
#else
315
            // Complete the MAC
316
            out->result.t.size = CryptMacEnd(&hashObject->state.hmacState,
34✔
317
                                             sizeof(out->result.t.buffer),
318
                                             out->result.t.buffer);
17✔
319
#endif
320
            // No ticket is generated for HMAC sequence
321
            out->validation.tag = TPM_ST_HASHCHECK;
17✔
322
            out->validation.hierarchy = TPM_RH_NULL;
17✔
323
            out->validation.digest.t.size = 0;
17✔
324
        }
325
    // Internal Data Update
326
    // mark sequence object as evict so it will be flushed on the way out
327
    hashObject->attributes.evict = SET;
49✔
328
    return TPM_RC_SUCCESS;
49✔
329
}
330
#endif // CC_SequenceComplete
331
#include "Tpm.h"
332
#include "EventSequenceComplete_fp.h"
333
#if CC_EventSequenceComplete  // Conditional expansion of this file
334
TPM_RC
335
TPM2_EventSequenceComplete(
15✔
336
                           EventSequenceComplete_In    *in,            // IN: input parameter list
337
                           EventSequenceComplete_Out   *out            // OUT: output parameter list
338
                           )
339
{
340
    HASH_OBJECT         *hashObject;
15✔
341
    UINT32               i;
15✔
342
    TPM_ALG_ID           hashAlg;
15✔
343
    // Input validation
344
    // get the event sequence object pointer
345
    hashObject = (HASH_OBJECT *)HandleToObject(in->sequenceHandle);
15✔
346
    pAssert_RC(hashObject != NULL);
15✔
347

348
    // input handle must reference an event sequence object
349
    if(hashObject->attributes.eventSeq != SET)
15✔
350
        return TPM_RCS_MODE + RC_EventSequenceComplete_sequenceHandle;
351
    // see if a PCR extend is requested in call
352
    if(in->pcrHandle != TPM_RH_NULL)
15✔
353
        {
354
            // see if extend of the PCR is allowed at the locality of the command,
355
            if(!PCRIsExtendAllowed(in->pcrHandle))
15✔
356
                return TPM_RC_LOCALITY;
357
            // if an extend is going to take place, then check to see if there has
358
            // been an orderly shutdown. If so, and the selected PCR is one of the
359
            // state saved PCR, then the orderly state has to change. The orderly state
360
            // does not change for PCR that are not preserved.
361
            // NOTE: This doesn't just check for Shutdown(STATE) because the orderly
362
            // state will have to change if this is a state-saved PCR regardless
363
            // of the current state. This is because a subsequent Shutdown(STATE) will
364
            // check to see if there was an orderly shutdown and not do anything if
365
            // there was. So, this must indicate that a future Shutdown(STATE) has
366
            // something to do.
367
            if(PCRIsStateSaved(in->pcrHandle))
15✔
UNCOV
368
                RETURN_IF_ORDERLY;
×
369
        }
370
    // Command Output
371
    out->results.count = 0;
15✔
372
    for(i = 0; i < HASH_COUNT; i++)
75✔
373
        {
374
            hashAlg = CryptHashGetAlgByIndex(i);
60✔
375
            // Update last piece of data
376
            CryptDigestUpdate2B(&hashObject->state.hashState[i], &in->buffer.b);
60✔
377
            // Complete hash
378
            out->results.digests[out->results.count].hashAlg = hashAlg;
60✔
379
            CryptHashEnd(&hashObject->state.hashState[i],
60✔
380
                         CryptHashGetDigestSize(hashAlg),
60✔
381
                         (BYTE *)&out->results.digests[out->results.count].digest);
60✔
382
            // Extend PCR
383
            if(in->pcrHandle != TPM_RH_NULL)
60✔
384
                PCRExtend(in->pcrHandle, hashAlg,
60✔
385
                          CryptHashGetDigestSize(hashAlg),
60✔
386
                          (BYTE *)&out->results.digests[out->results.count].digest);
60✔
387
            out->results.count++;
60✔
388
        }
389
    // Internal Data Update
390
    // mark sequence object as evict so it will be flushed on the way out
391
    hashObject->attributes.evict = SET;
15✔
392
    return TPM_RC_SUCCESS;
15✔
393
}
394
#endif // CC_EventSequenceComplete
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