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

stefanberger / libtpms / 2698

pending completion
2698

Pull #353

travis-ci-com

web-flow
Merge a8cae3f5d into d08b929de
Pull Request #353: Travis: Update from bionic to focal and from xenial to bionic

33875 of 43923 relevant lines covered (77.12%)

93992.6 hits per line

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

88.27
/src/tpm2/crypto/openssl/CryptHash.c
1
/********************************************************************************/
2
/*                                                                                */
3
/*                Implementation of cryptographic functions for hashing.                */
4
/*                             Written by Ken Goldman                                */
5
/*                       IBM Thomas J. Watson Research Center                        */
6
/*            $Id: CryptHash.c 1658 2021-01-22 23:14:01Z 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
/* 10.2.13        CryptHash.c */
63
/* 10.2.13.1        Description */
64
/* This file contains implementation of cryptographic functions for hashing. */
65
/* 10.2.13.2        Includes, Defines, and Types */
66
#define _CRYPT_HASH_C_
67
#include "Tpm.h"
68
#include "CryptHash_fp.h"
69
#include "CryptHash.h"
70
#include "OIDs.h"
71

72
/* Instance each of the hash descriptors based on the implemented algorithms */
73

74
FOR_EACH_HASH(HASH_DEF_TEMPLATE)
75

76
/* Instance a null def. */
77

78
    HASH_DEF NULL_Def = {{0}};
79

80
/* Create a table of pointers to the defined hash definitions */
81

82
#define HASH_DEF_ENTRY(HASH, Hash)     &Hash##_Def,
83
PHASH_DEF       HashDefArray[] = {
84
                                  // for each implemented HASH, expands to: &HASH_Def,
85
                                  FOR_EACH_HASH(HASH_DEF_ENTRY)
86
                                  &NULL_Def
87
};
88

89
/* 10.2.13.3        Obligatory Initialization Functions */
90
/* 10.2.13.3.1        CryptHashInit() */
91
/* This function is called by _TPM_Init() do perform the initialization operations for the
92
   library. */
93
BOOL
94
CryptHashInit(
12,213✔
95
              void
96
              )
97
{
98
    LibHashInit();
12,213✔
99
    return TRUE;
12,213✔
100
}
101
/* 10.2.13.3.2        CryptHashStartup() */
102
/* This function is called by TPM2_Startup().  It checks that the size of the HashDefArray() is
103
   consistent with the HASH_COUNT. */
104
BOOL
105
CryptHashStartup(
8,172✔
106
                 void
107
                 )
108
{
109
    int         i = sizeof(HashDefArray) / sizeof(PHASH_DEF) - 1;
8,172✔
110
    return (i == HASH_COUNT);
8,172✔
111
}
112
/* 10.2.13.4        Hash Information Access Functions */
113
/* 10.2.13.4.1        Introduction */
114
/* These functions provide access to the hash algorithm description information. */
115
/* 10.2.13.4.2        CryptGetHashDef() */
116
/* This function accesses the hash descriptor associated with a hash a algorithm. The function
117
   returns a pointer to a null descriptor if hashAlg is TPM_ALG_NULL or not a defined algorithm. */
118

119
PHASH_DEF
120
CryptGetHashDef(
581,404✔
121
                TPM_ALG_ID       hashAlg
122
                )
123
{
124
#define GET_DEF(HASH, Hash) case ALG_##HASH##_VALUE: return &Hash##_Def;
125
    switch(hashAlg)
581,404✔
126
        {
127
            FOR_EACH_HASH(GET_DEF)
386,319✔
128
          default:
158✔
129
            return &NULL_Def;
158✔
130
        }
131
#undef GET_DEF
132
}
133
/* 10.2.13.4.3        CryptHashIsValidAlg() */
134
/* This function tests to see if an algorithm ID is a valid hash algorithm. If flag is true, then
135
   TPM_ALG_NULL is a valid hash. */
136
/*     Return Value        Meaning */
137
/*     TRUE(1)        hashAlg is a valid, implemented hash on this TPM */
138
/*     FALSE(0)        hashAlg is not valid for this TPM */
139
BOOL
140
CryptHashIsValidAlg(
172✔
141
                    TPM_ALG_ID       hashAlg,           // IN: the algorithm to check
142
                    BOOL             flag               // IN: TRUE if TPM_ALG_NULL is to be treated
143
                    //     as a valid hash
144
                    )
145
{
146
    if(hashAlg == TPM_ALG_NULL)
172✔
147
        return flag;
148
    return CryptGetHashDef(hashAlg) != &NULL_Def;
172✔
149
}
150
/* 10.2.13.4.4 CryptHashGetAlgByIndex() */
151
/* This function is used to iterate through the hashes. TPM_ALG_NULL is returned for all indexes
152
   that are not valid hashes. If the TPM implements 3 hashes, then an index value of 0 will return
153
   the first implemented hash and an index of 2 will return the last. All other index values will
154
   return TPM_ALG_NULL. */
155
/*     Return Value        Meaning */
156
/*     TPM_ALG_xxx        a hash algorithm */
157
/*     TPM_ALG_NULL        this can be used as a stop value */
158
LIB_EXPORT TPM_ALG_ID
159
CryptHashGetAlgByIndex(
17,118✔
160
                       UINT32           index          // IN: the index
161
                       )
