• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
Info updated!

stefanberger / libtpms / #2037

05 Dec 2025 06:50PM UTC coverage: 77.185% (-0.03%) from 77.213%
#2037

push

travis-ci

web-flow
Merge 73eca8c26 into 4f71e9b45

992 of 1176 new or added lines in 85 files covered. (84.35%)

1748 existing lines in 62 files now uncovered.

36357 of 47104 relevant lines covered (77.18%)

125949.64 hits per line

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

96.99
/src/tpm2/crypto/openssl/CryptHash.c
1
// SPDX-License-Identifier: BSD-2-Clause
2

3
//** Description
4
//
5
// This file contains implementation of cryptographic functions for hashing.
6
//
7
//** Includes, Defines, and Types
8

9
#define _CRYPT_HASH_C_
10
#include "Tpm.h"
11
#include "CryptHash_fp.h"
12
#include "CryptHash.h"
13
#include "OIDs.h"
14

15
#if USE_OPENSSL_FUNCTIONS_SSKDF
16
# include "Helpers_fp.h"
17
# include <openssl/kdf.h>
18
# include <openssl/core_names.h>
19
#endif
20

21
// Instance each of the hash descriptors based on the implemented algorithms
22
FOR_EACH_HASH(HASH_DEF_TEMPLATE)
23
// Instance a 'null' def.
24
HASH_DEF NULL_Def = {{0}};
25

26
// Create a table of pointers to the defined hash definitions
27
#define HASH_DEF_ENTRY(HASH, Hash) &Hash##_Def,
28
PHASH_DEF HashDefArray[] = {
29
    // for each implemented HASH, expands to: &HASH_Def,
30
    FOR_EACH_HASH(HASH_DEF_ENTRY) & NULL_Def};
31
#undef HASH_DEF_ENTRY
32

33
//** Obligatory Initialization Functions
34

35
//*** CryptHashInit()
36
// This function is called by _TPM_Init do perform the initialization operations for
37
// the library.
38
BOOL CryptHashInit(void)
12,497✔
39
{
40
    LibHashInit();
12,497✔
41
    return TRUE;
12,497✔
42
}
43

44
//*** CryptHashStartup()
45
// This function is called by TPM2_Startup(). It checks that the size of the
46
// HashDefArray is consistent with the HASH_COUNT.
47
BOOL CryptHashStartup(void)
8,407✔
48
{
49
    int i = sizeof(HashDefArray) / sizeof(PHASH_DEF) - 1;
8,407✔
50
    return (i == HASH_COUNT);
8,407✔
51
}
52

53
//** Hash Information Access Functions
54
//*** Introduction
55
// These functions provide access to the hash algorithm description information.
56

57
//*** CryptGetHashDef()
58
// This function accesses the hash descriptor associated with a hash a
59
// algorithm. The function returns a pointer to a 'null' descriptor if hashAlg is
60
// TPM_ALG_NULL or not a defined algorithm.
61
PHASH_DEF
62
CryptGetHashDef(TPM_ALG_ID hashAlg)
1,006,730✔
63
{
64
#define GET_DEF(HASH, Hash)  \
65
    case ALG_##HASH##_VALUE: \
66
        return &Hash##_Def;
67
    switch(hashAlg)
1,006,730✔
68
    {
69
        FOR_EACH_HASH(GET_DEF)
706,261✔
70
        default:
169✔
71
            return &NULL_Def;
169✔
72
    }
73
#undef GET_DEF
74
}
75

76
//*** CryptHashIsValidAlg()
77
// This function tests to see if an algorithm ID is a valid hash algorithm. If
78
// flag is true, then TPM_ALG_NULL is a valid hash.
79
//  Return Type: BOOL
80
//      TRUE(1)         hashAlg is a valid, implemented hash on this TPM
81
//      FALSE(0)        hashAlg is not valid for this TPM
82
BOOL CryptHashIsValidAlg(
882✔
83
    TPM_ALG_ID hashAlg,        // IN: the algorithm to check
84
    BOOL       isAlgNullValid  // IN: TRUE if TPM_ALG_NULL is to be treated
85
                               //     as a valid hash
86
)
87
{
88
    if(hashAlg == TPM_ALG_NULL)
882✔
89
        return isAlgNullValid;
90
    return CryptGetHashDef(hashAlg) != &NULL_Def;
882✔
91
}
92

93
//*** CryptHashGetAlgByIndex()
94
// This function is used to iterate through the hashes. TPM_ALG_NULL
95
// is returned for all indexes that are not valid hashes.
96
// If the TPM implements 3 hashes, then an 'index' value of 0 will
97
// return the first implemented hash and an 'index' of 2 will return the
98
// last. All other index values will return TPM_ALG_NULL.
99
//
100
//  Return Type: TPM_ALG_ID
101
// TPM_ALG_xxx         a hash algorithm
102
// TPM_ALG_NULL        this can be used as a stop value
103
LIB_EXPORT TPM_ALG_ID CryptHashGetAlgByIndex(UINT32 index  // IN: the index
17,490✔
104
)
105
{
106
    TPM_ALG_ID hashAlg;
17,490✔
107
    if(index >= HASH_COUNT)
17,490✔
108
        hashAlg = TPM_ALG_NULL;
109
    else
110
        hashAlg = HashDefArray[index]->hashAlg;
17,440✔
111
    return hashAlg;
17,490✔
112
}
113

