blob: 62df56060c9b4ac32c889df3e23638c03e812c27 [file] [log] [blame]
Vadim Bendebury56797522015-05-20 10:32:25 -07001// 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
Vadim Bendebury34f0a9a2015-05-29 12:24:59 -07008#include <string.h>
9
Vadim Bendebury56797522015-05-20 10:32:25 -070010#include "OsslCryptoEngine.h"
11#include "CpriHashData.c"
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -070012#if OPENSSL_VERSION_NUMBER < 0x10100000L
Vadim Bendebury56797522015-05-20 10:32:25 -070013//
14// Temporary aliasing of SM3 to SHA256 until SM3 is available
15//
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -070016#define EVP_sm3 EVP_sha256
17
18static 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
26static EVP_MD_CTX *EVP_MD_CTX_new(void)
27{
28 return OPENSSL_zalloc(sizeof(EVP_MD_CTX));
29}
30
31static void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
32{
33 EVP_MD_CTX_cleanup(ctx);
34 OPENSSL_free(ctx);
35}
36#endif
Vadim Bendebury56797522015-05-20 10:32:25 -070037//
38//
39// Static Functions
40//
41// GetHashServer()
42//
43// This function returns the address of the hash server function
44//
45static EVP_MD *
46GetHashServer(
47 TPM_ALG_ID hashAlg
48)
49{
50 switch (hashAlg)
51 {
52#ifdef TPM_ALG_SHA1
53 case TPM_ALG_SHA1:
54 return (EVP_MD *)EVP_sha1();
55 break;
56#endif
57#ifdef TPM_ALG_SHA256
58 case TPM_ALG_SHA256:
59 return (EVP_MD *)EVP_sha256();
60 break;
61#endif
62#ifdef TPM_ALG_SHA384
63 case TPM_ALG_SHA384:
64 return (EVP_MD *)EVP_sha384();
65 break;
66#endif
67#ifdef TPM_ALG_SHA512
68 case TPM_ALG_SHA512:
69 return (EVP_MD *)EVP_sha512();
70 break;
71#endif
72#ifdef TPM_ALG_SM3_256
73 case TPM_ALG_SM3_256:
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -070074 return (EVP_MD *)EVP_sm3(); // OpenSSL 1.1 introduced this function
Vadim Bendebury56797522015-05-20 10:32:25 -070075 break;
76#endif
77 case TPM_ALG_NULL:
78 return NULL;
79 default:
80 FAIL(FATAL_ERROR_INTERNAL);
81 }
Vadim Bendebury34f0a9a2015-05-29 12:24:59 -070082 return NULL; // Never reached.
Vadim Bendebury56797522015-05-20 10:32:25 -070083}
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -070084
Vadim Bendebury56797522015-05-20 10:32:25 -070085//
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//
92static const HASH_INFO *
93GetHashInfoPointer(
94 TPM_ALG_ID hashAlg
95 )
96{
97 UINT32 i, tableSize;
98 // Get the table size of g_hashData
99 tableSize = sizeof(g_hashData) / sizeof(g_hashData[0]);
100 for(i = 0; i < tableSize - 1; i++)
101 {
102 if(g_hashData[i].alg == hashAlg)
103 return &g_hashData[i];
104 }
105 return &g_hashData[tableSize-1];
106}
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//
116LIB_EXPORT BOOL
117_cpri__HashStartup(
118 void
119 )
120{
Vadim Bendebury56797522015-05-20 10:32:25 -0700121 return TRUE;
122}
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//
140LIB_EXPORT TPM_ALG_ID
141_cpri__GetHashAlgByIndex(
142 UINT32 index // IN: the index
143 )
144{
145 if(index >= HASH_COUNT)
146 return TPM_ALG_NULL;
147 return g_hashData[index].alg;
148}
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//
160LIB_EXPORT UINT16
161_cpri__GetHashBlockSize(
162 TPM_ALG_ID hashAlg // IN: hash algorithm to look up
163 )
164{
165 return GetHashInfoPointer(hashAlg)->blockSize;
166}
167//
168//
169// _cpri__GetHashDER
170//
171// This function returns a pointer to the DER string for the algorithm and indicates its size.
172//
173LIB_EXPORT UINT16
174_cpri__GetHashDER(
175 TPM_ALG_ID hashAlg, // IN: the algorithm to look up
176 const BYTE **p
177 )
178{
179 const HASH_INFO *q;
180 q = GetHashInfoPointer(hashAlg);
181 *p = &q->der[0];
182 return q->derSize;
183}
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//
195LIB_EXPORT UINT16
196_cpri__GetDigestSize(
197 TPM_ALG_ID hashAlg // IN: hash algorithm to look up
198 )
199{
200 return GetHashInfoPointer(hashAlg)->digestSize;
201}
202//
203//
204// _cpri__GetContextAlg()
205//
206// This function returns the algorithm associated with a hash context
207//
208LIB_EXPORT TPM_ALG_ID
209_cpri__GetContextAlg(
210 CPRI_HASH_STATE *hashState // IN: the hash context
211 )
212{
213 return hashState->hashAlg;
214}
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//
221LIB_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{
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700227 EVP_MD_CTX *in_ctx = *(EVP_MD_CTX **)&in->state;
228 EVP_MD_CTX *out_ctx;
229 pAssert(sizeof(out->state) >= sizeof(EVP_MD_CTX *));
230 if((out_ctx = EVP_MD_CTX_new()) == NULL)
231 FAIL(FATAL_ERROR_INTERNAL);
232 if(!EVP_MD_CTX_copy_ex(out_ctx, in_ctx))
233 {
234 EVP_MD_CTX_free(out_ctx);
235 return 0;
236 }
237 *(EVP_MD_CTX**)&out->state = out_ctx;
Vadim Bendebury56797522015-05-20 10:32:25 -0700238 out->hashAlg = in->hashAlg;
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700239 return sizeof(EVP_MD_CTX *);
Vadim Bendebury56797522015-05-20 10:32:25 -0700240}
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700241
Vadim Bendebury56797522015-05-20 10:32:25 -0700242//
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
Vadim Bendebury56797522015-05-20 10:32:25 -0700255LIB_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{
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700262 EVP_MD_CTX *context = *(EVP_MD_CTX **)&hashState->state;
263 EVP_MD *evpmdAlgorithm = NULL;
264 pAssert(sizeof(hashState->state) >= sizeof(EVP_MD_CTX *));
265 evpmdAlgorithm = GetHashServer(hashAlg);
266 if(evpmdAlgorithm == NULL)
267 return 0;
268 if((context = EVP_MD_CTX_new()) == NULL)
269 FAIL(FATAL_ERROR_INTERNAL);
270 *(EVP_MD_CTX**)&hashState->state = context;
271 hashState->hashAlg = hashAlg;
272 if(EVP_DigestInit_ex(context, evpmdAlgorithm, NULL) != 1)
273 FAIL(FATAL_ERROR_INTERNAL);
274 return (CRYPT_RESULT)EVP_MD_CTX_size(context);
Vadim Bendebury56797522015-05-20 10:32:25 -0700275}
276//
277//
278// _cpri__UpdateHash()
279//
280// Add data to a hash or HMAC stack.
281//
282LIB_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{
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700290 EVP_MD_CTX *context = *(EVP_MD_CTX **)&hashState->state;
Vadim Bendebury56797522015-05-20 10:32:25 -0700291 // If there is no context, return
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700292 if(context == NULL)
Vadim Bendebury56797522015-05-20 10:32:25 -0700293 return;
Vadim Bendebury56797522015-05-20 10:32:25 -0700294 if(EVP_DigestUpdate(context, data, dataSize) != 1)
295 FAIL(FATAL_ERROR_INTERNAL);
Vadim Bendebury56797522015-05-20 10:32:25 -0700296 return;
297}
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//
311LIB_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{
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700318 EVP_MD_CTX *context = *(EVP_MD_CTX **)&hashState->state;
Vadim Bendebury56797522015-05-20 10:32:25 -0700319 UINT16 retVal;
320 int hLen;
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700321 BYTE temp[EVP_MAX_MD_SIZE];
Vadim Bendebury56797522015-05-20 10:32:25 -0700322 BYTE *rBuffer = dOut;
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700323 if(context == NULL)
Vadim Bendebury56797522015-05-20 10:32:25 -0700324 return 0;
Vadim Bendebury56797522015-05-20 10:32:25 -0700325 hLen = EVP_MD_CTX_size(context);
326 if((unsigned)hLen > dOutSize)
327 rBuffer = temp;
328 if(EVP_DigestFinal_ex(context, rBuffer, NULL) == 1)
329 {
330 if(rBuffer != dOut)
331 {
332 if(dOut != NULL)
333 {
334 memcpy(dOut, temp, dOutSize);
335 }
336 retVal = (UINT16)dOutSize;
337 }
338 else
339 {
340 retVal = (UINT16)hLen;
341 }
Vadim Bendebury56797522015-05-20 10:32:25 -0700342 }
343 else
344 {
345 retVal = 0; // Indicate that no data is returned
346 }
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700347
348 EVP_MD_CTX_free(context);
349 *(EVP_MD_CTX **)&hashState->state = NULL;
Vadim Bendebury56797522015-05-20 10:32:25 -0700350 return retVal;
351}
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//
359LIB_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{
367 UNREFERENCED_PARAMETER(direction);
368 UNREFERENCED_PARAMETER(externalFmt);
369 UNREFERENCED_PARAMETER(osslFmt);
370 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}
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//
396LIB_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{
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700405 EVP_MD_CTX *hashContext;
Vadim Bendebury56797522015-05-20 10:32:25 -0700406 EVP_MD *hashServer = NULL;
407 UINT16 retVal = 0;
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700408 BYTE b[EVP_MAX_MD_SIZE]; // temp buffer in case digestSize not
Vadim Bendebury56797522015-05-20 10:32:25 -0700409 // a full digest
410 unsigned int dSize = _cpri__GetDigestSize(hashAlg);
411 // If there is no digest to compute return
412 if(dSize == 0)
413 return 0;
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700414 if ((hashContext = EVP_MD_CTX_new()) == NULL)
415 FAIL(FATAL_ERROR_INTERNAL);
Vadim Bendebury56797522015-05-20 10:32:25 -0700416 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 if( (hashServer == NULL)
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700419 || (EVP_DigestInit_ex(hashContext, hashServer, NULL) != 1)
420 || (EVP_DigestUpdate(hashContext, data, dataSize) != 1))
Vadim Bendebury56797522015-05-20 10:32:25 -0700421 FAIL(FATAL_ERROR_INTERNAL);
422 else
423 {
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 if(dSize > digestSize)
428 {
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700429 if(EVP_DigestFinal_ex(hashContext, b, &dSize) != 1)
Vadim Bendebury56797522015-05-20 10:32:25 -0700430 FAIL(FATAL_ERROR_INTERNAL);
431 memcpy(digest, b, digestSize);
432 retVal = (UINT16)digestSize;
433 }
434 else
435 {
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700436 if((EVP_DigestFinal_ex(hashContext, digest, &dSize)) != 1)
Vadim Bendebury56797522015-05-20 10:32:25 -0700437 FAIL(FATAL_ERROR_INTERNAL);
438 retVal = (UINT16) dSize;
439 }
440 }
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700441 EVP_MD_CTX_free(hashContext);
Vadim Bendebury56797522015-05-20 10:32:25 -0700442 return retVal;
443}
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//
459LIB_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{
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700470 CPRI_HASH_STATE localState = {};
Vadim Bendebury56797522015-05-20 10:32:25 -0700471 UINT16 blockSize = _cpri__GetHashBlockSize(hashAlg);
472 UINT16 digestSize;
473 BYTE *pb; // temp pointer
474 UINT32 i;
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700475
Vadim Bendebury56797522015-05-20 10:32:25 -0700476 // If the key size is larger than the block size, then the hash of the key
477 // is used as the key
478 if(keySize > blockSize)
479 {
480 // large key so digest
481 if((digestSize = _cpri__StartHash(hashAlg, FALSE, &localState)) == 0)
482 return 0;
483 _cpri__UpdateHash(&localState, keySize, key);
484 _cpri__CompleteHash(&localState, digestSize, oPadKey->buffer);
485 oPadKey->size = digestSize;
486 }
487 else
488 {
489 // key size is ok
490 memcpy(oPadKey->buffer, key, keySize);
491 oPadKey->size = keySize;
492 }
493 // XOR the key with iPad (0x36)
494 pb = oPadKey->buffer;
495 for(i = oPadKey->size; i > 0; i--)
496 *pb++ ^= 0x36;
497 // if the keySize is smaller than a block, fill the rest with 0x36
498 for(i = blockSize - oPadKey->size; i > 0; i--)
499 *pb++ = 0x36;
500 // Increase the oPadSize to a full block
501 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 if((digestSize = _cpri__StartHash(hashAlg, sequence, state)) > 0)
505 {
506 _cpri__UpdateHash(state, oPadKey->size, oPadKey->buffer);
507 // XOR the key block with 0x5c ^ 0x36
508 for(pb = oPadKey->buffer, i = blockSize; i > 0; i--)
509 *pb++ ^= (0x5c ^ 0x36);
510 }
511 return digestSize;
512}
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//
525LIB_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{
533 BYTE digest[MAX_DIGEST_SIZE];
534 CPRI_HASH_STATE *state = (CPRI_HASH_STATE *)hashState;
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700535 CPRI_HASH_STATE localState = {};
Vadim Bendebury56797522015-05-20 10:32:25 -0700536 UINT16 digestSize = _cpri__GetDigestSize(state->hashAlg);
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700537
Vadim Bendebury56797522015-05-20 10:32:25 -0700538 _cpri__CompleteHash(hashState, digestSize, digest);
539 // Using the local hash state, do a hash with the oPad
540 if(_cpri__StartHash(state->hashAlg, FALSE, &localState) != digestSize)
541 return 0;
542 _cpri__UpdateHash(&localState, oPadKey->size, oPadKey->buffer);
543 _cpri__UpdateHash(&localState, digestSize, digest);
544 return _cpri__CompleteHash(&localState, dOutSize, dOut);
545}
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//
561LIB_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{
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700570 EVP_MD_CTX *hashContext;
Vadim Bendebury56797522015-05-20 10:32:25 -0700571 EVP_MD *hashServer = NULL;
572 CRYPT_RESULT retVal = 0;
573 BYTE b[MAX_DIGEST_SIZE]; // temp buffer in case mask is not an
574 // even multiple of a full digest
575 CRYPT_RESULT dSize = _cpri__GetDigestSize(hashAlg);
576 unsigned int digestSize = (UINT32)dSize;
577 UINT32 remaining;
578 UINT32 counter;
579 BYTE swappedCounter[4];
580 // Parameter check
581 if(mSize > (1024*16)) // Semi-arbitrary maximum
582 FAIL(FATAL_ERROR_INTERNAL);
583 // If there is no digest to compute return
584 if(dSize <= 0)
585 return 0;
Vadim Bendebury56797522015-05-20 10:32:25 -0700586 hashServer = GetHashServer(hashAlg); // Find the hash server
587 if(hashServer == NULL)
588 // If there is no server, then there is no digest
589 return 0;
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700590 if ((hashContext = EVP_MD_CTX_new()) == NULL)
591 FAIL(FATAL_ERROR_INTERNAL);
Vadim Bendebury56797522015-05-20 10:32:25 -0700592 for(counter = 0, remaining = mSize; remaining > 0; counter++)
593 {
594 // Because the system may be either Endian...
595 UINT32_TO_BYTE_ARRAY(counter, swappedCounter);
596 // Start the hash and include the seed and counter
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700597 if( (EVP_DigestInit_ex(hashContext, hashServer, NULL) != 1)
598 || (EVP_DigestUpdate(hashContext, seed, sSize) != 1)
599 || (EVP_DigestUpdate(hashContext, swappedCounter, 4) != 1)
Vadim Bendebury56797522015-05-20 10:32:25 -0700600 )
601 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 if(remaining < (unsigned)dSize)
607 {
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700608 if(EVP_DigestFinal_ex(hashContext, b, &digestSize) != 1)
Vadim Bendebury56797522015-05-20 10:32:25 -0700609 FAIL(FATAL_ERROR_INTERNAL);
610 memcpy(mask, b, remaining);
611 break;
612 }
613 else
614 {
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700615 if(EVP_DigestFinal_ex(hashContext, mask, &digestSize) != 1)
Vadim Bendebury56797522015-05-20 10:32:25 -0700616 FAIL(FATAL_ERROR_INTERNAL);
617 remaining -= dSize;
618 mask = &mask[dSize];
619 }
620 retVal = (CRYPT_RESULT)mSize;
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700621 }
622 EVP_MD_CTX_free(hashContext);
Vadim Bendebury56797522015-05-20 10:32:25 -0700623 return retVal;
624}
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//
645LIB_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{
662 UINT32 counter = 0; // counter value
663 INT32 lLen = 0; // length of the label
664 INT16 hLen; // length of the hash
665 INT16 bytes; // number of bytes to produce
666 BYTE *stream = keyStream;
667 BYTE marshaledUint32[4];
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700668 CPRI_HASH_STATE hashState = {};
Vadim Bendebury56797522015-05-20 10:32:25 -0700669 TPM2B_MAX_HASH_BLOCK hmacKey;
670 pAssert(key != NULL && keyStream != NULL);
671 pAssert(once == FALSE || (sizeInBits & 7) == 0);
672 if(counterInOut != NULL)
673 counter = *counterInOut;
674 // Prepare label buffer. Calculate its size and keep the last 0 byte
675 if(label != NULL)
676 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 if((hLen = (INT16) _cpri__GetDigestSize(hashAlg)) == 0)
685 return 0;
686 // If the size of the request is larger than the numbers will handle,
687 // it is a fatal error.
688 pAssert(((sizeInBits + 7)/ 8) <= INT16_MAX);
689 bytes = once ? hLen : (INT16)((sizeInBits + 7) / 8);
690 // Generate required bytes
691 for (; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen)
692 {
693 if(bytes < hLen)
694 hLen = bytes;
695 counter++;
696 // Start HMAC
697 if(_cpri__StartHMAC(hashAlg,
698 FALSE,
699 &hashState,
700 key->size,
701 &key->buffer[0],
702 &hmacKey.b) <= 0)
703 FAIL(FATAL_ERROR_INTERNAL);
704 // Adding counter
705 UINT32_TO_BYTE_ARRAY(counter, marshaledUint32);
706 _cpri__UpdateHash(&hashState, sizeof(UINT32), marshaledUint32);
707 // Adding label
708 if(label != NULL)
709 _cpri__UpdateHash(&hashState, lLen, (BYTE *)label);
710 // Adding contextU
711 if(contextU != NULL)
712 _cpri__UpdateHash(&hashState, contextU->size, contextU->buffer);
713 // Adding contextV
714 if(contextV != NULL)
715 _cpri__UpdateHash(&hashState, contextV->size, contextV->buffer);
716 // Adding size in bits
717 UINT32_TO_BYTE_ARRAY(sizeInBits, marshaledUint32);
718 _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 _cpri__CompleteHMAC(&hashState, &hmacKey.b, hLen, stream);
723 }
724 // Mask off bits if the required bits is not a multiple of byte size
725 if((sizeInBits % 8) != 0)
726 keyStream[0] &= ((1 << (sizeInBits % 8)) - 1);
727 if(counterInOut != NULL)
728 *counterInOut = counter;
729 return (CRYPT_RESULT)((sizeInBits + 7)/8);
730}
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//
747LIB_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{
758 UINT32 counter = 0; // counter value
759 UINT32 lSize = 0;
760 BYTE *stream = keyStream;
Vadim Sukhomlinov6a2d0e02019-08-01 18:18:56 -0700761 CPRI_HASH_STATE hashState = {};
Vadim Bendebury56797522015-05-20 10:32:25 -0700762 INT16 hLen = (INT16) _cpri__GetDigestSize(hashAlg);
763 INT16 bytes; // number of bytes to generate
764 BYTE marshaledUint32[4];
765 pAssert( keyStream != NULL
766 && Z != NULL
767 && ((sizeInBits + 7) / 8) < INT16_MAX);
768 if(hLen == 0)
769 return 0;
770 bytes = (INT16)((sizeInBits + 7) / 8);
771 // Prepare label buffer. Calculate its size and keep the last 0 byte
772 if(label != NULL)
773 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 for (; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen)
788 {
789 if(bytes < hLen)
790 hLen = bytes;
791//
792 counter++;
793 // Start hash
794 if(_cpri__StartHash(hashAlg, FALSE, &hashState) == 0)
795 return 0;
796 // Add counter
797 UINT32_TO_BYTE_ARRAY(counter, marshaledUint32);
798 _cpri__UpdateHash(&hashState, sizeof(UINT32), marshaledUint32);
799 // Add Z
800 if(Z != NULL)
801 _cpri__UpdateHash(&hashState, Z->size, Z->buffer);
802 // Add label
803 if(label != NULL)
804 _cpri__UpdateHash(&hashState, lSize, (BYTE *)label);
805 else
806 // The SP800-108 specification requires a zero between the label
807 // and the context.
808 _cpri__UpdateHash(&hashState, 1, (BYTE *)"");
809 // Add PartyUInfo
810 if(partyUInfo != NULL)
811 _cpri__UpdateHash(&hashState, partyUInfo->size, partyUInfo->buffer);
812 // Add PartyVInfo
813 if(partyVInfo != NULL)
814 _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 _cpri__CompleteHash(&hashState, hLen, stream);
818 }
819 // Mask off bits if the required bits is not a multiple of byte size
820 if((sizeInBits % 8) != 0)
821 keyStream[0] &= ((1 << (sizeInBits % 8)) - 1);
822 return (CRYPT_RESULT)((sizeInBits + 7) / 8);
823}