162
{
163
    TPM_ALG_ID       hashAlg;
17,118✔
164
    if(index >= HASH_COUNT)
17,118✔
165
        hashAlg = TPM_ALG_NULL;
166
    else
167
        hashAlg = HashDefArray[index]->hashAlg;
17,068✔
168
    return hashAlg;
17,118✔
169
}
170
/* 10.2.13.4.5        CryptHashGetDigestSize() */
171
/* Returns the size of the digest produced by the hash. If hashAlg is not a hash algorithm, the TPM
172
   will FAIL. */
173
/*     Return Value        Meaning */
174
/*     0        TPM_ALG_NULL */
175
/*     > 0        the digest size */
176
LIB_EXPORT UINT16
177
CryptHashGetDigestSize(
433,651✔
178
                       TPM_ALG_ID       hashAlg        // IN: hash algorithm to look up
179
                       )
180
{
181
    return CryptGetHashDef(hashAlg)->digestSize;
433,651✔
182
}
183
/* 10.2.13.4.6        CryptHashGetBlockSize() */
184
/* Returns the size of the block used by the hash. If hashAlg is not a hash algorithm, the TPM will
185
   FAIL. */
186
/*     Return Value        Meaning */
187
/*     0        TPM_ALG_NULL */
188
/*     > 0        the digest size */
189
LIB_EXPORT UINT16
190
CryptHashGetBlockSize(
9,357✔
191
                      TPM_ALG_ID       hashAlg        // IN: hash algorithm to look up
192
                      )
193
{
194
    return CryptGetHashDef(hashAlg)->blockSize;
9,357✔
195
}
196
/* 10.2.13.4.7        CryptHashGetOid() */
197
/* This function returns a pointer to DER=encoded OID for a hash algorithm. All OIDs are full OID
198
   values including the Tag (0x06) and length byte. */
199
#if 0                // libtpms added
200
LIB_EXPORT const BYTE *
201
CryptHashGetOid(
202
                TPM_ALG_ID      hashAlg
203
                )
204
{
205
    return CryptGetHashDef(hashAlg)->OID;
206
}
207
#endif                // libtpms added
208
/* 10.2.13.4.8        CryptHashGetContextAlg() */
209
/* This function returns the hash algorithm associated with a hash context. */
210
#if 0                // libtpms added
211
TPM_ALG_ID
212
CryptHashGetContextAlg(
213
                       PHASH_STATE      state          // IN: the context to check
214
                       )
215
{
216
    return state->hashAlg;
217
}
218
#endif                // libtpms added
219
/* 10.2.13.5        State Import and Export */
220
/* 10.2.13.5.1        CryptHashCopyState */
221
/* This function is used to clone a HASH_STATE. */
222
#if 0 // libtpms added
223
LIB_EXPORT void
224
CryptHashCopyState(
225
                   HASH_STATE          *out,           // OUT: destination of the state
226
                   const HASH_STATE    *in             // IN: source of the state
227
                   )
228
{
229
    pAssert(out->type == in->type);
230
    out->hashAlg = in->hashAlg;
231
    out->def = in->def;
232
    if(in->hashAlg != TPM_ALG_NULL)
233
        {
234
            HASH_STATE_COPY(out, in);
235
        }
236
    if(in->type == HASH_STATE_HMAC)
237
        {
238
            const HMAC_STATE    *hIn = (HMAC_STATE *)in;
239
            HMAC_STATE          *hOut = (HMAC_STATE *)out;
240
            hOut->hmacKey = hIn->hmacKey;
241
        }
242
    return;
243
}
244
#endif // libtpms added
245
#if 0  // libtpms added
246
/* 10.2.13.5.2        CryptHashExportState() */
247
/* This function is used to export a hash or HMAC hash state. This function would be called when
248
   preparing to context save a sequence object. */
249
void
250
CryptHashExportState(
251
                     PCHASH_STATE         internalFmt,   // IN: the hash state formatted for use by
252
                     //     library
253
                     PEXPORT_HASH_STATE   externalFmt    // OUT: the exported hash state
254
                     )
255
{
256
    BYTE                    *outBuf = (BYTE *)externalFmt;
257
    //
258
    cAssert(sizeof(HASH_STATE) <= sizeof(EXPORT_HASH_STATE));
259
    // the following #define is used to move data from an aligned internal data
260
    // structure to a byte buffer (external format data.
261
#define CopyToOffset(value)                                                \
262
    memcpy(&outBuf[offsetof(HASH_STATE,value)], &internalFmt->value,        \
263
           sizeof(internalFmt->value))
264
    // Copy the hashAlg
265
    CopyToOffset(hashAlg);
266
    CopyToOffset(type);
267
#ifdef HASH_STATE_SMAC
268
    if(internalFmt->type == HASH_STATE_SMAC)
269
        {
270
            memcpy(outBuf, internalFmt, sizeof(HASH_STATE));
271
            return;
272
            
273
        }
274
#endif
275
    if(internalFmt->type == HASH_STATE_HMAC)
276
        {
277
            HMAC_STATE              *from = (HMAC_STATE *)internalFmt;
278
            memcpy(&outBuf[offsetof(HMAC_STATE, hmacKey)], &from->hmacKey,
279
                   sizeof(from->hmacKey));
280
        }
281
    if(internalFmt->hashAlg != TPM_ALG_NULL)
282
        HASH_STATE_EXPORT(externalFmt, internalFmt);
283
}
284
/* 10.2.13.5.3        CryptHashImportState() */
285
/* This function is used to import the hash state. This function would be called to import a hash
286
   state when the context of a sequence object was being loaded. */