114
//*** CryptHashGetDigestSize()
115
// Returns the size of the digest produced by the hash. If 'hashAlg' is not a hash
116
// algorithm, the TPM will FAIL.
117
//  Return Type: UINT16
118
//   0       TPM_ALG_NULL
119
//   > 0     the digest size
120
//
121
LIB_EXPORT UINT16 CryptHashGetDigestSize(
854,141✔
122
    TPM_ALG_ID hashAlg  // IN: hash algorithm to look up
123
)
124
{
125
    return CryptGetHashDef(hashAlg)->digestSize;
854,141✔
126
}
127

128
//*** CryptHashGetBlockSize()
129
// Returns the size of the block used by the hash. If 'hashAlg' is not a hash
130
// algorithm, the TPM will FAIL.
131
//  Return Type: UINT16
132
//   0       TPM_ALG_NULL
133
//   > 0     the digest size
134
//
135
LIB_EXPORT UINT16 CryptHashGetBlockSize(
9,389✔
136
    TPM_ALG_ID hashAlg  // IN: hash algorithm to look up
137
)
138
{
139
    return CryptGetHashDef(hashAlg)->blockSize;
9,389✔
140
}
141

142
#if 0                // libtpms added
143
//*** CryptHashGetOid()
144
// This function returns a pointer to DER=encoded OID for a hash algorithm. All OIDs
145
// are full OID values including the Tag (0x06) and length byte.
146
LIB_EXPORT const BYTE* CryptHashGetOid(TPM_ALG_ID hashAlg)
147
{
148
    return CryptGetHashDef(hashAlg)->OID;
149
}
150
#endif                // libtpms added
151

152
#if 0                // libtpms added
153
//***  CryptHashGetContextAlg()
154
// This function returns the hash algorithm associated with a hash context.
155
TPM_ALG_ID
156
CryptHashGetContextAlg(PHASH_STATE state  // IN: the context to check
157
)
158
{
159
    return state->hashAlg;
160
}
161
#endif                // libtpms added
162

163
#if 0 // libtpms added
164
//** State Import and Export
165

166
//*** CryptHashCopyState
167
// This function is used to clone a HASH_STATE.
168
LIB_EXPORT void CryptHashCopyState(HASH_STATE* out,  // OUT: destination of the state
169
                                   const HASH_STATE* in  // IN: source of the state
170
)
171
{
172
    pAssert(out->type == in->type);
173
    out->hashAlg = in->hashAlg;
174
    out->def     = in->def;
175
    if(in->hashAlg != TPM_ALG_NULL)
176
    {
177
        HASH_STATE_COPY(out, in);
178
    }
179
    if(in->type == HASH_STATE_HMAC)
180
    {
181
        const HMAC_STATE* hIn  = (HMAC_STATE*)in;
182
        HMAC_STATE*       hOut = (HMAC_STATE*)out;
183
        hOut->hmacKey          = hIn->hmacKey;
184
    }
185
    return;
186
}
187
#endif // libtpms added
188

189
#if 0  // libtpms added
190
//*** CryptHashExportState()
191
// This function is used to export a hash or HMAC hash state. This function
192
// would be called when preparing to context save a sequence object.
193
void CryptHashExportState(
194
    PCHASH_STATE internalFmt,       // IN: the hash state formatted for use by
195
                                    //     library
196
    PEXPORT_HASH_STATE externalFmt  // OUT: the exported hash state
197
)
198
{
199
    BYTE* outBuf = (BYTE*)externalFmt;
200
    //
201
    MUST_BE(sizeof(HASH_STATE) <= sizeof(EXPORT_HASH_STATE));
202
    // the following #define is used to move data from an aligned internal data
203
    // structure to a byte buffer (external format data.
204
#define CopyToOffset(value)                      \
205
    memcpy(&outBuf[offsetof(HASH_STATE, value)], \
206
           &internalFmt->value,                  \
207
           sizeof(internalFmt->value))
208
    // Copy the hashAlg
209
    CopyToOffset(hashAlg);
210
    CopyToOffset(type);
211
#ifdef HASH_STATE_SMAC
212
    if(internalFmt->type == HASH_STATE_SMAC)
213
    {
214
        memcpy(outBuf, internalFmt, sizeof(HASH_STATE));
215
        return;
216
    }
217
#endif
218
    if(internalFmt->type == HASH_STATE_HMAC)
219
    {
220
        HMAC_STATE* from = (HMAC_STATE*)internalFmt;
221
        memcpy(&outBuf[offsetof(HMAC_STATE, hmacKey)],
222
               &from->hmacKey,
223
               sizeof(from->hmacKey));
224
    }
225
    if(internalFmt->hashAlg != TPM_ALG_NULL)
226
        HASH_STATE_EXPORT(externalFmt, internalFmt);
227
}
228

