Coverage Report

Created: 2025-07-12 06:49

/src/tpm2/CpriHash.c
Line
Count
Source (jump to first uncovered line)
1
// This file was extracted from the TCG Published
2
// Trusted Platform Module Library
3
// Part 4: Supporting Routines
4
// Family "2.0"
5
// Level 00 Revision 01.16
6
// October 30, 2014
7
8
#include <string.h>
9
10
#include     "OsslCryptoEngine.h"
11
#include     "CpriHashData.c"
12
#if OPENSSL_VERSION_NUMBER < 0x10100000L
13
//
14
//     Temporary aliasing of SM3 to SHA256 until SM3 is available
15
//
16
#define EVP_sm3            EVP_sha256
17
18
static void *OPENSSL_zalloc(size_t num)
19
{
20
    void *ret = OPENSSL_malloc(num);
21
    if (ret != NULL)
22
        memset(ret, 0, num);
23
    return ret;
24
}
25
26
static EVP_MD_CTX *EVP_MD_CTX_new(void)
27
{
28
    return OPENSSL_zalloc(sizeof(EVP_MD_CTX));
29
}
30
31
static void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
32
{
33
    EVP_MD_CTX_cleanup(ctx);
34
    OPENSSL_free(ctx);
35
}
36
#endif
37
//
38
//
39
//          Static Functions
40
//
41
//          GetHashServer()
42
//
43
//     This function returns the address of the hash server function
44
//
45
static EVP_MD *
46
GetHashServer(
47
     TPM_ALG_ID      hashAlg
48
)
49
90
{
50
90
   switch (hashAlg)
51
90
   {
52
0
#ifdef TPM_ALG_SHA1
53
9
   case TPM_ALG_SHA1:
54
9
       return (EVP_MD *)EVP_sha1();
55
0
       break;
56
0
#endif
57
0
#ifdef TPM_ALG_SHA256
58
28
   case TPM_ALG_SHA256:
59
28
       return (EVP_MD *)EVP_sha256();
60
0
       break;
61
0
#endif
62
0
#ifdef TPM_ALG_SHA384
63
38
   case TPM_ALG_SHA384:
64
38
       return (EVP_MD *)EVP_sha384();
65
0
       break;
66
0
#endif
67
0
#ifdef TPM_ALG_SHA512
68
15
   case TPM_ALG_SHA512:
69
15
       return (EVP_MD *)EVP_sha512();
70
0
       break;
71
0
#endif
72
#ifdef TPM_ALG_SM3_256
73
   case TPM_ALG_SM3_256:
74
       return (EVP_MD *)EVP_sm3();      // OpenSSL 1.1 introduced this function
75
       break;
76
#endif
77
0
   case TPM_ALG_NULL:
78
0
       return NULL;
79
0
   default:
80
0
       FAIL(FATAL_ERROR_INTERNAL);
81
90
   }
82
0
   return NULL; // Never reached.
83
90
}
84
85
//
86
//
87
//          GetHashInfoPointer()
88
//
89
//      This function returns a pointer to the hash info for the algorithm. If the algorithm is not supported, function
90
//      returns a pointer to the data block associated with TPM_ALG_NULL.
91
//
92
static const HASH_INFO *
93
GetHashInfoPointer(
94
    TPM_ALG_ID           hashAlg
95
    )
96
22.2k
{
97
22.2k
    UINT32 i, tableSize;
98
    // Get the table size of g_hashData
99
22.2k
    tableSize = sizeof(g_hashData) / sizeof(g_hashData[0]);
100
55.6k
    for(i = 0; i < tableSize - 1; i++)
101
55.6k
    {
102
55.6k
        if(g_hashData[i].alg == hashAlg)
103
22.2k
            return &g_hashData[i];
104
55.6k
    }
105
1
    return &g_hashData[tableSize-1];
106
22.2k
}
107
//
108
//
109
//           Hash Functions
110
//
111
//          _cpri__HashStartup()
112
//
113
//      Function that is called to initialize the hash service. In this implementation, this function does nothing but
114
//      it is called by the CryptUtilStartup() function and must be present.
115
//
116
LIB_EXPORT BOOL
117
_cpri__HashStartup(
118
    void
119
    )
120
693
{
121
693
    return TRUE;
122
693
}
123
//
124
//
125
//          _cpri__GetHashAlgByIndex()
126
//
127
//      This function is used to iterate through the hashes. TPM_ALG_NULL is returned for all indexes that are
128
//      not valid hashes. If the TPM implements 3 hashes, then an index value of 0 will return the first
129
//      implemented hash and and index of 2 will return the last. All other index values will return
130
//      TPM_ALG_NULL.
131
//
132
//
133
//
134
//
135
//      Return Value                      Meaning
136
//
137
//      TPM_ALG_xxx()                     a hash algorithm
138
//      TPM_ALG_NULL                      this can be used as a stop value
139
//
140
LIB_EXPORT TPM_ALG_ID
141
_cpri__GetHashAlgByIndex(
142
    UINT32               index               // IN: the index
143
    )