287
void
288
CryptHashImportState(
289
                     PHASH_STATE          internalFmt,   // OUT: the hash state formatted for use by
290
                     //     the library
291
                     PCEXPORT_HASH_STATE  externalFmt    // IN: the exported hash state
292
                     )
293
{
294
    BYTE                    *inBuf = (BYTE *)externalFmt;
295
    //
296
#define CopyFromOffset(value)                                                \
297
    memcpy(&internalFmt->value, &inBuf[offsetof(HASH_STATE,value)],        \
298
           sizeof(internalFmt->value))
299
    
300
    // Copy the hashAlg of the byte-aligned input structure to the structure-aligned
301
    // internal structure.
302
    CopyFromOffset(hashAlg);
303
    CopyFromOffset(type);
304
    if(internalFmt->hashAlg != TPM_ALG_NULL)
305
        {
306
#ifdef HASH_STATE_SMAC
307
            if(internalFmt->type == HASH_STATE_SMAC)
308
                {
309
                    memcpy(internalFmt, inBuf, sizeof(HASH_STATE));
310
                    return;
311
                }
312
#endif
313
            internalFmt->def = CryptGetHashDef(internalFmt->hashAlg);
314
            HASH_STATE_IMPORT(internalFmt, inBuf);
315
            if(internalFmt->type == HASH_STATE_HMAC)
316
                {
317
                    HMAC_STATE              *to = (HMAC_STATE *)internalFmt;
318
                    memcpy(&to->hmacKey, &inBuf[offsetof(HMAC_STATE, hmacKey)],
319
                           sizeof(to->hmacKey));
320
                }
321
        }
322
}
323
#endif  // libtpms added
324
/* 10.2.13.6        State Modification Functions */
325
/* 10.2.13.6.1        HashEnd() */
326
/* Local function to complete a hash that uses the hashDef instead of an algorithm ID. This function
327
   is used to complete the hash and only return a partial digest. The return value is the size of
328
   the data copied. */
329
static UINT16
330
HashEnd(
52,884✔
331
        PHASH_STATE      hashState,     // IN: the hash state
332
        UINT32           dOutSize,      // IN: the size of receive buffer
333
        PBYTE            dOut           // OUT: the receive buffer
334
        )
335
{
336
    BYTE                temp[MAX_DIGEST_SIZE];
52,884✔
337
    if((hashState->hashAlg == TPM_ALG_NULL)
52,884✔
338
       || (hashState->type != HASH_STATE_HASH))
52,884✔
339
        dOutSize = 0;
340
    if(dOutSize > 0)
52,884✔
341
        {
342
            hashState->def = CryptGetHashDef(hashState->hashAlg);
52,884✔
343
            // Set the final size
344
            dOutSize = MIN(dOutSize, hashState->def->digestSize);
52,884✔
345
            // Complete into the temp buffer and then copy
346
            HASH_END(hashState, temp);
52,884✔
347
            // Don't want any other functions calling the HASH_END method
348
            // directly.
349
#undef HASH_END
350
            memcpy(dOut, &temp, dOutSize);
52,884✔
351
        }
352
    hashState->type = HASH_STATE_EMPTY;
52,884✔
353
    return (UINT16)dOutSize;
52,884✔
354
}
355
/* 10.2.13.6.2        CryptHashStart() */
356
/* Functions starts a hash stack Start a hash stack and returns the digest size. As a side effect,
357
   the value of stateSize in hashState is updated to indicate the number of bytes of state that were
358
   saved. This function calls GetHashServer() and that function will put the TPM into failure mode
359
   if the hash algorithm is not supported. */
360
/* This function does not use the sequence parameter. If it is necessary to import or export
361
   context, this will start the sequence in a local state and export the state to the input
362
   buffer. Will need to add a flag to the state structure to indicate that it needs to be imported
363
   before it can be used. (BLEH). */
364
/*     Return Value        Meaning */
365
/*     0        hash is TPM_ALG_NULL */
366
/*     >0        digest size */
367
LIB_EXPORT UINT16
368
CryptHashStart(
52,904✔
369
               PHASH_STATE      hashState,     // OUT: the running hash state
370
               TPM_ALG_ID       hashAlg        // IN: hash algorithm
371
               )