229
//*** CryptHashImportState()
230
// This function is used to import the hash state. This function
231
// would be called to import a hash state when the context of a sequence object
232
// was being loaded.
233
void CryptHashImportState(
234
    PHASH_STATE internalFmt,         // OUT: the hash state formatted for use by
235
                                     //     the library
236
    PCEXPORT_HASH_STATE externalFmt  // IN: the exported hash state
237
)
238
{
239
    BYTE* inBuf = (BYTE*)externalFmt;
240
//
241
#define CopyFromOffset(value)                   \
242
    memcpy(&internalFmt->value,                 \
243
           &inBuf[offsetof(HASH_STATE, value)], \
244
           sizeof(internalFmt->value))
245

246
    // Copy the hashAlg of the byte-aligned input structure to the structure-aligned
247
    // internal structure.
248
    CopyFromOffset(hashAlg);
249
    CopyFromOffset(type);
250
    if(internalFmt->hashAlg != TPM_ALG_NULL)
251
    {
252
#ifdef HASH_STATE_SMAC
253
        if(internalFmt->type == HASH_STATE_SMAC)
254
        {
255
            memcpy(internalFmt, inBuf, sizeof(HASH_STATE));
256
            return;
257
        }
258
#endif
259
        internalFmt->def = CryptGetHashDef(internalFmt->hashAlg);
260
        HASH_STATE_IMPORT(internalFmt, inBuf);
261
        if(internalFmt->type == HASH_STATE_HMAC)
262
        {
263
            HMAC_STATE* to = (HMAC_STATE*)internalFmt;
264
            memcpy(&to->hmacKey,
265
                   &inBuf[offsetof(HMAC_STATE, hmacKey)],
266
                   sizeof(to->hmacKey));
267
        }
268
    }
269
}
270
#endif  // libtpms added
271

272
//** State Modification Functions
273

274
//***HashEnd()
275
// Local function to complete a hash that uses the hashDef instead of an algorithm
276
// ID. This function is used to complete the hash and only return a partial digest.
277
// The return value is the size of the data copied.
278
static UINT16 HashEnd(PHASH_STATE hashState,  // IN: the hash state
54,573✔
279
                      UINT32      dOutSize,   // IN: the size of receive buffer
280
                      PBYTE       dOut        // OUT: the receive buffer
281
)
282
{
283
    BYTE temp[MAX_DIGEST_SIZE];
54,573✔
284
    if((hashState->hashAlg == TPM_ALG_NULL) || (hashState->type != HASH_STATE_HASH))
54,573✔
285
        dOutSize = 0;
286
    if(dOutSize > 0)
54,573✔
287
    {
288
        hashState->def = CryptGetHashDef(hashState->hashAlg);
54,573✔
289
        // Set the final size
290
        dOutSize = MIN(dOutSize, hashState->def->digestSize);
54,573✔
291
        // Complete into the temp buffer and then copy
292
        HASH_END(hashState, temp);
54,573✔
293
        // Don't want any other functions calling the HASH_END method
294
        // directly.
295
#undef HASH_END
296
        memcpy(dOut, &temp, dOutSize);
54,573✔
297
    }
298
    hashState->type = HASH_STATE_EMPTY;
54,573✔
299
    return (UINT16)dOutSize;
54,573✔
300
}
301

302
//*** CryptHashStart()
303
// Functions starts a hash stack
304
// Start a hash stack and returns the digest size. As a side effect, the
305
// value of 'stateSize' in hashState is updated to indicate the number of bytes
306
// of state that were saved. This function calls GetHashServer() and that function
307
// will put the TPM into failure mode if the hash algorithm is not supported.
308
//
309
// This function does not use the sequence parameter. If it is necessary to import
310
// or export context, this will start the sequence in a local state
311
// and export the state to the input buffer. Will need to add a flag to the state
312
// structure to indicate that it needs to be imported before it can be used.
313
// (BLEH).
314
//  Return Type: UINT16
315
//  0           hash is TPM_ALG_NULL
316
// >0           digest size
317
LIB_EXPORT UINT16 CryptHashStart(
54,593✔
318
    PHASH_STATE hashState,  // OUT: the running hash state
319
    TPM_ALG_ID  hashAlg     // IN: hash algorithm
320
)
321
{
322
    UINT16 retVal;
54,593✔
323

324
    TPM_DO_SELF_TEST(hashAlg);
54,593✔
325

326
    hashState->hashAlg = hashAlg;
54,593✔
327
    if(hashAlg == TPM_ALG_NULL)
54,593✔
328
    {
329
        retVal = 0;
330
    }
331
    else
332
    {
333
        hashState->def = CryptGetHashDef(hashAlg);
54,593✔
334
        HASH_START(hashState);
54,593✔
335
        retVal = hashState->def->digestSize;
54,593✔
336
    }
337
#undef HASH_START
338
    hashState->type = HASH_STATE_HASH;
54,593✔
339
    return retVal;
54,593✔
340
}
341