144
924
{
145
924
    if(index >= HASH_COUNT)
146
0
        return TPM_ALG_NULL;
147
924
    return g_hashData[index].alg;
148
924
}
149
//
150
//
151
//         _cpri__GetHashBlockSize()
152
//
153
//      Returns the size of the block used for the hash
154
//
155
//      Return Value                      Meaning
156
//
157
//      <0                                the algorithm is not a supported hash
158
//      >=                                the digest size (0 for TPM_ALG_NULL)
159
//
160
LIB_EXPORT UINT16
161
_cpri__GetHashBlockSize(
162
    TPM_ALG_ID           hashAlg             // IN: hash algorithm to look up
163
    )
164
6
{
165
6
    return GetHashInfoPointer(hashAlg)->blockSize;
166
6
}
167
//
168
//
169
//         _cpri__GetHashDER
170
//
171
//      This function returns a pointer to the DER string for the algorithm and indicates its size.
172
//
173
LIB_EXPORT UINT16
174
_cpri__GetHashDER(
175
    TPM_ALG_ID           hashAlg,            // IN: the algorithm to look up
176
    const BYTE          **p
177
    )
178
0
{
179
0
    const HASH_INFO       *q;
180
0
    q = GetHashInfoPointer(hashAlg);
181
0
    *p = &q->der[0];
182
0
    return q->derSize;
183
0
}
184
//
185
//
186
//         _cpri__GetDigestSize()
187
//
188
//      Gets the digest size of the algorithm. The algorithm is required to be supported.
189
//
190
//      Return Value                      Meaning
191
//
192
//      =0                                the digest size for TPM_ALG_NULL
193
//      >0                                the digest size of a hash algorithm
194
//
195
LIB_EXPORT UINT16
196
_cpri__GetDigestSize(
197
    TPM_ALG_ID           hashAlg               // IN: hash algorithm to look up
198
    )
199
22.2k
{
200
22.2k
    return GetHashInfoPointer(hashAlg)->digestSize;
201
22.2k
}
202
//
203
//
204
//         _cpri__GetContextAlg()
205
//
206
//      This function returns the algorithm associated with a hash context
207
//
208
LIB_EXPORT TPM_ALG_ID
209
_cpri__GetContextAlg(
210
    CPRI_HASH_STATE         *hashState             // IN: the hash context
211
    )
212
0
{
213
0
    return hashState->hashAlg;
214
0
}
215
//
216
//
217
//         _cpri__CopyHashState
218
//
219
//      This function is used to clone a CPRI_HASH_STATE. The return value is the size of the state.
220
//
221
LIB_EXPORT UINT16
222
_cpri__CopyHashState (
223
    CPRI_HASH_STATE         *out,                  // OUT: destination of the state
224
    CPRI_HASH_STATE         *in                    // IN: source of the state
225
    )
226
14.8k
{
227
14.8k
    EVP_MD_CTX *in_ctx = *(EVP_MD_CTX **)&in->state;
228
14.8k
    EVP_MD_CTX *out_ctx;
229
14.8k
    pAssert(sizeof(out->state) >= sizeof(EVP_MD_CTX *));
230
14.8k
    if((out_ctx = EVP_MD_CTX_new()) == NULL)
231
0
        FAIL(FATAL_ERROR_INTERNAL);
232
14.8k
    if(!EVP_MD_CTX_copy_ex(out_ctx, in_ctx))
233
0
    {
234
0
        EVP_MD_CTX_free(out_ctx);
235
0
        return 0;
236
0
    }
237
14.8k
    *(EVP_MD_CTX**)&out->state = out_ctx;
238
14.8k
    out->hashAlg = in->hashAlg;
239
14.8k
    return sizeof(EVP_MD_CTX *);
240
14.8k
}
241
242
//
243
//
244
//         _cpri__StartHash()
245
//
246
//      Functions starts a hash stack Start a hash stack and returns the digest size. As a side effect, the value of
247
//      stateSize in hashState is updated to indicate the number of bytes of state that were saved. This function
248
//      calls GetHashServer() and that function will put the TPM into failure mode if the hash algorithm is not
249
//      supported.
250
//
251
//      Return Value                      Meaning
252
//
253
//      0                                 hash is TPM_ALG_NULL
254
//      >0                                digest size
255
LIB_EXPORT UINT16
256
_cpri__StartHash(
257
    TPM_ALG_ID               hashAlg,              // IN: hash algorithm
258
    BOOL                     sequence,             // IN: TRUE if the state should be saved
259
    CPRI_HASH_STATE         *hashState             // OUT: the state of hash stack.
260
    )