372
{
373
    UINT16               retVal;
52,904✔
374
        
375
    TEST(hashAlg);
52,904✔
376
        
377
    hashState->hashAlg = hashAlg;
52,904✔
378
    if(hashAlg == TPM_ALG_NULL)
52,904✔
379
        {
380
            retVal = 0;
381
        }
382
    else
383
        {
384
            hashState->def = CryptGetHashDef(hashAlg);
52,904✔
385
            HASH_START(hashState);
52,904✔
386
            retVal = hashState->def->digestSize;
52,904✔
387
        }
388
#undef HASH_START
389
    hashState->type = HASH_STATE_HASH;
52,904✔
390
    return retVal;
52,904✔
391
}
392
/* 10.2.13.6.3        CryptDigestUpdate() */
393
/* Add data to a hash or HMAC, SMAC stack. */
394
void
395
CryptDigestUpdate(
107,997✔
396
                  PHASH_STATE      hashState,     // IN: the hash context information
397
                  UINT32           dataSize,      // IN: the size of data to be added
398
                  const BYTE      *data           // IN: data to be hashed
399
                  )
400
{
401
    if(hashState->hashAlg != TPM_ALG_NULL)
107,997✔
402
        {
403
            if((hashState->type == HASH_STATE_HASH)
107,997✔
404
               || (hashState->type == HASH_STATE_HMAC))
107,997✔
405
                HASH_DATA(hashState, dataSize, (BYTE *)data);
107,913✔
406
#if SMAC_IMPLEMENTED
407
            else if(hashState->type == HASH_STATE_SMAC)
84✔
408
                (hashState->state.smac.smacMethods.data)(&hashState->state.smac.state,
84✔
409
                                                         dataSize, data);
410
#endif // SMAC_IMPLEMENTED
411
            else
412
                FAIL(FATAL_ERROR_INTERNAL);
×
413
        }
414
    return;
107,997✔
415
}
416
/* 10.2.13.6.4 CryptHashEnd() */
417
/* Complete a hash or HMAC computation. This function will place the smaller of digestSize or the
418
   size of the digest in dOut. The number of bytes in the placed in the buffer is returned. If there
419
   is a failure, the returned value is <= 0. */
420
/*     Return Value        Meaning */
421
/*     0        no data returned */
422
/*     > 0        the number of bytes in the digest or dOutSize, whichever is smaller */
423
LIB_EXPORT UINT16
424
CryptHashEnd(
5,834✔
425
             PHASH_STATE      hashState,     // IN: the state of hash stack
426
             UINT32           dOutSize,      // IN: size of digest buffer
427
             BYTE            *dOut           // OUT: hash digest
428
             )
429
{
430
    pAssert(hashState->type == HASH_STATE_HASH);
5,834✔
431
    return HashEnd(hashState, dOutSize, dOut);
5,834✔
432
}
433
/* 10.2.13.6.5        CryptHashBlock() */
434
/* Start a hash, hash a single block, update digest and return the size of the results. */
435
/*     The digestSize parameter can be smaller than the digest. If so, only the more significant
436
       bytes are returned. */
437
/*     Return Value        Meaning */
438
/*     >= 0        number of bytes placed in dOut */
439
LIB_EXPORT UINT16
440
CryptHashBlock(
14,882✔
441
               TPM_ALG_ID       hashAlg,       // IN: The hash algorithm
442
               UINT32           dataSize,      // IN: size of buffer to hash
443
               const BYTE      *data,          // IN: the buffer to hash
444
               UINT32           dOutSize,      // IN: size of the digest buffer
445
               BYTE            *dOut           // OUT: digest buffer
446
               )
447
{
448
    HASH_STATE          state;
14,882✔
449
    CryptHashStart(&state, hashAlg);
14,882✔
450
    CryptDigestUpdate(&state, dataSize, data);
14,882✔
451
    return HashEnd(&state, dOutSize, dOut);
14,882✔
452
}
453
/* 10.2.13.6.6        CryptDigestUpdate2B() */
454
/* This function updates a digest (hash or HMAC) with a TPM2B. */
455
/* This function can be used for both HMAC and hash functions so the digestState is void so that
456
   either state type can be passed. */
457
LIB_EXPORT void
458
CryptDigestUpdate2B(
13,573✔
459
                    PHASH_STATE      state,         // IN: the digest state
460
                    const TPM2B     *bIn            // IN: 2B containing the data
461
                    )
462
{
463
    // Only compute the digest if a pointer to the 2B is provided.
464
    // In CryptDigestUpdate(), if size is zero or buffer is NULL, then no change
465
    // to the digest occurs. This function should not provide a buffer if bIn is
466
    // not provided.
467
    pAssert(bIn != NULL);
13,573✔
468
    CryptDigestUpdate(state, bIn->size, bIn->buffer);
13,573✔
469
    return;
13,573✔
470
}
471
/* 10.2.13.6.7        CryptHashEnd2B() */
472
/* This function is the same as CryptCompleteHash() but the digest is placed in a TPM2B. This is the
473
   most common use and this is provided for specification clarity. digest.size should be set to
474
   indicate the number of bytes to place in the buffer */
475
/* Return Value        Meaning */
476
/* >=0        the number of bytes placed in digest.buffer */
477
LIB_EXPORT UINT16
478
CryptHashEnd2B(
3,874✔
479
               PHASH_STATE      state,         // IN: the hash state
480
               P2B              digest         // IN: the size of the buffer Out: requested
481
               //     number of bytes
482
               )