342
//*** CryptDigestUpdate()
343
// Add data to a hash or HMAC, SMAC stack.
344
//
345
void CryptDigestUpdate(PHASH_STATE hashState,  // IN: the hash context information
111,878✔
346
                       UINT32      dataSize,   // IN: the size of data to be added
347
                       const BYTE* data        // IN: data to be hashed
348
)
349
{
350
    if(hashState->hashAlg != TPM_ALG_NULL)
111,878✔
351
    {
352
        if((hashState->type == HASH_STATE_HASH)
111,878✔
353
           || (hashState->type == HASH_STATE_HMAC))
111,878✔
354
            HASH_DATA(hashState, dataSize, (BYTE*)data);
111,786✔
355
#if SMAC_IMPLEMENTED
356
        else if(hashState->type == HASH_STATE_SMAC)
92✔
357
            (hashState->state.smac.smacMethods.data)(
92✔
358
                &hashState->state.smac.state, dataSize, data);
92✔
359
#endif  // SMAC_IMPLEMENTED
360
        else
361
        {
362
            // this void assert is OK because these values only indicate the
363
            // intention of the hash, but don't actually affect the hash
364
            // calculation or buffer size calculations.  IOW, the failure
365
            // set here can safely percolate out and be checked at a higher
366
            // level.
NEW
367
            FAIL_VOID(FATAL_ERROR_INTERNAL);
×
368
        }
369
    }
370
    return;
111,878✔
371
}
372

373
//*** CryptHashEnd()
374
// Complete a hash or HMAC computation. This function will place the smaller of
375
// 'digestSize' or the size of the digest in 'dOut'. The number of bytes in the
376
// placed in the buffer is returned. If there is a failure, the returned value
377
// is <= 0.
378
//  Return Type: UINT16
379
//       0      no data returned
380
//      > 0     the number of bytes in the digest or dOutSize, whichever is smaller
381
LIB_EXPORT UINT16 CryptHashEnd(PHASH_STATE hashState,  // IN: the state of hash stack
6,637✔
382
                               UINT32      dOutSize,   // IN: size of digest buffer
383
                               BYTE*       dOut        // OUT: hash digest
384
)
385
{
386
    pAssert_ZERO(hashState->type == HASH_STATE_HASH);
6,637✔
387
    return HashEnd(hashState, dOutSize, dOut);
6,637✔
388
}
389

390
//*** CryptHashBlock()
391
// Start a hash, hash a single block, update 'digest' and return the size of
392
// the results.
393
//
394
// The 'digestSize' parameter can be smaller than the digest. If so, only the more
395
// significant bytes are returned.
396
//  Return Type: UINT16
397
//  >= 0        number of bytes placed in 'dOut'
398
LIB_EXPORT UINT16 CryptHashBlock(TPM_ALG_ID  hashAlg,   // IN: The hash algorithm
15,050✔
399
                                 UINT32      dataSize,  // IN: size of buffer to hash
400
                                 const BYTE* data,      // IN: the buffer to hash
401
                                 UINT32 dOutSize,  // IN: size of the digest buffer
402
                                 BYTE*  dOut       // OUT: digest buffer
403
)
404
{
405
    HASH_STATE state;
15,050✔
406
    CryptHashStart(&state, hashAlg);
15,050✔
407
    CryptDigestUpdate(&state, dataSize, data);
15,050✔
408
    return HashEnd(&state, dOutSize, dOut);
15,050✔
409
}
410

411
//*** CryptDigestUpdate2B()
412
// This function updates a digest (hash or HMAC) with a TPM2B.
413
//
414
// This function can be used for both HMAC and hash functions so the
415
// 'digestState' is void so that either state type can be passed.
416
LIB_EXPORT void CryptDigestUpdate2B(PHASH_STATE  state,  // IN: the digest state
14,712✔
417
                                    const TPM2B* bIn     // IN: 2B containing the data
418
)
419
{
420
    // Only compute the digest if a pointer to the 2B is provided.
421
    // In CryptDigestUpdate(), if size is zero or buffer is NULL, then no change
422
    // to the digest occurs. This function should not provide a buffer if bIn is
423
    // not provided.
424
    // as indicated by the comment above CryptDigestUpdate is tolerant of null, but
425
    // we don't expect a null pointer here, so simply return but trigger failure
426
    // mode because this is an unexpected internal programming error.
427
    pAssert_VOID_OK(bIn != NULL);
14,712✔
428
    CryptDigestUpdate(state, bIn->size, bIn->buffer);
14,712✔
429
    return;
14,712✔
430
}
431

432
//*** CryptHashEnd2B()
433
// This function is the same as CryptCompleteHash() but the digest is
434
// placed in a TPM2B. This is the most common use and this is provided
435
// for specification clarity. 'digest.size' should be set to indicate the number of
436
// bytes to place in the buffer
437
//  Return Type: UINT16
438
//      >=0     the number of bytes placed in 'digest.buffer'
439
LIB_EXPORT UINT16 CryptHashEnd2B(
4,399✔
440
    PHASH_STATE state,  // IN: the hash state
441
    P2B         digest  // IN: the size of the buffer Out: requested
442
                        //     number of bytes
443
)
444
{
445
    return CryptHashEnd(state, digest->size, digest->buffer);
4,399✔
446
}
447

448
//*** CryptDigestUpdateInt()
449
// This function is used to include an integer value to a hash stack. The function
450
// marshals the integer into its canonical form before calling CryptDigestUpdate().
451
LIB_EXPORT void CryptDigestUpdateInt(
10,183✔
452
    void*  state,    // IN: the state of hash stack
453
    UINT32 intSize,  // IN: the size of 'intValue' in bytes
454
    UINT64 intValue  // IN: integer value to be hashed
455
)
456
{
457
#if LITTLE_ENDIAN_TPM
458
    intValue = REVERSE_ENDIAN_64(intValue);
10,183✔
459
#endif
460
    CryptDigestUpdate(state, intSize, &((BYTE*)&intValue)[8 - intSize]);
10,183✔
461
}
10,183✔
462