261
90
{
262
90
    EVP_MD_CTX         *context = *(EVP_MD_CTX **)&hashState->state;
263
90
    EVP_MD             *evpmdAlgorithm = NULL;
264
90
    pAssert(sizeof(hashState->state) >= sizeof(EVP_MD_CTX *));
265
90
    evpmdAlgorithm = GetHashServer(hashAlg);
266
90
    if(evpmdAlgorithm == NULL)
267
0
        return 0;
268
90
    if((context = EVP_MD_CTX_new()) == NULL)
269
0
        FAIL(FATAL_ERROR_INTERNAL);
270
90
    *(EVP_MD_CTX**)&hashState->state = context;
271
90
    hashState->hashAlg = hashAlg;
272
90
    if(EVP_DigestInit_ex(context, evpmdAlgorithm, NULL) != 1)
273
0
        FAIL(FATAL_ERROR_INTERNAL);
274
90
    return (CRYPT_RESULT)EVP_MD_CTX_size(context);
275
90
}
276
//
277
//
278
//         _cpri__UpdateHash()
279
//
280
//      Add data to a hash or HMAC stack.
281
//
282
LIB_EXPORT void
283
_cpri__UpdateHash(
284
   CPRI_HASH_STATE           *hashState,      // IN: the hash context information
285
   UINT32                     dataSize,       // IN: the size of data to be added to the
286
                                              //     digest
287
   BYTE                      *data            // IN: data to be hashed
288
   )
289
44.6k
{
290
44.6k
   EVP_MD_CTX         *context = *(EVP_MD_CTX **)&hashState->state;
291
    // If there is no context, return
292
44.6k
    if(context == NULL)
293
0
        return;
294
44.6k
    if(EVP_DigestUpdate(context, data, dataSize) != 1)
295
0
        FAIL(FATAL_ERROR_INTERNAL);
296
44.6k
    return;
297
44.6k
}
298
//
299
//
300
//       _cpri__CompleteHash()
301
//
302
//      Complete a hash or HMAC computation. This function will place the smaller of digestSize or the size of
303
//      the digest in dOut. The number of bytes in the placed in the buffer is returned. If there is a failure, the
304
//      returned value is <= 0.
305
//
306
//      Return Value                      Meaning
307
//
308
//      0                                 no data returned
309
//      >0                                the number of bytes in the digest
310
//
311
LIB_EXPORT UINT16
312
_cpri__CompleteHash(
313
    CPRI_HASH_STATE         *hashState,             // IN: the state of hash stack
314
    UINT32                   dOutSize,              // IN: size of digest buffer
315
    BYTE                    *dOut                   // OUT: hash digest
316
    )
317
14.9k
{
318
14.9k
    EVP_MD_CTX         *context = *(EVP_MD_CTX **)&hashState->state;
319
14.9k
    UINT16              retVal;
320
14.9k
    int                 hLen;
321
14.9k
    BYTE                temp[EVP_MAX_MD_SIZE];
322
14.9k
    BYTE               *rBuffer = dOut;
323
14.9k
    if(context == NULL)
324
0
        return 0;
325
14.9k
   hLen = EVP_MD_CTX_size(context);
326
14.9k
   if((unsigned)hLen > dOutSize)
327
6
       rBuffer = temp;
328
14.9k
   if(EVP_DigestFinal_ex(context, rBuffer, NULL) == 1)
329
14.9k
   {
330
14.9k
       if(rBuffer != dOut)
331
6
       {
332
6
            if(dOut != NULL)
333
0
            {
334
0
                memcpy(dOut, temp, dOutSize);
335
0
            }
336
6
            retVal = (UINT16)dOutSize;
337
6
       }
338
14.9k
       else
339
14.9k
       {
340
14.9k
            retVal = (UINT16)hLen;
341
14.9k
       }
342
14.9k
   }
343
0
   else
344
0
   {
345
0
       retVal = 0; // Indicate that no data is returned
346
0
   }
347
348
14.9k
   EVP_MD_CTX_free(context);
349
14.9k
   *(EVP_MD_CTX **)&hashState->state = NULL;
350
14.9k
   return retVal;
351
14.9k
}
352
//
353
//
354
//       _cpri__ImportExportHashState()
355
//
356
//      This function is used to import or export the hash state. This function would be called to export state when
357
//      a sequence object was being prepared for export
358
//
359
LIB_EXPORT void
360
_cpri__ImportExportHashState(
361
   CPRI_HASH_STATE           *osslFmt,          // IN/OUT: the hash state formated for use
362
                                                //     by openSSL
363
   EXPORT_HASH_STATE         *externalFmt,      // IN/OUT: the exported hash state
364
   IMPORT_EXPORT              direction         //
365
   )
