blob: b90854a960e530098b33f514d9d96b877e176fb2 [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
8#include "TPM_Types.h"
9#include "CryptoEngine.h" // types shared by CryptUtil and CryptoEngine.
10 // Includes the function prototypes for the
11 // CryptoEngine functions.
12#include "Global.h"
13#include "InternalRoutines.h"
14#include "MemoryLib_fp.h"
15//#include "CryptSelfTest_fp.h"
16//
17//
18// 10.2.2 TranslateCryptErrors()
19//
20// This function converts errors from the cryptographic library into TPM_RC_VALUES.
21//
22// Error Returns Meaning
23//
24// TPM_RC_VALUE CRYPT_FAIL
25// TPM_RC_NO_RESULT CRYPT_NO_RESULT
26// TPM_RC_SCHEME CRYPT_SCHEME
27// TPM_RC_VALUE CRYPT_PARAMETER
28// TPM_RC_SIZE CRYPT_UNDERFLOW
29// TPM_RC_ECC_POINT CRYPT_POINT
30// TPM_RC_CANCELLED CRYPT_CANCEL
31//
32static TPM_RC
33TranslateCryptErrors (
34 CRYPT_RESULT retVal // IN: crypt error to evaluate
35)
36{
37 switch (retVal)
38 {
39 case CRYPT_SUCCESS:
40 return TPM_RC_SUCCESS;
41 case CRYPT_FAIL:
42 return TPM_RC_VALUE;
43 case CRYPT_NO_RESULT:
44 return TPM_RC_NO_RESULT;
45 case CRYPT_SCHEME:
46 return TPM_RC_SCHEME;
47 case CRYPT_PARAMETER:
48 return TPM_RC_VALUE;
49 case CRYPT_UNDERFLOW:
50 return TPM_RC_SIZE;
51 case CRYPT_POINT:
52 return TPM_RC_ECC_POINT;
53 case CRYPT_CANCEL:
54 return TPM_RC_CANCELED;
55 default: // Other unknown warnings
56 return TPM_RC_FAILURE;
57 }
58}
59//
60//
61// 10.2.3 Random Number Generation Functions
62//
63#ifdef TPM_ALG_NULL //%
64#ifdef _DRBG_STATE_SAVE //%
65//
66//
67// 10.2.3.1 CryptDrbgGetPutState()
68//
69// Read or write the current state from the DRBG in the cryptoEngine.
70//
71void
72CryptDrbgGetPutState(
73 GET_PUT direction // IN: Get from or put to DRBG
74 )
75{
76 _cpri__DrbgGetPutState(direction,
77 sizeof(go.drbgState),
78 (BYTE *)&go.drbgState);
79}
80#else //% 00
81//%#define CryptDrbgGetPutState(ignored) // If not doing state save, turn this
82//% // into a null macro
83#endif //%
84//
85//
86// 10.2.3.2 CryptStirRandom()
87//
88// Stir random entropy
89//
90void
91CryptStirRandom(
92 UINT32 entropySize, // IN: size of entropy buffer
93 BYTE *buffer // IN: entropy buffer
94 )
95{
96 // RNG self testing code may be inserted here
97 // Call crypto engine random number stirring function
98 _cpri__StirRandom(entropySize, buffer);
99 return;
100}
101//
102//
103// 10.2.3.3 CryptGenerateRandom()
104//
105// This is the interface to _cpri__GenerateRandom().
106//
107UINT16
108CryptGenerateRandom(
109 UINT16 randomSize, // IN: size of random number
110 BYTE *buffer // OUT: buffer of random number
111 )
112{
113 UINT16 result;
114 pAssert(randomSize <= MAX_RSA_KEY_BYTES || randomSize <= PRIMARY_SEED_SIZE);
115 if(randomSize == 0)
116 return 0;
117 // Call crypto engine random number generation
118 result = _cpri__GenerateRandom(randomSize, buffer);
119 if(result != randomSize)
120 FAIL(FATAL_ERROR_INTERNAL);
121 return result;
122}
123#endif //TPM_ALG_NULL //%
124//
125//
126// 10.2.4 Hash/HMAC Functions
127//
128// 10.2.4.1 CryptGetContextAlg()
129//
130// This function returns the hash algorithm associated with a hash context.
131//
132#ifdef TPM_ALG_KEYEDHASH //% 1
133TPM_ALG_ID
134CryptGetContextAlg(
135 void *state // IN: the context to check
136 )
137{
138 HASH_STATE *context = (HASH_STATE *)state;
139 return _cpri__GetContextAlg(&context->state);
140}
141//
142//
143// 10.2.4.2 CryptStartHash()
144//
145// This function starts a hash and return the size, in bytes, of the digest.
146//
147// Return Value Meaning
148//
149// >0 the digest size of the algorithm
150// =0 the hashAlg was TPM_ALG_NULL
151//
152UINT16
153CryptStartHash(
154 TPMI_ALG_HASH hashAlg, // IN: hash algorithm
155 HASH_STATE *hashState // OUT: the state of hash stack. It will be used
156 // in hash update and completion
157 )
158{
159 CRYPT_RESULT retVal = 0;
160 pAssert(hashState != NULL);
161 TEST_HASH(hashAlg);
162 hashState->type = HASH_STATE_EMPTY;
163 // Call crypto engine start hash function
164 if((retVal = _cpri__StartHash(hashAlg, FALSE, &hashState->state)) > 0)
165 hashState->type = HASH_STATE_HASH;
166 return retVal;
167}
168//
169//
170//
171// 10.2.4.3 CryptStartHashSequence()
172//
173// Start a hash stack for a sequence object and return the size, in bytes, of the digest. This call uses the
174// form of the hash state that requires context save and restored.
175//
176// Return Value Meaning
177//
178// >0 the digest size of the algorithm
179// =0 the hashAlg was TPM_ALG_NULL
180//
181UINT16
182CryptStartHashSequence(
183 TPMI_ALG_HASH hashAlg, // IN: hash algorithm
184 HASH_STATE *hashState // OUT: the state of hash stack. It will be used
185 // in hash update and completion
186 )
187{
188 CRYPT_RESULT retVal = 0;
189 pAssert(hashState != NULL);
190 TEST_HASH(hashAlg);
191 hashState->type = HASH_STATE_EMPTY;
192 // Call crypto engine start hash function
193 if((retVal = _cpri__StartHash(hashAlg, TRUE, &hashState->state)) > 0)
194 hashState->type = HASH_STATE_HASH;
195 return retVal;
196}
197//
198//
199// 10.2.4.4 CryptStartHMAC()
200//
201// This function starts an HMAC sequence and returns the size of the digest that will be produced.
202// The caller must provide a block of memory in which the hash sequence state is kept. The caller should
203// not alter the contents of this buffer until the hash sequence is completed or abandoned.
204//
205// Return Value Meaning
206//
207// >0 the digest size of the algorithm
208// =0 the hashAlg was TPM_ALG_NULL
209//
210UINT16
211CryptStartHMAC(
212 TPMI_ALG_HASH hashAlg, // IN: hash algorithm
213 UINT16 keySize, // IN: the size of HMAC key in byte
214 BYTE *key, // IN: HMAC key
215 HMAC_STATE *hmacState // OUT: the state of HMAC stack. It will be used
216 // in HMAC update and completion
217 )
218{
219 HASH_STATE *hashState = (HASH_STATE *)hmacState;
220 CRYPT_RESULT retVal;
221 // This has to come before the pAssert in case we all calling this function
222 // during testing. If so, the first instance will have no arguments but the
223 // hash algorithm. The call from the test routine will have arguments. When
224 // the second call is done, then we return to the test dispatcher.
225 TEST_HASH(hashAlg);
226 pAssert(hashState != NULL);
227 hashState->type = HASH_STATE_EMPTY;
228 if((retVal = _cpri__StartHMAC(hashAlg, FALSE, &hashState->state, keySize, key,
229 &hmacState->hmacKey.b)) > 0)
230 hashState->type = HASH_STATE_HMAC;
231 return retVal;
232}
233//
234//
235// 10.2.4.5 CryptStartHMACSequence()
236//
237// This function starts an HMAC sequence and returns the size of the digest that will be produced.
238// The caller must provide a block of memory in which the hash sequence state is kept. The caller should
239// not alter the contents of this buffer until the hash sequence is completed or abandoned.
240// This call is used to start a sequence HMAC that spans multiple TPM commands.
241//
242// Return Value Meaning
243//
244// >0 the digest size of the algorithm
245// =0 the hashAlg was TPM_ALG_NULL
246//
247UINT16
248CryptStartHMACSequence(
249 TPMI_ALG_HASH hashAlg, // IN: hash algorithm
250 UINT16 keySize, // IN: the size of HMAC key in byte
251 BYTE *key, // IN: HMAC key
252 HMAC_STATE *hmacState // OUT: the state of HMAC stack. It will be used
253 // in HMAC update and completion
254 )
255{
256 HASH_STATE *hashState = (HASH_STATE *)hmacState;
257 CRYPT_RESULT retVal;
258 TEST_HASH(hashAlg);
259 hashState->type = HASH_STATE_EMPTY;
260 if((retVal = _cpri__StartHMAC(hashAlg, TRUE, &hashState->state,
261 keySize, key, &hmacState->hmacKey.b)) > 0)
262 hashState->type = HASH_STATE_HMAC;
263 return retVal;
264}
265//
266//
267// 10.2.4.6 CryptStartHMAC2B()
268//
269// This function starts an HMAC and returns the size of the digest that will be produced.
270// This function is provided to support the most common use of starting an HMAC with a TPM2B key.
271// The caller must provide a block of memory in which the hash sequence state is kept. The caller should
272// not alter the contents of this buffer until the hash sequence is completed or abandoned.
273//
274//
275//
276//
277// Return Value Meaning
278//
279// >0 the digest size of the algorithm
280// =0 the hashAlg was TPM_ALG_NULL
281//
282LIB_EXPORT UINT16
283CryptStartHMAC2B(
284 TPMI_ALG_HASH hashAlg, // IN: hash algorithm
285 TPM2B *key, // IN: HMAC key
286 HMAC_STATE *hmacState // OUT: the state of HMAC stack. It will be used
287 // in HMAC update and completion
288 )
289{
290 return CryptStartHMAC(hashAlg, key->size, key->buffer, hmacState);
291}
292//
293//
294// 10.2.4.7 CryptStartHMACSequence2B()
295//
296// This function starts an HMAC sequence and returns the size of the digest that will be produced.
297// This function is provided to support the most common use of starting an HMAC with a TPM2B key.
298// The caller must provide a block of memory in which the hash sequence state is kept. The caller should
299// not alter the contents of this buffer until the hash sequence is completed or abandoned.
300//
301// Return Value Meaning
302//
303// >0 the digest size of the algorithm
304// =0 the hashAlg was TPM_ALG_NULL
305//
306UINT16
307CryptStartHMACSequence2B(
308 TPMI_ALG_HASH hashAlg, // IN: hash algorithm
309 TPM2B *key, // IN: HMAC key
310 HMAC_STATE *hmacState // OUT: the state of HMAC stack. It will be used
311 // in HMAC update and completion
312 )
313{
314 return CryptStartHMACSequence(hashAlg, key->size, key->buffer, hmacState);
315}
316//
317//
318// 10.2.4.8 CryptUpdateDigest()
319//
320// This function updates a digest (hash or HMAC) with an array of octets.
321// This function can be used for both HMAC and hash functions so the digestState is void so that either
322// state type can be passed.
323//
324LIB_EXPORT void
325CryptUpdateDigest(
326 void *digestState, // IN: the state of hash stack
327 UINT32 dataSize, // IN: the size of data
328 BYTE *data // IN: data to be hashed
329 )
330{
331 HASH_STATE *hashState = (HASH_STATE *)digestState;
332 pAssert(digestState != NULL);
333 if(hashState->type != HASH_STATE_EMPTY && data != NULL && dataSize != 0)
334 {
335 // Call crypto engine update hash function
336 _cpri__UpdateHash(&hashState->state, dataSize, data);
337 }
338 return;
339}
340//
341//
342// 10.2.4.9 CryptUpdateDigest2B()
343//
344// This function updates a digest (hash or HMAC) with a TPM2B.
345// This function can be used for both HMAC and hash functions so the digestState is void so that either
346// state type can be passed.
347//
348LIB_EXPORT void
349CryptUpdateDigest2B(
350 void *digestState, // IN: the digest state
351 TPM2B *bIn // IN: 2B containing the data
352 )
353{
354 // Only compute the digest if a pointer to the 2B is provided.
355 // In CryptUpdateDigest(), if size is zero or buffer is NULL, then no change
356 // to the digest occurs. This function should not provide a buffer if bIn is
357 // not provided.
358 if(bIn != NULL)
359 CryptUpdateDigest(digestState, bIn->size, bIn->buffer);
360 return;
361}
362//
363//
364// 10.2.4.10 CryptUpdateDigestInt()
365//
366// This function is used to include an integer value to a hash stack. The function marshals the integer into its
367// canonical form before calling CryptUpdateHash().
368//
369LIB_EXPORT void
370CryptUpdateDigestInt(
371 void *state, // IN: the state of hash stack
372 UINT32 intSize, // IN: the size of 'intValue' in byte
373 void *intValue // IN: integer value to be hashed
374 )
375{
376#if BIG_ENDIAN_TPM == YES
377 pAssert( intValue != NULL && (intSize == 1 || intSize == 2
378 || intSize == 4 || intSize == 8));
379 CryptUpdateHash(state, inSize, (BYTE *)intValue);
380#else
381 BYTE marshalBuffer[8];
382 // Point to the big end of an little-endian value
383 BYTE *p = &((BYTE *)intValue)[intSize - 1];
384 // Point to the big end of an big-endian value
385 BYTE *q = marshalBuffer;
386 pAssert(intValue != NULL);
387 switch (intSize)
388 {
389 case 8:
390 *q++ = *p--;
391 *q++ = *p--;
392 *q++ = *p--;
393 *q++ = *p--;
394 case 4:
395 *q++ = *p--;
396 *q++ = *p--;
397 case 2:
398 *q++ = *p--;
399 case 1:
400 *q = *p;
401 // Call update the hash
402 CryptUpdateDigest(state, intSize, marshalBuffer);
403 break;
404 default:
405 FAIL(0);
406 }
407#endif
408 return;
409}
410//
411//
412// 10.2.4.11 CryptCompleteHash()
413//
414// This function completes a hash sequence and returns the digest.
415// This function can be called to complete either an HMAC or hash sequence. The state type determines if
416// the context type is a hash or HMAC. If an HMAC, then the call is forwarded to CryptCompleteHash().
417// If digestSize is smaller than the digest size of hash/HMAC algorithm, the most significant bytes of
418// required size will be returned
419//
420// Return Value Meaning
421//
422// >=0 the number of bytes placed in digest
423//
424LIB_EXPORT UINT16
425CryptCompleteHash(
426 void *state, // IN: the state of hash stack
427 UINT16 digestSize, // IN: size of digest buffer
428 BYTE *digest // OUT: hash digest
429 )
430{
431 HASH_STATE *hashState = (HASH_STATE *)state; // local value
432 // If the session type is HMAC, then could forward this to
433 // the HMAC processing and not cause an error. However, if no
434 // function calls this routine to forward it, then we can't get
435 // test coverage. The decision is to assert if this is called with
436 // the type == HMAC and fix anything that makes the wrong call.
437 pAssert(hashState->type == HASH_STATE_HASH);
438 // Set the state to empty so that it doesn't get used again
439 hashState->type = HASH_STATE_EMPTY;
440 // Call crypto engine complete hash function
441 return _cpri__CompleteHash(&hashState->state, digestSize, digest);
442}
443//
444//
445// 10.2.4.12 CryptCompleteHash2B()
446//
447// This function is the same as CypteCompleteHash() but the digest is placed in a TPM2B. This is the most
448// common use and this is provided for specification clarity. 'digest.size' should be set to indicate the number
449// of bytes to place in the buffer
450//
451//
452//
453//
454// Return Value Meaning
455//
456// >=0 the number of bytes placed in 'digest.buffer'
457//
458LIB_EXPORT UINT16
459CryptCompleteHash2B(
460 void *state, // IN: the state of hash stack
461 TPM2B *digest // IN: the size of the buffer Out: requested
462 // number of byte
463 )
464{
465 UINT16 retVal = 0;
466 if(digest != NULL)
467 retVal = CryptCompleteHash(state, digest->size, digest->buffer);
468 return retVal;
469}
470//
471//
472// 10.2.4.13 CryptHashBlock()
473//
474// Hash a block of data and return the results. If the digest is larger than retSize, it is truncated and with the
475// least significant octets dropped.
476//
477// Return Value Meaning
478//
479// >=0 the number of bytes placed in ret
480//
481LIB_EXPORT UINT16
482CryptHashBlock(
483 TPM_ALG_ID algId, // IN: the hash algorithm to use
484 UINT16 blockSize, // IN: size of the data block
485 BYTE *block, // IN: address of the block to hash
486 UINT16 retSize, // IN: size of the return buffer
487 BYTE *ret // OUT: address of the buffer
488 )
489{
490 TEST_HASH(algId);
491 return _cpri__HashBlock(algId, blockSize, block, retSize, ret);
492}
493//
494//
495// 10.2.4.14 CryptCompleteHMAC()
496//
497// This function completes a HMAC sequence and returns the digest. If digestSize is smaller than the digest
498// size of the HMAC algorithm, the most significant bytes of required size will be returned.
499//
500// Return Value Meaning
501//
502// >=0 the number of bytes placed in digest
503//
504LIB_EXPORT UINT16
505CryptCompleteHMAC(
506 HMAC_STATE *hmacState, // IN: the state of HMAC stack
507 UINT32 digestSize, // IN: size of digest buffer
508 BYTE *digest // OUT: HMAC digest
509 )
510{
511 HASH_STATE *hashState;
512 pAssert(hmacState != NULL);
513 hashState = &hmacState->hashState;
514 pAssert(hashState->type == HASH_STATE_HMAC);
515 hashState->type = HASH_STATE_EMPTY;
516 return _cpri__CompleteHMAC(&hashState->state, &hmacState->hmacKey.b,
517 digestSize, digest);
518}
519//
520//
521// 10.2.4.15 CryptCompleteHMAC2B()
522//
523// This function is the same as CryptCompleteHMAC() but the HMAC result is returned in a TPM2B which is
524// the most common use.
525//
526// Return Value Meaning
527//
528// >=0 the number of bytes placed in digest
529//
530LIB_EXPORT UINT16
531CryptCompleteHMAC2B(
532 HMAC_STATE *hmacState, // IN: the state of HMAC stack
533 TPM2B *digest // OUT: HMAC
534 )
535{
536 UINT16 retVal = 0;
537 if(digest != NULL)
538 retVal = CryptCompleteHMAC(hmacState, digest->size, digest->buffer);
539 return retVal;
540}
541//
542//
543// 10.2.4.16 CryptHashStateImportExport()
544//
545// This function is used to prepare a hash state context for LIB_EXPORT or to import it into the internal
546// format. It is used by TPM2_ContextSave() and TPM2_ContextLoad() via SequenceDataImportExport().
547// This is just a pass-through function to the crypto library.
548//
549void
550CryptHashStateImportExport(
551 HASH_STATE *internalFmt, // IN: state to LIB_EXPORT
552 HASH_STATE *externalFmt, // OUT: exported state
553 IMPORT_EXPORT direction
554 )
555{
556 _cpri__ImportExportHashState(&internalFmt->state,
557 (EXPORT_HASH_STATE *)&externalFmt->state,
558 direction);
559}
560//
561//
562// 10.2.4.17 CryptGetHashDigestSize()
563//
564// This function returns the digest size in bytes for a hash algorithm.
565//
566// Return Value Meaning
567//
568// 0 digest size for TPM_ALG_NULL
569// >0 digest size
570//
571LIB_EXPORT UINT16
572CryptGetHashDigestSize(
573 TPM_ALG_ID hashAlg // IN: hash algorithm
574 )
575{
576 return _cpri__GetDigestSize(hashAlg);
577}
578//
579//
580// 10.2.4.18 CryptGetHashBlockSize()
581//
582// Get the digest size in byte of a hash algorithm.
583//
584// Return Value Meaning
585//
586// 0 block size for TPM_ALG_NULL
587// >0 block size
588//
589LIB_EXPORT UINT16
590CryptGetHashBlockSize(
591 TPM_ALG_ID hash // IN: hash algorithm to look up
592 )
593{
594 return _cpri__GetHashBlockSize(hash);
595}
596//
597//
598// 10.2.4.19 CryptGetHashAlgByIndex()
599//
600// This function is used to iterate through the hashes. TPM_ALG_NULL is returned for all indexes that are
601// not valid hashes. If the TPM implements 3 hashes, then an index value of 0 will return the first
602// implemented hash and an index value of 2 will return the last implemented hash. All other index values
603// will return TPM_ALG_NULL.
604//
605// Return Value Meaning
606//
607// TPM_ALG_xxx() a hash algorithm
608// TPM_ALG_NULL this can be used as a stop value
609//
610LIB_EXPORT TPM_ALG_ID
611CryptGetHashAlgByIndex(
612 UINT32 index // IN: the index
613 )
614{
615 return _cpri__GetHashAlgByIndex(index);
616}
617//
618//
619// 10.2.4.20 CryptSignHMAC()
620//
621// Sign a digest using an HMAC key. This an HMAC of a digest, not an HMAC of a message.
622//
623// Error Returns Meaning
624//
625static TPM_RC
626CryptSignHMAC(
627 OBJECT *signKey, // IN: HMAC key sign the hash
628 TPMT_SIG_SCHEME *scheme, // IN: signing scheme
629 TPM2B_DIGEST *hashData, // IN: hash to be signed
630 TPMT_SIGNATURE *signature // OUT: signature
631 )
632{
633//
634 HMAC_STATE hmacState;
635 UINT32 digestSize;
636 // HMAC algorithm self testing code may be inserted here
637 digestSize = CryptStartHMAC2B(scheme->details.hmac.hashAlg,
638 &signKey->sensitive.sensitive.bits.b,
639 &hmacState);
640 // The hash algorithm must be a valid one.
641 pAssert(digestSize > 0);
642 CryptUpdateDigest2B(&hmacState, &hashData->b);
643 CryptCompleteHMAC(&hmacState, digestSize,
644 (BYTE *) &signature->signature.hmac.digest);
645 // Set HMAC algorithm
646 signature->signature.hmac.hashAlg = scheme->details.hmac.hashAlg;
647 return TPM_RC_SUCCESS;
648}
649//
650//
651// 10.2.4.21 CryptHMACVerifySignature()
652//
653// This function will verify a signature signed by a HMAC key.
654//
655// Error Returns Meaning
656//
657// TPM_RC_SIGNATURE if invalid input or signature is not genuine
658//
659static TPM_RC
660CryptHMACVerifySignature(
661 OBJECT *signKey, // IN: HMAC key signed the hash
662 TPM2B_DIGEST *hashData, // IN: digest being verified
663 TPMT_SIGNATURE *signature // IN: signature to be verified
664 )
665{
666 HMAC_STATE hmacState;
667 TPM2B_DIGEST digestToCompare;
668 digestToCompare.t.size = CryptStartHMAC2B(signature->signature.hmac.hashAlg,
669 &signKey->sensitive.sensitive.bits.b, &hmacState);
670 CryptUpdateDigest2B(&hmacState, &hashData->b);
671 CryptCompleteHMAC2B(&hmacState, &digestToCompare.b);
672 // Compare digest
673 if(MemoryEqual(digestToCompare.t.buffer,
674 (BYTE *) &signature->signature.hmac.digest,
675 digestToCompare.t.size))
676 return TPM_RC_SUCCESS;
677 else
678 return TPM_RC_SIGNATURE;
679}
680//
681//
682// 10.2.4.22 CryptGenerateKeyedHash()
683//
684// This function creates a keyedHash object.
685//
686//
687//
688// Error Returns Meaning
689//
690// TPM_RC_SIZE sensitive data size is larger than allowed for the scheme
691//
692static TPM_RC
693CryptGenerateKeyedHash(
694 TPMT_PUBLIC *publicArea, // IN/OUT: the public area template
695 // for the new key.
696 TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation data
697 TPMT_SENSITIVE *sensitive, // OUT: sensitive area
698 TPM_ALG_ID kdfHashAlg, // IN: algorithm for the KDF
699 TPM2B_SEED *seed, // IN: the seed
700 TPM2B_NAME *name // IN: name of the object
701 )
702{
703 TPMT_KEYEDHASH_SCHEME *scheme;
704 TPM_ALG_ID hashAlg;
705 UINT16 hashBlockSize;
706 scheme = &publicArea->parameters.keyedHashDetail.scheme;
707 pAssert(publicArea->type == TPM_ALG_KEYEDHASH);
708 // Pick the limiting hash algorithm
709 if(scheme->scheme == TPM_ALG_NULL)
710 hashAlg = publicArea->nameAlg;
711 else if(scheme->scheme == TPM_ALG_XOR)
712 hashAlg = scheme->details.xor.hashAlg;
713 else
714 hashAlg = scheme->details.hmac.hashAlg;
715 hashBlockSize = CryptGetHashBlockSize(hashAlg);
716 // if this is a signing or a decryption key, then then the limit
717 // for the data size is the block size of the hash. This limit
718 // is set because larger values have lower entropy because of the
719 // HMAC function.
720 if(publicArea->objectAttributes.sensitiveDataOrigin == CLEAR)
721 {
722 if( ( publicArea->objectAttributes.decrypt
723 || publicArea->objectAttributes.sign)
724 && sensitiveCreate->data.t.size > hashBlockSize)
725 return TPM_RC_SIZE;
726 }
727 else
728 {
729 // If the TPM is going to generate the data, then set the size to be the
730 // size of the digest of the algorithm
731 sensitive->sensitive.sym.t.size = CryptGetHashDigestSize(hashAlg);
732 sensitiveCreate->data.t.size = 0;
733 }
734 // Fill in the sensitive area
735 CryptGenerateNewSymmetric(sensitiveCreate, sensitive, kdfHashAlg,
736 seed, name);
737 // Create unique area in public
738 CryptComputeSymmetricUnique(publicArea->nameAlg,
739 sensitive, &publicArea->unique.sym);
740 return TPM_RC_SUCCESS;
741}
742//
743//
Vadim Bendebury56797522015-05-20 10:32:25 -0700744// 10.2.4.25 KDFa()
745//
746// This function is used by functions outside of CryptUtil() to access _cpri_KDFa().
747//
748void
749KDFa(
750 TPM_ALG_ID hash, // IN: hash algorithm used in HMAC
751 TPM2B *key, // IN: HMAC key
752 const char *label, // IN: a null-terminated label for KDF
753 TPM2B *contextU, // IN: context U
754 TPM2B *contextV, // IN: context V
755 UINT32 sizeInBits, // IN: size of generated key in bit
756 BYTE *keyStream, // OUT: key buffer
757 UINT32 *counterInOut // IN/OUT: caller may provide the iteration
758 // counter for incremental operations to
759 // avoid large intermediate buffers.
760 )
761{
762 CryptKDFa(hash, key, label, contextU, contextV, sizeInBits,
763 keyStream, counterInOut);
764}
Vadim Bendebury56797522015-05-20 10:32:25 -0700765#endif //TPM_ALG_KEYEDHASH //% 1
766//
767//
768// 10.2.5 RSA Functions
769//
770// 10.2.5.1 BuildRSA()
771//
772// Function to set the cryptographic elements of an RSA key into a structure to simplify the interface to
773// _cpri__ RSA function. This can/should be eliminated by building this structure into the object structure.
774//
775#ifdef TPM_ALG_RSA //% 2
776static void
777BuildRSA(
778 OBJECT *rsaKey,
779 RSA_KEY *key
780 )
781{
782 key->exponent = rsaKey->publicArea.parameters.rsaDetail.exponent;
783 if(key->exponent == 0)
784 key->exponent = RSA_DEFAULT_PUBLIC_EXPONENT;
785 key->publicKey = &rsaKey->publicArea.unique.rsa.b;
786 if(rsaKey->attributes.publicOnly || rsaKey->privateExponent.t.size == 0)
787 key->privateKey = NULL;
788 else
789 key->privateKey = &(rsaKey->privateExponent.b);
790}
791//
792//
793// 10.2.5.2 CryptTestKeyRSA()
794//
795// This function provides the interface to _cpri__TestKeyRSA(). If both p and q are provided, n will be set to
796// p*q.
797// If only p is provided, q is computed by q = n/p. If n mod p != 0, TPM_RC_BINDING is returned.
798// The key is validated by checking that a d can be found such that e d mod ((p-1)*(q-1)) = 1. If d is found
799// that satisfies this requirement, it will be placed in d.
800// Page 286 TCG Published Family "2.0"
801// October 30, 2014 Copyright © TCG 2006-2014 Level 00 Revision 01.16
802// Part 4: Supporting Routines Trusted Platform Module Library
803//
804//
805// Error Returns Meaning
806//
807// TPM_RC_BINDING the public and private portions of the key are not matched
808//
809TPM_RC
810CryptTestKeyRSA(
811 TPM2B *d, // OUT: receives the private exponent
812 UINT32 e, // IN: public exponent
813 TPM2B *n, // IN/OUT: public modulu
814 TPM2B *p, // IN: a first prime
815 TPM2B *q // IN: an optional second prime
816 )
817{
818 CRYPT_RESULT retVal;
819 TEST(ALG_NULL_VALUE);
820 pAssert(d != NULL && n != NULL && p != NULL);
821 // Set the exponent
822 if(e == 0)
823 e = RSA_DEFAULT_PUBLIC_EXPONENT;
824 // CRYPT_PARAMETER
825 retVal =_cpri__TestKeyRSA(d, e, n, p, q);
826 if(retVal == CRYPT_SUCCESS)
827 return TPM_RC_SUCCESS;
828 else
829 return TPM_RC_BINDING; // convert CRYPT_PARAMETER
830}
831//
832//
833// 10.2.5.3 CryptGenerateKeyRSA()
834//
835// This function is called to generate an RSA key from a provided seed. It calls _cpri__GenerateKeyRSA()
836// to perform the computations. The implementation is vendor specific.
837//
838// Error Returns Meaning
839//
840// TPM_RC_RANGE the exponent value is not supported
841// TPM_RC_CANCELLED key generation has been canceled
842// TPM_RC_VALUE exponent is not prime or is less than 3; or could not find a prime using
843// the provided parameters
844//
845static TPM_RC
846CryptGenerateKeyRSA(
847 TPMT_PUBLIC *publicArea, // IN/OUT: The public area template for
848 // the new key. The public key
849 // area will be replaced by the
850 // product of two primes found by
851 // this function
852 TPMT_SENSITIVE *sensitive, // OUT: the sensitive area will be
853 // updated to contain the first
854 // prime and the symmetric
855 // encryption key
856 TPM_ALG_ID hashAlg, // IN: the hash algorithm for the KDF
857 TPM2B_SEED *seed, // IN: Seed for the creation
858 TPM2B_NAME *name, // IN: Object name
859 UINT32 *counter // OUT: last iteration of the counter
860)
861{
862 CRYPT_RESULT retVal;
863 UINT32 exponent = publicArea->parameters.rsaDetail.exponent;
864 TEST_HASH(hashAlg);
865 TEST(ALG_NULL_VALUE);
866 // In this implementation, only the default exponent is allowed
867 if(exponent != 0 && exponent != RSA_DEFAULT_PUBLIC_EXPONENT)
868 return TPM_RC_RANGE;
869 exponent = RSA_DEFAULT_PUBLIC_EXPONENT;
870 *counter = 0;
871 // _cpri_GenerateKeyRSA can return CRYPT_CANCEL or CRYPT_FAIL
872 retVal = _cpri__GenerateKeyRSA(&publicArea->unique.rsa.b,
873 &sensitive->sensitive.rsa.b,
874 publicArea->parameters.rsaDetail.keyBits,
875 exponent,
876 hashAlg,
877 &seed->b,
878 "RSA key by vendor",
879 &name->b,
880 counter);
881 // CRYPT_CANCEL -> TPM_RC_CANCELLED; CRYPT_FAIL -> TPM_RC_VALUE
882 return TranslateCryptErrors(retVal);
883}
884//
885//
886// 10.2.5.4 CryptLoadPrivateRSA()
887//
888// This function is called to generate the private exponent of an RSA key. It uses CryptTestKeyRSA().
889//
890// Error Returns Meaning
891//
892// TPM_RC_BINDING public and private parts of rsaKey are not matched
893//
894TPM_RC
895CryptLoadPrivateRSA(
896 OBJECT *rsaKey // IN: the RSA key object
897 )
898{
899 TPM_RC result;
900 TPMT_PUBLIC *publicArea = &rsaKey->publicArea;
901 TPMT_SENSITIVE *sensitive = &rsaKey->sensitive;
902 // Load key by computing the private exponent
903 // TPM_RC_BINDING
904 result = CryptTestKeyRSA(&(rsaKey->privateExponent.b),
905 publicArea->parameters.rsaDetail.exponent,
906 &(publicArea->unique.rsa.b),
907 &(sensitive->sensitive.rsa.b),
908 NULL);
909 if(result == TPM_RC_SUCCESS)
910 rsaKey->attributes.privateExp = SET;
911 return result;
912}
913//
914//
915// 10.2.5.5 CryptSelectRSAScheme()
916//
917// This function is used by TPM2_RSA_Decrypt() and TPM2_RSA_Encrypt(). It sets up the rules to select a
918// scheme between input and object default. This function assume the RSA object is loaded. If a default
919// scheme is defined in object, the default scheme should be chosen, otherwise, the input scheme should
920// be chosen. In the case that both the object and scheme are not TPM_ALG_NULL, then if the schemes
921//
922//
923// are the same, the input scheme will be chosen. if the scheme are not compatible, a NULL pointer will be
924// returned.
925// The return pointer may point to a TPM_ALG_NULL scheme.
926//
927TPMT_RSA_DECRYPT*
928CryptSelectRSAScheme(
929 TPMI_DH_OBJECT rsaHandle, // IN: handle of sign key
930 TPMT_RSA_DECRYPT *scheme // IN: a sign or decrypt scheme
931 )
932{
933 OBJECT *rsaObject;
934 TPMT_ASYM_SCHEME *keyScheme;
935 TPMT_RSA_DECRYPT *retVal = NULL;
936 // Get sign object pointer
937 rsaObject = ObjectGet(rsaHandle);
938 keyScheme = &rsaObject->publicArea.parameters.asymDetail.scheme;
939 // if the default scheme of the object is TPM_ALG_NULL, then select the
940 // input scheme
941 if(keyScheme->scheme == TPM_ALG_NULL)
942 {
943 retVal = scheme;
944 }
945 // if the object scheme is not TPM_ALG_NULL and the input scheme is
946 // TPM_ALG_NULL, then select the default scheme of the object.
947 else if(scheme->scheme == TPM_ALG_NULL)
948 {
949 // if input scheme is NULL
950 retVal = (TPMT_RSA_DECRYPT *)keyScheme;
951 }
952 // get here if both the object scheme and the input scheme are
953 // not TPM_ALG_NULL. Need to insure that they are the same.
954 // IMPLEMENTATION NOTE: This could cause problems if future versions have
955 // schemes that have more values than just a hash algorithm. A new function
956 // (IsSchemeSame()) might be needed then.
957 else if( keyScheme->scheme == scheme->scheme
958 && keyScheme->details.anySig.hashAlg == scheme->details.anySig.hashAlg)
959 {
960 retVal = scheme;
961 }
962 // two different, incompatible schemes specified will return NULL
963 return retVal;
964}
965//
966//
967// 10.2.5.6 CryptDecryptRSA()
968//
969// This function is the interface to _cpri__DecryptRSA(). It handles the return codes from that function and
970// converts them from CRYPT_RESULT to TPM_RC values. The rsaKey parameter must reference an RSA
971// decryption key
972//
973// Error Returns Meaning
974//
975// TPM_RC_BINDING Public and private parts of the key are not cryptographically bound.
976// TPM_RC_SIZE Size of data to decrypt is not the same as the key size.
977// TPM_RC_VALUE Numeric value of the encrypted data is greater than the public
978// exponent, or output buffer is too small for the decrypted message.
979//
980TPM_RC
981CryptDecryptRSA(
982 UINT16 *dataOutSize, // OUT: size of plain text in byte
983 BYTE *dataOut, // OUT: plain text
984 OBJECT *rsaKey, // IN: internal RSA key
985 TPMT_RSA_DECRYPT *scheme, // IN: selects the padding scheme
986 UINT16 cipherInSize, // IN: size of cipher text in byte
987 BYTE *cipherIn, // IN: cipher text
988 const char *label // IN: a label, when needed
989 )
990{
991 RSA_KEY key;
992 CRYPT_RESULT retVal = CRYPT_SUCCESS;
993 UINT32 dSize; // Place to put temporary value for the
994 // returned data size
995 TPMI_ALG_HASH hashAlg = TPM_ALG_NULL; // hash algorithm in the selected
996 // padding scheme
997 TPM_RC result = TPM_RC_SUCCESS;
998 // pointer checks
999 pAssert( (dataOutSize != NULL) && (dataOut != NULL)
1000 && (rsaKey != NULL) && (cipherIn != NULL));
1001 // The public type is a RSA decrypt key
1002 pAssert( (rsaKey->publicArea.type == TPM_ALG_RSA
1003 && rsaKey->publicArea.objectAttributes.decrypt == SET));
1004 // Must have the private portion loaded. This check is made before this
1005 // function is called.
1006 pAssert(rsaKey->attributes.publicOnly == CLEAR);
1007 // decryption requires that the private modulus be present
1008 if(rsaKey->attributes.privateExp == CLEAR)
1009 {
1010 // Load key by computing the private exponent
1011 // CryptLoadPrivateRSA may return TPM_RC_BINDING
1012 result = CryptLoadPrivateRSA(rsaKey);
1013 }
1014 // the input buffer must be the size of the key
1015 if(result == TPM_RC_SUCCESS)
1016 {
1017 if(cipherInSize != rsaKey->publicArea.unique.rsa.t.size)
1018 result = TPM_RC_SIZE;
1019 else
1020 {
1021 BuildRSA(rsaKey, &key);
1022 // Initialize the dOutSize parameter
1023 dSize = *dataOutSize;
1024 // For OAEP scheme, initialize the hash algorithm for padding
1025 if(scheme->scheme == TPM_ALG_OAEP)
1026 {
1027 hashAlg = scheme->details.oaep.hashAlg;
1028 TEST_HASH(hashAlg);
1029 }
1030 // See if the padding mode needs to be tested
1031 TEST(scheme->scheme);
1032 // _cpri__DecryptRSA may return CRYPT_PARAMETER CRYPT_FAIL CRYPT_SCHEME
1033 retVal = _cpri__DecryptRSA(&dSize, dataOut, &key, scheme->scheme,
1034 cipherInSize, cipherIn, hashAlg, label);
1035 // Scheme must have been validated when the key was loaded/imported
1036 pAssert(retVal != CRYPT_SCHEME);
1037 // Set the return size
1038 pAssert(dSize <= UINT16_MAX);
1039 *dataOutSize = (UINT16)dSize;
1040 // CRYPT_PARAMETER -> TPM_RC_VALUE, CRYPT_FAIL -> TPM_RC_VALUE
1041 result = TranslateCryptErrors(retVal);
1042 }
1043 }
1044 return result;
1045}
1046//
1047//
1048// 10.2.5.7 CryptEncryptRSA()
1049//
1050// This function provides the interface to _cpri__EncryptRSA(). The object referenced by rsaKey is required
1051// to be an RSA decryption key.
1052//
1053// Error Returns Meaning
1054//
1055// TPM_RC_SCHEME scheme is not supported
1056// TPM_RC_VALUE numeric value of dataIn is greater than the key modulus
1057//
1058TPM_RC
1059CryptEncryptRSA(
1060 UINT16 *cipherOutSize, // OUT: size of cipher text in byte
1061 BYTE *cipherOut, // OUT: cipher text
1062 OBJECT *rsaKey, // IN: internal RSA key
1063 TPMT_RSA_DECRYPT *scheme, // IN: selects the padding scheme
1064 UINT16 dataInSize, // IN: size of plain text in byte
1065 BYTE *dataIn, // IN: plain text
1066 const char *label // IN: an optional label
1067 )
1068{
1069 RSA_KEY key;
1070 CRYPT_RESULT retVal;
1071 UINT32 cOutSize; // Conversion variable
1072 TPMI_ALG_HASH hashAlg = TPM_ALG_NULL; // hash algorithm in selected
1073 // padding scheme
1074 // must have a pointer to a key and some data to encrypt
1075 pAssert(rsaKey != NULL && dataIn != NULL);
1076 // The public type is a RSA decryption key
1077 pAssert( rsaKey->publicArea.type == TPM_ALG_RSA
1078 && rsaKey->publicArea.objectAttributes.decrypt == SET);
1079 // If the cipher buffer must be provided and it must be large enough
1080 // for the result
1081 pAssert( cipherOut != NULL
1082 && cipherOutSize != NULL
1083 && *cipherOutSize >= rsaKey->publicArea.unique.rsa.t.size);
1084 // Only need the public key and exponent for encryption
1085 BuildRSA(rsaKey, &key);
1086 // Copy the size to the conversion buffer
1087 cOutSize = *cipherOutSize;
1088 // For OAEP scheme, initialize the hash algorithm for padding
1089 if(scheme->scheme == TPM_ALG_OAEP)
1090 {
1091 hashAlg = scheme->details.oaep.hashAlg;
1092 TEST_HASH(hashAlg);
1093 }
1094 // This is a public key operation and does not require that the private key
1095 // be loaded. To verify this, need to do the full algorithm
1096 TEST(scheme->scheme);
1097 // Encrypt the data with the public exponent
1098 // _cpri__EncryptRSA may return CRYPT_PARAMETER or CRYPT_SCHEME
1099 retVal = _cpri__EncryptRSA(&cOutSize,cipherOut, &key, scheme->scheme,
1100 dataInSize, dataIn, hashAlg, label);
1101 pAssert (cOutSize <= UINT16_MAX);
1102 *cipherOutSize = (UINT16)cOutSize;
1103 // CRYPT_PARAMETER -> TPM_RC_VALUE, CRYPT_SCHEME -> TPM_RC_SCHEME
1104 return TranslateCryptErrors(retVal);
1105}
1106//
1107//
1108// 10.2.5.8 CryptSignRSA()
1109//
1110// This function is used to sign a digest with an RSA signing key.
1111//
1112// Error Returns Meaning
1113//
1114// TPM_RC_BINDING public and private part of signKey are not properly bound
1115// TPM_RC_SCHEME scheme is not supported
1116// TPM_RC_VALUE hashData is larger than the modulus of signKey, or the size of
1117// hashData does not match hash algorithm in scheme
1118//
1119static TPM_RC
1120CryptSignRSA(
1121 OBJECT *signKey, // IN: RSA key signs the hash
1122 TPMT_SIG_SCHEME *scheme, // IN: sign scheme
1123 TPM2B_DIGEST *hashData, // IN: hash to be signed
1124 TPMT_SIGNATURE *sig // OUT: signature
1125 )
1126{
1127 UINT32 signSize;
1128 RSA_KEY key;
1129 CRYPT_RESULT retVal;
1130 TPM_RC result = TPM_RC_SUCCESS;
1131 pAssert( (signKey != NULL) && (scheme != NULL)
1132 && (hashData != NULL) && (sig != NULL));
1133 // assume that the key has private part loaded and that it is a signing key.
1134 pAssert( (signKey->attributes.publicOnly == CLEAR)
1135 && (signKey->publicArea.objectAttributes.sign == SET));
1136 // check if the private exponent has been computed
1137 if(signKey->attributes.privateExp == CLEAR)
1138 // May return TPM_RC_BINDING
1139 result = CryptLoadPrivateRSA(signKey);
1140 if(result == TPM_RC_SUCCESS)
1141 {
1142 BuildRSA(signKey, &key);
1143 // Make sure that the hash is tested
1144 TEST_HASH(sig->signature.any.hashAlg);
1145 // Run a test of the RSA sign
1146 TEST(scheme->scheme);
1147 // _crypi__SignRSA can return CRYPT_SCHEME and CRYPT_PARAMETER
1148 retVal = _cpri__SignRSA(&signSize,
1149 sig->signature.rsassa.sig.t.buffer,
1150 &key,
1151 sig->sigAlg,
1152 sig->signature.any.hashAlg,
1153 hashData->t.size, hashData->t.buffer);
1154 pAssert(signSize <= UINT16_MAX);
1155 sig->signature.rsassa.sig.t.size = (UINT16)signSize;
1156 // CRYPT_SCHEME -> TPM_RC_SCHEME; CRYPT_PARAMTER -> TPM_RC_VALUE
1157 result = TranslateCryptErrors(retVal);
1158 }
1159 return result;
1160}
1161//
1162//
1163// 10.2.5.9 CryptRSAVerifySignature()
1164//
1165// This function is used to verify signature signed by a RSA key.
1166//
1167// Error Returns Meaning
1168//
1169// TPM_RC_SIGNATURE if signature is not genuine
1170// TPM_RC_SCHEME signature scheme not supported
1171//
1172static TPM_RC
1173CryptRSAVerifySignature(
1174 OBJECT *signKey, // IN: RSA key signed the hash
1175 TPM2B_DIGEST *digestData, // IN: digest being signed
1176 TPMT_SIGNATURE *sig // IN: signature to be verified
1177 )
1178{
1179 RSA_KEY key;
1180 CRYPT_RESULT retVal;
1181 TPM_RC result;
1182 // Validate parameter assumptions
1183 pAssert((signKey != NULL) && (digestData != NULL) && (sig != NULL));
1184 TEST_HASH(sig->signature.any.hashAlg);
1185 TEST(sig->sigAlg);
1186 // This is a public-key-only operation
1187 BuildRSA(signKey, &key);
1188 // Call crypto engine to verify signature
1189 // _cpri_ValidateSignaturRSA may return CRYPT_FAIL or CRYPT_SCHEME
1190 retVal = _cpri__ValidateSignatureRSA(&key,
1191 sig->sigAlg,
1192 sig->signature.any.hashAlg,
1193 digestData->t.size,
1194 digestData->t.buffer,
1195 sig->signature.rsassa.sig.t.size,
1196 sig->signature.rsassa.sig.t.buffer,
1197 0);
1198 // _cpri__ValidateSignatureRSA can return CRYPT_SUCCESS, CRYPT_FAIL, or
1199 // CRYPT_SCHEME. Translate CRYPT_FAIL to TPM_RC_SIGNATURE
1200 if(retVal == CRYPT_FAIL)
1201 result = TPM_RC_SIGNATURE;
1202 else
1203 // CRYPT_SCHEME -> TPM_RC_SCHEME
1204 result = TranslateCryptErrors(retVal);
1205 return result;
1206}
1207//
1208#endif //TPM_ALG_RSA //% 2
1209//
1210//
1211// 10.2.6 ECC Functions
1212//
1213// 10.2.6.1 CryptEccGetCurveDataPointer()
1214//
1215// This function returns a pointer to an ECC_CURVE_VALUES structure that contains the parameters for
1216// the key size and schemes for a given curve.
1217//
1218#ifdef TPM_ALG_ECC //% 3
1219static const ECC_CURVE *
1220CryptEccGetCurveDataPointer(
1221 TPM_ECC_CURVE curveID // IN: id of the curve
1222 )
1223{
1224 return _cpri__EccGetParametersByCurveId(curveID);
1225}
1226//
1227//
1228// 10.2.6.2 CryptEccGetKeySizeInBits()
1229//
1230// This function returns the size in bits of the key associated with a curve.
1231//
1232UINT16
1233CryptEccGetKeySizeInBits(
1234 TPM_ECC_CURVE curveID // IN: id of the curve
1235 )
1236{
1237 const ECC_CURVE *curve = CryptEccGetCurveDataPointer(curveID);
1238 UINT16 keySizeInBits = 0;
1239 if(curve != NULL)
1240 keySizeInBits = curve->keySizeBits;
1241 return keySizeInBits;
1242}
1243//
1244//
Vadim Bendebury56797522015-05-20 10:32:25 -07001245// 10.2.6.4 CryptEccGetParameter()
1246//
1247// This function returns a pointer to an ECC curve parameter. The parameter is selected by a single
1248// character designator from the set of {pnabxyh}.
1249//
1250LIB_EXPORT const TPM2B *
1251CryptEccGetParameter(
1252 char p, // IN: the parameter selector
1253 TPM_ECC_CURVE curveId // IN: the curve id
1254 )
1255{
1256 const ECC_CURVE *curve = _cpri__EccGetParametersByCurveId(curveId);
1257 const TPM2B *parameter = NULL;
1258 if(curve != NULL)
1259 {
1260 switch (p)
1261 {
1262 case 'p':
1263 parameter = curve->curveData->p;
1264 break;
1265 case 'n':
1266 parameter = curve->curveData->n;
1267 break;
1268 case 'a':
1269 parameter = curve->curveData->a;
1270 break;
1271 case 'b':
1272 parameter = curve->curveData->b;
1273 break;
1274 case 'x':
1275 parameter = curve->curveData->x;
1276 break;
1277 case 'y':
1278 parameter = curve->curveData->y;
1279 break;
1280 case 'h':
1281 parameter = curve->curveData->h;
1282 break;
1283 default:
1284 break;
1285 }
1286 }
1287 return parameter;
1288}
1289//
1290//
1291// 10.2.6.5 CryptGetCurveSignScheme()
1292//
1293// This function will return a pointer to the scheme of the curve.
1294//
1295const TPMT_ECC_SCHEME *
1296CryptGetCurveSignScheme(
1297 TPM_ECC_CURVE curveId // IN: The curve selector
1298 )
1299{
1300 const ECC_CURVE *curve = _cpri__EccGetParametersByCurveId(curveId);
1301 const TPMT_ECC_SCHEME *scheme = NULL;
1302 if(curve != NULL)
1303 scheme = &(curve->sign);
1304 return scheme;
1305}
1306//
1307//
1308// 10.2.6.6 CryptEccIsPointOnCurve()
1309//
1310// This function will validate that an ECC point is on the curve of given curveID.
1311//
1312// Return Value Meaning
1313//
1314// TRUE if the point is on curve
1315// FALSE if the point is not on curve
1316//
1317BOOL
1318CryptEccIsPointOnCurve(
1319 TPM_ECC_CURVE curveID, // IN: ECC curve ID
1320 TPMS_ECC_POINT *Q // IN: ECC point
1321 )
1322{
1323 // Make sure that point multiply is working
1324 TEST(TPM_ALG_ECC);
1325 // Check point on curve logic by seeing if the test key is on the curve
1326 // Call crypto engine function to check if a ECC public point is on the
1327 // given curve
1328 if(_cpri__EccIsPointOnCurve(curveID, Q))
1329 return TRUE;
1330 else
1331 return FALSE;
1332}
1333//
1334//
1335// 10.2.6.7 CryptNewEccKey()
1336//
1337// This function creates a random ECC key that is not derived from other parameters as is a Primary Key.
1338//
1339TPM_RC
1340CryptNewEccKey(
1341 TPM_ECC_CURVE curveID, // IN: ECC curve
1342 TPMS_ECC_POINT *publicPoint, // OUT: public point
1343 TPM2B_ECC_PARAMETER *sensitive // OUT: private area
1344 )
1345{
1346 TPM_RC result = TPM_RC_SUCCESS;
1347 // _cpri__GetEphemeralECC may return CRYPT_PARAMETER
1348 if(_cpri__GetEphemeralEcc(publicPoint, sensitive, curveID) != CRYPT_SUCCESS)
1349 // Something is wrong with the key.
1350 result = TPM_RC_KEY;
1351 return result;
1352}
1353//
1354//
1355// 10.2.6.8 CryptEccPointMultiply()
1356//
1357// This function is used to perform a point multiply R = [d]Q. If Q is not provided, the multiplication is
1358// performed using the generator point of the curve.
1359//
1360// Error Returns Meaning
1361//
1362// TPM_RC_ECC_POINT invalid optional ECC point pIn
1363// TPM_RC_NO_RESULT multiplication resulted in a point at infinity
1364// TPM_RC_CANCELED if a self-test was done, it might have been aborted
1365//
1366TPM_RC
1367CryptEccPointMultiply(
1368 TPMS_ECC_POINT *pOut, // OUT: output point
1369 TPM_ECC_CURVE curveId, // IN: curve selector
1370 TPM2B_ECC_PARAMETER *dIn, // IN: public scalar
1371 TPMS_ECC_POINT *pIn // IN: optional point
1372 )
1373{
1374 TPM2B_ECC_PARAMETER *n = NULL;
1375 CRYPT_RESULT retVal;
1376 pAssert(pOut != NULL && dIn != NULL);
1377 if(pIn != NULL)
1378 {
1379 n = dIn;
1380 dIn = NULL;
1381 }
1382 // Do a test of point multiply
1383 TEST(TPM_ALG_ECC);
1384 // _cpri__EccPointMultiply may return CRYPT_POINT or CRYPT_NO_RESULT
1385 retVal = _cpri__EccPointMultiply(pOut, curveId, dIn, pIn, n);
1386 // CRYPT_POINT->TPM_RC_ECC_POINT and CRYPT_NO_RESULT->TPM_RC_NO_RESULT
1387 return TranslateCryptErrors(retVal);
1388}
1389//
1390//
1391// 10.2.6.9 CryptGenerateKeyECC()
1392//
1393// This function generates an ECC key from a seed value.
1394// The method here may not work for objects that have an order (G) that with a different size than a private
1395// key.
1396//
1397// Error Returns Meaning
1398//
1399// TPM_RC_VALUE hash algorithm is not supported
1400//
1401static TPM_RC
1402CryptGenerateKeyECC(
1403 TPMT_PUBLIC *publicArea, // IN/OUT: The public area template for the new
1404 // key.
1405 TPMT_SENSITIVE *sensitive, // IN/OUT: the sensitive area
1406 TPM_ALG_ID hashAlg, // IN: algorithm for the KDF
1407 TPM2B_SEED *seed, // IN: the seed value
1408 TPM2B_NAME *name, // IN: the name of the object
1409 UINT32 *counter // OUT: the iteration counter
1410 )
1411{
1412 CRYPT_RESULT retVal;
1413 TEST_HASH(hashAlg);
1414 TEST(ALG_ECDSA_VALUE); // ECDSA is used to verify each key
1415 // The iteration counter has no meaning for ECC key generation. The parameter
1416 // will be overloaded for those implementations that have a requirement for
1417 // doing pair-wise consistency checks on signing keys. If the counter parameter
1418 // is 0 or NULL, then no consistency check is done. If it is other than 0, then
1419 // a consistency check is run. This modification allow this code to work with
1420 // the existing versions of the CrytpoEngine and with FIPS-compliant versions
1421 // as well.
1422 *counter = (UINT32)(publicArea->objectAttributes.sign == SET);
1423 // _cpri__GenerateKeyEcc only has one error return (CRYPT_PARAMETER) which means
1424 // that the hash algorithm is not supported. This should not be possible
1425 retVal = _cpri__GenerateKeyEcc(&publicArea->unique.ecc,
1426 &sensitive->sensitive.ecc,
1427 publicArea->parameters.eccDetail.curveID,
1428 hashAlg, &seed->b, "ECC key by vendor",
1429 &name->b, counter);
1430 // This will only be useful if _cpri__GenerateKeyEcc return CRYPT_CANCEL
1431 return TranslateCryptErrors(retVal);
1432}
1433//
1434//
1435// 10.2.6.10 CryptSignECC()
1436//
1437// This function is used for ECC signing operations. If the signing scheme is a split scheme, and the signing
1438// operation is successful, the commit value is retired.
1439//
1440//
1441// Error Returns Meaning
1442//
1443// TPM_RC_SCHEME unsupported scheme
1444// TPM_RC_VALUE invalid commit status (in case of a split scheme) or failed to generate
1445// r value.
1446//
1447static TPM_RC
1448CryptSignECC(
1449 OBJECT *signKey, // IN: ECC key to sign the hash
1450 TPMT_SIG_SCHEME *scheme, // IN: sign scheme
1451 TPM2B_DIGEST *hashData, // IN: hash to be signed
1452 TPMT_SIGNATURE *signature // OUT: signature
1453 )
1454{
1455 TPM2B_ECC_PARAMETER r;
1456 TPM2B_ECC_PARAMETER *pr = NULL;
1457 CRYPT_RESULT retVal;
1458 // Run a test of the ECC sign and verify if it has not already been run
1459 TEST_HASH(scheme->details.any.hashAlg);
1460 TEST(scheme->scheme);
1461 if(CryptIsSplitSign(scheme->scheme))
1462 {
1463 // When this code was written, the only split scheme was ECDAA
1464 // (which can also be used for U-Prove).
1465 if(!CryptGenerateR(&r,
1466 &scheme->details.ecdaa.count,
1467 signKey->publicArea.parameters.eccDetail.curveID,
1468 &signKey->name))
1469 return TPM_RC_VALUE;
1470 pr = &r;
1471 }
1472 // Call crypto engine function to sign
1473 // _cpri__SignEcc may return CRYPT_SCHEME
1474 retVal = _cpri__SignEcc(&signature->signature.ecdsa.signatureR,
1475 &signature->signature.ecdsa.signatureS,
1476 scheme->scheme,
1477 scheme->details.any.hashAlg,
1478 signKey->publicArea.parameters.eccDetail.curveID,
1479 &signKey->sensitive.sensitive.ecc,
1480 &hashData->b,
1481 pr
1482 );
1483 if(CryptIsSplitSign(scheme->scheme) && retVal == CRYPT_SUCCESS)
1484 CryptEndCommit(scheme->details.ecdaa.count);
1485 // CRYPT_SCHEME->TPM_RC_SCHEME
1486 return TranslateCryptErrors(retVal);
1487}
1488//
1489//
1490// 10.2.6.11 CryptECCVerifySignature()
1491//
1492// This function is used to verify a signature created with an ECC key.
1493//
1494// Error Returns Meaning
1495//
1496// TPM_RC_SIGNATURE if signature is not valid
1497// TPM_RC_SCHEME the signing scheme or hashAlg is not supported
1498//
1499static TPM_RC
1500CryptECCVerifySignature(
1501 OBJECT *signKey, // IN: ECC key signed the hash
1502 TPM2B_DIGEST *digestData, // IN: digest being signed
1503 TPMT_SIGNATURE *signature // IN: signature to be verified
1504 )
1505{
1506 CRYPT_RESULT retVal;
1507 TEST_HASH(signature->signature.any.hashAlg);
1508 TEST(signature->sigAlg);
1509 // This implementation uses the fact that all the defined ECC signing
1510 // schemes have the hash as the first parameter.
1511 // _cpriValidateSignatureEcc may return CRYPT_FAIL or CRYP_SCHEME
1512 retVal = _cpri__ValidateSignatureEcc(&signature->signature.ecdsa.signatureR,
1513 &signature->signature.ecdsa.signatureS,
1514 signature->sigAlg,
1515 signature->signature.any.hashAlg,
1516 signKey->publicArea.parameters.eccDetail.curveID,
1517 &signKey->publicArea.unique.ecc,
1518 &digestData->b);
1519 if(retVal == CRYPT_FAIL)
1520 return TPM_RC_SIGNATURE;
1521 // CRYPT_SCHEME->TPM_RC_SCHEME
1522 return TranslateCryptErrors(retVal);
1523}
1524//
1525//
1526// 10.2.6.12 CryptGenerateR()
1527//
1528// This function computes the commit random value for a split signing scheme.
1529// If c is NULL, it indicates that r is being generated for TPM2_Commit(). If c is not NULL, the TPM will
1530// validate that the gr.commitArray bit associated with the input value of c is SET. If not, the TPM returns
1531// FALSE and no r value is generated.
1532//
1533// Return Value Meaning
1534//
1535// TRUE r value computed
1536// FALSE no r value computed
1537//
1538BOOL
1539CryptGenerateR(
1540 TPM2B_ECC_PARAMETER *r, // OUT: the generated random value
1541 UINT16 *c, // IN/OUT: count value.
1542 TPMI_ECC_CURVE curveID, // IN: the curve for the value
1543 TPM2B_NAME *name // IN: optional name of a key to
1544 // associate with 'r'
1545 )
1546{
1547 // This holds the marshaled g_commitCounter.
1548 TPM2B_TYPE(8B, 8);
Vadim Bendeburyc00055c2015-05-29 22:50:18 -07001549 TPM2B_8B cntr = {.b.size = 8};
Vadim Bendebury56797522015-05-20 10:32:25 -07001550 UINT32 iterations;
1551 const TPM2B *n;
1552 UINT64 currentCount = gr.commitCounter;
1553 // This is just to suppress a compiler warning about a conditional expression
1554 // being a constant. This is because of the macro expansion of ryptKDFa
1555 TPMI_ALG_HASH hashAlg = CONTEXT_INTEGRITY_HASH_ALG;
1556 n = CryptEccGetParameter('n', curveID);
1557 pAssert(r != NULL && n != NULL);
1558 // If this is the commit phase, use the current value of the commit counter
1559 if(c != NULL)
1560//
1561 {
1562 UINT16 t1;
1563 // if the array bit is not set, can't use the value.
1564 if(!BitIsSet((*c & COMMIT_INDEX_MASK), gr.commitArray,
1565 sizeof(gr.commitArray)))
1566 return FALSE;
1567 // If it is the sign phase, figure out what the counter value was
1568 // when the commitment was made.
1569 //
1570 // When gr.commitArray has less than 64K bits, the extra
1571 // bits of 'c' are used as a check to make sure that the
1572 // signing operation is not using an out of range count value
1573 t1 = (UINT16)currentCount;
1574 // If the lower bits of c are greater or equal to the lower bits of t1
1575 // then the upper bits of t1 must be one more than the upper bits
1576 // of c
1577 if((*c & COMMIT_INDEX_MASK) >= (t1 & COMMIT_INDEX_MASK))
1578 // Since the counter is behind, reduce the current count
1579 currentCount = currentCount - (COMMIT_INDEX_MASK + 1);
1580 t1 = (UINT16)currentCount;
1581 if((t1 & ~COMMIT_INDEX_MASK) != (*c & ~COMMIT_INDEX_MASK))
1582 return FALSE;
1583 // set the counter to the value that was
1584 // present when the commitment was made
1585 currentCount = (currentCount & 0xffffffffffff0000) | *c;
1586 }
1587 // Marshal the count value to a TPM2B buffer for the KDF
1588 cntr.t.size = sizeof(currentCount);
1589 UINT64_TO_BYTE_ARRAY(currentCount, cntr.t.buffer);
1590 // Now can do the KDF to create the random value for the signing operation
1591 // During the creation process, we may generate an r that does not meet the
1592 // requirements of the random value.
1593 // want to generate a new r.
1594 r->t.size = n->size;
1595 // Arbitrary upper limit on the number of times that we can look for
1596 // a suitable random value. The normally number of tries will be 1.
1597 for(iterations = 1; iterations < 1000000;)
1598 {
1599 BYTE *pr = &r->b.buffer[0];
1600 int i;
1601 CryptKDFa(hashAlg, &gr.commitNonce.b, "ECDAA Commit",
1602 name, &cntr.b, n->size * 8, r->t.buffer, &iterations);
1603 // random value must be less than the prime
1604 if(CryptCompare(r->b.size, r->b.buffer, n->size, n->buffer) >= 0)
1605 continue;
1606 // in this implementation it is required that at least bit
1607 // in the upper half of the number be set
1608 for(i = n->size/2; i > 0; i--)
1609 if(*pr++ != 0)
1610 return TRUE;
1611 }
1612 return FALSE;
1613}
1614//
1615//
1616//
1617// 10.2.6.13 CryptCommit()
1618//
1619// This function is called when the count value is committed. The gr.commitArray value associated with the
1620// current count value is SET and g_commitCounter is incremented. The low-order 16 bits of old value of the
1621// counter is returned.
1622//
1623UINT16
1624CryptCommit(
1625 void
1626 )
1627{
1628 UINT16 oldCount = (UINT16)gr.commitCounter;
1629 gr.commitCounter++;
1630 BitSet(oldCount & COMMIT_INDEX_MASK, gr.commitArray, sizeof(gr.commitArray));
1631 return oldCount;
1632}
1633//
1634//
1635// 10.2.6.14 CryptEndCommit()
1636//
1637// This function is called when the signing operation using the committed value is completed. It clears the
1638// gr.commitArray bit associated with the count value so that it can't be used again.
1639//
1640void
1641CryptEndCommit(
1642 UINT16 c // IN: the counter value of the commitment
1643 )
1644{
1645 BitClear((c & COMMIT_INDEX_MASK), gr.commitArray, sizeof(gr.commitArray));
1646}
1647//
1648//
1649// 10.2.6.15 CryptCommitCompute()
1650//
1651// This function performs the computations for the TPM2_Commit() command. This could be a macro.
1652//
1653// Error Returns Meaning
1654//
1655// TPM_RC_NO_RESULT K, L, or E is the point at infinity
1656// TPM_RC_CANCELLED command was canceled
1657//
1658TPM_RC
1659CryptCommitCompute(
1660 TPMS_ECC_POINT *K, // OUT: [d]B
1661 TPMS_ECC_POINT *L, // OUT: [r]B
1662 TPMS_ECC_POINT *E, // OUT: [r]M
1663 TPM_ECC_CURVE curveID, // IN: The curve for the computation
1664 TPMS_ECC_POINT *M, // IN: M (P1)
1665 TPMS_ECC_POINT *B, // IN: B (x2, y2)
1666 TPM2B_ECC_PARAMETER *d, // IN: the private scalar
1667 TPM2B_ECC_PARAMETER *r // IN: the computed r value
1668 )
1669{
1670 TEST(ALG_ECDH_VALUE);
1671 // CRYPT_NO_RESULT->TPM_RC_NO_RESULT CRYPT_CANCEL->TPM_RC_CANCELLED
1672 return TranslateCryptErrors(
1673 _cpri__EccCommitCompute(K, L , E, curveID, M, B, d, r));
1674}
1675//
1676//
1677//
1678// 10.2.6.16 CryptEccGetParameters()
1679//
1680// This function returns the ECC parameter details of the given curve
1681//
1682// Return Value Meaning
1683//
1684// TRUE Get parameters success
1685// FALSE Unsupported ECC curve ID
1686//
1687BOOL
1688CryptEccGetParameters(
1689 TPM_ECC_CURVE curveId, // IN: ECC curve ID
1690 TPMS_ALGORITHM_DETAIL_ECC *parameters // OUT: ECC parameter
1691 )
1692{
1693 const ECC_CURVE *curve = _cpri__EccGetParametersByCurveId(curveId);
1694 const ECC_CURVE_DATA *data;
1695 BOOL found = curve != NULL;
1696 if(found)
1697 {
1698 data = curve->curveData;
1699 parameters->curveID = curve->curveId;
1700 // Key size in bit
1701 parameters->keySize = curve->keySizeBits;
1702 // KDF
1703 parameters->kdf = curve->kdf;
1704 // Sign
1705 parameters->sign = curve->sign;
1706 // Copy p value
1707 MemoryCopy2B(&parameters->p.b, data->p, sizeof(parameters->p.t.buffer));
1708 // Copy a value
1709 MemoryCopy2B(&parameters->a.b, data->a, sizeof(parameters->a.t.buffer));
1710 // Copy b value
1711 MemoryCopy2B(&parameters->b.b, data->b, sizeof(parameters->b.t.buffer));
1712 // Copy Gx value
1713 MemoryCopy2B(&parameters->gX.b, data->x, sizeof(parameters->gX.t.buffer));
1714 // Copy Gy value
1715 MemoryCopy2B(&parameters->gY.b, data->y, sizeof(parameters->gY.t.buffer));
1716 // Copy n value
1717 MemoryCopy2B(&parameters->n.b, data->n, sizeof(parameters->n.t.buffer));
1718 // Copy h value
1719 MemoryCopy2B(&parameters->h.b, data->h, sizeof(parameters->h.t.buffer));
1720 }
1721 return found;
1722}
1723#if CC_ZGen_2Phase == YES
1724//
1725// CryptEcc2PhaseKeyExchange() This is the interface to the key exchange function.
1726//
1727TPM_RC
1728CryptEcc2PhaseKeyExchange(
1729 TPMS_ECC_POINT *outZ1, // OUT: the computed point
1730 TPMS_ECC_POINT *outZ2, // OUT: optional second point
1731 TPM_ALG_ID scheme, // IN: the key exchange scheme
1732 TPM_ECC_CURVE curveId, // IN: the curve for the computation
1733 TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key
1734 TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key
1735 TPMS_ECC_POINT *QsB, // IN: static public party B key
1736 TPMS_ECC_POINT *QeB // IN: ephemeral public party B key
1737 )
1738{
1739 return (TranslateCryptErrors(_cpri__C_2_2_KeyExchange(outZ1,
1740 outZ2,
1741 scheme,
1742 curveId,
1743 dsA,
1744 deA,
1745 QsB,
1746 QeB)));
1747}
1748#endif // CC_ZGen_2Phase
1749#endif //TPM_ALG_ECC //% 3
1750//
1751//
1752// 10.2.6.17 CryptIsSchemeAnonymous()
1753//
1754// This function is used to test a scheme to see if it is an anonymous scheme The only anonymous scheme
1755// is ECDAA. ECDAA can be used to do things like U-Prove.
1756//
1757BOOL
1758CryptIsSchemeAnonymous(
1759 TPM_ALG_ID scheme // IN: the scheme algorithm to test
1760 )
1761{
1762#ifdef TPM_ALG_ECDAA
1763 return (scheme == TPM_ALG_ECDAA);
1764#else
1765 UNREFERENCED(scheme);
1766 return 0;
1767#endif
1768}
1769//
1770//
1771// 10.2.7 Symmetric Functions
1772//
1773// 10.2.7.1 ParmDecryptSym()
1774//
1775// This function performs parameter decryption using symmetric block cipher.
1776//
1777void
1778ParmDecryptSym(
1779 TPM_ALG_ID symAlg, // IN: the symmetric algorithm
1780 TPM_ALG_ID hash, // IN: hash algorithm for KDFa
1781 UINT16 keySizeInBits, // IN: key key size in bit
1782 TPM2B *key, // IN: KDF HMAC key
1783 TPM2B *nonceCaller, // IN: nonce caller
1784 TPM2B *nonceTpm, // IN: nonce TPM
1785 UINT32 dataSize, // IN: size of parameter buffer
1786 BYTE *data // OUT: buffer to be decrypted
1787 )
1788{
1789 // KDF output buffer
1790 // It contains parameters for the CFB encryption
1791 // From MSB to LSB, they are the key and iv
1792 BYTE symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE];
1793 // Symmetric key size in byte
1794 UINT16 keySize = (keySizeInBits + 7) / 8;
1795 TPM2B_IV iv;
1796 iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits);
1797 // If there is decryption to do...
1798 if(iv.t.size > 0)
1799 {
1800 // Generate key and iv
1801 CryptKDFa(hash, key, "CFB", nonceCaller, nonceTpm,
1802 keySizeInBits + (iv.t.size * 8), symParmString, NULL);
1803 MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size,
1804 sizeof(iv.t.buffer));
1805 CryptSymmetricDecrypt(data, symAlg, keySizeInBits, TPM_ALG_CFB,
1806 symParmString, &iv, dataSize, data);
1807 }
1808 return;
1809}
1810//
1811//
1812// 10.2.7.2 ParmEncryptSym()
1813//
1814// This function performs parameter encryption using symmetric block cipher.
1815//
1816void
1817ParmEncryptSym(
1818 TPM_ALG_ID symAlg, // IN: symmetric algorithm
1819 TPM_ALG_ID hash, // IN: hash algorithm for KDFa
1820 UINT16 keySizeInBits, // IN: AES key size in bit
1821 TPM2B *key, // IN: KDF HMAC key
1822 TPM2B *nonceCaller, // IN: nonce caller
1823 TPM2B *nonceTpm, // IN: nonce TPM
1824 UINT32 dataSize, // IN: size of parameter buffer
1825 BYTE *data // OUT: buffer to be encrypted
1826 )
1827{
1828 // KDF output buffer
1829 // It contains parameters for the CFB encryption
1830 BYTE symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE];
1831 // Symmetric key size in bytes
1832 UINT16 keySize = (keySizeInBits + 7) / 8;
1833 TPM2B_IV iv;
1834 iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits);
1835 // See if there is any encryption to do
1836 if(iv.t.size > 0)
1837 {
1838 // Generate key and iv
1839 CryptKDFa(hash, key, "CFB", nonceTpm, nonceCaller,
1840 keySizeInBits + (iv.t.size * 8), symParmString, NULL);
1841 MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size,
1842 sizeof(iv.t.buffer));
1843 CryptSymmetricEncrypt(data, symAlg, keySizeInBits, TPM_ALG_CFB,
1844 symParmString, &iv, dataSize, data);
1845 }
1846 return;
1847}
1848//
1849//
1850//
1851// 10.2.7.3 CryptGenerateNewSymmetric()
1852//
1853// This function creates the sensitive symmetric values for an HMAC or symmetric key. If the sensitive area
1854// is zero, then the sensitive creation key data is copied. If it is not zero, then the TPM will generate a
1855// random value of the selected size.
1856//
1857void
1858CryptGenerateNewSymmetric(
1859 TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation data
1860 TPMT_SENSITIVE *sensitive, // OUT: sensitive area
1861 TPM_ALG_ID hashAlg, // IN: hash algorithm for the KDF
1862 TPM2B_SEED *seed, // IN: seed used in creation
1863 TPM2B_NAME *name // IN: name of the object
1864 )
1865{
1866 // This function is called to create a key and obfuscation value for a
1867 // symmetric key that can either be a block cipher or an XOR key. The buffer
1868 // in sensitive->sensitive will hold either. When we call the function
1869 // to copy the input value or generated value to the sensitive->sensitive
1870 // buffer we will need to have a size for the output buffer. This define
1871 // computes the maximum that it might need to be and uses that. It will always
1872 // be smaller than the largest value that will fit.
1873 #define MAX_SENSITIVE_SIZE \
1874 (MAX(sizeof(sensitive->sensitive.bits.t.buffer), \
1875 sizeof(sensitive->sensitive.sym.t.buffer)))
1876 // set the size of the obfuscation value
1877 sensitive->seedValue.t.size = CryptGetHashDigestSize(hashAlg);
1878 // If the input sensitive size is zero, then create both the sensitive data
1879 // and the obfuscation value
1880 if(sensitiveCreate->data.t.size == 0)
1881 {
1882 BYTE symValues[MAX(MAX_DIGEST_SIZE, MAX_SYM_KEY_BYTES)
1883 + MAX_DIGEST_SIZE];
1884 UINT16 requestSize;
1885 // Set the size of the request to be the size of the key and the
1886 // obfuscation value
1887 requestSize = sensitive->sensitive.sym.t.size
1888 + sensitive->seedValue.t.size;
1889 pAssert(requestSize <= sizeof(symValues));
1890 requestSize = _cpri__GenerateSeededRandom(requestSize, symValues, hashAlg,
1891 &seed->b,
1892 "symmetric sensitive", &name->b,
1893 NULL);
1894 pAssert(requestSize != 0);
1895 // Copy the new key
1896 MemoryCopy(sensitive->sensitive.sym.t.buffer,
1897 symValues, sensitive->sensitive.sym.t.size,
1898 MAX_SENSITIVE_SIZE);
1899 // copy the obfuscation value
1900 MemoryCopy(sensitive->seedValue.t.buffer,
1901 &symValues[sensitive->sensitive.sym.t.size],
1902 sensitive->seedValue.t.size,
1903 sizeof(sensitive->seedValue.t.buffer));
1904 }
1905 else
1906 {
1907 // Copy input symmetric key to sensitive area as long as it will fit
1908 MemoryCopy2B(&sensitive->sensitive.sym.b, &sensitiveCreate->data.b,
1909 MAX_SENSITIVE_SIZE);
1910 // Create the obfuscation value
1911 _cpri__GenerateSeededRandom(sensitive->seedValue.t.size,
1912 sensitive->seedValue.t.buffer,
1913 hashAlg, &seed->b,
1914 "symmetric obfuscation", &name->b, NULL);
1915 }
1916 return;
1917}
1918//
1919//
1920// 10.2.7.4 CryptGenerateKeySymmetric()
1921//
1922// This function derives a symmetric cipher key from the provided seed.
1923//
1924// Error Returns Meaning
1925//
1926// TPM_RC_KEY_SIZE key size in the public area does not match the size in the sensitive
1927// creation area
1928//
1929static TPM_RC
1930CryptGenerateKeySymmetric(
1931 TPMT_PUBLIC *publicArea, // IN/OUT: The public area template
1932 // for the new key.
1933 TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation data
1934 TPMT_SENSITIVE *sensitive, // OUT: sensitive area
1935 TPM_ALG_ID hashAlg, // IN: hash algorithm for the KDF
1936 TPM2B_SEED *seed, // IN: seed used in creation
1937 TPM2B_NAME *name // IN: name of the object
1938 )
1939{
1940 // If this is not a new key, then the provided key data must be the right size
1941 if(publicArea->objectAttributes.sensitiveDataOrigin == CLEAR)
1942 {
1943 if( (sensitiveCreate->data.t.size * 8)
Vadim Bendeburyc00055c2015-05-29 22:50:18 -07001944 != publicArea->parameters.symDetail.keyBits.sym)
Vadim Bendebury56797522015-05-20 10:32:25 -07001945 return TPM_RC_KEY_SIZE;
1946 // Make sure that the key size is OK.
1947 // This implementation only supports symmetric key sizes that are
1948 // multiples of 8
Vadim Bendeburyc00055c2015-05-29 22:50:18 -07001949 if(publicArea->parameters.symDetail.keyBits.sym % 8 != 0)
Vadim Bendebury56797522015-05-20 10:32:25 -07001950 return TPM_RC_KEY_SIZE;
1951 }
1952 else
1953 {
1954 // TPM is going to generate the key so set the size
1955 sensitive->sensitive.sym.t.size
Vadim Bendeburyc00055c2015-05-29 22:50:18 -07001956 = publicArea->parameters.symDetail.keyBits.sym / 8;
Vadim Bendebury56797522015-05-20 10:32:25 -07001957 sensitiveCreate->data.t.size = 0;
1958 }
1959 // Fill in the sensitive area
1960 CryptGenerateNewSymmetric(sensitiveCreate, sensitive, hashAlg,
1961 seed, name);
1962 // Create unique area in public
1963 CryptComputeSymmetricUnique(publicArea->nameAlg,
1964 sensitive, &publicArea->unique.sym);
1965 return TPM_RC_SUCCESS;
1966}
1967//
1968//
1969//
1970// 10.2.7.5 CryptXORObfuscation()
1971//
1972// This function implements XOR obfuscation. It should not be called if the hash algorithm is not
1973// implemented. The only return value from this function is TPM_RC_SUCCESS.
1974//
1975#ifdef TPM_ALG_KEYEDHASH //% 5
1976void
1977CryptXORObfuscation(
1978 TPM_ALG_ID hash, // IN: hash algorithm for KDF
1979 TPM2B *key, // IN: KDF key
1980 TPM2B *contextU, // IN: contextU
1981 TPM2B *contextV, // IN: contextV
1982 UINT32 dataSize, // IN: size of data buffer
1983 BYTE *data // IN/OUT: data to be XORed in place
1984 )
1985{
1986 BYTE mask[MAX_DIGEST_SIZE]; // Allocate a digest sized buffer
1987 BYTE *pm;
1988 UINT32 i;
1989 UINT32 counter = 0;
1990 UINT16 hLen = CryptGetHashDigestSize(hash);
1991 UINT32 requestSize = dataSize * 8;
1992 INT32 remainBytes = (INT32) dataSize;
1993 pAssert((key != NULL) && (data != NULL) && (hLen != 0));
1994 // Call KDFa to generate XOR mask
1995 for(; remainBytes > 0; remainBytes -= hLen)
1996 {
1997 // Make a call to KDFa to get next iteration
1998 CryptKDFaOnce(hash, key, "XOR", contextU, contextV,
1999 requestSize, mask, &counter);
2000 // XOR next piece of the data
2001 pm = mask;
2002 for(i = hLen < remainBytes ? hLen : remainBytes; i > 0; i--)
2003 *data++ ^= *pm++;
2004 }
2005 return;
2006}
2007#endif //TPM_ALG_KEYED_HASH //%5
2008//
2009//
2010// 10.2.8 Initialization and shut down
2011//
2012// 10.2.8.1 CryptInitUnits()
2013//
2014// This function is called when the TPM receives a _TPM_Init() indication. After function returns, the hash
2015// algorithms should be available.
2016//
2017// NOTE: The hash algorithms do not have to be tested, they just need to be available. They have to be tested before the
2018// TPM can accept HMAC authorization or return any result that relies on a hash algorithm.
2019//
2020void
2021CryptInitUnits(
2022 void
2023 )
2024{
2025 // Initialize the vector of implemented algorithms
2026 AlgorithmGetImplementedVector(&g_implementedAlgorithms);
2027 // Indicate that all test are necessary
2028 CryptInitializeToTest();
2029//
2030 // Call crypto engine unit initialization
2031 // It is assumed that crypt engine initialization should always succeed.
2032 // Otherwise, TPM should go to failure mode.
2033 if(_cpri__InitCryptoUnits(&TpmFail) != CRYPT_SUCCESS)
2034 FAIL(FATAL_ERROR_INTERNAL);
2035 return;
2036}
2037//
2038//
2039// 10.2.8.2 CryptStopUnits()
2040//
2041// This function is only used in a simulated environment. There should be no reason to shut down the
2042// cryptography on an actual TPM other than loss of power. After receiving TPM2_Startup(), the TPM should
2043// be able to accept commands until it loses power and, unless the TPM is in Failure Mode, the
2044// cryptographic algorithms should be available.
2045//
2046void
2047CryptStopUnits(
2048 void
2049 )
2050{
2051 // Call crypto engine unit stopping
2052 _cpri__StopCryptoUnits();
2053 return;
2054}
2055//
2056//
2057// 10.2.8.3 CryptUtilStartup()
2058//
2059// This function is called by TPM2_Startup() to initialize the functions in this crypto library and in the
2060// provided CryptoEngine(). In this implementation, the only initialization required in this library is
2061// initialization of the Commit nonce on TPM Reset.
2062// This function returns false if some problem prevents the functions from starting correctly. The TPM should
2063// go into failure mode.
2064//
2065BOOL
2066CryptUtilStartup(
2067 STARTUP_TYPE type // IN: the startup type
2068 )
2069{
2070 // Make sure that the crypto library functions are ready.
2071 // NOTE: need to initialize the crypto before loading
2072 // the RND state may trigger a self-test which
2073 // uses the
2074 if( !_cpri__Startup())
2075 return FALSE;
2076 // Initialize the state of the RNG.
2077 CryptDrbgGetPutState(PUT_STATE);
2078 if(type == SU_RESET)
2079 {
2080#ifdef TPM_ALG_ECC
2081 // Get a new random commit nonce
2082 gr.commitNonce.t.size = sizeof(gr.commitNonce.t.buffer);
2083 _cpri__GenerateRandom(gr.commitNonce.t.size, gr.commitNonce.t.buffer);
2084 // Reset the counter and commit array
2085 gr.commitCounter = 0;
2086 MemorySet(gr.commitArray, 0, sizeof(gr.commitArray));
2087#endif // TPM_ALG_ECC
2088 }
2089 // If the shutdown was orderly, then the values recovered from NV will
2090 // be OK to use. If the shutdown was not orderly, then a TPM Reset was required
2091 // and we would have initialized in the code above.
2092 return TRUE;
2093}
2094//
2095//
2096// 10.2.9 Algorithm-Independent Functions
2097//
2098// 10.2.9.1 Introduction
2099//
2100// These functions are used generically when a function of a general type (e.g., symmetric encryption) is
2101// required. The functions will modify the parameters as required to interface to the indicated algorithms.
2102//
2103// 10.2.9.2 CryptIsAsymAlgorithm()
2104//
2105// This function indicates if an algorithm is an asymmetric algorithm.
2106//
2107// Return Value Meaning
2108//
2109// TRUE if it is an asymmetric algorithm
2110// FALSE if it is not an asymmetric algorithm
2111//
2112BOOL
2113CryptIsAsymAlgorithm(
2114 TPM_ALG_ID algID // IN: algorithm ID
2115 )
2116{
2117 return (
2118#ifdef TPM_ALG_RSA
2119 algID == TPM_ALG_RSA
2120#endif
2121#if defined TPM_ALG_RSA && defined TPM_ALG_ECC
2122 ||
2123#endif
2124#ifdef TPM_ALG_ECC
2125 algID == TPM_ALG_ECC
2126#endif
2127 );
2128}
2129//
2130//
2131// 10.2.9.3 CryptGetSymmetricBlockSize()
2132//
2133// This function returns the size in octets of the symmetric encryption block used by an algorithm and key
2134// size combination.
2135//
2136INT16
2137CryptGetSymmetricBlockSize(
2138 TPMI_ALG_SYM algorithm, // IN: symmetric algorithm
2139 UINT16 keySize // IN: key size in bit
2140 )
2141{
2142 return _cpri__GetSymmetricBlockSize(algorithm, keySize);
2143}
2144//
2145//
2146//
2147// 10.2.9.4 CryptSymmetricEncrypt()
2148//
2149// This function does in-place encryption of a buffer using the indicated symmetric algorithm, key, IV, and
2150// mode. If the symmetric algorithm and mode are not defined, the TPM will fail.
2151//
2152void
2153CryptSymmetricEncrypt(
2154 BYTE *encrypted, // OUT: the encrypted data
2155 TPM_ALG_ID algorithm, // IN: algorithm for encryption
2156 UINT16 keySizeInBits, // IN: key size in bit
2157 TPMI_ALG_SYM_MODE mode, // IN: symmetric encryption mode
2158 BYTE *key, // IN: encryption key
2159 TPM2B_IV *ivIn, // IN/OUT: Input IV and output chaining
2160 // value for the next block
2161 UINT32 dataSize, // IN: data size in byte
2162 BYTE *data // IN/OUT: data buffer
2163 )
2164{
Vadim Bendeburyc00055c2015-05-29 22:50:18 -07002165 TPM2B_IV defaultIv = {};
Vadim Bendebury56797522015-05-20 10:32:25 -07002166 TPM2B_IV *iv = (ivIn != NULL) ? ivIn : &defaultIv;
2167 TEST(algorithm);
2168 pAssert(encrypted != NULL && key != NULL);
2169 // this check can pass but the case below can fail. ALG_xx_VALUE values are
2170 // defined for all algorithms but the TPM_ALG_xx might not be.
2171 if(algorithm == ALG_AES_VALUE || algorithm == ALG_SM4_VALUE)
2172 {
2173 if(mode != TPM_ALG_ECB)
2174 defaultIv.t.size = 16;
2175 // A provided IV has to be the right size
2176 pAssert(mode == TPM_ALG_ECB || iv->t.size == 16);
2177 }
2178 switch(algorithm)
2179 {
2180#ifdef TPM_ALG_AES
2181 case TPM_ALG_AES:
2182 {
2183 switch (mode)
2184 {
2185 case TPM_ALG_CTR:
2186 _cpri__AESEncryptCTR(encrypted, keySizeInBits, key,
2187 iv->t.buffer, dataSize, data);
2188 break;
2189 case TPM_ALG_OFB:
2190 _cpri__AESEncryptOFB(encrypted, keySizeInBits, key,
2191 iv->t.buffer, dataSize, data);
2192 break;
2193 case TPM_ALG_CBC:
2194 _cpri__AESEncryptCBC(encrypted, keySizeInBits, key,
2195 iv->t.buffer, dataSize, data);
2196 break;
2197 case TPM_ALG_CFB:
2198 _cpri__AESEncryptCFB(encrypted, keySizeInBits, key,
2199 iv->t.buffer, dataSize, data);
2200 break;
2201 case TPM_ALG_ECB:
2202 _cpri__AESEncryptECB(encrypted, keySizeInBits, key,
2203 dataSize, data);
2204 break;
2205 default:
2206 pAssert(0);
2207 }
2208 }
2209 break;
2210#endif
2211#ifdef TPM_ALG_SM4
2212 case TPM_ALG_SM4:
2213 {
2214 switch (mode)
2215 {
2216 case TPM_ALG_CTR:
2217 _cpri__SM4EncryptCTR(encrypted, keySizeInBits, key,
2218 iv->t.buffer, dataSize, data);
2219 break;
2220 case TPM_ALG_OFB:
2221 _cpri__SM4EncryptOFB(encrypted, keySizeInBits, key,
2222 iv->t.buffer, dataSize, data);
2223 break;
2224 case TPM_ALG_CBC:
2225 _cpri__SM4EncryptCBC(encrypted, keySizeInBits, key,
2226 iv->t.buffer, dataSize, data);
2227 break;
2228 case TPM_ALG_CFB:
2229 _cpri__SM4EncryptCFB(encrypted, keySizeInBits, key,
2230 iv->t.buffer, dataSize, data);
2231 break;
2232 case TPM_ALG_ECB:
2233 _cpri__SM4EncryptECB(encrypted, keySizeInBits, key,
2234 dataSize, data);
2235 break;
2236 default:
2237 pAssert(0);
2238 }
2239 }
2240 break;
2241#endif
2242 default:
2243 pAssert(FALSE);
2244 break;
2245 }
2246 return;
2247}
2248//
2249//
2250// 10.2.9.5 CryptSymmetricDecrypt()
2251//
2252// This function does in-place decryption of a buffer using the indicated symmetric algorithm, key, IV, and
2253// mode. If the symmetric algorithm and mode are not defined, the TPM will fail.
2254//
2255void
2256CryptSymmetricDecrypt(
2257 BYTE *decrypted,
2258 TPM_ALG_ID algorithm, // IN: algorithm for encryption
2259 UINT16 keySizeInBits, // IN: key size in bit
2260 TPMI_ALG_SYM_MODE mode, // IN: symmetric encryption mode
2261 BYTE *key, // IN: encryption key
2262 TPM2B_IV *ivIn, // IN/OUT: IV for next block
2263 UINT32 dataSize, // IN: data size in byte
2264 BYTE *data // IN/OUT: data buffer
2265 )
2266{
2267 BYTE *iv = NULL;
2268 BYTE defaultIV[sizeof(TPMT_HA)];
2269 TEST(algorithm);
2270 if(
2271#ifdef TPM_ALG_AES
2272 algorithm == TPM_ALG_AES
2273#endif
2274#if defined TPM_ALG_AES && defined TPM_ALG_SM4
2275 ||
2276#endif
2277#ifdef TPM_ALG_SM4
2278 algorithm == TPM_ALG_SM4
2279#endif
2280 )
2281 {
2282 // Both SM4 and AES have block size of 128 bits
2283 // If the iv is not provided, create a default of 0
2284 if(ivIn == NULL)
2285 {
2286 // Initialize the default IV
2287 iv = defaultIV;
2288 MemorySet(defaultIV, 0, 16);
2289 }
2290 else
2291 {
2292 // A provided IV has to be the right size
2293 pAssert(mode == TPM_ALG_ECB || ivIn->t.size == 16);
2294 iv = &(ivIn->t.buffer[0]);
2295 }
2296 }
2297 switch(algorithm)
2298 {
2299#ifdef TPM_ALG_AES
2300 case TPM_ALG_AES:
2301 {
2302 switch (mode)
2303 {
2304 case TPM_ALG_CTR:
2305 _cpri__AESDecryptCTR(decrypted, keySizeInBits, key, iv,
2306 dataSize, data);
2307 break;
2308 case TPM_ALG_OFB:
2309 _cpri__AESDecryptOFB(decrypted, keySizeInBits, key, iv,
2310 dataSize, data);
2311 break;
2312 case TPM_ALG_CBC:
2313 _cpri__AESDecryptCBC(decrypted, keySizeInBits, key, iv,
2314 dataSize, data);
2315 break;
2316 case TPM_ALG_CFB:
2317 _cpri__AESDecryptCFB(decrypted, keySizeInBits, key, iv,
2318 dataSize, data);
2319 break;
2320 case TPM_ALG_ECB:
2321 _cpri__AESDecryptECB(decrypted, keySizeInBits, key,
2322 dataSize, data);
2323 break;
2324 default:
2325 pAssert(0);
2326 }
2327 break;
2328 }
2329#endif //TPM_ALG_AES
2330#ifdef TPM_ALG_SM4
2331 case TPM_ALG_SM4 :
2332 switch (mode)
2333 {
2334 case TPM_ALG_CTR:
2335 _cpri__SM4DecryptCTR(decrypted, keySizeInBits, key, iv,
2336 dataSize, data);
2337 break;
2338 case TPM_ALG_OFB:
2339 _cpri__SM4DecryptOFB(decrypted, keySizeInBits, key, iv,
2340 dataSize, data);
2341 break;
2342 case TPM_ALG_CBC:
2343 _cpri__SM4DecryptCBC(decrypted, keySizeInBits, key, iv,
2344 dataSize, data);
2345 break;
2346 case TPM_ALG_CFB:
2347 _cpri__SM4DecryptCFB(decrypted, keySizeInBits, key, iv,
2348 dataSize, data);
2349 break;
2350 case TPM_ALG_ECB:
2351 _cpri__SM4DecryptECB(decrypted, keySizeInBits, key,
2352 dataSize, data);
2353 break;
2354 default:
2355 pAssert(0);
2356 }
2357 break;
2358#endif //TPM_ALG_SM4
2359 default:
2360 pAssert(FALSE);
2361 break;
2362 }
2363 return;
2364}
2365//
2366//
2367// 10.2.9.6 CryptSecretEncrypt()
2368//
2369// This function creates a secret value and its associated secret structure using an asymmetric algorithm.
2370// This function is used by TPM2_Rewrap() TPM2_MakeCredential(), and TPM2_Duplicate().
2371//
2372// Error Returns Meaning
2373//
2374// TPM_RC_ATTRIBUTES keyHandle does not reference a valid decryption key
2375// TPM_RC_KEY invalid ECC key (public point is not on the curve)
2376// TPM_RC_SCHEME RSA key with an unsupported padding scheme
2377// TPM_RC_VALUE numeric value of the data to be decrypted is greater than the RSA
2378// key modulus
2379//
2380TPM_RC
2381CryptSecretEncrypt(
2382 TPMI_DH_OBJECT keyHandle, // IN: encryption key handle
2383 const char *label, // IN: a null-terminated string as L
2384 TPM2B_DATA *data, // OUT: secret value
2385 TPM2B_ENCRYPTED_SECRET *secret // OUT: secret structure
2386 )
2387{
2388 TPM_RC result = TPM_RC_SUCCESS;
2389 OBJECT *encryptKey = ObjectGet(keyHandle); // TPM key used for encrypt
2390 pAssert(data != NULL && secret != NULL);
2391 // The output secret value has the size of the digest produced by the nameAlg.
2392 data->t.size = CryptGetHashDigestSize(encryptKey->publicArea.nameAlg);
2393 pAssert(encryptKey->publicArea.objectAttributes.decrypt == SET);
2394 switch(encryptKey->publicArea.type)
2395 {
2396#ifdef TPM_ALG_RSA
2397 case TPM_ALG_RSA:
2398 {
2399 TPMT_RSA_DECRYPT scheme;
2400 // Use OAEP scheme
2401 scheme.scheme = TPM_ALG_OAEP;
2402 scheme.details.oaep.hashAlg = encryptKey->publicArea.nameAlg;
2403 // Create secret data from RNG
2404 CryptGenerateRandom(data->t.size, data->t.buffer);
2405 // Encrypt the data by RSA OAEP into encrypted secret
Vadim Bendeburyc00055c2015-05-29 22:50:18 -07002406 result = CryptEncryptRSA(&secret->t.size, secret->t.buffer,
Vadim Bendebury56797522015-05-20 10:32:25 -07002407 encryptKey, &scheme,
2408 data->t.size, data->t.buffer, label);
2409 }
2410 break;
2411#endif //TPM_ALG_RSA
2412#ifdef TPM_ALG_ECC
2413 case TPM_ALG_ECC:
2414 {
2415 TPMS_ECC_POINT eccPublic;
2416 TPM2B_ECC_PARAMETER eccPrivate;
2417 TPMS_ECC_POINT eccSecret;
Vadim Bendeburyc00055c2015-05-29 22:50:18 -07002418 BYTE *buffer = secret->t.buffer;
Vadim Bendebury56797522015-05-20 10:32:25 -07002419 // Need to make sure that the public point of the key is on the
2420 // curve defined by the key.
2421 if(!_cpri__EccIsPointOnCurve(
2422 encryptKey->publicArea.parameters.eccDetail.curveID,
2423 &encryptKey->publicArea.unique.ecc))
2424 result = TPM_RC_KEY;
2425 else
2426 {
2427 // Call crypto engine to create an auxiliary ECC key
2428 // We assume crypt engine initialization should always success.
2429 // Otherwise, TPM should go to failure mode.
2430 CryptNewEccKey(encryptKey->publicArea.parameters.eccDetail.curveID,
2431 &eccPublic, &eccPrivate);
2432 // Marshal ECC public to secret structure. This will be used by the
2433 // recipient to decrypt the secret with their private key.
2434 secret->t.size = TPMS_ECC_POINT_Marshal(&eccPublic, &buffer, NULL);
2435 // Compute ECDH shared secret which is R = [d]Q where d is the
2436 // private part of the ephemeral key and Q is the public part of a
2437 // TPM key. TPM_RC_KEY error return from CryptComputeECDHSecret
2438 // because the auxiliary ECC key is just created according to the
2439 // parameters of input ECC encrypt key.
2440 if( CryptEccPointMultiply(&eccSecret,
2441 encryptKey->publicArea.parameters.eccDetail.curveID,
2442 &eccPrivate,
2443 &encryptKey->publicArea.unique.ecc)
2444 != CRYPT_SUCCESS)
2445 result = TPM_RC_KEY;
2446 else
2447 // The secret value is computed from Z using KDFe as:
2448 // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits)
2449 // Where:
2450 // HashID the nameAlg of the decrypt key
2451 // Z the x coordinate (Px) of the product (P) of the point
2452 // (Q) of the secret and the private x coordinate (de,V)
2453 // of the decryption key
2454 // Use a null-terminated string containing "SECRET"
2455 // PartyUInfo the x coordinate of the point in the secret
2456 // (Qe,U )
2457 // PartyVInfo the x coordinate of the public key (Qs,V )
2458 // bits the number of bits in the digest of HashID
2459 // Retrieve seed from KDFe
2460 CryptKDFe(encryptKey->publicArea.nameAlg, &eccSecret.x.b,
2461 label, &eccPublic.x.b,
2462 &encryptKey->publicArea.unique.ecc.x.b,
2463 data->t.size * 8, data->t.buffer);
2464 }
2465 }
2466 break;
2467#endif //TPM_ALG_ECC
2468 default:
2469 FAIL(FATAL_ERROR_INTERNAL);
2470 break;
2471 }
2472 return result;
2473}
2474//
2475//
2476// 10.2.9.7 CryptSecretDecrypt()
2477//
2478// Decrypt a secret value by asymmetric (or symmetric) algorithm This function is used for
2479// ActivateCredential() and Import for asymmetric decryption, and StartAuthSession() for both asymmetric
2480// and symmetric decryption process
2481//
2482// Error Returns Meaning
2483//
2484// TPM_RC_ATTRIBUTES RSA key is not a decryption key
2485// TPM_RC_BINDING Invalid RSA key (public and private parts are not cryptographically
2486// bound.
2487// TPM_RC_ECC_POINT ECC point in the secret is not on the curve
2488// TPM_RC_INSUFFICIENT failed to retrieve ECC point from the secret
2489// TPM_RC_NO_RESULT multiplication resulted in ECC point at infinity
2490// TPM_RC_SIZE data to decrypt is not of the same size as RSA key
2491// TPM_RC_VALUE For RSA key, numeric value of the encrypted data is greater than the
2492// modulus, or the recovered data is larger than the output buffer. For
2493// keyedHash or symmetric key, the secret is larger than the size of the
2494// digest produced by the name algorithm.
2495// TPM_RC_FAILURE internal error
2496//
2497TPM_RC
2498CryptSecretDecrypt(
2499 TPM_HANDLE tpmKey, // IN: decrypt key
2500 TPM2B_NONCE *nonceCaller, // IN: nonceCaller. It is needed for
2501 // symmetric decryption. For
2502 // asymmetric decryption, this
2503 // parameter is NULL
2504 const char *label, // IN: a null-terminated string as L
2505 TPM2B_ENCRYPTED_SECRET *secret, // IN: input secret
2506 TPM2B_DATA *data // OUT: decrypted secret value
2507 )
2508{
2509 TPM_RC result = TPM_RC_SUCCESS;
2510 OBJECT *decryptKey = ObjectGet(tpmKey); //TPM key used for decrypting
2511 // Decryption for secret
2512 switch(decryptKey->publicArea.type)
2513 {
2514#ifdef TPM_ALG_RSA
2515 case TPM_ALG_RSA:
2516 {
2517 TPMT_RSA_DECRYPT scheme;
2518 // Use OAEP scheme
2519 scheme.scheme = TPM_ALG_OAEP;
2520 scheme.details.oaep.hashAlg = decryptKey->publicArea.nameAlg;
2521 // Set the output buffer capacity
2522 data->t.size = sizeof(data->t.buffer);
2523 // Decrypt seed by RSA OAEP
2524 result = CryptDecryptRSA(&data->t.size, data->t.buffer, decryptKey,
2525 &scheme,
Vadim Bendeburyc00055c2015-05-29 22:50:18 -07002526 secret->t.size, secret->t.buffer,label);
Vadim Bendebury56797522015-05-20 10:32:25 -07002527 if( (result == TPM_RC_SUCCESS)
2528 && (data->t.size
2529 > CryptGetHashDigestSize(decryptKey->publicArea.nameAlg)))
2530 result = TPM_RC_VALUE;
2531 }
2532 break;
2533#endif //TPM_ALG_RSA
2534#ifdef TPM_ALG_ECC
2535 case TPM_ALG_ECC:
2536 {
2537 TPMS_ECC_POINT eccPublic;
2538 TPMS_ECC_POINT eccSecret;
Vadim Bendeburyc00055c2015-05-29 22:50:18 -07002539 BYTE *buffer = secret->t.buffer;
Vadim Bendebury56797522015-05-20 10:32:25 -07002540 INT32 size = secret->t.size;
2541 // Retrieve ECC point from secret buffer
2542 result = TPMS_ECC_POINT_Unmarshal(&eccPublic, &buffer, &size);
2543 if(result == TPM_RC_SUCCESS)
2544 {
2545 result = CryptEccPointMultiply(&eccSecret,
2546 decryptKey->publicArea.parameters.eccDetail.curveID,
2547 &decryptKey->sensitive.sensitive.ecc,
2548 &eccPublic);
2549 if(result == TPM_RC_SUCCESS)
2550 {
2551 // Set the size of the "recovered" secret value to be the size
2552 // of the digest produced by the nameAlg.
2553 data->t.size =
2554 CryptGetHashDigestSize(decryptKey->publicArea.nameAlg);
2555 // The secret value is computed from Z using KDFe as:
2556 // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits)
2557 // Where:
2558 // HashID -- the nameAlg of the decrypt key
2559 // Z -- the x coordinate (Px) of the product (P) of the point
2560 // (Q) of the secret and the private x coordinate (de,V)
2561 // of the decryption key
2562 // Use -- a null-terminated string containing "SECRET"
2563 // PartyUInfo -- the x coordinate of the point in the secret
2564 // (Qe,U )
2565 // PartyVInfo -- the x coordinate of the public key (Qs,V )
2566 // bits -- the number of bits in the digest of HashID
2567 // Retrieve seed from KDFe
2568 CryptKDFe(decryptKey->publicArea.nameAlg, &eccSecret.x.b, label,
2569 &eccPublic.x.b,
2570 &decryptKey->publicArea.unique.ecc.x.b,
2571 data->t.size * 8, data->t.buffer);
2572 }
2573 }
2574 }
2575 break;
2576#endif //TPM_ALG_ECC
2577 case TPM_ALG_KEYEDHASH:
2578 // The seed size can not be bigger than the digest size of nameAlg
2579 if(secret->t.size >
2580 CryptGetHashDigestSize(decryptKey->publicArea.nameAlg))
2581 result = TPM_RC_VALUE;
2582 else
2583 {
2584 // Retrieve seed by XOR Obfuscation:
2585 // seed = XOR(secret, hash, key, nonceCaller, nullNonce)
2586 // where:
2587 // secret the secret parameter from the TPM2_StartAuthHMAC
2588 // command
2589 // which contains the seed value
2590 // hash nameAlg of tpmKey
2591 // key the key or data value in the object referenced by
2592 // entityHandle in the TPM2_StartAuthHMAC command
2593 // nonceCaller the parameter from the TPM2_StartAuthHMAC command
2594 // nullNonce a zero-length nonce
2595 // XOR Obfuscation in place
2596 CryptXORObfuscation(decryptKey->publicArea.nameAlg,
2597 &decryptKey->sensitive.sensitive.bits.b,
2598 &nonceCaller->b, NULL,
Vadim Bendeburyc00055c2015-05-29 22:50:18 -07002599 secret->t.size, secret->t.buffer);
Vadim Bendebury56797522015-05-20 10:32:25 -07002600 // Copy decrypted seed
2601 MemoryCopy2B(&data->b, &secret->b, sizeof(data->t.buffer));
2602 }
2603 break;
2604 case TPM_ALG_SYMCIPHER:
2605 {
Vadim Bendeburyc00055c2015-05-29 22:50:18 -07002606 TPM2B_IV iv = {};
Vadim Bendebury56797522015-05-20 10:32:25 -07002607 TPMT_SYM_DEF_OBJECT *symDef;
2608 // The seed size can not be bigger than the digest size of nameAlg
2609 if(secret->t.size >
2610 CryptGetHashDigestSize(decryptKey->publicArea.nameAlg))
2611 result = TPM_RC_VALUE;
2612 else
2613 {
Vadim Bendeburyc00055c2015-05-29 22:50:18 -07002614 symDef = &decryptKey->publicArea.parameters.symDetail;
Vadim Bendebury56797522015-05-20 10:32:25 -07002615 iv.t.size = CryptGetSymmetricBlockSize(symDef->algorithm,
2616 symDef->keyBits.sym);
2617 pAssert(iv.t.size != 0);
2618 if(nonceCaller->t.size >= iv.t.size)
2619 MemoryCopy(iv.t.buffer, nonceCaller->t.buffer, iv.t.size,
2620 sizeof(iv.t.buffer));
2621 else
2622 MemoryCopy(iv.b.buffer, nonceCaller->t.buffer,
2623 nonceCaller->t.size, sizeof(iv.t.buffer));
2624 // CFB decrypt in place, using nonceCaller as iv
Vadim Bendeburyc00055c2015-05-29 22:50:18 -07002625 CryptSymmetricDecrypt(secret->t.buffer, symDef->algorithm,
Vadim Bendebury56797522015-05-20 10:32:25 -07002626 symDef->keyBits.sym, TPM_ALG_CFB,
2627 decryptKey->sensitive.sensitive.sym.t.buffer,
Vadim Bendeburyc00055c2015-05-29 22:50:18 -07002628 &iv, secret->t.size, secret->t.buffer);
Vadim Bendebury56797522015-05-20 10:32:25 -07002629 // Copy decrypted seed
2630 MemoryCopy2B(&data->b, &secret->b, sizeof(data->t.buffer));
2631 }
2632 }
2633 break;
2634 default:
2635 pAssert(0);
2636 break;
2637 }
2638 return result;
2639}
2640//
2641//
2642// 10.2.9.8 CryptParameterEncryption()
2643//
2644// This function does in-place encryption of a response parameter.
2645//
2646void
2647CryptParameterEncryption(
2648 TPM_HANDLE handle, // IN: encrypt session handle
2649 TPM2B *nonceCaller, // IN: nonce caller
2650 UINT16 leadingSizeInByte, // IN: the size of the leading size field in
2651 // byte
2652 TPM2B_AUTH *extraKey, // IN: additional key material other than
2653 // session auth
2654 BYTE *buffer // IN/OUT: parameter buffer to be encrypted
2655 )
2656{
2657 SESSION *session = SessionGet(handle); // encrypt session
2658 TPM2B_TYPE(SYM_KEY, ( sizeof(extraKey->t.buffer)
2659 + sizeof(session->sessionKey.t.buffer)));
2660 TPM2B_SYM_KEY key; // encryption key
2661 UINT32 cipherSize = 0; // size of cipher text
2662 pAssert(session->sessionKey.t.size + extraKey->t.size <= sizeof(key.t.buffer));
2663 // Retrieve encrypted data size.
2664 if(leadingSizeInByte == 2)
2665 {
2666 // Extract the first two bytes as the size field as the data size
2667 // encrypt
2668 cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer);
2669 // advance the buffer
2670 buffer = &buffer[2];
2671 }
2672#ifdef TPM4B
2673 else if(leadingSizeInByte == 4)
2674 {
2675 // use the first four bytes to indicate the number of bytes to encrypt
2676 cipherSize = BYTE_ARRAY_TO_UINT32(buffer);
2677 //advance pointer
2678 buffer = &buffer[4];
2679 }
2680#endif
2681 else
2682 {
2683 pAssert(FALSE);
2684 }
2685//
2686 // Compute encryption key by concatenating sessionAuth with extra key
2687 MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
2688 MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer));
2689 if (session->symmetric.algorithm == TPM_ALG_XOR)
2690 // XOR parameter encryption formulation:
2691 // XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder)
2692 CryptXORObfuscation(session->authHashAlg, &(key.b),
2693 &(session->nonceTPM.b),
2694 nonceCaller, cipherSize, buffer);
2695 else
2696 ParmEncryptSym(session->symmetric.algorithm, session->authHashAlg,
2697 session->symmetric.keyBits.aes, &(key.b),
2698 nonceCaller, &(session->nonceTPM.b),
2699 cipherSize, buffer);
2700 return;
2701}
2702//
2703//
2704// 10.2.9.9 CryptParameterDecryption()
2705//
2706// This function does in-place decryption of a command parameter.
2707//
2708// Error Returns Meaning
2709//
2710// TPM_RC_SIZE The number of bytes in the input buffer is less than the number of
2711// bytes to be decrypted.
2712//
2713TPM_RC
2714CryptParameterDecryption(
2715 TPM_HANDLE handle, // IN: encrypted session handle
2716 TPM2B *nonceCaller, // IN: nonce caller
2717 UINT32 bufferSize, // IN: size of parameter buffer
2718 UINT16 leadingSizeInByte, // IN: the size of the leading size field in
2719 // byte
2720 TPM2B_AUTH *extraKey, // IN: the authValue
2721 BYTE *buffer // IN/OUT: parameter buffer to be decrypted
2722 )
2723{
2724 SESSION *session = SessionGet(handle); // encrypt session
2725 // The HMAC key is going to be the concatenation of the session key and any
2726 // additional key material (like the authValue). The size of both of these
2727 // is the size of the buffer which can contain a TPMT_HA.
2728 TPM2B_TYPE(HMAC_KEY, ( sizeof(extraKey->t.buffer)
2729 + sizeof(session->sessionKey.t.buffer)));
2730 TPM2B_HMAC_KEY key; // decryption key
2731 UINT32 cipherSize = 0; // size of cipher text
2732 pAssert(session->sessionKey.t.size + extraKey->t.size <= sizeof(key.t.buffer));
2733 // Retrieve encrypted data size.
2734 if(leadingSizeInByte == 2)
2735 {
2736 // The first two bytes of the buffer are the size of the
2737 // data to be decrypted
2738 cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer);
2739 buffer = &buffer[2]; // advance the buffer
2740 }
2741#ifdef TPM4B
2742 else if(leadingSizeInByte == 4)
2743 {
2744 // the leading size is four bytes so get the four byte size field
2745 cipherSize = BYTE_ARRAY_TO_UINT32(buffer);
2746 buffer = &buffer[4]; //advance pointer
2747 }
2748#endif
2749 else
2750 {
2751 pAssert(FALSE);
2752 }
2753 if(cipherSize > bufferSize)
2754 return TPM_RC_SIZE;
2755 // Compute decryption key by concatenating sessionAuth with extra input key
2756 MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
2757 MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer));
2758 if(session->symmetric.algorithm == TPM_ALG_XOR)
2759 // XOR parameter decryption formulation:
2760 // XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder)
2761 // Call XOR obfuscation function
2762 CryptXORObfuscation(session->authHashAlg, &key.b, nonceCaller,
2763 &(session->nonceTPM.b), cipherSize, buffer);
2764 else
2765 // Assume that it is one of the symmetric block ciphers.
2766 ParmDecryptSym(session->symmetric.algorithm, session->authHashAlg,
2767 session->symmetric.keyBits.sym,
2768 &key.b, nonceCaller, &session->nonceTPM.b,
2769 cipherSize, buffer);
2770 return TPM_RC_SUCCESS;
2771}
2772//
2773//
2774// 10.2.9.10 CryptComputeSymmetricUnique()
2775//
2776// This function computes the unique field in public area for symmetric objects.
2777//
2778void
2779CryptComputeSymmetricUnique(
2780 TPMI_ALG_HASH nameAlg, // IN: object name algorithm
2781 TPMT_SENSITIVE *sensitive, // IN: sensitive area
2782 TPM2B_DIGEST *unique // OUT: unique buffer
2783 )
2784{
2785 HASH_STATE hashState;
2786 pAssert(sensitive != NULL && unique != NULL);
2787 // Compute the public value as the hash of sensitive.symkey || unique.buffer
2788 unique->t.size = CryptGetHashDigestSize(nameAlg);
2789 CryptStartHash(nameAlg, &hashState);
2790 // Add obfuscation value
2791 CryptUpdateDigest2B(&hashState, &sensitive->seedValue.b);
2792 // Add sensitive value
2793 CryptUpdateDigest2B(&hashState, &sensitive->sensitive.any.b);
2794 CryptCompleteHash2B(&hashState, &unique->b);
2795 return;
2796}
2797#if 0 //%
2798//
2799//
2800//
2801// 10.2.9.11 CryptComputeSymValue()
2802//
2803// This function computes the seedValue field in asymmetric sensitive areas.
2804//
2805void
2806CryptComputeSymValue(
2807 TPM_HANDLE parentHandle, // IN: parent handle of the object to be created
2808 TPMT_PUBLIC *publicArea, // IN/OUT: the public area template
2809 TPMT_SENSITIVE *sensitive, // IN: sensitive area
2810 TPM2B_SEED *seed, // IN: the seed
2811 TPMI_ALG_HASH hashAlg, // IN: hash algorithm for KDFa
2812 TPM2B_NAME *name // IN: object name
2813 )
2814{
2815 TPM2B_AUTH *proof = NULL;
2816 if(CryptIsAsymAlgorithm(publicArea->type))
2817 {
2818 // Generate seedValue only when an asymmetric key is a storage key
2819 if(publicArea->objectAttributes.decrypt == SET
2820 && publicArea->objectAttributes.restricted == SET)
2821 {
2822 // If this is a primary object in the endorsement hierarchy, use
2823 // ehProof in the creation of the symmetric seed so that child
2824 // objects in the endorsement hierarchy are voided on TPM2_Clear()
2825 // or TPM2_ChangeEPS()
2826 if( parentHandle == TPM_RH_ENDORSEMENT
2827 && publicArea->objectAttributes.fixedTPM == SET)
2828 proof = &gp.ehProof;
2829 }
2830 else
2831 {
2832 sensitive->seedValue.t.size = 0;
2833 return;
2834 }
2835 }
2836 // For all object types, the size of seedValue is the digest size of nameAlg
2837 sensitive->seedValue.t.size = CryptGetHashDigestSize(publicArea->nameAlg);
2838 // Compute seedValue using implementation-dependent method
2839 _cpri__GenerateSeededRandom(sensitive->seedValue.t.size,
2840 sensitive->seedValue.t.buffer,
2841 hashAlg,
2842 &seed->b,
2843 "seedValue",
2844 &name->b,
2845 (TPM2B *)proof);
2846 return;
2847}
2848#endif //%
2849//
2850//
2851// 10.2.9.12 CryptCreateObject()
2852//
2853// This function creates an object. It:
2854// a) fills in the created key in public and sensitive area;
2855// b) creates a random number in sensitive area for symmetric keys; and
2856// c) compute the unique id in public area for symmetric keys.
2857//
2858//
2859//
2860//
2861// Error Returns Meaning
2862//
2863// TPM_RC_KEY_SIZE key size in the public area does not match the size in the sensitive
2864// creation area for a symmetric key
2865// TPM_RC_RANGE for an RSA key, the exponent is not supported
2866// TPM_RC_SIZE sensitive data size is larger than allowed for the scheme for a keyed
2867// hash object
2868// TPM_RC_VALUE exponent is not prime or could not find a prime using the provided
2869// parameters for an RSA key; unsupported name algorithm for an ECC
2870// key
2871//
2872TPM_RC
2873CryptCreateObject(
2874 TPM_HANDLE parentHandle, // IN/OUT: indication of the seed
2875 // source
2876 TPMT_PUBLIC *publicArea, // IN/OUT: public area
2877 TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation
2878 TPMT_SENSITIVE *sensitive // OUT: sensitive area
2879 )
2880{
2881 // Next value is a placeholder for a random seed that is used in
2882 // key creation when the parent is not a primary seed. It has the same
2883 // size as the primary seed.
2884 TPM2B_SEED localSeed; // data to seed key creation if this
2885 // is not a primary seed
2886 TPM2B_SEED *seed = NULL;
2887 TPM_RC result = TPM_RC_SUCCESS;
2888 TPM2B_NAME name;
2889 TPM_ALG_ID hashAlg = CONTEXT_INTEGRITY_HASH_ALG;
2890 OBJECT *parent;
2891 UINT32 counter;
2892 // Set the sensitive type for the object
2893 sensitive->sensitiveType = publicArea->type;
2894 ObjectComputeName(publicArea, &name);
2895 // For all objects, copy the initial auth data
2896 sensitive->authValue = sensitiveCreate->userAuth;
2897 // If this is a permanent handle assume that it is a hierarchy
2898 if(HandleGetType(parentHandle) == TPM_HT_PERMANENT)
2899 {
2900 seed = HierarchyGetPrimarySeed(parentHandle);
2901 }
2902 else
2903 {
2904 // If not hierarchy handle, get parent
2905 parent = ObjectGet(parentHandle);
2906 hashAlg = parent->publicArea.nameAlg;
2907 // Use random value as seed for non-primary objects
2908 localSeed.t.size = PRIMARY_SEED_SIZE;
2909 CryptGenerateRandom(PRIMARY_SEED_SIZE, localSeed.t.buffer);
2910 seed = &localSeed;
2911 }
2912 switch(publicArea->type)
2913 {
2914#ifdef TPM_ALG_RSA
2915 // Create RSA key
2916 case TPM_ALG_RSA:
2917 result = CryptGenerateKeyRSA(publicArea, sensitive,
2918 hashAlg, seed, &name, &counter);
2919 break;
2920#endif // TPM_ALG_RSA
2921#ifdef TPM_ALG_ECC
2922 // Create ECC key
2923 case TPM_ALG_ECC:
2924 result = CryptGenerateKeyECC(publicArea, sensitive,
2925 hashAlg, seed, &name, &counter);
2926 break;
2927#endif // TPM_ALG_ECC
2928 // Collect symmetric key information
2929 case TPM_ALG_SYMCIPHER:
2930 return CryptGenerateKeySymmetric(publicArea, sensitiveCreate,
2931 sensitive, hashAlg, seed, &name);
2932 break;
2933 case TPM_ALG_KEYEDHASH:
2934 return CryptGenerateKeyedHash(publicArea, sensitiveCreate,
2935 sensitive, hashAlg, seed, &name);
2936 break;
2937 default:
2938 pAssert(0);
2939 break;
2940 }
2941 if(result == TPM_RC_SUCCESS)
2942 {
2943 TPM2B_AUTH *proof = NULL;
2944 if(publicArea->objectAttributes.decrypt == SET
2945 && publicArea->objectAttributes.restricted == SET)
2946 {
2947 // If this is a primary object in the endorsement hierarchy, use
2948 // ehProof in the creation of the symmetric seed so that child
2949 // objects in the endorsement hierarchy are voided on TPM2_Clear()
2950 // or TPM2_ChangeEPS()
2951 if( parentHandle == TPM_RH_ENDORSEMENT
2952 && publicArea->objectAttributes.fixedTPM == SET)
2953 proof = &gp.ehProof;
2954 // For all object types, the size of seedValue is the digest size
2955 // of its nameAlg
2956 sensitive->seedValue.t.size
2957 = CryptGetHashDigestSize(publicArea->nameAlg);
2958 // Compute seedValue using implementation-dependent method
2959 _cpri__GenerateSeededRandom(sensitive->seedValue.t.size,
2960 sensitive->seedValue.t.buffer,
2961 hashAlg,
2962 &seed->b,
2963 "seedValuea",
2964 &name.b,
2965 (TPM2B *)proof);
2966 }
2967 else
2968 {
2969 sensitive->seedValue.t.size = 0;
2970 }
2971 }
2972 return result;
2973}
2974//
2975// 10.2.9.13 CryptObjectIsPublicConsistent()
2976//
2977// This function checks that the key sizes in the public area are consistent. For an asymmetric key, the size
2978// of the public key must match the size indicated by the public->parameters.
2979// Checks for the algorithm types matching the key type are handled by the unmarshaling operation.
2980//
2981// Return Value Meaning
2982//
2983// TRUE sizes are consistent
2984// FALSE sizes are not consistent
2985//
2986BOOL
2987CryptObjectIsPublicConsistent(
2988 TPMT_PUBLIC *publicArea // IN: public area
2989 )
2990{
2991 BOOL OK = TRUE;
2992 switch (publicArea->type)
2993 {
2994#ifdef TPM_ALG_RSA
2995 case TPM_ALG_RSA:
2996 OK = CryptAreKeySizesConsistent(publicArea);
2997 break;
2998#endif //TPM_ALG_RSA
2999#ifdef TPM_ALG_ECC
3000 case TPM_ALG_ECC:
3001 {
3002 const ECC_CURVE *curveValue;
3003 // Check that the public point is on the indicated curve.
3004 OK = CryptEccIsPointOnCurve(
3005 publicArea->parameters.eccDetail.curveID,
3006 &publicArea->unique.ecc);
3007 if(OK)
3008 {
3009 curveValue = CryptEccGetCurveDataPointer(
3010 publicArea->parameters.eccDetail.curveID);
3011 pAssert(curveValue != NULL);
3012 // The input ECC curve must be a supported curve
3013 // IF a scheme is defined for the curve, then that scheme must
3014 // be used.
3015 OK = (curveValue->sign.scheme == TPM_ALG_NULL
3016 || ( publicArea->parameters.eccDetail.scheme.scheme
3017 == curveValue->sign.scheme));
3018 OK = OK && CryptAreKeySizesConsistent(publicArea);
3019 }
3020 }
3021 break;
3022#endif //TPM_ALG_ECC
3023 default:
3024 // Symmetric object common checks
3025 // There is noting to check with a symmetric key that is public only.
3026 // Also not sure that there is anything useful to be done with it
3027 // either.
3028 break;
3029 }
3030 return OK;
3031}
3032//
3033//
3034//
3035// 10.2.9.14 CryptObjectPublicPrivateMatch()
3036//
3037// This function checks the cryptographic binding between the public and sensitive areas.
3038//
3039// Error Returns Meaning
3040//
3041// TPM_RC_TYPE the type of the public and private areas are not the same
3042// TPM_RC_FAILURE crypto error
3043// TPM_RC_BINDING the public and private areas are not cryptographically matched.
3044//
3045TPM_RC
3046CryptObjectPublicPrivateMatch(
3047 OBJECT *object // IN: the object to check
3048 )
3049{
3050 TPMT_PUBLIC *publicArea;
3051 TPMT_SENSITIVE *sensitive;
3052 TPM_RC result = TPM_RC_SUCCESS;
3053 BOOL isAsymmetric = FALSE;
3054 pAssert(object != NULL);
3055 publicArea = &object->publicArea;
3056 sensitive = &object->sensitive;
3057 if(publicArea->type != sensitive->sensitiveType)
3058 return TPM_RC_TYPE;
3059 switch(publicArea->type)
3060 {
3061#ifdef TPM_ALG_RSA
3062 case TPM_ALG_RSA:
3063 isAsymmetric = TRUE;
3064 // The public and private key sizes need to be consistent
3065 if(sensitive->sensitive.rsa.t.size != publicArea->unique.rsa.t.size/2)
3066 result = TPM_RC_BINDING;
3067 else
3068 // Load key by computing the private exponent
3069 result = CryptLoadPrivateRSA(object);
3070 break;
3071#endif
3072#ifdef TPM_ALG_ECC
3073 // This function is called from ObjectLoad() which has already checked to
3074 // see that the public point is on the curve so no need to repeat that
3075 // check.
3076 case TPM_ALG_ECC:
3077 isAsymmetric = TRUE;
3078 if( publicArea->unique.ecc.x.t.size
3079 != sensitive->sensitive.ecc.t.size)
3080 result = TPM_RC_BINDING;
3081 else if(publicArea->nameAlg != TPM_ALG_NULL)
3082 {
3083 TPMS_ECC_POINT publicToCompare;
3084 // Compute ECC public key
3085 CryptEccPointMultiply(&publicToCompare,
3086 publicArea->parameters.eccDetail.curveID,
3087 &sensitive->sensitive.ecc, NULL);
3088 // Compare ECC public key
3089 if( (!Memory2BEqual(&publicArea->unique.ecc.x.b,
3090 &publicToCompare.x.b))
3091 || (!Memory2BEqual(&publicArea->unique.ecc.y.b,
3092 &publicToCompare.y.b)))
3093 result = TPM_RC_BINDING;
3094 }
3095 break;
3096//
3097#endif
3098 case TPM_ALG_KEYEDHASH:
3099 break;
3100 case TPM_ALG_SYMCIPHER:
Vadim Bendeburyc00055c2015-05-29 22:50:18 -07003101 if( (publicArea->parameters.symDetail.keyBits.sym + 7)/8
Vadim Bendebury56797522015-05-20 10:32:25 -07003102 != sensitive->sensitive.sym.t.size)
3103 result = TPM_RC_BINDING;
3104 break;
3105 default:
3106 // The choice here is an assert or a return of a bad type for the object
3107 pAssert(0);
3108 break;
3109 }
3110 // For asymmetric keys, the algorithm for validating the linkage between
3111 // the public and private areas is algorithm dependent. For symmetric keys
3112 // the linkage is based on hashing the symKey and obfuscation values.
3113 if( result == TPM_RC_SUCCESS && !isAsymmetric
3114 && publicArea->nameAlg != TPM_ALG_NULL)
3115 {
3116 TPM2B_DIGEST uniqueToCompare;
3117 // Compute unique for symmetric key
3118 CryptComputeSymmetricUnique(publicArea->nameAlg, sensitive,
3119 &uniqueToCompare);
3120 // Compare unique
3121 if(!Memory2BEqual(&publicArea->unique.sym.b,
3122 &uniqueToCompare.b))
3123 result = TPM_RC_BINDING;
3124 }
3125 return result;
3126}
3127//
3128//
3129// 10.2.9.15 CryptGetSignHashAlg()
3130//
3131// Get the hash algorithm of signature from a TPMT_SIGNATURE structure. It assumes the signature is not
3132// NULL This is a function for easy access
3133//
3134TPMI_ALG_HASH
3135CryptGetSignHashAlg(
3136 TPMT_SIGNATURE *auth // IN: signature
3137 )
3138{
3139 pAssert(auth->sigAlg != TPM_ALG_NULL);
3140 // Get authHash algorithm based on signing scheme
3141 switch(auth->sigAlg)
3142 {
3143#ifdef TPM_ALG_RSA
3144 case TPM_ALG_RSASSA:
3145 return auth->signature.rsassa.hash;
3146 case TPM_ALG_RSAPSS:
3147 return auth->signature.rsapss.hash;
3148 #endif //TPM_ALG_RSA
3149 #ifdef TPM_ALG_ECC
3150 case TPM_ALG_ECDSA:
3151 return auth->signature.ecdsa.hash;
3152 #endif //TPM_ALG_ECC
3153 case TPM_ALG_HMAC:
3154 return auth->signature.hmac.hashAlg;
3155 default:
3156 return TPM_ALG_NULL;
3157 }
3158}
3159//
3160//
3161// 10.2.9.16 CryptIsSplitSign()
3162//
3163// This function us used to determine if the signing operation is a split signing operation that required a
3164// TPM2_Commit().
3165//
3166BOOL
3167CryptIsSplitSign(
3168 TPM_ALG_ID scheme // IN: the algorithm selector
3169 )
3170{
3171 if( scheme != scheme
3172# ifdef TPM_ALG_ECDAA
3173 || scheme == TPM_ALG_ECDAA
3174# endif // TPM_ALG_ECDAA
3175 )
3176 return TRUE;
3177 return FALSE;
3178}
3179//
3180//
3181// 10.2.9.17 CryptIsSignScheme()
3182//
3183// This function indicates if a scheme algorithm is a sign algorithm.
3184//
3185BOOL
3186CryptIsSignScheme(
3187 TPMI_ALG_ASYM_SCHEME scheme
3188 )
3189{
3190 BOOL isSignScheme = FALSE;
3191 switch(scheme)
3192 {
3193#ifdef TPM_ALG_RSA
3194 // If RSA is implemented, then both signing schemes are required
3195 case TPM_ALG_RSASSA:
3196 case TPM_ALG_RSAPSS:
3197 isSignScheme = TRUE;
3198 break;
3199#endif //TPM_ALG_RSA
3200#ifdef TPM_ALG_ECC
3201 // If ECC is implemented ECDSA is required
3202 case TPM_ALG_ECDSA:
3203#ifdef TPM_ALG_ECDAA
3204 // ECDAA is optional
3205 case TPM_ALG_ECDAA:
3206#endif
3207#ifdef TPM_ALG_ECSCHNORR
3208 // Schnorr is also optional
3209 case TPM_ALG_ECSCHNORR:
3210#endif
3211#ifdef TPM_ALG_SM2
3212 case TPM_ALG_SM2:
3213#endif
3214 isSignScheme = TRUE;
3215 break;
3216#endif //TPM_ALG_ECC
3217 default:
3218 break;
3219 }
3220 return isSignScheme;
3221}
3222//
3223//
3224// 10.2.9.18 CryptIsDecryptScheme()
3225//
3226// This function indicate if a scheme algorithm is a decrypt algorithm.
3227//
3228BOOL
3229CryptIsDecryptScheme(
3230 TPMI_ALG_ASYM_SCHEME scheme
3231 )
3232{
3233 BOOL isDecryptScheme = FALSE;
3234 switch(scheme)
3235 {
3236#ifdef TPM_ALG_RSA
3237 // If RSA is implemented, then both decrypt schemes are required
3238 case TPM_ALG_RSAES:
3239 case TPM_ALG_OAEP:
3240 isDecryptScheme = TRUE;
3241 break;
3242#endif //TPM_ALG_RSA
3243#ifdef TPM_ALG_ECC
3244 // If ECC is implemented ECDH is required
3245 case TPM_ALG_ECDH:
3246#ifdef TPM_ALG_SM2
3247 case TPM_ALG_SM2:
3248#endif
3249#ifdef TPM_ALG_ECMQV
3250 case TPM_ALG_ECMQV:
3251#endif
3252 isDecryptScheme = TRUE;
3253 break;
3254#endif //TPM_ALG_ECC
3255 default:
3256 break;
3257 }
3258 return isDecryptScheme;
3259}
3260//
3261//
3262// 10.2.9.19 CryptSelectSignScheme()
3263//
3264// This function is used by the attestation and signing commands. It implements the rules for selecting the
3265// signature scheme to use in signing. This function requires that the signing key either be TPM_RH_NULL
3266// or be loaded.
3267// If a default scheme is defined in object, the default scheme should be chosen, otherwise, the input
3268// scheme should be chosen. In the case that both object and input scheme has a non-NULL scheme
3269// algorithm, if the schemes are compatible, the input scheme will be chosen.
3270//
3271//
3272//
3273//
3274// Error Returns Meaning
3275//
3276// TPM_RC_KEY key referenced by signHandle is not a signing key
3277// TPM_RC_SCHEME both scheme and key's default scheme are empty; or scheme is
3278// empty while key's default scheme requires explicit input scheme (split
3279// signing); or non-empty default key scheme differs from scheme
3280//
3281TPM_RC
3282CryptSelectSignScheme(
3283 TPMI_DH_OBJECT signHandle, // IN: handle of signing key
3284 TPMT_SIG_SCHEME *scheme // IN/OUT: signing scheme
3285 )
3286{
3287 OBJECT *signObject;
3288 TPMT_SIG_SCHEME *objectScheme;
3289 TPMT_PUBLIC *publicArea;
3290 TPM_RC result = TPM_RC_SUCCESS;
3291 // If the signHandle is TPM_RH_NULL, then the NULL scheme is used, regardless
3292 // of the setting of scheme
3293 if(signHandle == TPM_RH_NULL)
3294 {
3295 scheme->scheme = TPM_ALG_NULL;
3296 scheme->details.any.hashAlg = TPM_ALG_NULL;
3297 }
3298 else
3299 {
3300 // sign handle is not NULL so...
3301 // Get sign object pointer
3302 signObject = ObjectGet(signHandle);
3303 publicArea = &signObject->publicArea;
3304 // is this a signing key?
3305 if(!publicArea->objectAttributes.sign)
3306 result = TPM_RC_KEY;
3307 else
3308 {
3309 // "parms" defined to avoid long code lines.
3310 TPMU_PUBLIC_PARMS *parms = &publicArea->parameters;
3311 if(CryptIsAsymAlgorithm(publicArea->type))
3312 objectScheme = (TPMT_SIG_SCHEME *)&parms->asymDetail.scheme;
3313 else
3314 objectScheme = (TPMT_SIG_SCHEME *)&parms->keyedHashDetail.scheme;
3315 // If the object doesn't have a default scheme, then use the
3316 // input scheme.
3317 if(objectScheme->scheme == TPM_ALG_NULL)
3318 {
3319 // Input and default can't both be NULL
3320 if(scheme->scheme == TPM_ALG_NULL)
3321 result = TPM_RC_SCHEME;
3322 // Assume that the scheme is compatible with the key. If not,
3323 // we will generate an error in the signing operation.
3324 }
3325 else if(scheme->scheme == TPM_ALG_NULL)
3326 {
3327 // input scheme is NULL so use default
3328 // First, check to see if the default requires that the caller
3329 // provided scheme data
3330 if(CryptIsSplitSign(objectScheme->scheme))
3331 result = TPM_RC_SCHEME;
3332 else
3333 {
3334 scheme->scheme = objectScheme->scheme;
3335 scheme->details.any.hashAlg
3336 = objectScheme->details.any.hashAlg;
3337 }
3338 }
3339 else
3340 {
3341 // Both input and object have scheme selectors
3342 // If the scheme and the hash are not the same then...
3343 if( objectScheme->scheme != scheme->scheme
3344 || ( objectScheme->details.any.hashAlg
3345 != scheme->details.any.hashAlg))
3346 result = TPM_RC_SCHEME;
3347 }
3348 }
3349 }
3350 return result;
3351}
3352//
3353//
3354// 10.2.9.20 CryptSign()
3355//
3356// Sign a digest with asymmetric key or HMAC. This function is called by attestation commands and the
3357// generic TPM2_Sign() command. This function checks the key scheme and digest size. It does not check
3358// if the sign operation is allowed for restricted key. It should be checked before the function is called. The
3359// function will assert if the key is not a signing key.
3360//
3361// Error Returns Meaning
3362//
3363// TPM_RC_SCHEME signScheme is not compatible with the signing key type
3364// TPM_RC_VALUE digest value is greater than the modulus of signHandle or size of
3365// hashData does not match hash algorithm insignScheme (for an RSA
3366// key); invalid commit status or failed to generate r value (for an ECC
3367// key)
3368//
3369TPM_RC
3370CryptSign(
3371 TPMI_DH_OBJECT signHandle, // IN: The handle of sign key
3372 TPMT_SIG_SCHEME *signScheme, // IN: sign scheme.
3373 TPM2B_DIGEST *digest, // IN: The digest being signed
3374 TPMT_SIGNATURE *signature // OUT: signature
3375 )
3376{
3377 OBJECT *signKey = ObjectGet(signHandle);
3378 TPM_RC result = TPM_RC_SCHEME;
3379 // check if input handle is a sign key
3380 pAssert(signKey->publicArea.objectAttributes.sign == SET);
3381 // Must have the private portion loaded. This check is made during
3382 // authorization.
3383 pAssert(signKey->attributes.publicOnly == CLEAR);
3384 // Initialize signature scheme
3385 signature->sigAlg = signScheme->scheme;
3386 // If the signature algorithm is TPM_ALG_NULL, then we are done
3387 if(signature->sigAlg == TPM_ALG_NULL)
3388 return TPM_RC_SUCCESS;
3389 // All the schemes other than TPM_ALG_NULL have a hash algorithm
3390 TEST_HASH(signScheme->details.any.hashAlg);
3391 // Initialize signature hash
3392 // Note: need to do the check for alg null first because the null scheme
3393 // doesn't have a hashAlg member.
3394 signature->signature.any.hashAlg = signScheme->details.any.hashAlg;
3395 // perform sign operation based on different key type
3396 switch (signKey->publicArea.type)
3397 {
3398#ifdef TPM_ALG_RSA
3399 case TPM_ALG_RSA:
3400 result = CryptSignRSA(signKey, signScheme, digest, signature);
3401 break;
3402#endif //TPM_ALG_RSA
3403#ifdef TPM_ALG_ECC
3404 case TPM_ALG_ECC:
3405 result = CryptSignECC(signKey, signScheme, digest, signature);
3406 break;
3407#endif //TPM_ALG_ECC
3408 case TPM_ALG_KEYEDHASH:
3409 result = CryptSignHMAC(signKey, signScheme, digest, signature);
3410 break;
3411 default:
3412 break;
3413 }
3414 return result;
3415}
3416//
3417//
3418// 10.2.9.21 CryptVerifySignature()
3419//
3420// This function is used to verify a signature. It is called by TPM2_VerifySignature() and
3421// TPM2_PolicySigned().
3422// Since this operation only requires use of a public key, no consistency checks are necessary for the key to
3423// signature type because a caller can load any public key that they like with any scheme that they like. This
3424// routine simply makes sure that the signature is correct, whatever the type.
3425// This function requires that auth is not a NULL pointer.
3426//
3427// Error Returns Meaning
3428//
3429// TPM_RC_SIGNATURE the signature is not genuine
3430// TPM_RC_SCHEME the scheme is not supported
3431// TPM_RC_HANDLE an HMAC key was selected but the private part of the key is not
3432// loaded
3433//
3434TPM_RC
3435CryptVerifySignature(
3436 TPMI_DH_OBJECT keyHandle, // IN: The handle of sign key
3437 TPM2B_DIGEST *digest, // IN: The digest being validated
3438 TPMT_SIGNATURE *signature // IN: signature
3439 )
3440{
3441 // NOTE: ObjectGet will either return a pointer to a loaded object or
3442 // will assert. It will never return a non-valid value. This makes it save
3443 // to initialize 'publicArea' with the return value from ObjectGet() without
3444 // checking it first.
3445 OBJECT *authObject = ObjectGet(keyHandle);
3446 TPMT_PUBLIC *publicArea = &authObject->publicArea;
3447 TPM_RC result = TPM_RC_SCHEME;
3448 // The input unmarshaling should prevent any input signature from being
3449 // a NULL signature, but just in case
3450 if(signature->sigAlg == TPM_ALG_NULL)
3451 return TPM_RC_SIGNATURE;
3452 switch (publicArea->type)
3453 {
3454#ifdef TPM_ALG_RSA
3455 case TPM_ALG_RSA:
3456 result = CryptRSAVerifySignature(authObject, digest, signature);
3457 break;
3458#endif //TPM_ALG_RSA
3459#ifdef TPM_ALG_ECC
3460 case TPM_ALG_ECC:
3461 result = CryptECCVerifySignature(authObject, digest, signature);
3462 break;
3463#endif // TPM_ALG_ECC
3464 case TPM_ALG_KEYEDHASH:
3465 if(authObject->attributes.publicOnly)
3466 result = TPM_RCS_HANDLE;
3467 else
3468 result = CryptHMACVerifySignature(authObject, digest, signature);
3469 break;
3470 default:
3471 break;
3472 }
3473 return result;
3474}
3475//
3476//
3477// 10.2.10 Math functions
3478//
3479// 10.2.10.1 CryptDivide()
3480//
3481// This function interfaces to the math library for large number divide.
3482//
3483// Error Returns Meaning
3484//
3485// TPM_RC_SIZE quotient or remainder is too small to receive the result
3486//
3487TPM_RC
3488CryptDivide(
3489 TPM2B *numerator, // IN: numerator
3490 TPM2B *denominator, // IN: denominator
3491 TPM2B *quotient, // OUT: quotient = numerator / denominator.
3492 TPM2B *remainder // OUT: numerator mod denominator.
3493 )
3494{
3495 pAssert( numerator != NULL && denominator!= NULL
3496 && (quotient != NULL || remainder != NULL)
3497 );
3498 // assume denominator is not 0
3499 pAssert(denominator->size != 0);
3500 return TranslateCryptErrors(_math__Div(numerator,
3501 denominator,
3502 quotient,
3503 remainder)
3504 );
3505}
3506//
3507//
3508// 10.2.10.2 CryptCompare()
3509//
3510// This function interfaces to the math library for large number, unsigned compare.
3511//
3512// Return Value Meaning
3513//
3514// 1 if a > b
3515// 0 if a = b
3516// -1 if a < b
3517//
3518LIB_EXPORT int
3519CryptCompare(
3520 const UINT32 aSize, // IN: size of a
3521 const BYTE *a, // IN: a buffer
3522 const UINT32 bSize, // IN: size of b
3523 const BYTE *b // IN: b buffer
3524 )
3525{
3526 return _math__uComp(aSize, a, bSize, b);
3527}
3528//
3529//
3530// 10.2.10.3 CryptCompareSigned()
3531//
3532// This function interfaces to the math library for large number, signed compare.
3533//
3534// Return Value Meaning
3535//
3536// 1 if a > b
3537// 0 if a = b
3538// -1 if a < b
3539//
3540int
3541CryptCompareSigned(
3542 UINT32 aSize, // IN: size of a
3543 BYTE *a, // IN: a buffer
3544 UINT32 bSize, // IN: size of b
3545 BYTE *b // IN: b buffer
3546 )
3547{
3548 return _math__Comp(aSize, a, bSize, b);
3549}
3550//
3551//
3552// 10.2.10.4 CryptGetTestResult
3553//
3554// This function returns the results of a self-test function.
3555//
3556// NOTE: the behavior in this function is NOT the correct behavior for a real TPM implementation. An artificial behavior is
3557// placed here due to the limitation of a software simulation environment. For the correct behavior, consult the
3558// part 3 specification for TPM2_GetTestResult().
3559//
3560TPM_RC
3561CryptGetTestResult(
3562 TPM2B_MAX_BUFFER *outData // OUT: test result data
3563 )
3564{
3565 outData->t.size = 0;
3566 return TPM_RC_SUCCESS;
3567}
3568//
3569//
3570// 10.2.11 Capability Support
3571//
3572// 10.2.11.1 CryptCapGetECCCurve()
3573//
3574// This function returns the list of implemented ECC curves.
3575//
3576// Return Value Meaning
3577//
3578// YES if no more ECC curve is available
3579// NO if there are more ECC curves not reported
3580//
3581#ifdef TPM_ALG_ECC //% 5
3582TPMI_YES_NO
3583CryptCapGetECCCurve(
3584 TPM_ECC_CURVE curveID, // IN: the starting ECC curve
3585 UINT32 maxCount, // IN: count of returned curve
3586 TPML_ECC_CURVE *curveList // OUT: ECC curve list
3587 )
3588{
3589 TPMI_YES_NO more = NO;
3590 UINT16 i;
3591 UINT32 count = _cpri__EccGetCurveCount();
3592 TPM_ECC_CURVE curve;
3593 // Initialize output property list
3594 curveList->count = 0;
3595 // The maximum count of curves we may return is MAX_ECC_CURVES
3596 if(maxCount > MAX_ECC_CURVES) maxCount = MAX_ECC_CURVES;
3597 // Scan the eccCurveValues array
3598 for(i = 0; i < count; i++)
3599 {
3600 curve = _cpri__GetCurveIdByIndex(i);
3601 // If curveID is less than the starting curveID, skip it
3602 if(curve < curveID)
3603 continue;
3604 if(curveList->count < maxCount)
3605 {
3606 // If we have not filled up the return list, add more curves to
3607 // it
3608 curveList->eccCurves[curveList->count] = curve;
3609 curveList->count++;
3610 }
3611 else
3612 {
3613 // If the return list is full but we still have curves
3614 // available, report this and stop iterating
3615 more = YES;
3616 break;
3617 }
3618 }
3619 return more;
3620}
3621//
3622//
3623// 10.2.11.2 CryptCapGetEccCurveNumber()
3624//
3625// This function returns the number of ECC curves supported by the TPM.
3626//
3627UINT32
3628CryptCapGetEccCurveNumber(
3629 void
3630 )
3631{
3632 // There is an array that holds the curve data. Its size divided by the
3633 // size of an entry is the number of values in the table.
3634 return _cpri__EccGetCurveCount();
3635}
3636#endif //TPM_ALG_ECC //% 5
3637//
3638//
3639// 10.2.11.3 CryptAreKeySizesConsistent()
3640//
3641// This function validates that the public key size values are consistent for an asymmetric key.
3642//
3643// NOTE: This is not a comprehensive test of the public key.
3644//
3645//
3646// Return Value Meaning
3647//
3648// TRUE sizes are consistent
3649// FALSE sizes are not consistent
3650//
3651BOOL
3652CryptAreKeySizesConsistent(
3653 TPMT_PUBLIC *publicArea // IN: the public area to check
3654 )
3655{
3656 BOOL consistent = FALSE;
3657 switch (publicArea->type)
3658 {
3659#ifdef TPM_ALG_RSA
3660 case TPM_ALG_RSA:
3661 // The key size in bits is filtered by the unmarshaling
3662 consistent = ( ((publicArea->parameters.rsaDetail.keyBits+7)/8)
3663 == publicArea->unique.rsa.t.size);
3664 break;
3665#endif //TPM_ALG_RSA
3666#ifdef TPM_ALG_ECC
3667 case TPM_ALG_ECC:
3668 {
3669 UINT16 keySizeInBytes;
3670 TPM_ECC_CURVE curveId = publicArea->parameters.eccDetail.curveID;
3671 keySizeInBytes = CryptEccGetKeySizeInBytes(curveId);
3672 consistent = keySizeInBytes > 0
3673 && publicArea->unique.ecc.x.t.size <= keySizeInBytes
3674 && publicArea->unique.ecc.y.t.size <= keySizeInBytes;
3675 }
3676 break;
3677#endif //TPM_ALG_ECC
3678 default:
3679 break;
3680 }
3681 return consistent;
3682}
3683//
3684//
3685// 10.2.11.4 CryptAlgSetImplemented()
3686//
3687// This function initializes the bit vector with one bit for each implemented algorithm. This function is called
3688// from _TPM_Init(). The vector of implemented algorithms should be generated by the part 2 parser so that
3689// the g_implementedAlgorithms vector can be a const. That's not how it is now
3690//
3691void
3692CryptAlgsSetImplemented(
3693 void
3694 )
3695{
3696 AlgorithmGetImplementedVector(&g_implementedAlgorithms);
3697}