483
{
484
    return CryptHashEnd(state, digest->size, digest->buffer);
3,874✔
485
}
486
/* 10.2.13.6.8        CryptDigestUpdateInt() */
487
/* This function is used to include an integer value to a hash stack. The function marshals the
488
   integer into its canonical form before calling CryptDigestUpdate(). */
489
LIB_EXPORT void
490
CryptDigestUpdateInt(
9,369✔
491
                     void            *state,         // IN: the state of hash stack
492
                     UINT32           intSize,       // IN: the size of 'intValue' in bytes
493
                     UINT64           intValue       // IN: integer value to be hashed
494
                     )
495
{
496
#if LITTLE_ENDIAN_TPM
497
    intValue = REVERSE_ENDIAN_64(intValue);
9,369✔
498
#endif
499
    CryptDigestUpdate(state, intSize, &((BYTE *)&intValue)[8 - intSize]);
9,369✔
500
}
9,369✔
501
/* 10.2.13.7        HMAC Functions */
502
/* 10.2.13.7.1        CryptHmacStart() */
503
/* This function is used to start an HMAC using a temp hash context. The function does the
504
   initialization of the hash with the HMAC key XOR iPad and updates the HMAC key XOR oPad. */
505
/* The function returns the number of bytes in a digest produced by hashAlg. */
506
/* Return Value        Meaning */
507
/* >= 0        number of bytes in digest produced by hashAlg (may be zero) */
508
LIB_EXPORT UINT16
509
CryptHmacStart(
16,083✔
510
               PHMAC_STATE      state,         // IN/OUT: the state buffer
511
               TPM_ALG_ID       hashAlg,       // IN: the algorithm to use
512
               UINT16           keySize,       // IN: the size of the HMAC key
513
               const BYTE      *key            // IN: the HMAC key
514
               )
515
{
516
    PHASH_DEF                hashDef;
16,083✔
517
    BYTE *                   pb;
16,083✔
518
    UINT32                   i;
16,083✔
519
    //
520
    hashDef = CryptGetHashDef(hashAlg);
16,083✔
521
    if(hashDef->digestSize != 0)
16,083✔
522
        {
523
            // If the HMAC key is larger than the hash block size, it has to be reduced
524
            // to fit. The reduction is a digest of the hashKey.
525
            if(keySize > hashDef->blockSize)
16,083✔
526
                {
527
                    // if the key is too big, reduce it to a digest of itself
528
                    state->hmacKey.t.size = CryptHashBlock(hashAlg, keySize, key,
×
529
                                                           hashDef->digestSize,
530
                                                           state->hmacKey.t.buffer);
×
531
                }
532
            else
533
                {
534
                    memcpy(state->hmacKey.t.buffer, key, keySize);
16,083✔
535
                    state->hmacKey.t.size = keySize;
16,083✔
536
                }
537
            // XOR the key with iPad (0x36)
538
            pb = state->hmacKey.t.buffer;
16,083✔
539
            for(i = state->hmacKey.t.size; i > 0; i--)
691,881✔
540
                *pb++ ^= 0x36;
675,798✔
541
            
542
            // if the keySize is smaller than a block, fill the rest with 0x36
543
            for(i = hashDef->blockSize - state->hmacKey.t.size; i > 0; i--)
550,205✔
544
                *pb++ = 0x36;
534,122✔
545
            
546
            // Increase the oPadSize to a full block
547
            state->hmacKey.t.size = hashDef->blockSize;
16,083✔
548
            
549
            // Start a new hash with the HMAC key
550
            // This will go in the caller's state structure and may be a sequence or not
551
            CryptHashStart((PHASH_STATE)state, hashAlg);
16,083✔
552
            CryptDigestUpdate((PHASH_STATE)state, state->hmacKey.t.size,
16,083✔
553
                              state->hmacKey.t.buffer);
554
            // XOR the key block with 0x5c ^ 0x36
555
            for(pb = state->hmacKey.t.buffer, i = hashDef->blockSize; i > 0; i--)
1,226,003✔
556
                *pb++ ^= (0x5c ^ 0x36);
1,209,920✔
557
        }
558
    // Set the hash algorithm
559
    state->hashState.hashAlg = hashAlg;
16,083✔
560
    // Set the hash state type
561
    state->hashState.type = HASH_STATE_HMAC;
16,083✔
562
    
563
    return hashDef->digestSize;
16,083✔
564
}
565
/* 10.2.13.7.2        CryptHmacEnd() */
566
/* This function is called to complete an HMAC. It will finish the current digest, and start a new digest. It will then add the oPadKey and the completed digest and return the results in dOut. It will not return more than dOutSize bytes. */
567
/*     Return Value        Meaning */
568
/*     >= 0        number of bytes in dOut (may be zero) */
569
LIB_EXPORT UINT16
570
CryptHmacEnd(
16,084✔
571
             PHMAC_STATE      state,         // IN: the hash state buffer
572
             UINT32           dOutSize,      // IN: size of digest buffer
573
             BYTE            *dOut           // OUT: hash digest
574
             )