366
0
{
367
0
   UNREFERENCED_PARAMETER(direction);
368
0
   UNREFERENCED_PARAMETER(externalFmt);
369
0
   UNREFERENCED_PARAMETER(osslFmt);
370
0
   return;
371
#if 0
372
   if(direction == IMPORT_STATE)
373
   {
374
       // don't have the import export functions yet so just copy
375
       _cpri__CopyHashState(osslFmt, (CPRI_HASH_STATE *)externalFmt);
376
   }
377
   else
378
   {
379
       _cpri__CopyHashState((CPRI_HASH_STATE *)externalFmt, osslFmt);
380
   }
381
#endif
382
0
}
383
//
384
//
385
//
386
//       _cpri__HashBlock()
387
//
388
//      Start a hash, hash a single block, update digest and return the size of the results.
389
//      The digestSize parameter can be smaller than the digest. If so, only the more significant bytes are
390
//      returned.
391
//
392
//      Return Value                      Meaning
393
//
394
//      >= 0                              number of bytes in digest (may be zero)
395
//
396
LIB_EXPORT UINT16
397
_cpri__HashBlock(
398
      TPM_ALG_ID         hashAlg,            //   IN: The hash algorithm
399
      UINT32             dataSize,           //   IN: size of buffer to hash
400
      BYTE              *data,               //   IN: the buffer to hash
401
      UINT32             digestSize,         //   IN: size of the digest buffer
402
      BYTE              *digest              //   OUT: hash digest
403
      )
404
0
{
405
0
      EVP_MD_CTX       *hashContext;
406
0
      EVP_MD           *hashServer = NULL;
407
0
      UINT16            retVal = 0;
408
0
      BYTE              b[EVP_MAX_MD_SIZE]; // temp buffer in case digestSize not
409
      // a full digest
410
0
      unsigned int      dSize = _cpri__GetDigestSize(hashAlg);
411
      // If there is no digest to compute return
412
0
      if(dSize == 0)
413
0
          return 0;
414
0
      if ((hashContext = EVP_MD_CTX_new()) == NULL)
415
0
          FAIL(FATAL_ERROR_INTERNAL);
416
0
      hashServer = GetHashServer(hashAlg); // Find the hash server
417
      // It is an error if the digest size is non-zero but there is no                server
418
0
      if(   (hashServer == NULL)
419
0
         || (EVP_DigestInit_ex(hashContext, hashServer, NULL) != 1)
420
0
         || (EVP_DigestUpdate(hashContext, data, dataSize) != 1))
421
0
          FAIL(FATAL_ERROR_INTERNAL);
422
0
      else
423
0
      {
424
          // If the size of the digest produced (dSize) is larger than                the available
425
          // buffer (digestSize), then put the digest in a temp buffer                and only copy
426
          // the most significant part into the available buffer.
427
0
          if(dSize > digestSize)
428
0
          {
429
0
               if(EVP_DigestFinal_ex(hashContext, b, &dSize) != 1)
430
0
                   FAIL(FATAL_ERROR_INTERNAL);
431
0
               memcpy(digest, b, digestSize);
432
0
               retVal = (UINT16)digestSize;
433
0
          }
434
0
          else
435
0
          {
436
0
               if((EVP_DigestFinal_ex(hashContext, digest, &dSize)) !=               1)
437
0
                   FAIL(FATAL_ERROR_INTERNAL);
438
0
               retVal = (UINT16) dSize;
439
0
          }
440
0
      }
441
0
      EVP_MD_CTX_free(hashContext);
442
0
      return retVal;
443
0
}
444
//
445
//
446
//
447
//           HMAC Functions
448
//
449
//          _cpri__StartHMAC
450
//
451
//      This function is used to start an HMAC using a temp hash context. The function does the initialization of
452
//      the hash with the HMAC key XOR iPad and updates the HMAC key XOR oPad.
453
//      The function returns the number of bytes in a digest produced by hashAlg.
454
//
455
//      Return Value                    Meaning
456
//
457
//      >= 0                            number of bytes in digest produced by hashAlg (may be zero)
458
//
459
LIB_EXPORT UINT16
460
_cpri__StartHMAC(
461
      TPM_ALG_ID              hashAlg,          //   IN: the algorithm to use
462
      BOOL                    sequence,         //   IN: indicates if the state should be
463
                                                //       saved
464
      CPRI_HASH_STATE        *state,            //   IN/OUT: the state buffer
465
      UINT16                  keySize,          //   IN: the size of the HMAC key
466
      BYTE                   *key,              //   IN: the HMAC key
467
      TPM2B                  *oPadKey           //   OUT: the key prepared for the oPad round
468
      )