463
//** HMAC Functions
464

465
//*** CryptHmacStart()
466
// This function is used to start an HMAC using a temp
467
// hash context. The function does the initialization
468
// of the hash with the HMAC key XOR iPad and updates the
469
// HMAC key XOR oPad.
470
//
471
// The function returns the number of bytes in a digest produced by 'hashAlg'.
472
//  Return Type: UINT16
473
//  >= 0        number of bytes in digest produced by 'hashAlg' (may be zero)
474
//
475
LIB_EXPORT UINT16 CryptHmacStart(PHMAC_STATE state,    // IN/OUT: the state buffer
16,442✔
476
                                 TPM_ALG_ID  hashAlg,  // IN: the algorithm to use
477
                                 UINT16      keySize,  // IN: the size of the HMAC key
478
                                 const BYTE* key       // IN: the HMAC key
479
)
480
{
481
    PHASH_DEF hashDef;
16,442✔
482
    BYTE*     pb;
16,442✔
483
    UINT32    i;
16,442✔
484
    //
485
    hashDef = CryptGetHashDef(hashAlg);
16,442✔
486
    if(hashDef->digestSize != 0)
16,442✔
487
    {
488
        // If the HMAC key is larger than the hash block size, it has to be reduced
489
        // to fit. The reduction is a digest of the hashKey.
490
        if(keySize > hashDef->blockSize)
16,442✔
491
        {
492
            // if the key is too big, reduce it to a digest of itself
UNCOV
493
            state->hmacKey.t.size = CryptHashBlock(
×
UNCOV
494
                hashAlg, keySize, key, hashDef->digestSize, state->hmacKey.t.buffer);
×
495
        }
496
        else
497
        {
498
            memcpy(state->hmacKey.t.buffer, key, keySize);
16,442✔
499
            state->hmacKey.t.size = keySize;
16,442✔
500
        }
501
        // XOR the key with iPad (0x36)
502
        pb = state->hmacKey.t.buffer;
16,442✔
503
        for(i = state->hmacKey.t.size; i > 0; i--)
702,433✔
504
            *pb++ ^= 0x36;
685,991✔
505

506
        // if the keySize is smaller than a block, fill the rest with 0x36
507
        for(i = hashDef->blockSize - state->hmacKey.t.size; i > 0; i--)
568,019✔
508
            *pb++ = 0x36;
551,577✔
509

510
        // Increase the oPadSize to a full block
511
        state->hmacKey.t.size = hashDef->blockSize;
16,442✔
512

513
        // Start a new hash with the HMAC key
514
        // This will go in the caller's state structure and may be a sequence or not
515
        CryptHashStart((PHASH_STATE)state, hashAlg);
16,442✔
516
        CryptDigestUpdate(
16,442✔
517
            (PHASH_STATE)state, state->hmacKey.t.size, state->hmacKey.t.buffer);
16,442✔
518
        // XOR the key block with 0x5c ^ 0x36
519
        for(pb = state->hmacKey.t.buffer, i = hashDef->blockSize; i > 0; i--)
1,254,010✔
520
            *pb++ ^= (0x5c ^ 0x36);
1,237,568✔
521
    }
522
    // Set the hash algorithm
523
    state->hashState.hashAlg = hashAlg;
16,442✔
524
    // Set the hash state type
525
    state->hashState.type = HASH_STATE_HMAC;
16,442✔
526

527
    return hashDef->digestSize;
16,442✔
528
}
529

530
//*** CryptHmacEnd()
531
// This function is called to complete an HMAC. It will finish the current
532
// digest, and start a new digest. It will then add the oPadKey and the
533
// completed digest and return the results in dOut. It will not return more
534
// than dOutSize bytes.
535
//  Return Type: UINT16
536
//  >= 0        number of bytes in 'dOut' (may be zero)
537
LIB_EXPORT UINT16 CryptHmacEnd(PHMAC_STATE state,     // IN: the hash state buffer
16,443✔
538
                               UINT32      dOutSize,  // IN: size of digest buffer
539
                               BYTE*       dOut       // OUT: hash digest
540
)
541
{
542
    BYTE        temp[MAX_DIGEST_SIZE];
16,443✔
543
    PHASH_STATE hState = (PHASH_STATE)&state->hashState;
16,443✔
544

545
#if SMAC_IMPLEMENTED
546
    if(hState->type == HASH_STATE_SMAC)
16,443✔
UNCOV
547
        return (state->hashState.state.smac.smacMethods.end)(
×
UNCOV
548
            &state->hashState.state.smac.state, dOutSize, dOut);
×
549
#endif
550
    pAssert_ZERO(hState->type == HASH_STATE_HMAC);
16,443✔
551
    hState->def = CryptGetHashDef(hState->hashAlg);
16,443✔
552
    // Change the state type for completion processing
553
    hState->type = HASH_STATE_HASH;
16,443✔
554
    if(hState->hashAlg == TPM_ALG_NULL)
16,443✔
555
        dOutSize = 0;
556
    else
557
    {
558
        // Complete the current hash
559
        HashEnd(hState, hState->def->digestSize, temp);
16,443✔
560
        // Do another hash starting with the oPad
561
        CryptHashStart(hState, hState->hashAlg);
16,443✔
562
        CryptDigestUpdate(hState, state->hmacKey.t.size, state->hmacKey.t.buffer);
16,443✔
563
        CryptDigestUpdate(hState, hState->def->digestSize, temp);
16,443✔
564
    }
565
    return HashEnd(hState, dOutSize, dOut);
16,443✔
566
}
567