575
{
576
    BYTE                 temp[MAX_DIGEST_SIZE];
16,084✔
577
    PHASH_STATE          hState = (PHASH_STATE)&state->hashState;
16,084✔
578
    
579
#if SMAC_IMPLEMENTED
580
    if(hState->type == HASH_STATE_SMAC)
16,084✔
581
        return (state->hashState.state.smac.smacMethods.end)
×
582
            (&state->hashState.state.smac.state,
×
583
             dOutSize,
584
             dOut);
585
#endif
586
    pAssert(hState->type == HASH_STATE_HMAC);
16,084✔
587
    hState->def = CryptGetHashDef(hState->hashAlg);
16,084✔
588
    // Change the state type for completion processing
589
    hState->type = HASH_STATE_HASH;
16,084✔
590
    if(hState->hashAlg == TPM_ALG_NULL)
16,084✔
591
        dOutSize = 0;
592
    else
593
        {
594
            
595
            // Complete the current hash
596
            HashEnd(hState, hState->def->digestSize, temp);
16,084✔
597
            // Do another hash starting with the oPad
598
            CryptHashStart(hState, hState->hashAlg);
16,084✔
599
            CryptDigestUpdate(hState, state->hmacKey.t.size, state->hmacKey.t.buffer);
16,084✔
600
            CryptDigestUpdate(hState, hState->def->digestSize, temp);
16,084✔
601
        }
602
    return HashEnd(hState, dOutSize, dOut);
16,084✔
603
}
604
/* 10.2.13.7.3        CryptHmacStart2B() */
605
/* This function starts an HMAC and returns the size of the digest that will be produced. */
606
/* This function is provided to support the most common use of starting an HMAC with a TPM2B key. */
607
/* The caller must provide a block of memory in which the hash sequence state is kept. The caller
608
   should not alter the contents of this buffer until the hash sequence is completed or
609
   abandoned. */
610
/* Return Value        Meaning */
611
/* > 0        the digest size of the algorithm */
612
/* = 0        the hashAlg was TPM_ALG_NULL */
613
LIB_EXPORT UINT16
614
CryptHmacStart2B(
4,102✔
615
                 PHMAC_STATE      hmacState,     // OUT: the state of HMAC stack. It will be used
616
                 //     in HMAC update and completion
617
                 TPMI_ALG_HASH    hashAlg,       // IN: hash algorithm
618
                 P2B              key            // IN: HMAC key
619
                 )
620
{
621
    return CryptHmacStart(hmacState, hashAlg, key->size, key->buffer);
4,102✔
622
}
623
    /* 10.2.13.7.4        CryptHmacEnd2B() */
624
    /* This function is the same as CryptHmacEnd() but the HMAC result is returned in a TPM2B which is the most common use. */
625
    /* Return Value        Meaning */
626
    /* >=0        the number of bytes placed in digest */
627
LIB_EXPORT UINT16
628
CryptHmacEnd2B(
4,078✔
629
               PHMAC_STATE      hmacState,     // IN: the state of HMAC stack
630
               P2B              digest         // OUT: HMAC
631
               )
632
{
633
    return CryptHmacEnd(hmacState, digest->size, digest->buffer);
4,078✔
634
}
635
/* 10.2.13.8        Mask and Key Generation Functions */
636
/* 10.2.13.8.1        CryptMGF_KDF() */
637
/* This function performs MGF1/KDF1 or KDF2 using the selected hash. KDF1 and KDF2 are T(n) = T(n-1)
638
   || H(seed || counter) with the difference being that, with KDF1, counter starts at 0 but with
639
   KDF2, counter starts at 1. The caller determines which version by setting the initial value of
640
   counter to either 0 or 1. */
641
/*         Return Value        Meaning */
642
/*         0        hash algorithm was TPM_ALG_NULL */
643
/*         > 0        should be the same as mSize */
644
LIB_EXPORT UINT16
645
CryptMGF_KDF(
×
646
          UINT32           mSize,         // IN: length of the mask to be produced
647
          BYTE            *mask,          // OUT: buffer to receive the mask
648
          TPM_ALG_ID       hashAlg,       // IN: hash to use
649
          UINT32           seedSize,      // IN: size of the seed
650
          BYTE            *seed,          // IN: seed size
651
          UINT32           counter        // IN: counter initial value
652
          )
653
{
654
    HASH_STATE           hashState;
×
655
    PHASH_DEF            hDef = CryptGetHashDef(hashAlg);
×
656
    UINT32               hLen;
×
657
    UINT32               bytes;
×
658
    //
659
    // If there is no digest to compute return
660
    if((hDef->digestSize == 0) || (mSize == 0))
×
661
        return 0;
662
    if(counter != 0)
×
663
        counter = 1;
664
    hLen = hDef->digestSize;
×
665
    for(bytes = 0; bytes < mSize; bytes += hLen)
×
666
        {
667
            // Start the hash and include the seed and counter
668
            CryptHashStart(&hashState, hashAlg);
×
669
            CryptDigestUpdate(&hashState, seedSize, seed);
×
670
            CryptDigestUpdateInt(&hashState, 4, counter);
×
671
            // Get as much as will fit.
672
            CryptHashEnd(&hashState, MIN((mSize - bytes), hLen),
×
673
                         &mask[bytes]);
674
            counter++;
×
675
        }
676
    return (UINT16)mSize;
×
677
}
678
/* 10.2.13.8.2        CryptKDFa() */
679
/* This function performs the key generation according to Part 1 of the TPM specification. */
680
/* This function returns the number of bytes generated which may be zero. */
681
/* The key and keyStream pointers are not allowed to be NULL. The other pointer values may be
682
   NULL. The value of sizeInBits must be no larger than (2^18)-1 = 256K bits (32385 bytes). */