469
6
{
470
6
      CPRI_HASH_STATE  localState = {};
471
6
      UINT16           blockSize = _cpri__GetHashBlockSize(hashAlg);
472
6
      UINT16           digestSize;
473
6
      BYTE            *pb;         // temp pointer
474
6
      UINT32           i;
475
476
      // If the key size is larger than the block size, then the hash of the key
477
      // is used as the key
478
6
      if(keySize > blockSize)
479
0
      {
480
          // large key so digest
481
0
          if((digestSize = _cpri__StartHash(hashAlg, FALSE, &localState)) == 0)
482
0
              return 0;
483
0
          _cpri__UpdateHash(&localState, keySize, key);
484
0
          _cpri__CompleteHash(&localState, digestSize, oPadKey->buffer);
485
0
          oPadKey->size = digestSize;
486
0
      }
487
6
      else
488
6
      {
489
          // key size is ok
490
6
          memcpy(oPadKey->buffer, key, keySize);
491
6
          oPadKey->size = keySize;
492
6
      }
493
      // XOR the key with iPad (0x36)
494
6
      pb = oPadKey->buffer;
495
198
      for(i = oPadKey->size; i > 0; i--)
496
192
          *pb++ ^= 0x36;
497
      // if the keySize is smaller than a block, fill the rest with 0x36
498
198
      for(i = blockSize - oPadKey->size; i > 0; i--)
499
192
          *pb++ = 0x36;
500
      // Increase the oPadSize to a full block
501
6
      oPadKey->size = blockSize;
502
      // Start a new hash with the HMAC key
503
      // This will go in the caller's state structure and may be a sequence or not
504
6
      if((digestSize = _cpri__StartHash(hashAlg, sequence, state)) > 0)
505
6
      {
506
6
          _cpri__UpdateHash(state, oPadKey->size, oPadKey->buffer);
507
          // XOR the key block with 0x5c ^ 0x36
508
390
          for(pb = oPadKey->buffer, i = blockSize; i > 0; i--)
509
384
              *pb++ ^= (0x5c ^ 0x36);
510
6
      }
511
6
      return digestSize;
512
6
}
513
//
514
//
515
//          _cpri_CompleteHMAC()
516
//
517
//      This function is called to complete an HMAC. It will finish the current digest, and start a new digest. It will
518
//      then add the oPadKey and the completed digest and return the results in dOut. It will not return more than
519
//      dOutSize bytes.
520
//
521
//      Return Value                      Meaning
522
//
523
//      >= 0                              number of bytes in dOut (may be zero)
524
//
525
LIB_EXPORT UINT16
526
_cpri__CompleteHMAC(
527
      CPRI_HASH_STATE        *hashState,          //   IN: the state of hash stack
528
      TPM2B                  *oPadKey,            //   IN: the HMAC key in oPad format
529
      UINT32                  dOutSize,           //   IN: size of digest buffer
530
      BYTE                   *dOut                //   OUT: hash digest
531
      )
532
3
{
533
3
      BYTE             digest[MAX_DIGEST_SIZE];
534
3
      CPRI_HASH_STATE *state = (CPRI_HASH_STATE *)hashState;
535
3
      CPRI_HASH_STATE  localState = {};
536
3
      UINT16           digestSize = _cpri__GetDigestSize(state->hashAlg);
537
538
3
      _cpri__CompleteHash(hashState, digestSize, digest);
539
      // Using the local hash state, do a hash with the oPad
540
3
      if(_cpri__StartHash(state->hashAlg, FALSE, &localState) != digestSize)
541
0
          return 0;
542
3
      _cpri__UpdateHash(&localState, oPadKey->size, oPadKey->buffer);
543
3
      _cpri__UpdateHash(&localState, digestSize, digest);
544
3
      return _cpri__CompleteHash(&localState, dOutSize, dOut);
545
3
}
546
//
547
//
548
//           Mask and Key Generation Functions
549
//
550
//          _crypi_MGF1()
551
//
552
//      This function performs MGF1 using the selected hash. MGF1 is T(n) = T(n-1) || H(seed || counter). This
553
//      function returns the length of the mask produced which could be zero if the digest algorithm is not
554
//      supported
555
//
556
//      Return Value                      Meaning
557
//
558
//      0                                 hash algorithm not supported
559
//      >0                                should be the same as mSize
560
//
561
LIB_EXPORT CRYPT_RESULT
562
_cpri__MGF1(
563
   UINT32              mSize,          //   IN: length of the mask to be produced
564
   BYTE               *mask,           //   OUT: buffer to receive the mask
565
   TPM_ALG_ID          hashAlg,        //   IN: hash to use
566
   UINT32              sSize,          //   IN: size of the seed
567
   BYTE               *seed            //   IN: seed size
568
   )