568
//*** CryptHmacStart2B()
569
// This function starts an HMAC and returns the size of the digest
570
// that will be produced.
571
//
572
// This function is provided to support the most common use of starting an HMAC
573
// with a TPM2B key.
574
//
575
// The caller must provide a block of memory in which the hash sequence state
576
// is kept.  The caller should not alter the contents of this buffer until the
577
// hash sequence is completed or abandoned.
578
//
579
//  Return Type: UINT16
580
//      > 0     the digest size of the algorithm
581
//      = 0     the hashAlg was TPM_ALG_NULL
582
LIB_EXPORT UINT16 CryptHmacStart2B(
4,343✔
583
    PHMAC_STATE hmacState,  // OUT: the state of HMAC stack. It will be used
584
                            //     in HMAC update and completion
585
    TPMI_ALG_HASH hashAlg,  // IN: hash algorithm
586
    P2B           key       // IN: HMAC key
587
)
588
{
589
    return CryptHmacStart(hmacState, hashAlg, key->size, key->buffer);
4,343✔
590
}
591

592
//*** CryptHmacEnd2B()
593
//   This function is the same as CryptHmacEnd() but the HMAC result
594
//   is returned in a TPM2B which is the most common use.
595
//  Return Type: UINT16
596
//      >=0     the number of bytes placed in 'digest'
597
LIB_EXPORT UINT16 CryptHmacEnd2B(
4,319✔
598
    PHMAC_STATE hmacState,  // IN: the state of HMAC stack
599
    P2B         digest      // OUT: HMAC
600
)
601
{
602
    return CryptHmacEnd(hmacState, digest->size, digest->buffer);
4,319✔
603
}
604

605
//** Mask and Key Generation Functions
606
//*** CryptMGF_KDF()
607
// This function performs MGF1/KDF1 or KDF2 using the selected hash. KDF1 and KDF2 are
608
// T('n') = T('n'-1) || H('seed' || 'counter') with the difference being that, with
609
// KDF1, 'counter' starts at 0 but with KDF2, 'counter' starts at 1. The caller
610
// determines which version by setting the initial value of counter to either 0 or 1.
611
// Note: Any value that is not 0 is considered to be 1.
612
//
613
// This function returns the length of the mask produced which
614
// could be zero if the digest algorithm is not supported
615
//  Return Type: UINT16
616
//      0       hash algorithm was TPM_ALG_NULL
617
//    > 0       should be the same as 'mSize'
618
LIB_EXPORT UINT16 CryptMGF_KDF(UINT32 mSize,  // IN: length of the mask to be produced
48✔
619
                               BYTE*  mask,   // OUT: buffer to receive the mask
620
                               TPM_ALG_ID hashAlg,   // IN: hash to use
621
                               UINT32     seedSize,  // IN: size of the seed
622
                               BYTE*      seed,      // IN: seed size
623
                               UINT32     counter    // IN: counter initial value
624
)
625
{
626
    HASH_STATE hashState;
48✔
627
    PHASH_DEF  hDef = CryptGetHashDef(hashAlg);
48✔
628
    UINT32     hLen;
48✔
629
    UINT32     bytes;
48✔
630
    //
631
    // If there is no digest to compute return
632
    if((hDef->digestSize == 0) || (mSize == 0))
48✔
633
        return 0;
634
    if(counter != 0)
48✔
635
        counter = 1;
48✔
636
    hLen = hDef->digestSize;
48✔
637
    for(bytes = 0; bytes < mSize; bytes += hLen)
96✔
638
    {
639
        // Start the hash and include the seed and counter
640
        CryptHashStart(&hashState, hashAlg);
48✔
641
        CryptDigestUpdate(&hashState, seedSize, seed);
48✔
642
        CryptDigestUpdateInt(&hashState, 4, counter);
48✔
643
        // Get as much as will fit.
644
        CryptHashEnd(&hashState, MIN((mSize - bytes), hLen), &mask[bytes]);
48✔
645
        counter++;
48✔
646
    }
647
    return (UINT16)mSize;
48✔
648
}
649