683
/*     The once parameter is set to allow incremental generation of a large value. If this flag is
684
       TRUE, sizeInBits will be used in the HMAC computation but only one iteration of the KDF is
685
       performed. This would be used for XOR obfuscation so that the mask value can be generated in
686
       digest-sized chunks rather than having to be generated all at once in an arbitrarily large
687
       buffer and then XORed into the result. If once is TRUE, then sizeInBits must be a multiple of
688
       8. */
689
/*     Any error in the processing of this command is considered fatal. */
690
/*     Return Value        Meaning */
691
/*     0        hash algorithm is not supported or is TPM_ALG_NULL */
692
/*     > 0        the number of bytes in the keyStream buffer */
693
LIB_EXPORT UINT16
694
CryptKDFa(
2,596✔
695
          TPM_ALG_ID       hashAlg,       // IN: hash algorithm used in HMAC
696
          const TPM2B     *key,           // IN: HMAC key
697
          const TPM2B     *label,         // IN: a label for the KDF
698
          const TPM2B     *contextU,      // IN: context U
699
          const TPM2B     *contextV,      // IN: context V
700
          UINT32           sizeInBits,    // IN: size of generated key in bits
701
          BYTE            *keyStream,     // OUT: key buffer
702
          UINT32          *counterInOut,  // IN/OUT: caller may provide the iteration
703
          //     counter for incremental operations to
704
          //     avoid large intermediate buffers.
705
          UINT16           blocks         // IN: If non-zero, this is the maximum number
706
          //     of blocks to be returned, regardless
707
          //     of sizeInBits
708
          )
709
{
710
    UINT32                   counter = 0;       // counter value
2,596✔
711
    INT16                    bytes;             // number of bytes to produce
2,596✔
712
    UINT16                   generated;         // number of bytes generated
2,596✔
713
    BYTE                    *stream = keyStream;
2,596✔
714
    HMAC_STATE               hState;
2,596✔
715
    UINT16                   digestSize = CryptHashGetDigestSize(hashAlg);
2,596✔
716
    
717
    pAssert(key != NULL && keyStream != NULL);
2,596✔
718
    
719
    TEST(TPM_ALG_KDF1_SP800_108);
2,596✔
720
    
721
    if(digestSize == 0)
2,596✔
722
        return 0;
723
    
724
    if(counterInOut != NULL)
2,596✔
725
        counter = *counterInOut;
669✔
726
    
727
    // If the size of the request is larger than the numbers will handle,
728
    // it is a fatal error.
729
    pAssert(((sizeInBits + 7) / 8) <= INT16_MAX);
2,596✔
730
    
731
    // The number of bytes to be generated is the smaller of the sizeInBits bytes or
732
    // the number of requested blocks. The number of blocks is the smaller of the
733
    // number requested or the number allowed by sizeInBits. A partial block is
734
    // a full block.
735
    bytes = (blocks > 0) ? blocks * digestSize : (UINT16)BITS_TO_BYTES(sizeInBits);
2,596✔
736
    generated = bytes;
2,596✔
737
    
738
    // Generate required bytes
739
    for(; bytes > 0; bytes -= digestSize)
5,192✔
740
        {
741
            counter++;
2,596✔
742
            // Start HMAC
743
            if(CryptHmacStart(&hState, hashAlg, key->size, key->buffer) == 0)
2,596✔
744
                return 0;
745
            // Adding counter
746
            CryptDigestUpdateInt(&hState.hashState, 4, counter);
2,596✔
747
            
748
            // Adding label
749
            if(label != NULL)
2,596✔
750
                HASH_DATA(&hState.hashState, label->size, (BYTE *)label->buffer);
2,596✔
751
            // Add a null. SP108 is not very clear about when the 0 is needed but to
752
            // make this like the previous version that did not add an 0x00 after
753
            // a null-terminated string, this version will only add a null byte
754
            // if the label parameter did not end in a null byte, or if no label
755
            // is present.
756
            if((label == NULL)
2,596✔
757
               || (label->size == 0)
2,596✔
758
               || (label->buffer[label->size - 1] != 0))
2,587✔
759
                CryptDigestUpdateInt(&hState.hashState, 1, 0);
9✔
760
            // Adding contextU
761
            if(contextU != NULL)
2,596✔
762
                HASH_DATA(&hState.hashState, contextU->size, contextU->buffer);
1,738✔
763
            // Adding contextV
764
            if(contextV != NULL)
2,596✔
765
                HASH_DATA(&hState.hashState, contextV->size, contextV->buffer);
914✔
766
            // Adding size in bits
767
            CryptDigestUpdateInt(&hState.hashState, 4, sizeInBits);
2,596✔
768
            
769
            // Complete and put the data in the buffer
770
            CryptHmacEnd(&hState, bytes, stream);
2,596✔
771
            stream = &stream[digestSize];
2,596✔
772
        }
773
    // Masking in the KDF is disabled. If the calling function wants something
774
    // less than even number of bytes, then the caller should do the masking
775
    // because there is no universal way to do it here
776
    if(counterInOut != NULL)
2,596✔
777
        *counterInOut = counter;
669✔
778
    return generated;
779
}
780
/* 10.2.13.8.3        CryptKDFe() */
781
/* This function implements KDFe() as defined in TPM specification part 1. */
782
/* This function returns the number of bytes generated which may be zero. */
783
/* The Z and keyStream pointers are not allowed to be NULL. The other pointer values may be
784
   NULL. The value of sizeInBits must be no larger than (2^18)-1 = 256K bits (32385 bytes). Any
785
   error in the processing of this command is considered fatal. */