569
0
{
570
0
   EVP_MD_CTX          *hashContext;
571
0
   EVP_MD              *hashServer = NULL;
572
0
   CRYPT_RESULT         retVal = 0;
573
0
   BYTE                 b[MAX_DIGEST_SIZE]; // temp buffer in case mask is not an
574
   // even multiple of a full digest
575
0
   CRYPT_RESULT         dSize = _cpri__GetDigestSize(hashAlg);
576
0
   unsigned int         digestSize = (UINT32)dSize;
577
0
   UINT32               remaining;
578
0
   UINT32               counter;
579
0
   BYTE                 swappedCounter[4];
580
   // Parameter check
581
0
   if(mSize > (1024*16)) // Semi-arbitrary maximum
582
0
       FAIL(FATAL_ERROR_INTERNAL);
583
   // If there is no digest to compute return
584
0
   if(dSize <= 0)
585
0
       return 0;
586
0
   hashServer = GetHashServer(hashAlg); // Find the hash server
587
0
   if(hashServer == NULL)
588
       // If there is no server, then there is no digest
589
0
       return 0;
590
0
   if ((hashContext = EVP_MD_CTX_new()) == NULL)
591
0
       FAIL(FATAL_ERROR_INTERNAL);
592
0
   for(counter = 0, remaining = mSize; remaining > 0; counter++)
593
0
   {
594
       // Because the system may be either Endian...
595
0
       UINT32_TO_BYTE_ARRAY(counter, swappedCounter);
596
        // Start the hash and include the seed and counter
597
0
        if(    (EVP_DigestInit_ex(hashContext, hashServer, NULL) != 1)
598
0
            || (EVP_DigestUpdate(hashContext, seed, sSize) != 1)
599
0
            || (EVP_DigestUpdate(hashContext, swappedCounter, 4) != 1)
600
0
          )
601
0
             FAIL(FATAL_ERROR_INTERNAL);
602
        // Handling the completion depends on how much space remains in the mask
603
        // buffer. If it can hold the entire digest, put it there. If not
604
        // put the digest in a temp buffer and only copy the amount that
605
        // will fit into the mask buffer.
606
0
        if(remaining < (unsigned)dSize)
607
0
        {
608
0
             if(EVP_DigestFinal_ex(hashContext, b, &digestSize) != 1)
609
0
                 FAIL(FATAL_ERROR_INTERNAL);
610
0
             memcpy(mask, b, remaining);
611
0
             break;
612
0
        }
613
0
        else
614
0
        {
615
0
             if(EVP_DigestFinal_ex(hashContext, mask, &digestSize) != 1)
616
0
                 FAIL(FATAL_ERROR_INTERNAL);
617
0
             remaining -= dSize;
618
0
             mask = &mask[dSize];
619
0
        }
620
0
        retVal = (CRYPT_RESULT)mSize;
621
0
    }
622
0
    EVP_MD_CTX_free(hashContext);
623
0
    return retVal;
624
0
}
625
//
626
//
627
//          _cpri_KDFa()
628
//
629
//      This function performs the key generation according to Part 1 of the TPM specification.
630
//      This function returns the number of bytes generated which may be zero.
631
//      The key and keyStream pointers are not allowed to be NULL. The other pointer values may be NULL.
632
//      The value of sizeInBits must be no larger than (2^18)-1 = 256K bits (32385 bytes).
633
//      The once parameter is set to allow incremental generation of a large value. If this flag is TRUE,
634
//      sizeInBits will be used in the HMAC computation but only one iteration of the KDF is performed. This
635
//      would be used for XOR obfuscation so that the mask value can be generated in digest-sized chunks
636
//      rather than having to be generated all at once in an arbitrarily large buffer and then XORed() into the
637
//      result. If once is TRUE, then sizeInBits must be a multiple of 8.
638
//      Any error in the processing of this command is considered fatal.
639
//
640
//      Return Value                      Meaning
641
//
642
//      0                                 hash algorithm is not supported or is TPM_ALG_NULL
643
//      >0                                the number of bytes in the keyStream buffer
644
//
645
LIB_EXPORT UINT16
646
_cpri__KDFa(
647
    TPM_ALG_ID          hashAlg,             //   IN: hash algorithm used in HMAC
648
    TPM2B              *key,                 //   IN: HMAC key
649
    const char         *label,               //   IN: a 0-byte terminated label used in KDF
650
    TPM2B              *contextU,            //   IN: context U
651
    TPM2B              *contextV,            //   IN: context V
652
    UINT32              sizeInBits,          //   IN: size of generated key in bit
653
    BYTE               *keyStream,           //   OUT: key buffer
654
    UINT32             *counterInOut,        //   IN/OUT: caller may provide the iteration
655
                                             //       counter for incremental operations to
656
                                             //       avoid large intermediate buffers.
657
    BOOL                once                 //   IN: TRUE if only one iteration is performed
658
                                             //       FALSE if iteration count determined by
659
                                             //       "sizeInBits"
660
    )