650
//*** CryptKDFa()
651
// This function performs the key generation according to Part 1 of the
652
// TPM specification.
653
//
654
// This function returns the number of bytes generated which may be zero.
655
//
656
// The 'key' and 'keyStream' pointers are not allowed to be NULL. The other
657
// pointer values may be NULL. The value of 'sizeInBits' must be no larger
658
// than (2^18)-1 = 256K bits (32385 bytes).
659
//
660
// The 'once' parameter is set to allow incremental generation of a large
661
// value. If this flag is TRUE, 'sizeInBits' will be used in the HMAC computation
662
// but only one iteration of the KDF is performed. This would be used for
663
// XOR obfuscation so that the mask value can be generated in digest-sized
664
// chunks rather than having to be generated all at once in an arbitrarily
665
// large buffer and then XORed into the result. If 'once' is TRUE, then
666
// 'sizeInBits' must be a multiple of 8.
667
//
668
// Any error in the processing of this command is considered fatal.
669
//  Return Type: UINT16
670
//     0            hash algorithm is not supported or is TPM_ALG_NULL
671
//    > 0           the number of bytes in the 'keyStream' buffer
672
LIB_EXPORT UINT16 CryptKDFa(
2,682✔
673
    TPM_ALG_ID   hashAlg,       // IN: hash algorithm used in HMAC
674
    const TPM2B* key,           // IN: HMAC key
675
    const TPM2B* label,         // IN: a label for the KDF
676
    const TPM2B* contextU,      // IN: context U
677
    const TPM2B* contextV,      // IN: context V
678
    UINT32       sizeInBits,    // IN: size of generated key in bits
679
    BYTE*        keyStream,     // OUT: key buffer
680
    UINT32*      counterInOut,  // IN/OUT: caller may provide the iteration
681
                                //     counter for incremental operations to
682
                                //     avoid large intermediate buffers.
683
    UINT16 blocks               // IN: If non-zero, this is the maximum number
684
                                //     of blocks to be returned, regardless
685
                                //     of sizeInBits
686
)
687
{
688
    UINT32     counter = 0;  // counter value
2,682✔
689
    INT16      bytes;        // number of bytes to produce
2,682✔
690
    UINT16     generated;    // number of bytes generated
2,682✔
691
    BYTE*      stream = keyStream;
2,682✔
692
    HMAC_STATE hState;
2,682✔
693
    UINT16     digestSize = CryptHashGetDigestSize(hashAlg);
2,682✔
694

695
    pAssert_ZERO(key != NULL && keyStream != NULL);
2,682✔
696

697
    TPM_DO_SELF_TEST(TPM_ALG_KDF1_SP800_108);
2,682✔
698

699
    if(digestSize == 0)
2,682✔
700
        return 0;
701

702
    if(counterInOut != NULL)
2,682✔
703
        counter = *counterInOut;
701✔
704

705
    // If the size of the request is larger than the numbers will handle,
706
    // it is a fatal error.
707
    pAssert_ZERO(((sizeInBits + 7) / 8) <= INT16_MAX);
2,682✔
708

709
    // The number of bytes to be generated is the smaller of the sizeInBits bytes or
710
    // the number of requested blocks. The number of blocks is the smaller of the
711
    // number requested or the number allowed by sizeInBits. A partial block is
712
    // a full block.
713
    bytes = (blocks > 0) ? blocks * digestSize : (UINT16)BITS_TO_BYTES(sizeInBits);
2,682✔
714
    generated = bytes;
2,682✔
715

716
    // Generate required bytes
717
    for(; bytes > 0; bytes -= digestSize)
5,364✔
718
    {
719
        counter++;
2,682✔
720
        // Start HMAC
721
        if(CryptHmacStart(&hState, hashAlg, key->size, key->buffer) == 0)
2,682✔
722
            return 0;
723
        // Adding counter
724
        CryptDigestUpdateInt(&hState.hashState, 4, counter);
2,682✔
725

726
        // Adding label
727
        if(label != NULL)
2,682✔
728
            HASH_DATA(&hState.hashState, label->size, (BYTE*)label->buffer);
2,682✔
729
        // Add a null. SP108 is not very clear about when the 0 is needed but to
730
        // make this like the previous version that did not add an 0x00 after
731
        // a null-terminated string, this version will only add a null byte
732
        // if the label parameter did not end in a null byte, or if no label
733
        // is present.
734
        if((label == NULL) || (label->size == 0)
2,682✔
735
           || (label->buffer[label->size - 1] != 0))
2,643✔
736
            CryptDigestUpdateInt(&hState.hashState, 1, 0);
39✔
737
        // Adding contextU
738
        if(contextU != NULL)
2,682✔
739
            HASH_DATA(&hState.hashState, contextU->size, contextU->buffer);
1,805✔
740
        // Adding contextV
741
        if(contextV != NULL)
2,682✔
742
            HASH_DATA(&hState.hashState, contextV->size, contextV->buffer);
932✔
743
        // Adding size in bits
744
        CryptDigestUpdateInt(&hState.hashState, 4, sizeInBits);
2,682✔
745

746
        // Complete and put the data in the buffer
747
        CryptHmacEnd(&hState, bytes, stream);
2,682✔
748
        stream = &stream[digestSize];
2,682✔
749
    }
750
    // Masking in the KDF is disabled. If the calling function wants something
751
    // less than even number of bytes, then the caller should do the masking
752
    // because there is no universal way to do it here
753
    if(counterInOut != NULL)
2,682✔
754
        *counterInOut = counter;
701✔
755
    return generated;
756
}
757