786
/*     Return Value        Meaning */
787
/*     0        hash algorithm is not supported or is TPM_ALG_NULL */
788
/*     > 0        the number of bytes in the keyStream buffer */
789
LIB_EXPORT UINT16
790
CryptKDFe(
50✔
791
          TPM_ALG_ID       hashAlg,       // IN: hash algorithm used in HMAC
792
          TPM2B           *Z,             // IN: Z
793
          const TPM2B     *label,         // IN: a label value for the KDF
794
          TPM2B           *partyUInfo,    // IN: PartyUInfo
795
          TPM2B           *partyVInfo,    // IN: PartyVInfo
796
          UINT32           sizeInBits,    // IN: size of generated key in bits
797
          BYTE            *keyStream      // OUT: key buffer
798
          )
799
{
800
    HASH_STATE       hashState;
50✔
801
    PHASH_DEF        hashDef = CryptGetHashDef(hashAlg);
50✔
802
    
803
    UINT32           counter = 0;       // counter value
50✔
804
    UINT16           hLen;
50✔
805
    BYTE            *stream = keyStream;
50✔
806
    INT16            bytes;             // number of bytes to generate
50✔
807
    
808
    pAssert(keyStream != NULL && Z != NULL && ((sizeInBits + 7) / 8) < INT16_MAX);
50✔
809
    //
810
    hLen = hashDef->digestSize;
50✔
811
    bytes = (INT16)((sizeInBits + 7) / 8);
50✔
812
    if(hashAlg == TPM_ALG_NULL || bytes == 0)
50✔
813
        return 0;
814
    
815
    // Generate required bytes
816
    //The inner loop of that KDF uses:
817
    //  Hash[i] := H(counter | Z | OtherInfo) (5)
818
    // Where:
819
    //  Hash[i]         the hash generated on the i-th iteration of the loop.
820
    //  H()             an approved hash function
821
    //  counter         a 32-bit counter that is initialized to 1 and incremented
822
    //                  on each iteration
823
    //  Z               the X coordinate of the product of a public ECC key and a
824
    //                  different private ECC key.
825
    //  OtherInfo       a collection of qualifying data for the KDF defined below.
826
    //  In this specification, OtherInfo will be constructed by:
827
    //      OtherInfo := Use | PartyUInfo  | PartyVInfo
828
    for(; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen)
100✔
829
        {
830
            if(bytes < hLen)
50✔
831
                hLen = bytes;
×
832
            counter++;
50✔
833
            // Do the hash
834
            CryptHashStart(&hashState, hashAlg);
50✔
835
            // Add counter
836
            CryptDigestUpdateInt(&hashState, 4, counter);
50✔
837
            
838
            // Add Z
839
            if(Z != NULL)
50✔
840
                CryptDigestUpdate2B(&hashState, Z);
50✔
841
            // Add label
842
            if(label != NULL)
50✔
843
                CryptDigestUpdate2B(&hashState, label);
50✔
844
            // Add a null. SP108 is not very clear about when the 0 is needed but to
845
            // make this like the previous version that did not add an 0x00 after
846
            // a null-terminated string, this version will only add a null byte
847
            // if the label parameter did not end in a null byte, or if no label
848
            // is present.
849
            if((label == NULL)
50✔
850
               || (label->size == 0)
50✔
851
               || (label->buffer[label->size - 1] != 0))
50✔
852
                CryptDigestUpdateInt(&hashState, 1, 0);
×
853
            // Add PartyUInfo
854
            if(partyUInfo != NULL)
50✔
855
                CryptDigestUpdate2B(&hashState, partyUInfo);
50✔
856
            
857
            // Add PartyVInfo
858
            if(partyVInfo != NULL)
50✔
859
                CryptDigestUpdate2B(&hashState, partyVInfo);
50✔
860
            
861
            // Compute Hash. hLen was changed to be the smaller of bytes or hLen
862
            // at the start of each iteration.
863
            CryptHashEnd(&hashState, hLen, stream);
50✔
864
        }
865
    
866
    // Mask off bits if the required bits is not a multiple of byte size
867
    if((sizeInBits % 8) != 0)
50✔
868
        keyStream[0] &= ((1 << (sizeInBits % 8)) - 1);
×
869
    
870
    return (UINT16)((sizeInBits + 7) / 8);
50✔
871
}
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