661
0
{
662
0
    UINT32                         counter = 0;    // counter value
663
0
    INT32                          lLen = 0;       // length of the label
664
0
    INT16                          hLen;           // length of the hash
665
0
    INT16                          bytes;          // number of bytes to produce
666
0
    BYTE                          *stream = keyStream;
667
0
    BYTE                           marshaledUint32[4];
668
0
    CPRI_HASH_STATE                hashState = {};
669
0
    TPM2B_MAX_HASH_BLOCK           hmacKey;
670
0
    pAssert(key != NULL && keyStream != NULL);
671
0
    pAssert(once == FALSE || (sizeInBits & 7) == 0);
672
0
    if(counterInOut != NULL)
673
0
        counter = *counterInOut;
674
    // Prepare label buffer. Calculate its size and keep the last 0 byte
675
0
    if(label != NULL)
676
0
        for(lLen = 0; label[lLen++] != 0; );
677
    // Get the hash size. If it is less than or 0, either the
678
    // algorithm is not supported or the hash is TPM_ALG_NULL
679
//
680
   // In either case the digest size is zero. This is the only return
681
   // other than the one at the end. All other exits from this function
682
   // are fatal errors. After we check that the algorithm is supported
683
   // anything else that goes wrong is an implementation flaw.
684
0
   if((hLen = (INT16) _cpri__GetDigestSize(hashAlg)) == 0)
685
0
       return 0;
686
   // If the size of the request is larger than the numbers will handle,
687
   // it is a fatal error.
688
0
   pAssert(((sizeInBits + 7)/ 8) <= INT16_MAX);
689
0
   bytes = once ? hLen : (INT16)((sizeInBits + 7) / 8);
690
   // Generate required bytes
691
0
   for (; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen)
692
0
   {
693
0
       if(bytes < hLen)
694
0
           hLen = bytes;
695
0
        counter++;
696
        // Start HMAC
697
0
        if(_cpri__StartHMAC(hashAlg,
698
0
                            FALSE,
699
0
                            &hashState,
700
0
                            key->size,
701
0
                            &key->buffer[0],
702
0
                            &hmacKey.b)          <= 0)
703
0
            FAIL(FATAL_ERROR_INTERNAL);
704
        // Adding counter
705
0
        UINT32_TO_BYTE_ARRAY(counter, marshaledUint32);
706
0
        _cpri__UpdateHash(&hashState, sizeof(UINT32), marshaledUint32);
707
        // Adding label
708
0
        if(label != NULL)
709
0
            _cpri__UpdateHash(&hashState,   lLen, (BYTE *)label);
710
        // Adding contextU
711
0
        if(contextU != NULL)
712
0
            _cpri__UpdateHash(&hashState, contextU->size, contextU->buffer);
713
        // Adding contextV
714
0
        if(contextV != NULL)
715
0
            _cpri__UpdateHash(&hashState, contextV->size, contextV->buffer);
716
        // Adding size in bits
717
0
        UINT32_TO_BYTE_ARRAY(sizeInBits, marshaledUint32);
718
0
        _cpri__UpdateHash(&hashState, sizeof(UINT32), marshaledUint32);
719
        // Compute HMAC. At the start of each iteration, hLen is set
720
        // to the smaller of hLen and bytes. This causes bytes to decrement
721
        // exactly to zero to complete the loop
722
0
        _cpri__CompleteHMAC(&hashState, &hmacKey.b, hLen, stream);
723
0
   }
724
   // Mask off bits if the required bits is not a multiple of byte size
725
0
   if((sizeInBits % 8) != 0)
726
0
       keyStream[0] &= ((1 << (sizeInBits % 8)) - 1);
727
0
   if(counterInOut != NULL)
728
0
       *counterInOut = counter;
729
0
   return (CRYPT_RESULT)((sizeInBits + 7)/8);
730
0
}
731
//
732
//
733
//
734
//         _cpri__KDFe()
735
//
736
//      KDFe() as defined in TPM specification part 1.
737
//      This function returns the number of bytes generated which may be zero.
738
//      The Z and keyStream pointers are not allowed to be NULL. The other pointer values may be NULL. The
739
//      value of sizeInBits must be no larger than (2^18)-1 = 256K bits (32385 bytes). Any error in the processing
740
//      of this command is considered fatal.
741
//
742
//      Return Value                      Meaning
743
//
744
//      0                                 hash algorithm is not supported or is TPM_ALG_NULL
745
//      >0                                the number of bytes in the keyStream buffer
746
//
747
LIB_EXPORT UINT16
748
_cpri__KDFe(
749
    TPM_ALG_ID          hashAlg,             //   IN: hash algorithm used in HMAC
750
    TPM2B              *Z,                   //   IN: Z
751
    const char         *label,               //   IN: a 0 terminated label using in KDF
752
    TPM2B              *partyUInfo,          //   IN: PartyUInfo
753
    TPM2B              *partyVInfo,          //   IN: PartyVInfo
754
    UINT32              sizeInBits,          //   IN: size of generated key in bit
755
    BYTE               *keyStream            //   OUT: key buffer
756
    )