758
//*** CryptKDFe()
759
// This function implements KDFe() as defined in TPM specification part 1.
760
//
761
// This function returns the number of bytes generated which may be zero.
762
//
763
// The 'Z' and 'keyStream' pointers are not allowed to be NULL. The other
764
// pointer values may be NULL. The value of 'sizeInBits' must be no larger
765
// than (2^18)-1 = 256K bits (32385 bytes).
766
// Any error in the processing of this command is considered fatal.
767
//  Return Type: UINT16
768
//     0            hash algorithm is not supported or is TPM_ALG_NULL
769
//    > 0           the number of bytes in the 'keyStream' buffer
770
//
771
#if ! USE_OPENSSL_FUNCTIONS_SSKDF                // libtpms added
772
LIB_EXPORT UINT16 CryptKDFe(TPM_ALG_ID   hashAlg,  // IN: hash algorithm used in HMAC
773
                            TPM2B*       Z,        // IN: Z
774
                            const TPM2B* label,    // IN: a label value for the KDF
775
                            TPM2B*       partyUInfo,  // IN: PartyUInfo
776
                            TPM2B*       partyVInfo,  // IN: PartyVInfo
777
                            UINT32 sizeInBits,  // IN: size of generated key in bits
778
                            BYTE*  keyStream    // OUT: key buffer
779
)
780
{
781
    HASH_STATE hashState;
782
    PHASH_DEF  hashDef = CryptGetHashDef(hashAlg);
783

784
    UINT32     counter = 0;  // counter value
785
    UINT16     hLen;
786
    BYTE*      stream = keyStream;
787
    INT16      bytes;  // number of bytes to generate
788

789
    pAssert_ZERO(
790
        keyStream != NULL && Z != NULL && ((sizeInBits + 7) / 8) < INT16_MAX);
791
    //
792
    hLen  = hashDef->digestSize;
793
    bytes = (INT16)((sizeInBits + 7) / 8);
794
    if(hashAlg == TPM_ALG_NULL || bytes == 0)
795
        return 0;
796

797
    // Generate required bytes
798
    //The inner loop of that KDF uses:
799
    //  Hash[i] := H(counter | Z | OtherInfo) (5)
800
    // Where:
801
    //  Hash[i]         the hash generated on the i-th iteration of the loop.
802
    //  H()             an approved hash function
803
    //  counter         a 32-bit counter that is initialized to 1 and incremented
804
    //                  on each iteration
805
    //  Z               the X coordinate of the product of a public ECC key and a
806
    //                  different private ECC key.
807
    //  OtherInfo       a collection of qualifying data for the KDF defined below.
808
    //  In this specification, OtherInfo will be constructed by:
809
    //      OtherInfo := Use | PartyUInfo  | PartyVInfo
810
    for(; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen)
811
    {
812
        if(bytes < hLen)
813
            hLen = bytes;
814
        counter++;
815
        // Do the hash
816
        CryptHashStart(&hashState, hashAlg);
817
        // Add counter
818
        CryptDigestUpdateInt(&hashState, 4, counter);
819

820
        // Add Z
821
        if(Z != NULL)
822
            CryptDigestUpdate2B(&hashState, Z);
823
        // Add label
824
        if(label != NULL)
825
            CryptDigestUpdate2B(&hashState, label);
826

827
        // NIST.SP.800-56Cr2.pdf section 4.1 states that no NULL
828
        // character is required here.
829
        // Note, this is different from KDFa which is specified in
830
        // NIST.SP.800-108r1.pdf section 4 (a NULL character is required
831
        // for that case).
832

833
        // Add PartyUInfo
834
        if(partyUInfo != NULL)
835
            CryptDigestUpdate2B(&hashState, partyUInfo);
836

837
        // Add PartyVInfo
838
        if(partyVInfo != NULL)
839
            CryptDigestUpdate2B(&hashState, partyVInfo);
840

841
        // Compute Hash. hLen was changed to be the smaller of bytes or hLen
842
        // at the start of each iteration.
843
        CryptHashEnd(&hashState, hLen, stream);
844
    }
845

846
    // Mask off bits if the required bits is not a multiple of byte size
847
    if((sizeInBits % 8) != 0)
848
        keyStream[0] &= ((1 << (sizeInBits % 8)) - 1);
849

850
    return (UINT16)((sizeInBits + 7) / 8);
851
}
852

853
#else // USE_OPENSSL_FUNCTIONS_SSKDF
854
LIB_EXPORT UINT16 CryptKDFe(TPM_ALG_ID   hashAlg,  // IN: hash algorithm used in HMAC
50✔
855
                            TPM2B*       Z,        // IN: Z
856
                            const TPM2B* label,    // IN: a label value for the KDF
857
                            TPM2B*       partyUInfo,  // IN: PartyUInfo
858
                            TPM2B*       partyVInfo,  // IN: PartyVInfo
859
                            UINT32       sizeInBits,  // IN: size of generated key in bits
860
                            BYTE*        keyStream    // OUT: key buffer
861
                            )
862
{
863
    return OSSLCryptKDFe(hashAlg, Z, label, partyUInfo, partyVInfo,
50✔
864
                         sizeInBits, keyStream);
865
}
866
#endif //  USE_OPENSSL_FUNCTIONS_SSKDF
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