757
0
{
758
0
    UINT32       counter = 0;        // counter value
759
0
    UINT32       lSize = 0;
760
0
    BYTE        *stream = keyStream;
761
0
    CPRI_HASH_STATE         hashState = {};
762
0
    INT16        hLen = (INT16) _cpri__GetDigestSize(hashAlg);
763
0
    INT16        bytes;              // number of bytes to generate
764
0
    BYTE         marshaledUint32[4];
765
0
    pAssert(     keyStream != NULL
766
0
                 && Z != NULL
767
0
                 && ((sizeInBits + 7) / 8) < INT16_MAX);
768
0
    if(hLen == 0)
769
0
        return 0;
770
0
    bytes = (INT16)((sizeInBits + 7) / 8);
771
    // Prepare label buffer. Calculate its size and keep the last 0 byte
772
0
    if(label != NULL)
773
0
        for(lSize = 0; label[lSize++] != 0;);
774
    // Generate required bytes
775
    //The inner loop of that KDF uses:
776
    // Hashi := H(counter | Z | OtherInfo) (5)
777
    // Where:
778
    // Hashi    the hash generated on the i-th iteration of the loop.
779
    // H()      an approved hash function
780
    // counter a 32-bit counter that is initialized to 1 and incremented
781
    //          on each iteration
782
    // Z        the X coordinate of the product of a public ECC key and a
783
    //          different private ECC key.
784
    // OtherInfo    a collection of qualifying data for the KDF defined below.
785
    // In this specification, OtherInfo will be constructed by:
786
    //      OtherInfo := Use | PartyUInfo | PartyVInfo
787
0
    for (; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen)
788
0
    {
789
0
        if(bytes < hLen)
790
0
            hLen = bytes;
791
//
792
0
        counter++;
793
        // Start hash
794
0
        if(_cpri__StartHash(hashAlg, FALSE,   &hashState) == 0)
795
0
            return 0;
796
        // Add counter
797
0
        UINT32_TO_BYTE_ARRAY(counter, marshaledUint32);
798
0
        _cpri__UpdateHash(&hashState, sizeof(UINT32), marshaledUint32);
799
        // Add Z
800
0
        if(Z != NULL)
801
0
            _cpri__UpdateHash(&hashState, Z->size, Z->buffer);
802
        // Add label
803
0
        if(label != NULL)
804
0
             _cpri__UpdateHash(&hashState, lSize, (BYTE *)label);
805
0
        else
806
              // The SP800-108 specification requires a zero between the label
807
              // and the context.
808
0
              _cpri__UpdateHash(&hashState, 1, (BYTE *)"");
809
        // Add PartyUInfo
810
0
        if(partyUInfo != NULL)
811
0
            _cpri__UpdateHash(&hashState, partyUInfo->size, partyUInfo->buffer);
812
        // Add PartyVInfo
813
0
        if(partyVInfo != NULL)
814
0
            _cpri__UpdateHash(&hashState, partyVInfo->size, partyVInfo->buffer);
815
        // Compute Hash. hLen was changed to be the smaller of bytes or hLen
816
        // at the start of each iteration.
817
0
        _cpri__CompleteHash(&hashState, hLen, stream);
818
0
   }
819
   // Mask off bits if the required bits is not a multiple of byte size
820
0
   if((sizeInBits % 8) != 0)
821
0
       keyStream[0] &= ((1 << (sizeInBits % 8)) - 1);
822
0
   return (CRYPT_RESULT)((sizeInBits + 7) / 8);
823
0
}