blob: 912c3654c1dcc5f681393c1caff667629d13898e [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)
Jocelyn Bohr2d087042015-08-10 16:24:34 -0700712 hashAlg = scheme->details.xor_.hashAlg;
Vadim Bendebury56797522015-05-20 10:32:25 -0700713 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.
Vadim Bendeburyb37f66b2015-10-13 13:06:02 -0700954 // The hash algorithm match has to be verified for OAEP.
Vadim Bendebury56797522015-05-20 10:32:25 -0700955 // IMPLEMENTATION NOTE: This could cause problems if future versions have
956 // schemes that have more values than just a hash algorithm. A new function
957 // (IsSchemeSame()) might be needed then.
Vadim Bendeburyb37f66b2015-10-13 13:06:02 -0700958 else if (keyScheme->scheme == scheme->scheme
959 && ((keyScheme->scheme != TPM_ALG_OAEP) ||
960 (keyScheme->details.anySig.hashAlg == scheme->details.anySig.hashAlg)))
Vadim Bendebury56797522015-05-20 10:32:25 -0700961 {
962 retVal = scheme;
963 }
964 // two different, incompatible schemes specified will return NULL
965 return retVal;
966}
967//
968//
969// 10.2.5.6 CryptDecryptRSA()
970//
971// This function is the interface to _cpri__DecryptRSA(). It handles the return codes from that function and
972// converts them from CRYPT_RESULT to TPM_RC values. The rsaKey parameter must reference an RSA
973// decryption key
974//
975// Error Returns Meaning
976//
977// TPM_RC_BINDING Public and private parts of the key are not cryptographically bound.
978// TPM_RC_SIZE Size of data to decrypt is not the same as the key size.
979// TPM_RC_VALUE Numeric value of the encrypted data is greater than the public
980// exponent, or output buffer is too small for the decrypted message.
981//
982TPM_RC
983CryptDecryptRSA(
984 UINT16 *dataOutSize, // OUT: size of plain text in byte
985 BYTE *dataOut, // OUT: plain text
986 OBJECT *rsaKey, // IN: internal RSA key
987 TPMT_RSA_DECRYPT *scheme, // IN: selects the padding scheme
988 UINT16 cipherInSize, // IN: size of cipher text in byte
989 BYTE *cipherIn, // IN: cipher text
990 const char *label // IN: a label, when needed
991 )
992{
993 RSA_KEY key;
994 CRYPT_RESULT retVal = CRYPT_SUCCESS;
995 UINT32 dSize; // Place to put temporary value for the
996 // returned data size
997 TPMI_ALG_HASH hashAlg = TPM_ALG_NULL; // hash algorithm in the selected
998 // padding scheme
999 TPM_RC result = TPM_RC_SUCCESS;
1000 // pointer checks
1001 pAssert( (dataOutSize != NULL) && (dataOut != NULL)
1002 && (rsaKey != NULL) && (cipherIn != NULL));
1003 // The public type is a RSA decrypt key
1004 pAssert( (rsaKey->publicArea.type == TPM_ALG_RSA
1005 && rsaKey->publicArea.objectAttributes.decrypt == SET));
1006 // Must have the private portion loaded. This check is made before this
1007 // function is called.
1008 pAssert(rsaKey->attributes.publicOnly == CLEAR);
1009 // decryption requires that the private modulus be present
1010 if(rsaKey->attributes.privateExp == CLEAR)
1011 {
1012 // Load key by computing the private exponent
1013 // CryptLoadPrivateRSA may return TPM_RC_BINDING
1014 result = CryptLoadPrivateRSA(rsaKey);
1015 }
1016 // the input buffer must be the size of the key
1017 if(result == TPM_RC_SUCCESS)
1018 {
1019 if(cipherInSize != rsaKey->publicArea.unique.rsa.t.size)
1020 result = TPM_RC_SIZE;
1021 else
1022 {
1023 BuildRSA(rsaKey, &key);
1024 // Initialize the dOutSize parameter
1025 dSize = *dataOutSize;
1026 // For OAEP scheme, initialize the hash algorithm for padding
1027 if(scheme->scheme == TPM_ALG_OAEP)
1028 {
1029 hashAlg = scheme->details.oaep.hashAlg;
1030 TEST_HASH(hashAlg);
1031 }
1032 // See if the padding mode needs to be tested
1033 TEST(scheme->scheme);
1034 // _cpri__DecryptRSA may return CRYPT_PARAMETER CRYPT_FAIL CRYPT_SCHEME
1035 retVal = _cpri__DecryptRSA(&dSize, dataOut, &key, scheme->scheme,
1036 cipherInSize, cipherIn, hashAlg, label);
1037 // Scheme must have been validated when the key was loaded/imported
1038 pAssert(retVal != CRYPT_SCHEME);
1039 // Set the return size
1040 pAssert(dSize <= UINT16_MAX);
1041 *dataOutSize = (UINT16)dSize;
1042 // CRYPT_PARAMETER -> TPM_RC_VALUE, CRYPT_FAIL -> TPM_RC_VALUE
1043 result = TranslateCryptErrors(retVal);
1044 }
1045 }
1046 return result;
1047}
1048//
1049//
1050// 10.2.5.7 CryptEncryptRSA()
1051//
1052// This function provides the interface to _cpri__EncryptRSA(). The object referenced by rsaKey is required
1053// to be an RSA decryption key.
1054//
1055// Error Returns Meaning
1056//
1057// TPM_RC_SCHEME scheme is not supported
1058// TPM_RC_VALUE numeric value of dataIn is greater than the key modulus
1059//
1060TPM_RC
1061CryptEncryptRSA(
1062 UINT16 *cipherOutSize, // OUT: size of cipher text in byte
1063 BYTE *cipherOut, // OUT: cipher text
1064 OBJECT *rsaKey, // IN: internal RSA key
1065 TPMT_RSA_DECRYPT *scheme, // IN: selects the padding scheme
1066 UINT16 dataInSize, // IN: size of plain text in byte
1067 BYTE *dataIn, // IN: plain text
1068 const char *label // IN: an optional label
1069 )
1070{
1071 RSA_KEY key;
1072 CRYPT_RESULT retVal;
1073 UINT32 cOutSize; // Conversion variable
1074 TPMI_ALG_HASH hashAlg = TPM_ALG_NULL; // hash algorithm in selected
1075 // padding scheme
1076 // must have a pointer to a key and some data to encrypt
1077 pAssert(rsaKey != NULL && dataIn != NULL);
1078 // The public type is a RSA decryption key
1079 pAssert( rsaKey->publicArea.type == TPM_ALG_RSA
1080 && rsaKey->publicArea.objectAttributes.decrypt == SET);
1081 // If the cipher buffer must be provided and it must be large enough
1082 // for the result
1083 pAssert( cipherOut != NULL
1084 && cipherOutSize != NULL
1085 && *cipherOutSize >= rsaKey->publicArea.unique.rsa.t.size);
1086 // Only need the public key and exponent for encryption
1087 BuildRSA(rsaKey, &key);
1088 // Copy the size to the conversion buffer
1089 cOutSize = *cipherOutSize;
1090 // For OAEP scheme, initialize the hash algorithm for padding
1091 if(scheme->scheme == TPM_ALG_OAEP)
1092 {
1093 hashAlg = scheme->details.oaep.hashAlg;
1094 TEST_HASH(hashAlg);
1095 }
1096 // This is a public key operation and does not require that the private key
1097 // be loaded. To verify this, need to do the full algorithm
1098 TEST(scheme->scheme);
1099 // Encrypt the data with the public exponent
1100 // _cpri__EncryptRSA may return CRYPT_PARAMETER or CRYPT_SCHEME
1101 retVal = _cpri__EncryptRSA(&cOutSize,cipherOut, &key, scheme->scheme,
1102 dataInSize, dataIn, hashAlg, label);
1103 pAssert (cOutSize <= UINT16_MAX);
1104 *cipherOutSize = (UINT16)cOutSize;
1105 // CRYPT_PARAMETER -> TPM_RC_VALUE, CRYPT_SCHEME -> TPM_RC_SCHEME
1106 return TranslateCryptErrors(retVal);
1107}
1108//
1109//
1110// 10.2.5.8 CryptSignRSA()
1111//
1112// This function is used to sign a digest with an RSA signing key.
1113//
1114// Error Returns Meaning
1115//
1116// TPM_RC_BINDING public and private part of signKey are not properly bound
1117// TPM_RC_SCHEME scheme is not supported
1118// TPM_RC_VALUE hashData is larger than the modulus of signKey, or the size of
1119// hashData does not match hash algorithm in scheme
1120//
1121static TPM_RC
1122CryptSignRSA(
1123 OBJECT *signKey, // IN: RSA key signs the hash
1124 TPMT_SIG_SCHEME *scheme, // IN: sign scheme
1125 TPM2B_DIGEST *hashData, // IN: hash to be signed
1126 TPMT_SIGNATURE *sig // OUT: signature
1127 )
1128{
1129 UINT32 signSize;
1130 RSA_KEY key;
1131 CRYPT_RESULT retVal;
1132 TPM_RC result = TPM_RC_SUCCESS;
1133 pAssert( (signKey != NULL) && (scheme != NULL)
1134 && (hashData != NULL) && (sig != NULL));
1135 // assume that the key has private part loaded and that it is a signing key.
1136 pAssert( (signKey->attributes.publicOnly == CLEAR)
1137 && (signKey->publicArea.objectAttributes.sign == SET));
1138 // check if the private exponent has been computed
1139 if(signKey->attributes.privateExp == CLEAR)
1140 // May return TPM_RC_BINDING
1141 result = CryptLoadPrivateRSA(signKey);
1142 if(result == TPM_RC_SUCCESS)
1143 {
1144 BuildRSA(signKey, &key);
1145 // Make sure that the hash is tested
1146 TEST_HASH(sig->signature.any.hashAlg);
1147 // Run a test of the RSA sign
1148 TEST(scheme->scheme);
1149 // _crypi__SignRSA can return CRYPT_SCHEME and CRYPT_PARAMETER
1150 retVal = _cpri__SignRSA(&signSize,
1151 sig->signature.rsassa.sig.t.buffer,
1152 &key,
1153 sig->sigAlg,
1154 sig->signature.any.hashAlg,
1155 hashData->t.size, hashData->t.buffer);
1156 pAssert(signSize <= UINT16_MAX);
1157 sig->signature.rsassa.sig.t.size = (UINT16)signSize;
1158 // CRYPT_SCHEME -> TPM_RC_SCHEME; CRYPT_PARAMTER -> TPM_RC_VALUE
1159 result = TranslateCryptErrors(retVal);
1160 }
1161 return result;
1162}
1163//
1164//
1165// 10.2.5.9 CryptRSAVerifySignature()
1166//
1167// This function is used to verify signature signed by a RSA key.
1168//
1169// Error Returns Meaning
1170//
1171// TPM_RC_SIGNATURE if signature is not genuine
1172// TPM_RC_SCHEME signature scheme not supported
1173//
1174static TPM_RC
1175CryptRSAVerifySignature(
1176 OBJECT *signKey, // IN: RSA key signed the hash
1177 TPM2B_DIGEST *digestData, // IN: digest being signed
1178 TPMT_SIGNATURE *sig // IN: signature to be verified
1179 )
1180{
1181 RSA_KEY key;
1182 CRYPT_RESULT retVal;
1183 TPM_RC result;
1184 // Validate parameter assumptions
1185 pAssert((signKey != NULL) && (digestData != NULL) && (sig != NULL));
1186 TEST_HASH(sig->signature.any.hashAlg);
1187 TEST(sig->sigAlg);
1188 // This is a public-key-only operation
1189 BuildRSA(signKey, &key);
1190 // Call crypto engine to verify signature
1191 // _cpri_ValidateSignaturRSA may return CRYPT_FAIL or CRYPT_SCHEME
1192 retVal = _cpri__ValidateSignatureRSA(&key,
1193 sig->sigAlg,
1194 sig->signature.any.hashAlg,
1195 digestData->t.size,
1196 digestData->t.buffer,
1197 sig->signature.rsassa.sig.t.size,
1198 sig->signature.rsassa.sig.t.buffer,
1199 0);
1200 // _cpri__ValidateSignatureRSA can return CRYPT_SUCCESS, CRYPT_FAIL, or
1201 // CRYPT_SCHEME. Translate CRYPT_FAIL to TPM_RC_SIGNATURE
1202 if(retVal == CRYPT_FAIL)
1203 result = TPM_RC_SIGNATURE;
1204 else
1205 // CRYPT_SCHEME -> TPM_RC_SCHEME
1206 result = TranslateCryptErrors(retVal);
1207 return result;
1208}
1209//
1210#endif //TPM_ALG_RSA //% 2
1211//
1212//
1213// 10.2.6 ECC Functions
1214//
1215// 10.2.6.1 CryptEccGetCurveDataPointer()
1216//
1217// This function returns a pointer to an ECC_CURVE_VALUES structure that contains the parameters for
1218// the key size and schemes for a given curve.
1219//
1220#ifdef TPM_ALG_ECC //% 3
1221static const ECC_CURVE *
1222CryptEccGetCurveDataPointer(
1223 TPM_ECC_CURVE curveID // IN: id of the curve
1224 )
1225{
1226 return _cpri__EccGetParametersByCurveId(curveID);
1227}
1228//
1229//
1230// 10.2.6.2 CryptEccGetKeySizeInBits()
1231//
1232// This function returns the size in bits of the key associated with a curve.
1233//
1234UINT16
1235CryptEccGetKeySizeInBits(
1236 TPM_ECC_CURVE curveID // IN: id of the curve
1237 )
1238{
1239 const ECC_CURVE *curve = CryptEccGetCurveDataPointer(curveID);
1240 UINT16 keySizeInBits = 0;
1241 if(curve != NULL)
1242 keySizeInBits = curve->keySizeBits;
1243 return keySizeInBits;
1244}
1245//
1246//
Vadim Bendebury56797522015-05-20 10:32:25 -07001247// 10.2.6.4 CryptEccGetParameter()
1248//
1249// This function returns a pointer to an ECC curve parameter. The parameter is selected by a single
1250// character designator from the set of {pnabxyh}.
1251//
1252LIB_EXPORT const TPM2B *
1253CryptEccGetParameter(
1254 char p, // IN: the parameter selector
1255 TPM_ECC_CURVE curveId // IN: the curve id
1256 )
1257{
1258 const ECC_CURVE *curve = _cpri__EccGetParametersByCurveId(curveId);
1259 const TPM2B *parameter = NULL;
1260 if(curve != NULL)
1261 {
1262 switch (p)
1263 {
1264 case 'p':
1265 parameter = curve->curveData->p;
1266 break;
1267 case 'n':
1268 parameter = curve->curveData->n;
1269 break;
1270 case 'a':
1271 parameter = curve->curveData->a;
1272 break;
1273 case 'b':
1274 parameter = curve->curveData->b;
1275 break;
1276 case 'x':
1277 parameter = curve->curveData->x;
1278 break;
1279 case 'y':
1280 parameter = curve->curveData->y;
1281 break;
1282 case 'h':
1283 parameter = curve->curveData->h;
1284 break;
1285 default:
1286 break;
1287 }
1288 }
1289 return parameter;
1290}
1291//
1292//
1293// 10.2.6.5 CryptGetCurveSignScheme()
1294//
1295// This function will return a pointer to the scheme of the curve.
1296//
1297const TPMT_ECC_SCHEME *
1298CryptGetCurveSignScheme(
1299 TPM_ECC_CURVE curveId // IN: The curve selector
1300 )
1301{
1302 const ECC_CURVE *curve = _cpri__EccGetParametersByCurveId(curveId);
1303 const TPMT_ECC_SCHEME *scheme = NULL;
1304 if(curve != NULL)
1305 scheme = &(curve->sign);
1306 return scheme;
1307}
1308//
1309//
1310// 10.2.6.6 CryptEccIsPointOnCurve()
1311//
1312// This function will validate that an ECC point is on the curve of given curveID.
1313//
1314// Return Value Meaning
1315//
1316// TRUE if the point is on curve
1317// FALSE if the point is not on curve
1318//
1319BOOL
1320CryptEccIsPointOnCurve(
1321 TPM_ECC_CURVE curveID, // IN: ECC curve ID
1322 TPMS_ECC_POINT *Q // IN: ECC point
1323 )
1324{
1325 // Make sure that point multiply is working
1326 TEST(TPM_ALG_ECC);
1327 // Check point on curve logic by seeing if the test key is on the curve
1328 // Call crypto engine function to check if a ECC public point is on the
1329 // given curve
1330 if(_cpri__EccIsPointOnCurve(curveID, Q))
1331 return TRUE;
1332 else
1333 return FALSE;
1334}
1335//
1336//
1337// 10.2.6.7 CryptNewEccKey()
1338//
1339// This function creates a random ECC key that is not derived from other parameters as is a Primary Key.
1340//
1341TPM_RC
1342CryptNewEccKey(
1343 TPM_ECC_CURVE curveID, // IN: ECC curve
1344 TPMS_ECC_POINT *publicPoint, // OUT: public point
1345 TPM2B_ECC_PARAMETER *sensitive // OUT: private area
1346 )
1347{
1348 TPM_RC result = TPM_RC_SUCCESS;
1349 // _cpri__GetEphemeralECC may return CRYPT_PARAMETER
1350 if(_cpri__GetEphemeralEcc(publicPoint, sensitive, curveID) != CRYPT_SUCCESS)
1351 // Something is wrong with the key.
1352 result = TPM_RC_KEY;
1353 return result;
1354}
1355//
1356//
1357// 10.2.6.8 CryptEccPointMultiply()
1358//
1359// This function is used to perform a point multiply R = [d]Q. If Q is not provided, the multiplication is
1360// performed using the generator point of the curve.
1361//
1362// Error Returns Meaning
1363//
1364// TPM_RC_ECC_POINT invalid optional ECC point pIn
1365// TPM_RC_NO_RESULT multiplication resulted in a point at infinity
1366// TPM_RC_CANCELED if a self-test was done, it might have been aborted
1367//
1368TPM_RC
1369CryptEccPointMultiply(
1370 TPMS_ECC_POINT *pOut, // OUT: output point
1371 TPM_ECC_CURVE curveId, // IN: curve selector
1372 TPM2B_ECC_PARAMETER *dIn, // IN: public scalar
1373 TPMS_ECC_POINT *pIn // IN: optional point
1374 )
1375{
1376 TPM2B_ECC_PARAMETER *n = NULL;
1377 CRYPT_RESULT retVal;
1378 pAssert(pOut != NULL && dIn != NULL);
1379 if(pIn != NULL)
1380 {
1381 n = dIn;
1382 dIn = NULL;
1383 }
1384 // Do a test of point multiply
1385 TEST(TPM_ALG_ECC);
1386 // _cpri__EccPointMultiply may return CRYPT_POINT or CRYPT_NO_RESULT
1387 retVal = _cpri__EccPointMultiply(pOut, curveId, dIn, pIn, n);
1388 // CRYPT_POINT->TPM_RC_ECC_POINT and CRYPT_NO_RESULT->TPM_RC_NO_RESULT
1389 return TranslateCryptErrors(retVal);
1390}
1391//
1392//
1393// 10.2.6.9 CryptGenerateKeyECC()
1394//
1395// This function generates an ECC key from a seed value.
1396// The method here may not work for objects that have an order (G) that with a different size than a private
1397// key.
1398//
1399// Error Returns Meaning
1400//
1401// TPM_RC_VALUE hash algorithm is not supported
1402//
1403static TPM_RC
1404CryptGenerateKeyECC(
1405 TPMT_PUBLIC *publicArea, // IN/OUT: The public area template for the new
1406 // key.
1407 TPMT_SENSITIVE *sensitive, // IN/OUT: the sensitive area
1408 TPM_ALG_ID hashAlg, // IN: algorithm for the KDF
1409 TPM2B_SEED *seed, // IN: the seed value
1410 TPM2B_NAME *name, // IN: the name of the object
1411 UINT32 *counter // OUT: the iteration counter
1412 )
1413{
1414 CRYPT_RESULT retVal;
1415 TEST_HASH(hashAlg);
1416 TEST(ALG_ECDSA_VALUE); // ECDSA is used to verify each key
1417 // The iteration counter has no meaning for ECC key generation. The parameter
1418 // will be overloaded for those implementations that have a requirement for
1419 // doing pair-wise consistency checks on signing keys. If the counter parameter
1420 // is 0 or NULL, then no consistency check is done. If it is other than 0, then
1421 // a consistency check is run. This modification allow this code to work with
1422 // the existing versions of the CrytpoEngine and with FIPS-compliant versions
1423 // as well.
1424 *counter = (UINT32)(publicArea->objectAttributes.sign == SET);
1425 // _cpri__GenerateKeyEcc only has one error return (CRYPT_PARAMETER) which means
1426 // that the hash algorithm is not supported. This should not be possible
1427 retVal = _cpri__GenerateKeyEcc(&publicArea->unique.ecc,
1428 &sensitive->sensitive.ecc,
1429 publicArea->parameters.eccDetail.curveID,
1430 hashAlg, &seed->b, "ECC key by vendor",
1431 &name->b, counter);
1432 // This will only be useful if _cpri__GenerateKeyEcc return CRYPT_CANCEL
1433 return TranslateCryptErrors(retVal);
1434}
1435//
1436//
1437// 10.2.6.10 CryptSignECC()
1438//
1439// This function is used for ECC signing operations. If the signing scheme is a split scheme, and the signing
1440// operation is successful, the commit value is retired.
1441//
1442//
1443// Error Returns Meaning
1444//
1445// TPM_RC_SCHEME unsupported scheme
1446// TPM_RC_VALUE invalid commit status (in case of a split scheme) or failed to generate
1447// r value.
1448//
1449static TPM_RC
1450CryptSignECC(
1451 OBJECT *signKey, // IN: ECC key to sign the hash
1452 TPMT_SIG_SCHEME *scheme, // IN: sign scheme
1453 TPM2B_DIGEST *hashData, // IN: hash to be signed
1454 TPMT_SIGNATURE *signature // OUT: signature
1455 )
1456{
1457 TPM2B_ECC_PARAMETER r;
1458 TPM2B_ECC_PARAMETER *pr = NULL;
1459 CRYPT_RESULT retVal;
1460 // Run a test of the ECC sign and verify if it has not already been run
1461 TEST_HASH(scheme->details.any.hashAlg);
1462 TEST(scheme->scheme);
1463 if(CryptIsSplitSign(scheme->scheme))
1464 {
1465 // When this code was written, the only split scheme was ECDAA
1466 // (which can also be used for U-Prove).
1467 if(!CryptGenerateR(&r,
1468 &scheme->details.ecdaa.count,
1469 signKey->publicArea.parameters.eccDetail.curveID,
1470 &signKey->name))
1471 return TPM_RC_VALUE;
1472 pr = &r;
1473 }
1474 // Call crypto engine function to sign
1475 // _cpri__SignEcc may return CRYPT_SCHEME
1476 retVal = _cpri__SignEcc(&signature->signature.ecdsa.signatureR,
1477 &signature->signature.ecdsa.signatureS,
1478 scheme->scheme,
1479 scheme->details.any.hashAlg,
1480 signKey->publicArea.parameters.eccDetail.curveID,
1481 &signKey->sensitive.sensitive.ecc,
1482 &hashData->b,
1483 pr
1484 );
1485 if(CryptIsSplitSign(scheme->scheme) && retVal == CRYPT_SUCCESS)
1486 CryptEndCommit(scheme->details.ecdaa.count);
1487 // CRYPT_SCHEME->TPM_RC_SCHEME
1488 return TranslateCryptErrors(retVal);
1489}
1490//
1491//
1492// 10.2.6.11 CryptECCVerifySignature()
1493//
1494// This function is used to verify a signature created with an ECC key.
1495//
1496// Error Returns Meaning
1497//
1498// TPM_RC_SIGNATURE if signature is not valid
1499// TPM_RC_SCHEME the signing scheme or hashAlg is not supported
1500//
1501static TPM_RC
1502CryptECCVerifySignature(
1503 OBJECT *signKey, // IN: ECC key signed the hash
1504 TPM2B_DIGEST *digestData, // IN: digest being signed
1505 TPMT_SIGNATURE *signature // IN: signature to be verified
1506 )
1507{
1508 CRYPT_RESULT retVal;
1509 TEST_HASH(signature->signature.any.hashAlg);
1510 TEST(signature->sigAlg);
1511 // This implementation uses the fact that all the defined ECC signing
1512 // schemes have the hash as the first parameter.
1513 // _cpriValidateSignatureEcc may return CRYPT_FAIL or CRYP_SCHEME
1514 retVal = _cpri__ValidateSignatureEcc(&signature->signature.ecdsa.signatureR,
1515 &signature->signature.ecdsa.signatureS,
1516 signature->sigAlg,
1517 signature->signature.any.hashAlg,
1518 signKey->publicArea.parameters.eccDetail.curveID,
1519 &signKey->publicArea.unique.ecc,
1520 &digestData->b);
1521 if(retVal == CRYPT_FAIL)
1522 return TPM_RC_SIGNATURE;
1523 // CRYPT_SCHEME->TPM_RC_SCHEME
1524 return TranslateCryptErrors(retVal);
1525}
1526//
1527//
1528// 10.2.6.12 CryptGenerateR()
1529//
1530// This function computes the commit random value for a split signing scheme.
1531// If c is NULL, it indicates that r is being generated for TPM2_Commit(). If c is not NULL, the TPM will
1532// validate that the gr.commitArray bit associated with the input value of c is SET. If not, the TPM returns
1533// FALSE and no r value is generated.
1534//
1535// Return Value Meaning
1536//
1537// TRUE r value computed
1538// FALSE no r value computed
1539//
1540BOOL
1541CryptGenerateR(
1542 TPM2B_ECC_PARAMETER *r, // OUT: the generated random value
1543 UINT16 *c, // IN/OUT: count value.
1544 TPMI_ECC_CURVE curveID, // IN: the curve for the value
1545 TPM2B_NAME *name // IN: optional name of a key to
1546 // associate with 'r'
1547 )
1548{
1549 // This holds the marshaled g_commitCounter.
1550 TPM2B_TYPE(8B, 8);
Vadim Bendeburyc00055c2015-05-29 22:50:18 -07001551 TPM2B_8B cntr = {.b.size = 8};
Vadim Bendebury56797522015-05-20 10:32:25 -07001552 UINT32 iterations;
1553 const TPM2B *n;
1554 UINT64 currentCount = gr.commitCounter;
1555 // This is just to suppress a compiler warning about a conditional expression
1556 // being a constant. This is because of the macro expansion of ryptKDFa
1557 TPMI_ALG_HASH hashAlg = CONTEXT_INTEGRITY_HASH_ALG;
1558 n = CryptEccGetParameter('n', curveID);
1559 pAssert(r != NULL && n != NULL);
1560 // If this is the commit phase, use the current value of the commit counter
1561 if(c != NULL)
1562//
1563 {
1564 UINT16 t1;
1565 // if the array bit is not set, can't use the value.
1566 if(!BitIsSet((*c & COMMIT_INDEX_MASK), gr.commitArray,
1567 sizeof(gr.commitArray)))
1568 return FALSE;
1569 // If it is the sign phase, figure out what the counter value was
1570 // when the commitment was made.
1571 //
1572 // When gr.commitArray has less than 64K bits, the extra
1573 // bits of 'c' are used as a check to make sure that the
1574 // signing operation is not using an out of range count value
1575 t1 = (UINT16)currentCount;
1576 // If the lower bits of c are greater or equal to the lower bits of t1
1577 // then the upper bits of t1 must be one more than the upper bits
1578 // of c
1579 if((*c & COMMIT_INDEX_MASK) >= (t1 & COMMIT_INDEX_MASK))
1580 // Since the counter is behind, reduce the current count
1581 currentCount = currentCount - (COMMIT_INDEX_MASK + 1);
1582 t1 = (UINT16)currentCount;
1583 if((t1 & ~COMMIT_INDEX_MASK) != (*c & ~COMMIT_INDEX_MASK))
1584 return FALSE;
1585 // set the counter to the value that was
1586 // present when the commitment was made
1587 currentCount = (currentCount & 0xffffffffffff0000) | *c;
1588 }
1589 // Marshal the count value to a TPM2B buffer for the KDF
1590 cntr.t.size = sizeof(currentCount);
1591 UINT64_TO_BYTE_ARRAY(currentCount, cntr.t.buffer);
1592 // Now can do the KDF to create the random value for the signing operation
1593 // During the creation process, we may generate an r that does not meet the
1594 // requirements of the random value.
1595 // want to generate a new r.
1596 r->t.size = n->size;
1597 // Arbitrary upper limit on the number of times that we can look for
1598 // a suitable random value. The normally number of tries will be 1.
1599 for(iterations = 1; iterations < 1000000;)
1600 {
1601 BYTE *pr = &r->b.buffer[0];
1602 int i;
1603 CryptKDFa(hashAlg, &gr.commitNonce.b, "ECDAA Commit",
1604 name, &cntr.b, n->size * 8, r->t.buffer, &iterations);
1605 // random value must be less than the prime
1606 if(CryptCompare(r->b.size, r->b.buffer, n->size, n->buffer) >= 0)
1607 continue;
1608 // in this implementation it is required that at least bit
1609 // in the upper half of the number be set
1610 for(i = n->size/2; i > 0; i--)
1611 if(*pr++ != 0)
1612 return TRUE;
1613 }
1614 return FALSE;
1615}
1616//
1617//
1618//
1619// 10.2.6.13 CryptCommit()
1620//
1621// This function is called when the count value is committed. The gr.commitArray value associated with the
1622// current count value is SET and g_commitCounter is incremented. The low-order 16 bits of old value of the
1623// counter is returned.
1624//
1625UINT16
1626CryptCommit(
1627 void
1628 )
1629{
1630 UINT16 oldCount = (UINT16)gr.commitCounter;
1631 gr.commitCounter++;
1632 BitSet(oldCount & COMMIT_INDEX_MASK, gr.commitArray, sizeof(gr.commitArray));
1633 return oldCount;
1634}
1635//
1636//
1637// 10.2.6.14 CryptEndCommit()
1638//
1639// This function is called when the signing operation using the committed value is completed. It clears the
1640// gr.commitArray bit associated with the count value so that it can't be used again.
1641//
1642void
1643CryptEndCommit(
1644 UINT16 c // IN: the counter value of the commitment
1645 )
1646{
1647 BitClear((c & COMMIT_INDEX_MASK), gr.commitArray, sizeof(gr.commitArray));
1648}
1649//
1650//
1651// 10.2.6.15 CryptCommitCompute()
1652//
1653// This function performs the computations for the TPM2_Commit() command. This could be a macro.
1654//
1655// Error Returns Meaning
1656//
1657// TPM_RC_NO_RESULT K, L, or E is the point at infinity
1658// TPM_RC_CANCELLED command was canceled
1659//
1660TPM_RC
1661CryptCommitCompute(
1662 TPMS_ECC_POINT *K, // OUT: [d]B
1663 TPMS_ECC_POINT *L, // OUT: [r]B
1664 TPMS_ECC_POINT *E, // OUT: [r]M
1665 TPM_ECC_CURVE curveID, // IN: The curve for the computation
1666 TPMS_ECC_POINT *M, // IN: M (P1)
1667 TPMS_ECC_POINT *B, // IN: B (x2, y2)
1668 TPM2B_ECC_PARAMETER *d, // IN: the private scalar
1669 TPM2B_ECC_PARAMETER *r // IN: the computed r value
1670 )
1671{
1672 TEST(ALG_ECDH_VALUE);
1673 // CRYPT_NO_RESULT->TPM_RC_NO_RESULT CRYPT_CANCEL->TPM_RC_CANCELLED
1674 return TranslateCryptErrors(
1675 _cpri__EccCommitCompute(K, L , E, curveID, M, B, d, r));
1676}
1677//
1678//
1679//
1680// 10.2.6.16 CryptEccGetParameters()
1681//
1682// This function returns the ECC parameter details of the given curve
1683//
1684// Return Value Meaning
1685//
1686// TRUE Get parameters success
1687// FALSE Unsupported ECC curve ID
1688//
1689BOOL
1690CryptEccGetParameters(
1691 TPM_ECC_CURVE curveId, // IN: ECC curve ID
1692 TPMS_ALGORITHM_DETAIL_ECC *parameters // OUT: ECC parameter
1693 )
1694{
1695 const ECC_CURVE *curve = _cpri__EccGetParametersByCurveId(curveId);
1696 const ECC_CURVE_DATA *data;
1697 BOOL found = curve != NULL;
1698 if(found)
1699 {
1700 data = curve->curveData;
1701 parameters->curveID = curve->curveId;
1702 // Key size in bit
1703 parameters->keySize = curve->keySizeBits;
1704 // KDF
1705 parameters->kdf = curve->kdf;
1706 // Sign
1707 parameters->sign = curve->sign;
1708 // Copy p value
1709 MemoryCopy2B(&parameters->p.b, data->p, sizeof(parameters->p.t.buffer));
1710 // Copy a value
1711 MemoryCopy2B(&parameters->a.b, data->a, sizeof(parameters->a.t.buffer));
1712 // Copy b value
1713 MemoryCopy2B(&parameters->b.b, data->b, sizeof(parameters->b.t.buffer));
1714 // Copy Gx value
1715 MemoryCopy2B(&parameters->gX.b, data->x, sizeof(parameters->gX.t.buffer));
1716 // Copy Gy value
1717 MemoryCopy2B(&parameters->gY.b, data->y, sizeof(parameters->gY.t.buffer));
1718 // Copy n value
1719 MemoryCopy2B(&parameters->n.b, data->n, sizeof(parameters->n.t.buffer));
1720 // Copy h value
1721 MemoryCopy2B(&parameters->h.b, data->h, sizeof(parameters->h.t.buffer));
1722 }
1723 return found;
1724}
1725#if CC_ZGen_2Phase == YES
1726//
1727// CryptEcc2PhaseKeyExchange() This is the interface to the key exchange function.
1728//
1729TPM_RC
1730CryptEcc2PhaseKeyExchange(
1731 TPMS_ECC_POINT *outZ1, // OUT: the computed point
1732 TPMS_ECC_POINT *outZ2, // OUT: optional second point
1733 TPM_ALG_ID scheme, // IN: the key exchange scheme
1734 TPM_ECC_CURVE curveId, // IN: the curve for the computation
1735 TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key
1736 TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key
1737 TPMS_ECC_POINT *QsB, // IN: static public party B key
1738 TPMS_ECC_POINT *QeB // IN: ephemeral public party B key
1739 )
1740{
1741 return (TranslateCryptErrors(_cpri__C_2_2_KeyExchange(outZ1,
1742 outZ2,
1743 scheme,
1744 curveId,
1745 dsA,
1746 deA,
1747 QsB,
1748 QeB)));
1749}
1750#endif // CC_ZGen_2Phase
1751#endif //TPM_ALG_ECC //% 3
1752//
1753//
1754// 10.2.6.17 CryptIsSchemeAnonymous()
1755//
1756// This function is used to test a scheme to see if it is an anonymous scheme The only anonymous scheme
1757// is ECDAA. ECDAA can be used to do things like U-Prove.
1758//
1759BOOL
1760CryptIsSchemeAnonymous(
1761 TPM_ALG_ID scheme // IN: the scheme algorithm to test
1762 )
1763{
1764#ifdef TPM_ALG_ECDAA
1765 return (scheme == TPM_ALG_ECDAA);
1766#else
1767 UNREFERENCED(scheme);
1768 return 0;
1769#endif
1770}
1771//
1772//
1773// 10.2.7 Symmetric Functions
1774//
1775// 10.2.7.1 ParmDecryptSym()
1776//
1777// This function performs parameter decryption using symmetric block cipher.
1778//
1779void
1780ParmDecryptSym(
1781 TPM_ALG_ID symAlg, // IN: the symmetric algorithm
1782 TPM_ALG_ID hash, // IN: hash algorithm for KDFa
1783 UINT16 keySizeInBits, // IN: key key size in bit
1784 TPM2B *key, // IN: KDF HMAC key
1785 TPM2B *nonceCaller, // IN: nonce caller
1786 TPM2B *nonceTpm, // IN: nonce TPM
1787 UINT32 dataSize, // IN: size of parameter buffer
1788 BYTE *data // OUT: buffer to be decrypted
1789 )
1790{
1791 // KDF output buffer
1792 // It contains parameters for the CFB encryption
1793 // From MSB to LSB, they are the key and iv
1794 BYTE symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE];
1795 // Symmetric key size in byte
1796 UINT16 keySize = (keySizeInBits + 7) / 8;
1797 TPM2B_IV iv;
1798 iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits);
1799 // If there is decryption to do...
1800 if(iv.t.size > 0)
1801 {
1802 // Generate key and iv
1803 CryptKDFa(hash, key, "CFB", nonceCaller, nonceTpm,
1804 keySizeInBits + (iv.t.size * 8), symParmString, NULL);
1805 MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size,
1806 sizeof(iv.t.buffer));
1807 CryptSymmetricDecrypt(data, symAlg, keySizeInBits, TPM_ALG_CFB,
1808 symParmString, &iv, dataSize, data);
1809 }
1810 return;
1811}
1812//
1813//
1814// 10.2.7.2 ParmEncryptSym()
1815//
1816// This function performs parameter encryption using symmetric block cipher.
1817//
1818void
1819ParmEncryptSym(
1820 TPM_ALG_ID symAlg, // IN: symmetric algorithm
1821 TPM_ALG_ID hash, // IN: hash algorithm for KDFa
1822 UINT16 keySizeInBits, // IN: AES key size in bit
1823 TPM2B *key, // IN: KDF HMAC key
1824 TPM2B *nonceCaller, // IN: nonce caller
1825 TPM2B *nonceTpm, // IN: nonce TPM
1826 UINT32 dataSize, // IN: size of parameter buffer
1827 BYTE *data // OUT: buffer to be encrypted
1828 )
1829{
1830 // KDF output buffer
1831 // It contains parameters for the CFB encryption
1832 BYTE symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE];
1833 // Symmetric key size in bytes
1834 UINT16 keySize = (keySizeInBits + 7) / 8;
1835 TPM2B_IV iv;
1836 iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits);
1837 // See if there is any encryption to do
1838 if(iv.t.size > 0)
1839 {
1840 // Generate key and iv
1841 CryptKDFa(hash, key, "CFB", nonceTpm, nonceCaller,
1842 keySizeInBits + (iv.t.size * 8), symParmString, NULL);
1843 MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size,
1844 sizeof(iv.t.buffer));
1845 CryptSymmetricEncrypt(data, symAlg, keySizeInBits, TPM_ALG_CFB,
1846 symParmString, &iv, dataSize, data);
1847 }
1848 return;
1849}
1850//
1851//
1852//
1853// 10.2.7.3 CryptGenerateNewSymmetric()
1854//
1855// This function creates the sensitive symmetric values for an HMAC or symmetric key. If the sensitive area
1856// is zero, then the sensitive creation key data is copied. If it is not zero, then the TPM will generate a
1857// random value of the selected size.
1858//
1859void
1860CryptGenerateNewSymmetric(
1861 TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation data
1862 TPMT_SENSITIVE *sensitive, // OUT: sensitive area
1863 TPM_ALG_ID hashAlg, // IN: hash algorithm for the KDF
1864 TPM2B_SEED *seed, // IN: seed used in creation
1865 TPM2B_NAME *name // IN: name of the object
1866 )
1867{
1868 // This function is called to create a key and obfuscation value for a
1869 // symmetric key that can either be a block cipher or an XOR key. The buffer
1870 // in sensitive->sensitive will hold either. When we call the function
1871 // to copy the input value or generated value to the sensitive->sensitive
1872 // buffer we will need to have a size for the output buffer. This define
1873 // computes the maximum that it might need to be and uses that. It will always
1874 // be smaller than the largest value that will fit.
1875 #define MAX_SENSITIVE_SIZE \
1876 (MAX(sizeof(sensitive->sensitive.bits.t.buffer), \
1877 sizeof(sensitive->sensitive.sym.t.buffer)))
1878 // set the size of the obfuscation value
1879 sensitive->seedValue.t.size = CryptGetHashDigestSize(hashAlg);
1880 // If the input sensitive size is zero, then create both the sensitive data
1881 // and the obfuscation value
1882 if(sensitiveCreate->data.t.size == 0)
1883 {
1884 BYTE symValues[MAX(MAX_DIGEST_SIZE, MAX_SYM_KEY_BYTES)
1885 + MAX_DIGEST_SIZE];
1886 UINT16 requestSize;
1887 // Set the size of the request to be the size of the key and the
1888 // obfuscation value
1889 requestSize = sensitive->sensitive.sym.t.size
1890 + sensitive->seedValue.t.size;
1891 pAssert(requestSize <= sizeof(symValues));
1892 requestSize = _cpri__GenerateSeededRandom(requestSize, symValues, hashAlg,
1893 &seed->b,
1894 "symmetric sensitive", &name->b,
1895 NULL);
1896 pAssert(requestSize != 0);
1897 // Copy the new key
1898 MemoryCopy(sensitive->sensitive.sym.t.buffer,
1899 symValues, sensitive->sensitive.sym.t.size,
1900 MAX_SENSITIVE_SIZE);
1901 // copy the obfuscation value
1902 MemoryCopy(sensitive->seedValue.t.buffer,
1903 &symValues[sensitive->sensitive.sym.t.size],
1904 sensitive->seedValue.t.size,
1905 sizeof(sensitive->seedValue.t.buffer));
1906 }
1907 else
1908 {
1909 // Copy input symmetric key to sensitive area as long as it will fit
1910 MemoryCopy2B(&sensitive->sensitive.sym.b, &sensitiveCreate->data.b,
1911 MAX_SENSITIVE_SIZE);
1912 // Create the obfuscation value
1913 _cpri__GenerateSeededRandom(sensitive->seedValue.t.size,
1914 sensitive->seedValue.t.buffer,
1915 hashAlg, &seed->b,
1916 "symmetric obfuscation", &name->b, NULL);
1917 }
1918 return;
1919}
1920//
1921//
1922// 10.2.7.4 CryptGenerateKeySymmetric()
1923//
1924// This function derives a symmetric cipher key from the provided seed.
1925//
1926// Error Returns Meaning
1927//
1928// TPM_RC_KEY_SIZE key size in the public area does not match the size in the sensitive
1929// creation area
1930//
1931static TPM_RC
1932CryptGenerateKeySymmetric(
1933 TPMT_PUBLIC *publicArea, // IN/OUT: The public area template
1934 // for the new key.
1935 TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation data
1936 TPMT_SENSITIVE *sensitive, // OUT: sensitive area
1937 TPM_ALG_ID hashAlg, // IN: hash algorithm for the KDF
1938 TPM2B_SEED *seed, // IN: seed used in creation
1939 TPM2B_NAME *name // IN: name of the object
1940 )
1941{
1942 // If this is not a new key, then the provided key data must be the right size
1943 if(publicArea->objectAttributes.sensitiveDataOrigin == CLEAR)
1944 {
1945 if( (sensitiveCreate->data.t.size * 8)
Vadim Bendeburya49f9122015-10-27 16:32:54 -07001946 != publicArea->parameters.symDetail.sym.keyBits.sym)
Vadim Bendebury56797522015-05-20 10:32:25 -07001947 return TPM_RC_KEY_SIZE;
1948 // Make sure that the key size is OK.
1949 // This implementation only supports symmetric key sizes that are
1950 // multiples of 8
Vadim Bendeburya49f9122015-10-27 16:32:54 -07001951 if(publicArea->parameters.symDetail.sym.keyBits.sym % 8 != 0)
Vadim Bendebury56797522015-05-20 10:32:25 -07001952 return TPM_RC_KEY_SIZE;
1953 }
1954 else
1955 {
1956 // TPM is going to generate the key so set the size
1957 sensitive->sensitive.sym.t.size
Vadim Bendeburya49f9122015-10-27 16:32:54 -07001958 = publicArea->parameters.symDetail.sym.keyBits.sym / 8;
Vadim Bendebury56797522015-05-20 10:32:25 -07001959 sensitiveCreate->data.t.size = 0;
1960 }
1961 // Fill in the sensitive area
1962 CryptGenerateNewSymmetric(sensitiveCreate, sensitive, hashAlg,
1963 seed, name);
1964 // Create unique area in public
1965 CryptComputeSymmetricUnique(publicArea->nameAlg,
1966 sensitive, &publicArea->unique.sym);
1967 return TPM_RC_SUCCESS;
1968}
1969//
1970//
1971//
1972// 10.2.7.5 CryptXORObfuscation()
1973//
1974// This function implements XOR obfuscation. It should not be called if the hash algorithm is not
1975// implemented. The only return value from this function is TPM_RC_SUCCESS.
1976//
1977#ifdef TPM_ALG_KEYEDHASH //% 5
1978void
1979CryptXORObfuscation(
1980 TPM_ALG_ID hash, // IN: hash algorithm for KDF
1981 TPM2B *key, // IN: KDF key
1982 TPM2B *contextU, // IN: contextU
1983 TPM2B *contextV, // IN: contextV
1984 UINT32 dataSize, // IN: size of data buffer
1985 BYTE *data // IN/OUT: data to be XORed in place
1986 )
1987{
1988 BYTE mask[MAX_DIGEST_SIZE]; // Allocate a digest sized buffer
1989 BYTE *pm;
1990 UINT32 i;
1991 UINT32 counter = 0;
1992 UINT16 hLen = CryptGetHashDigestSize(hash);
1993 UINT32 requestSize = dataSize * 8;
1994 INT32 remainBytes = (INT32) dataSize;
1995 pAssert((key != NULL) && (data != NULL) && (hLen != 0));
1996 // Call KDFa to generate XOR mask
1997 for(; remainBytes > 0; remainBytes -= hLen)
1998 {
1999 // Make a call to KDFa to get next iteration
2000 CryptKDFaOnce(hash, key, "XOR", contextU, contextV,
2001 requestSize, mask, &counter);
2002 // XOR next piece of the data
2003 pm = mask;
2004 for(i = hLen < remainBytes ? hLen : remainBytes; i > 0; i--)
2005 *data++ ^= *pm++;
2006 }
2007 return;
2008}
2009#endif //TPM_ALG_KEYED_HASH //%5
2010//
2011//
2012// 10.2.8 Initialization and shut down
2013//
2014// 10.2.8.1 CryptInitUnits()
2015//
2016// This function is called when the TPM receives a _TPM_Init() indication. After function returns, the hash
2017// algorithms should be available.
2018//
2019// NOTE: The hash algorithms do not have to be tested, they just need to be available. They have to be tested before the
2020// TPM can accept HMAC authorization or return any result that relies on a hash algorithm.
2021//
2022void
2023CryptInitUnits(
2024 void
2025 )
2026{
2027 // Initialize the vector of implemented algorithms
2028 AlgorithmGetImplementedVector(&g_implementedAlgorithms);
2029 // Indicate that all test are necessary
2030 CryptInitializeToTest();
2031//
2032 // Call crypto engine unit initialization
2033 // It is assumed that crypt engine initialization should always succeed.
2034 // Otherwise, TPM should go to failure mode.
2035 if(_cpri__InitCryptoUnits(&TpmFail) != CRYPT_SUCCESS)
2036 FAIL(FATAL_ERROR_INTERNAL);
2037 return;
2038}
2039//
2040//
2041// 10.2.8.2 CryptStopUnits()
2042//
2043// This function is only used in a simulated environment. There should be no reason to shut down the
2044// cryptography on an actual TPM other than loss of power. After receiving TPM2_Startup(), the TPM should
2045// be able to accept commands until it loses power and, unless the TPM is in Failure Mode, the
2046// cryptographic algorithms should be available.
2047//
2048void
2049CryptStopUnits(
2050 void
2051 )
2052{
2053 // Call crypto engine unit stopping
2054 _cpri__StopCryptoUnits();
2055 return;
2056}
2057//
2058//
2059// 10.2.8.3 CryptUtilStartup()
2060//
2061// This function is called by TPM2_Startup() to initialize the functions in this crypto library and in the
2062// provided CryptoEngine(). In this implementation, the only initialization required in this library is
2063// initialization of the Commit nonce on TPM Reset.
2064// This function returns false if some problem prevents the functions from starting correctly. The TPM should
2065// go into failure mode.
2066//
2067BOOL
2068CryptUtilStartup(
2069 STARTUP_TYPE type // IN: the startup type
2070 )
2071{
2072 // Make sure that the crypto library functions are ready.
2073 // NOTE: need to initialize the crypto before loading
2074 // the RND state may trigger a self-test which
2075 // uses the
2076 if( !_cpri__Startup())
2077 return FALSE;
2078 // Initialize the state of the RNG.
2079 CryptDrbgGetPutState(PUT_STATE);
2080 if(type == SU_RESET)
2081 {
2082#ifdef TPM_ALG_ECC
2083 // Get a new random commit nonce
2084 gr.commitNonce.t.size = sizeof(gr.commitNonce.t.buffer);
2085 _cpri__GenerateRandom(gr.commitNonce.t.size, gr.commitNonce.t.buffer);
2086 // Reset the counter and commit array
2087 gr.commitCounter = 0;
2088 MemorySet(gr.commitArray, 0, sizeof(gr.commitArray));
2089#endif // TPM_ALG_ECC
2090 }
2091 // If the shutdown was orderly, then the values recovered from NV will
2092 // be OK to use. If the shutdown was not orderly, then a TPM Reset was required
2093 // and we would have initialized in the code above.
2094 return TRUE;
2095}
2096//
2097//
2098// 10.2.9 Algorithm-Independent Functions
2099//
2100// 10.2.9.1 Introduction
2101//
2102// These functions are used generically when a function of a general type (e.g., symmetric encryption) is
2103// required. The functions will modify the parameters as required to interface to the indicated algorithms.
2104//
2105// 10.2.9.2 CryptIsAsymAlgorithm()
2106//
2107// This function indicates if an algorithm is an asymmetric algorithm.
2108//
2109// Return Value Meaning
2110//
2111// TRUE if it is an asymmetric algorithm
2112// FALSE if it is not an asymmetric algorithm
2113//
2114BOOL
2115CryptIsAsymAlgorithm(
2116 TPM_ALG_ID algID // IN: algorithm ID
2117 )
2118{
2119 return (
2120#ifdef TPM_ALG_RSA
2121 algID == TPM_ALG_RSA
2122#endif
2123#if defined TPM_ALG_RSA && defined TPM_ALG_ECC
2124 ||
2125#endif
2126#ifdef TPM_ALG_ECC
2127 algID == TPM_ALG_ECC
2128#endif
2129 );
2130}
2131//
2132//
2133// 10.2.9.3 CryptGetSymmetricBlockSize()
2134//
2135// This function returns the size in octets of the symmetric encryption block used by an algorithm and key
2136// size combination.
2137//
2138INT16
2139CryptGetSymmetricBlockSize(
2140 TPMI_ALG_SYM algorithm, // IN: symmetric algorithm
2141 UINT16 keySize // IN: key size in bit
2142 )
2143{
2144 return _cpri__GetSymmetricBlockSize(algorithm, keySize);
2145}
2146//
2147//
2148//
2149// 10.2.9.4 CryptSymmetricEncrypt()
2150//
2151// This function does in-place encryption of a buffer using the indicated symmetric algorithm, key, IV, and
2152// mode. If the symmetric algorithm and mode are not defined, the TPM will fail.
2153//
2154void
2155CryptSymmetricEncrypt(
2156 BYTE *encrypted, // OUT: the encrypted data
2157 TPM_ALG_ID algorithm, // IN: algorithm for encryption
2158 UINT16 keySizeInBits, // IN: key size in bit
2159 TPMI_ALG_SYM_MODE mode, // IN: symmetric encryption mode
2160 BYTE *key, // IN: encryption key
2161 TPM2B_IV *ivIn, // IN/OUT: Input IV and output chaining
2162 // value for the next block
2163 UINT32 dataSize, // IN: data size in byte
2164 BYTE *data // IN/OUT: data buffer
2165 )
2166{
Vadim Bendeburyc00055c2015-05-29 22:50:18 -07002167 TPM2B_IV defaultIv = {};
Vadim Bendebury56797522015-05-20 10:32:25 -07002168 TPM2B_IV *iv = (ivIn != NULL) ? ivIn : &defaultIv;
2169 TEST(algorithm);
2170 pAssert(encrypted != NULL && key != NULL);
2171 // this check can pass but the case below can fail. ALG_xx_VALUE values are
2172 // defined for all algorithms but the TPM_ALG_xx might not be.
2173 if(algorithm == ALG_AES_VALUE || algorithm == ALG_SM4_VALUE)
2174 {
2175 if(mode != TPM_ALG_ECB)
2176 defaultIv.t.size = 16;
2177 // A provided IV has to be the right size
2178 pAssert(mode == TPM_ALG_ECB || iv->t.size == 16);
2179 }
2180 switch(algorithm)
2181 {
2182#ifdef TPM_ALG_AES
2183 case TPM_ALG_AES:
2184 {
2185 switch (mode)
2186 {
2187 case TPM_ALG_CTR:
2188 _cpri__AESEncryptCTR(encrypted, keySizeInBits, key,
2189 iv->t.buffer, dataSize, data);
2190 break;
2191 case TPM_ALG_OFB:
2192 _cpri__AESEncryptOFB(encrypted, keySizeInBits, key,
2193 iv->t.buffer, dataSize, data);
2194 break;
2195 case TPM_ALG_CBC:
2196 _cpri__AESEncryptCBC(encrypted, keySizeInBits, key,
2197 iv->t.buffer, dataSize, data);
2198 break;
2199 case TPM_ALG_CFB:
2200 _cpri__AESEncryptCFB(encrypted, keySizeInBits, key,
2201 iv->t.buffer, dataSize, data);
2202 break;
2203 case TPM_ALG_ECB:
2204 _cpri__AESEncryptECB(encrypted, keySizeInBits, key,
2205 dataSize, data);
2206 break;
2207 default:
2208 pAssert(0);
2209 }
2210 }
2211 break;
2212#endif
2213#ifdef TPM_ALG_SM4
2214 case TPM_ALG_SM4:
2215 {
2216 switch (mode)
2217 {
2218 case TPM_ALG_CTR:
2219 _cpri__SM4EncryptCTR(encrypted, keySizeInBits, key,
2220 iv->t.buffer, dataSize, data);
2221 break;
2222 case TPM_ALG_OFB:
2223 _cpri__SM4EncryptOFB(encrypted, keySizeInBits, key,
2224 iv->t.buffer, dataSize, data);
2225 break;
2226 case TPM_ALG_CBC:
2227 _cpri__SM4EncryptCBC(encrypted, keySizeInBits, key,
2228 iv->t.buffer, dataSize, data);
2229 break;
2230 case TPM_ALG_CFB:
2231 _cpri__SM4EncryptCFB(encrypted, keySizeInBits, key,
2232 iv->t.buffer, dataSize, data);
2233 break;
2234 case TPM_ALG_ECB:
2235 _cpri__SM4EncryptECB(encrypted, keySizeInBits, key,
2236 dataSize, data);
2237 break;
2238 default:
2239 pAssert(0);
2240 }
2241 }
2242 break;
2243#endif
2244 default:
2245 pAssert(FALSE);
2246 break;
2247 }
2248 return;
2249}
2250//
2251//
2252// 10.2.9.5 CryptSymmetricDecrypt()
2253//
2254// This function does in-place decryption of a buffer using the indicated symmetric algorithm, key, IV, and
2255// mode. If the symmetric algorithm and mode are not defined, the TPM will fail.
2256//
2257void
2258CryptSymmetricDecrypt(
2259 BYTE *decrypted,
2260 TPM_ALG_ID algorithm, // IN: algorithm for encryption
2261 UINT16 keySizeInBits, // IN: key size in bit
2262 TPMI_ALG_SYM_MODE mode, // IN: symmetric encryption mode
2263 BYTE *key, // IN: encryption key
2264 TPM2B_IV *ivIn, // IN/OUT: IV for next block
2265 UINT32 dataSize, // IN: data size in byte
2266 BYTE *data // IN/OUT: data buffer
2267 )
2268{
2269 BYTE *iv = NULL;
2270 BYTE defaultIV[sizeof(TPMT_HA)];
2271 TEST(algorithm);
2272 if(
2273#ifdef TPM_ALG_AES
2274 algorithm == TPM_ALG_AES
2275#endif
2276#if defined TPM_ALG_AES && defined TPM_ALG_SM4
2277 ||
2278#endif
2279#ifdef TPM_ALG_SM4
2280 algorithm == TPM_ALG_SM4
2281#endif
2282 )
2283 {
2284 // Both SM4 and AES have block size of 128 bits
2285 // If the iv is not provided, create a default of 0
2286 if(ivIn == NULL)
2287 {
2288 // Initialize the default IV
2289 iv = defaultIV;
2290 MemorySet(defaultIV, 0, 16);
2291 }
2292 else
2293 {
2294 // A provided IV has to be the right size
2295 pAssert(mode == TPM_ALG_ECB || ivIn->t.size == 16);
2296 iv = &(ivIn->t.buffer[0]);
2297 }
2298 }
2299 switch(algorithm)
2300 {
2301#ifdef TPM_ALG_AES
2302 case TPM_ALG_AES:
2303 {
2304 switch (mode)
2305 {
2306 case TPM_ALG_CTR:
2307 _cpri__AESDecryptCTR(decrypted, keySizeInBits, key, iv,
2308 dataSize, data);
2309 break;
2310 case TPM_ALG_OFB:
2311 _cpri__AESDecryptOFB(decrypted, keySizeInBits, key, iv,
2312 dataSize, data);
2313 break;
2314 case TPM_ALG_CBC:
2315 _cpri__AESDecryptCBC(decrypted, keySizeInBits, key, iv,
2316 dataSize, data);
2317 break;
2318 case TPM_ALG_CFB:
2319 _cpri__AESDecryptCFB(decrypted, keySizeInBits, key, iv,
2320 dataSize, data);
2321 break;
2322 case TPM_ALG_ECB:
2323 _cpri__AESDecryptECB(decrypted, keySizeInBits, key,
2324 dataSize, data);
2325 break;
2326 default:
2327 pAssert(0);
2328 }
2329 break;
2330 }
2331#endif //TPM_ALG_AES
2332#ifdef TPM_ALG_SM4
2333 case TPM_ALG_SM4 :
2334 switch (mode)
2335 {
2336 case TPM_ALG_CTR:
2337 _cpri__SM4DecryptCTR(decrypted, keySizeInBits, key, iv,
2338 dataSize, data);
2339 break;
2340 case TPM_ALG_OFB:
2341 _cpri__SM4DecryptOFB(decrypted, keySizeInBits, key, iv,
2342 dataSize, data);
2343 break;
2344 case TPM_ALG_CBC:
2345 _cpri__SM4DecryptCBC(decrypted, keySizeInBits, key, iv,
2346 dataSize, data);
2347 break;
2348 case TPM_ALG_CFB:
2349 _cpri__SM4DecryptCFB(decrypted, keySizeInBits, key, iv,
2350 dataSize, data);
2351 break;
2352 case TPM_ALG_ECB:
2353 _cpri__SM4DecryptECB(decrypted, keySizeInBits, key,
2354 dataSize, data);
2355 break;
2356 default:
2357 pAssert(0);
2358 }
2359 break;
2360#endif //TPM_ALG_SM4
2361 default:
2362 pAssert(FALSE);
2363 break;
2364 }
2365 return;
2366}
2367//
2368//
2369// 10.2.9.6 CryptSecretEncrypt()
2370//
2371// This function creates a secret value and its associated secret structure using an asymmetric algorithm.
2372// This function is used by TPM2_Rewrap() TPM2_MakeCredential(), and TPM2_Duplicate().
2373//
2374// Error Returns Meaning
2375//
2376// TPM_RC_ATTRIBUTES keyHandle does not reference a valid decryption key
2377// TPM_RC_KEY invalid ECC key (public point is not on the curve)
2378// TPM_RC_SCHEME RSA key with an unsupported padding scheme
2379// TPM_RC_VALUE numeric value of the data to be decrypted is greater than the RSA
2380// key modulus
2381//
2382TPM_RC
2383CryptSecretEncrypt(
2384 TPMI_DH_OBJECT keyHandle, // IN: encryption key handle
2385 const char *label, // IN: a null-terminated string as L
2386 TPM2B_DATA *data, // OUT: secret value
2387 TPM2B_ENCRYPTED_SECRET *secret // OUT: secret structure
2388 )
2389{
2390 TPM_RC result = TPM_RC_SUCCESS;
2391 OBJECT *encryptKey = ObjectGet(keyHandle); // TPM key used for encrypt
2392 pAssert(data != NULL && secret != NULL);
2393 // The output secret value has the size of the digest produced by the nameAlg.
2394 data->t.size = CryptGetHashDigestSize(encryptKey->publicArea.nameAlg);
2395 pAssert(encryptKey->publicArea.objectAttributes.decrypt == SET);
2396 switch(encryptKey->publicArea.type)
2397 {
2398#ifdef TPM_ALG_RSA
2399 case TPM_ALG_RSA:
2400 {
2401 TPMT_RSA_DECRYPT scheme;
2402 // Use OAEP scheme
2403 scheme.scheme = TPM_ALG_OAEP;
2404 scheme.details.oaep.hashAlg = encryptKey->publicArea.nameAlg;
2405 // Create secret data from RNG
2406 CryptGenerateRandom(data->t.size, data->t.buffer);
2407 // Encrypt the data by RSA OAEP into encrypted secret
ChromeOS Developere85c65b2015-07-10 10:12:43 -07002408 result = CryptEncryptRSA(&secret->t.size, secret->t.secret,
Vadim Bendebury56797522015-05-20 10:32:25 -07002409 encryptKey, &scheme,
2410 data->t.size, data->t.buffer, label);
2411 }
2412 break;
2413#endif //TPM_ALG_RSA
2414#ifdef TPM_ALG_ECC
2415 case TPM_ALG_ECC:
2416 {
2417 TPMS_ECC_POINT eccPublic;
2418 TPM2B_ECC_PARAMETER eccPrivate;
2419 TPMS_ECC_POINT eccSecret;
ChromeOS Developere85c65b2015-07-10 10:12:43 -07002420 BYTE *buffer = secret->t.secret;
Jocelyn Bohr5aac5852015-08-20 16:05:05 -07002421 INT32 bufferSize = sizeof(TPMS_ECC_POINT);
Vadim Bendebury56797522015-05-20 10:32:25 -07002422 // Need to make sure that the public point of the key is on the
2423 // curve defined by the key.
2424 if(!_cpri__EccIsPointOnCurve(
2425 encryptKey->publicArea.parameters.eccDetail.curveID,
2426 &encryptKey->publicArea.unique.ecc))
2427 result = TPM_RC_KEY;
2428 else
2429 {
2430 // Call crypto engine to create an auxiliary ECC key
2431 // We assume crypt engine initialization should always success.
2432 // Otherwise, TPM should go to failure mode.
2433 CryptNewEccKey(encryptKey->publicArea.parameters.eccDetail.curveID,
2434 &eccPublic, &eccPrivate);
2435 // Marshal ECC public to secret structure. This will be used by the
2436 // recipient to decrypt the secret with their private key.
Jocelyn Bohr32be4042015-07-29 15:14:01 -07002437 secret->t.size = TPMS_ECC_POINT_Marshal(&eccPublic, &buffer, &bufferSize);
Vadim Bendebury56797522015-05-20 10:32:25 -07002438 // Compute ECDH shared secret which is R = [d]Q where d is the
2439 // private part of the ephemeral key and Q is the public part of a
2440 // TPM key. TPM_RC_KEY error return from CryptComputeECDHSecret
2441 // because the auxiliary ECC key is just created according to the
2442 // parameters of input ECC encrypt key.
2443 if( CryptEccPointMultiply(&eccSecret,
2444 encryptKey->publicArea.parameters.eccDetail.curveID,
2445 &eccPrivate,
2446 &encryptKey->publicArea.unique.ecc)
2447 != CRYPT_SUCCESS)
2448 result = TPM_RC_KEY;
2449 else
2450 // The secret value is computed from Z using KDFe as:
2451 // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits)
2452 // Where:
2453 // HashID the nameAlg of the decrypt key
2454 // Z the x coordinate (Px) of the product (P) of the point
2455 // (Q) of the secret and the private x coordinate (de,V)
2456 // of the decryption key
2457 // Use a null-terminated string containing "SECRET"
2458 // PartyUInfo the x coordinate of the point in the secret
2459 // (Qe,U )
2460 // PartyVInfo the x coordinate of the public key (Qs,V )
2461 // bits the number of bits in the digest of HashID
2462 // Retrieve seed from KDFe
2463 CryptKDFe(encryptKey->publicArea.nameAlg, &eccSecret.x.b,
2464 label, &eccPublic.x.b,
2465 &encryptKey->publicArea.unique.ecc.x.b,
2466 data->t.size * 8, data->t.buffer);
2467 }
2468 }
2469 break;
2470#endif //TPM_ALG_ECC
2471 default:
2472 FAIL(FATAL_ERROR_INTERNAL);
2473 break;
2474 }
2475 return result;
2476}
2477//
2478//
2479// 10.2.9.7 CryptSecretDecrypt()
2480//
2481// Decrypt a secret value by asymmetric (or symmetric) algorithm This function is used for
2482// ActivateCredential() and Import for asymmetric decryption, and StartAuthSession() for both asymmetric
2483// and symmetric decryption process
2484//
2485// Error Returns Meaning
2486//
2487// TPM_RC_ATTRIBUTES RSA key is not a decryption key
2488// TPM_RC_BINDING Invalid RSA key (public and private parts are not cryptographically
2489// bound.
2490// TPM_RC_ECC_POINT ECC point in the secret is not on the curve
2491// TPM_RC_INSUFFICIENT failed to retrieve ECC point from the secret
2492// TPM_RC_NO_RESULT multiplication resulted in ECC point at infinity
2493// TPM_RC_SIZE data to decrypt is not of the same size as RSA key
2494// TPM_RC_VALUE For RSA key, numeric value of the encrypted data is greater than the
2495// modulus, or the recovered data is larger than the output buffer. For
2496// keyedHash or symmetric key, the secret is larger than the size of the
2497// digest produced by the name algorithm.
2498// TPM_RC_FAILURE internal error
2499//
2500TPM_RC
2501CryptSecretDecrypt(
2502 TPM_HANDLE tpmKey, // IN: decrypt key
2503 TPM2B_NONCE *nonceCaller, // IN: nonceCaller. It is needed for
2504 // symmetric decryption. For
2505 // asymmetric decryption, this
2506 // parameter is NULL
2507 const char *label, // IN: a null-terminated string as L
2508 TPM2B_ENCRYPTED_SECRET *secret, // IN: input secret
2509 TPM2B_DATA *data // OUT: decrypted secret value
2510 )
2511{
2512 TPM_RC result = TPM_RC_SUCCESS;
2513 OBJECT *decryptKey = ObjectGet(tpmKey); //TPM key used for decrypting
2514 // Decryption for secret
2515 switch(decryptKey->publicArea.type)
2516 {
2517#ifdef TPM_ALG_RSA
2518 case TPM_ALG_RSA:
2519 {
2520 TPMT_RSA_DECRYPT scheme;
2521 // Use OAEP scheme
2522 scheme.scheme = TPM_ALG_OAEP;
2523 scheme.details.oaep.hashAlg = decryptKey->publicArea.nameAlg;
2524 // Set the output buffer capacity
2525 data->t.size = sizeof(data->t.buffer);
2526 // Decrypt seed by RSA OAEP
2527 result = CryptDecryptRSA(&data->t.size, data->t.buffer, decryptKey,
2528 &scheme,
ChromeOS Developere85c65b2015-07-10 10:12:43 -07002529 secret->t.size, secret->t.secret,label);
Vadim Bendebury56797522015-05-20 10:32:25 -07002530 if( (result == TPM_RC_SUCCESS)
2531 && (data->t.size
2532 > CryptGetHashDigestSize(decryptKey->publicArea.nameAlg)))
2533 result = TPM_RC_VALUE;
2534 }
2535 break;
2536#endif //TPM_ALG_RSA
2537#ifdef TPM_ALG_ECC
2538 case TPM_ALG_ECC:
2539 {
2540 TPMS_ECC_POINT eccPublic;
2541 TPMS_ECC_POINT eccSecret;
ChromeOS Developere85c65b2015-07-10 10:12:43 -07002542 BYTE *buffer = secret->t.secret;
Vadim Bendebury56797522015-05-20 10:32:25 -07002543 INT32 size = secret->t.size;
2544 // Retrieve ECC point from secret buffer
2545 result = TPMS_ECC_POINT_Unmarshal(&eccPublic, &buffer, &size);
2546 if(result == TPM_RC_SUCCESS)
2547 {
2548 result = CryptEccPointMultiply(&eccSecret,
2549 decryptKey->publicArea.parameters.eccDetail.curveID,
2550 &decryptKey->sensitive.sensitive.ecc,
2551 &eccPublic);
2552 if(result == TPM_RC_SUCCESS)
2553 {
2554 // Set the size of the "recovered" secret value to be the size
2555 // of the digest produced by the nameAlg.
2556 data->t.size =
2557 CryptGetHashDigestSize(decryptKey->publicArea.nameAlg);
2558 // The secret value is computed from Z using KDFe as:
2559 // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits)
2560 // Where:
2561 // HashID -- the nameAlg of the decrypt key
2562 // Z -- the x coordinate (Px) of the product (P) of the point
2563 // (Q) of the secret and the private x coordinate (de,V)
2564 // of the decryption key
2565 // Use -- a null-terminated string containing "SECRET"
2566 // PartyUInfo -- the x coordinate of the point in the secret
2567 // (Qe,U )
2568 // PartyVInfo -- the x coordinate of the public key (Qs,V )
2569 // bits -- the number of bits in the digest of HashID
2570 // Retrieve seed from KDFe
2571 CryptKDFe(decryptKey->publicArea.nameAlg, &eccSecret.x.b, label,
2572 &eccPublic.x.b,
2573 &decryptKey->publicArea.unique.ecc.x.b,
2574 data->t.size * 8, data->t.buffer);
2575 }
2576 }
2577 }
2578 break;
2579#endif //TPM_ALG_ECC
2580 case TPM_ALG_KEYEDHASH:
2581 // The seed size can not be bigger than the digest size of nameAlg
2582 if(secret->t.size >
2583 CryptGetHashDigestSize(decryptKey->publicArea.nameAlg))
2584 result = TPM_RC_VALUE;
2585 else
2586 {
2587 // Retrieve seed by XOR Obfuscation:
2588 // seed = XOR(secret, hash, key, nonceCaller, nullNonce)
2589 // where:
2590 // secret the secret parameter from the TPM2_StartAuthHMAC
2591 // command
2592 // which contains the seed value
2593 // hash nameAlg of tpmKey
2594 // key the key or data value in the object referenced by
2595 // entityHandle in the TPM2_StartAuthHMAC command
2596 // nonceCaller the parameter from the TPM2_StartAuthHMAC command
2597 // nullNonce a zero-length nonce
2598 // XOR Obfuscation in place
2599 CryptXORObfuscation(decryptKey->publicArea.nameAlg,
2600 &decryptKey->sensitive.sensitive.bits.b,
2601 &nonceCaller->b, NULL,
ChromeOS Developere85c65b2015-07-10 10:12:43 -07002602 secret->t.size, secret->t.secret);
Vadim Bendebury56797522015-05-20 10:32:25 -07002603 // Copy decrypted seed
2604 MemoryCopy2B(&data->b, &secret->b, sizeof(data->t.buffer));
2605 }
2606 break;
2607 case TPM_ALG_SYMCIPHER:
2608 {
Vadim Bendeburyc00055c2015-05-29 22:50:18 -07002609 TPM2B_IV iv = {};
Vadim Bendebury56797522015-05-20 10:32:25 -07002610 TPMT_SYM_DEF_OBJECT *symDef;
2611 // The seed size can not be bigger than the digest size of nameAlg
2612 if(secret->t.size >
2613 CryptGetHashDigestSize(decryptKey->publicArea.nameAlg))
2614 result = TPM_RC_VALUE;
2615 else
2616 {
Vadim Bendeburya49f9122015-10-27 16:32:54 -07002617 symDef = &decryptKey->publicArea.parameters.symDetail.sym;
Vadim Bendebury56797522015-05-20 10:32:25 -07002618 iv.t.size = CryptGetSymmetricBlockSize(symDef->algorithm,
2619 symDef->keyBits.sym);
2620 pAssert(iv.t.size != 0);
2621 if(nonceCaller->t.size >= iv.t.size)
2622 MemoryCopy(iv.t.buffer, nonceCaller->t.buffer, iv.t.size,
2623 sizeof(iv.t.buffer));
2624 else
2625 MemoryCopy(iv.b.buffer, nonceCaller->t.buffer,
2626 nonceCaller->t.size, sizeof(iv.t.buffer));
2627 // CFB decrypt in place, using nonceCaller as iv
ChromeOS Developere85c65b2015-07-10 10:12:43 -07002628 CryptSymmetricDecrypt(secret->t.secret, symDef->algorithm,
Vadim Bendebury56797522015-05-20 10:32:25 -07002629 symDef->keyBits.sym, TPM_ALG_CFB,
2630 decryptKey->sensitive.sensitive.sym.t.buffer,
ChromeOS Developere85c65b2015-07-10 10:12:43 -07002631 &iv, secret->t.size, secret->t.secret);
Vadim Bendebury56797522015-05-20 10:32:25 -07002632 // Copy decrypted seed
2633 MemoryCopy2B(&data->b, &secret->b, sizeof(data->t.buffer));
2634 }
2635 }
2636 break;
2637 default:
2638 pAssert(0);
2639 break;
2640 }
2641 return result;
2642}
2643//
2644//
2645// 10.2.9.8 CryptParameterEncryption()
2646//
2647// This function does in-place encryption of a response parameter.
2648//
2649void
2650CryptParameterEncryption(
2651 TPM_HANDLE handle, // IN: encrypt session handle
2652 TPM2B *nonceCaller, // IN: nonce caller
2653 UINT16 leadingSizeInByte, // IN: the size of the leading size field in
2654 // byte
2655 TPM2B_AUTH *extraKey, // IN: additional key material other than
2656 // session auth
2657 BYTE *buffer // IN/OUT: parameter buffer to be encrypted
2658 )
2659{
2660 SESSION *session = SessionGet(handle); // encrypt session
2661 TPM2B_TYPE(SYM_KEY, ( sizeof(extraKey->t.buffer)
2662 + sizeof(session->sessionKey.t.buffer)));
2663 TPM2B_SYM_KEY key; // encryption key
2664 UINT32 cipherSize = 0; // size of cipher text
2665 pAssert(session->sessionKey.t.size + extraKey->t.size <= sizeof(key.t.buffer));
2666 // Retrieve encrypted data size.
2667 if(leadingSizeInByte == 2)
2668 {
2669 // Extract the first two bytes as the size field as the data size
2670 // encrypt
2671 cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer);
2672 // advance the buffer
2673 buffer = &buffer[2];
2674 }
2675#ifdef TPM4B
2676 else if(leadingSizeInByte == 4)
2677 {
2678 // use the first four bytes to indicate the number of bytes to encrypt
2679 cipherSize = BYTE_ARRAY_TO_UINT32(buffer);
2680 //advance pointer
2681 buffer = &buffer[4];
2682 }
2683#endif
2684 else
2685 {
2686 pAssert(FALSE);
2687 }
2688//
2689 // Compute encryption key by concatenating sessionAuth with extra key
2690 MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
2691 MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer));
2692 if (session->symmetric.algorithm == TPM_ALG_XOR)
2693 // XOR parameter encryption formulation:
2694 // XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder)
2695 CryptXORObfuscation(session->authHashAlg, &(key.b),
2696 &(session->nonceTPM.b),
2697 nonceCaller, cipherSize, buffer);
2698 else
2699 ParmEncryptSym(session->symmetric.algorithm, session->authHashAlg,
2700 session->symmetric.keyBits.aes, &(key.b),
2701 nonceCaller, &(session->nonceTPM.b),
2702 cipherSize, buffer);
2703 return;
2704}
2705//
2706//
2707// 10.2.9.9 CryptParameterDecryption()
2708//
2709// This function does in-place decryption of a command parameter.
2710//
2711// Error Returns Meaning
2712//
2713// TPM_RC_SIZE The number of bytes in the input buffer is less than the number of
2714// bytes to be decrypted.
2715//
2716TPM_RC
2717CryptParameterDecryption(
2718 TPM_HANDLE handle, // IN: encrypted session handle
2719 TPM2B *nonceCaller, // IN: nonce caller
2720 UINT32 bufferSize, // IN: size of parameter buffer
2721 UINT16 leadingSizeInByte, // IN: the size of the leading size field in
2722 // byte
2723 TPM2B_AUTH *extraKey, // IN: the authValue
2724 BYTE *buffer // IN/OUT: parameter buffer to be decrypted
2725 )
2726{
2727 SESSION *session = SessionGet(handle); // encrypt session
2728 // The HMAC key is going to be the concatenation of the session key and any
2729 // additional key material (like the authValue). The size of both of these
2730 // is the size of the buffer which can contain a TPMT_HA.
2731 TPM2B_TYPE(HMAC_KEY, ( sizeof(extraKey->t.buffer)
2732 + sizeof(session->sessionKey.t.buffer)));
2733 TPM2B_HMAC_KEY key; // decryption key
2734 UINT32 cipherSize = 0; // size of cipher text
2735 pAssert(session->sessionKey.t.size + extraKey->t.size <= sizeof(key.t.buffer));
2736 // Retrieve encrypted data size.
2737 if(leadingSizeInByte == 2)
2738 {
2739 // The first two bytes of the buffer are the size of the
2740 // data to be decrypted
2741 cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer);
2742 buffer = &buffer[2]; // advance the buffer
2743 }
2744#ifdef TPM4B
2745 else if(leadingSizeInByte == 4)
2746 {
2747 // the leading size is four bytes so get the four byte size field
2748 cipherSize = BYTE_ARRAY_TO_UINT32(buffer);
2749 buffer = &buffer[4]; //advance pointer
2750 }
2751#endif
2752 else
2753 {
2754 pAssert(FALSE);
2755 }
2756 if(cipherSize > bufferSize)
2757 return TPM_RC_SIZE;
2758 // Compute decryption key by concatenating sessionAuth with extra input key
2759 MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
2760 MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer));
2761 if(session->symmetric.algorithm == TPM_ALG_XOR)
2762 // XOR parameter decryption formulation:
2763 // XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder)
2764 // Call XOR obfuscation function
2765 CryptXORObfuscation(session->authHashAlg, &key.b, nonceCaller,
2766 &(session->nonceTPM.b), cipherSize, buffer);
2767 else
2768 // Assume that it is one of the symmetric block ciphers.
2769 ParmDecryptSym(session->symmetric.algorithm, session->authHashAlg,
2770 session->symmetric.keyBits.sym,
2771 &key.b, nonceCaller, &session->nonceTPM.b,
2772 cipherSize, buffer);
2773 return TPM_RC_SUCCESS;
2774}
2775//
2776//
2777// 10.2.9.10 CryptComputeSymmetricUnique()
2778//
2779// This function computes the unique field in public area for symmetric objects.
2780//
2781void
2782CryptComputeSymmetricUnique(
2783 TPMI_ALG_HASH nameAlg, // IN: object name algorithm
2784 TPMT_SENSITIVE *sensitive, // IN: sensitive area
2785 TPM2B_DIGEST *unique // OUT: unique buffer
2786 )
2787{
2788 HASH_STATE hashState;
2789 pAssert(sensitive != NULL && unique != NULL);
2790 // Compute the public value as the hash of sensitive.symkey || unique.buffer
2791 unique->t.size = CryptGetHashDigestSize(nameAlg);
2792 CryptStartHash(nameAlg, &hashState);
2793 // Add obfuscation value
2794 CryptUpdateDigest2B(&hashState, &sensitive->seedValue.b);
2795 // Add sensitive value
2796 CryptUpdateDigest2B(&hashState, &sensitive->sensitive.any.b);
2797 CryptCompleteHash2B(&hashState, &unique->b);
2798 return;
2799}
2800#if 0 //%
2801//
2802//
2803//
2804// 10.2.9.11 CryptComputeSymValue()
2805//
2806// This function computes the seedValue field in asymmetric sensitive areas.
2807//
2808void
2809CryptComputeSymValue(
2810 TPM_HANDLE parentHandle, // IN: parent handle of the object to be created
2811 TPMT_PUBLIC *publicArea, // IN/OUT: the public area template
2812 TPMT_SENSITIVE *sensitive, // IN: sensitive area
2813 TPM2B_SEED *seed, // IN: the seed
2814 TPMI_ALG_HASH hashAlg, // IN: hash algorithm for KDFa
2815 TPM2B_NAME *name // IN: object name
2816 )
2817{
2818 TPM2B_AUTH *proof = NULL;
2819 if(CryptIsAsymAlgorithm(publicArea->type))
2820 {
2821 // Generate seedValue only when an asymmetric key is a storage key
2822 if(publicArea->objectAttributes.decrypt == SET
2823 && publicArea->objectAttributes.restricted == SET)
2824 {
2825 // If this is a primary object in the endorsement hierarchy, use
2826 // ehProof in the creation of the symmetric seed so that child
2827 // objects in the endorsement hierarchy are voided on TPM2_Clear()
2828 // or TPM2_ChangeEPS()
2829 if( parentHandle == TPM_RH_ENDORSEMENT
2830 && publicArea->objectAttributes.fixedTPM == SET)
2831 proof = &gp.ehProof;
2832 }
2833 else
2834 {
2835 sensitive->seedValue.t.size = 0;
2836 return;
2837 }
2838 }
2839 // For all object types, the size of seedValue is the digest size of nameAlg
2840 sensitive->seedValue.t.size = CryptGetHashDigestSize(publicArea->nameAlg);
2841 // Compute seedValue using implementation-dependent method
2842 _cpri__GenerateSeededRandom(sensitive->seedValue.t.size,
2843 sensitive->seedValue.t.buffer,
2844 hashAlg,
2845 &seed->b,
2846 "seedValue",
2847 &name->b,
2848 (TPM2B *)proof);
2849 return;
2850}
2851#endif //%
2852//
2853//
2854// 10.2.9.12 CryptCreateObject()
2855//
2856// This function creates an object. It:
2857// a) fills in the created key in public and sensitive area;
2858// b) creates a random number in sensitive area for symmetric keys; and
2859// c) compute the unique id in public area for symmetric keys.
2860//
2861//
2862//
2863//
2864// Error Returns Meaning
2865//
2866// TPM_RC_KEY_SIZE key size in the public area does not match the size in the sensitive
2867// creation area for a symmetric key
2868// TPM_RC_RANGE for an RSA key, the exponent is not supported
2869// TPM_RC_SIZE sensitive data size is larger than allowed for the scheme for a keyed
2870// hash object
2871// TPM_RC_VALUE exponent is not prime or could not find a prime using the provided
2872// parameters for an RSA key; unsupported name algorithm for an ECC
2873// key
2874//
2875TPM_RC
2876CryptCreateObject(
2877 TPM_HANDLE parentHandle, // IN/OUT: indication of the seed
2878 // source
2879 TPMT_PUBLIC *publicArea, // IN/OUT: public area
2880 TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation
2881 TPMT_SENSITIVE *sensitive // OUT: sensitive area
2882 )
2883{
2884 // Next value is a placeholder for a random seed that is used in
2885 // key creation when the parent is not a primary seed. It has the same
2886 // size as the primary seed.
2887 TPM2B_SEED localSeed; // data to seed key creation if this
2888 // is not a primary seed
2889 TPM2B_SEED *seed = NULL;
2890 TPM_RC result = TPM_RC_SUCCESS;
2891 TPM2B_NAME name;
2892 TPM_ALG_ID hashAlg = CONTEXT_INTEGRITY_HASH_ALG;
2893 OBJECT *parent;
2894 UINT32 counter;
2895 // Set the sensitive type for the object
2896 sensitive->sensitiveType = publicArea->type;
2897 ObjectComputeName(publicArea, &name);
2898 // For all objects, copy the initial auth data
2899 sensitive->authValue = sensitiveCreate->userAuth;
2900 // If this is a permanent handle assume that it is a hierarchy
2901 if(HandleGetType(parentHandle) == TPM_HT_PERMANENT)
2902 {
2903 seed = HierarchyGetPrimarySeed(parentHandle);
2904 }
2905 else
2906 {
2907 // If not hierarchy handle, get parent
2908 parent = ObjectGet(parentHandle);
2909 hashAlg = parent->publicArea.nameAlg;
2910 // Use random value as seed for non-primary objects
2911 localSeed.t.size = PRIMARY_SEED_SIZE;
2912 CryptGenerateRandom(PRIMARY_SEED_SIZE, localSeed.t.buffer);
2913 seed = &localSeed;
2914 }
2915 switch(publicArea->type)
2916 {
2917#ifdef TPM_ALG_RSA
2918 // Create RSA key
2919 case TPM_ALG_RSA:
2920 result = CryptGenerateKeyRSA(publicArea, sensitive,
2921 hashAlg, seed, &name, &counter);
2922 break;
2923#endif // TPM_ALG_RSA
2924#ifdef TPM_ALG_ECC
2925 // Create ECC key
2926 case TPM_ALG_ECC:
2927 result = CryptGenerateKeyECC(publicArea, sensitive,
2928 hashAlg, seed, &name, &counter);
2929 break;
2930#endif // TPM_ALG_ECC
2931 // Collect symmetric key information
2932 case TPM_ALG_SYMCIPHER:
2933 return CryptGenerateKeySymmetric(publicArea, sensitiveCreate,
2934 sensitive, hashAlg, seed, &name);
2935 break;
2936 case TPM_ALG_KEYEDHASH:
2937 return CryptGenerateKeyedHash(publicArea, sensitiveCreate,
2938 sensitive, hashAlg, seed, &name);
2939 break;
2940 default:
2941 pAssert(0);
2942 break;
2943 }
2944 if(result == TPM_RC_SUCCESS)
2945 {
2946 TPM2B_AUTH *proof = NULL;
2947 if(publicArea->objectAttributes.decrypt == SET
2948 && publicArea->objectAttributes.restricted == SET)
2949 {
2950 // If this is a primary object in the endorsement hierarchy, use
2951 // ehProof in the creation of the symmetric seed so that child
2952 // objects in the endorsement hierarchy are voided on TPM2_Clear()
2953 // or TPM2_ChangeEPS()
2954 if( parentHandle == TPM_RH_ENDORSEMENT
2955 && publicArea->objectAttributes.fixedTPM == SET)
2956 proof = &gp.ehProof;
2957 // For all object types, the size of seedValue is the digest size
2958 // of its nameAlg
2959 sensitive->seedValue.t.size
2960 = CryptGetHashDigestSize(publicArea->nameAlg);
2961 // Compute seedValue using implementation-dependent method
2962 _cpri__GenerateSeededRandom(sensitive->seedValue.t.size,
2963 sensitive->seedValue.t.buffer,
2964 hashAlg,
2965 &seed->b,
2966 "seedValuea",
2967 &name.b,
2968 (TPM2B *)proof);
2969 }
2970 else
2971 {
2972 sensitive->seedValue.t.size = 0;
2973 }
2974 }
2975 return result;
2976}
2977//
2978// 10.2.9.13 CryptObjectIsPublicConsistent()
2979//
2980// This function checks that the key sizes in the public area are consistent. For an asymmetric key, the size
2981// of the public key must match the size indicated by the public->parameters.
2982// Checks for the algorithm types matching the key type are handled by the unmarshaling operation.
2983//
2984// Return Value Meaning
2985//
2986// TRUE sizes are consistent
2987// FALSE sizes are not consistent
2988//
2989BOOL
2990CryptObjectIsPublicConsistent(
2991 TPMT_PUBLIC *publicArea // IN: public area
2992 )
2993{
2994 BOOL OK = TRUE;
2995 switch (publicArea->type)
2996 {
2997#ifdef TPM_ALG_RSA
2998 case TPM_ALG_RSA:
2999 OK = CryptAreKeySizesConsistent(publicArea);
3000 break;
3001#endif //TPM_ALG_RSA
3002#ifdef TPM_ALG_ECC
3003 case TPM_ALG_ECC:
3004 {
3005 const ECC_CURVE *curveValue;
3006 // Check that the public point is on the indicated curve.
3007 OK = CryptEccIsPointOnCurve(
3008 publicArea->parameters.eccDetail.curveID,
3009 &publicArea->unique.ecc);
3010 if(OK)
3011 {
3012 curveValue = CryptEccGetCurveDataPointer(
3013 publicArea->parameters.eccDetail.curveID);
3014 pAssert(curveValue != NULL);
3015 // The input ECC curve must be a supported curve
3016 // IF a scheme is defined for the curve, then that scheme must
3017 // be used.
3018 OK = (curveValue->sign.scheme == TPM_ALG_NULL
3019 || ( publicArea->parameters.eccDetail.scheme.scheme
3020 == curveValue->sign.scheme));
3021 OK = OK && CryptAreKeySizesConsistent(publicArea);
3022 }
3023 }
3024 break;
3025#endif //TPM_ALG_ECC
3026 default:
3027 // Symmetric object common checks
3028 // There is noting to check with a symmetric key that is public only.
3029 // Also not sure that there is anything useful to be done with it
3030 // either.
3031 break;
3032 }
3033 return OK;
3034}
3035//
3036//
3037//
3038// 10.2.9.14 CryptObjectPublicPrivateMatch()
3039//
3040// This function checks the cryptographic binding between the public and sensitive areas.
3041//
3042// Error Returns Meaning
3043//
3044// TPM_RC_TYPE the type of the public and private areas are not the same
3045// TPM_RC_FAILURE crypto error
3046// TPM_RC_BINDING the public and private areas are not cryptographically matched.
3047//
3048TPM_RC
3049CryptObjectPublicPrivateMatch(
3050 OBJECT *object // IN: the object to check
3051 )
3052{
3053 TPMT_PUBLIC *publicArea;
3054 TPMT_SENSITIVE *sensitive;
3055 TPM_RC result = TPM_RC_SUCCESS;
3056 BOOL isAsymmetric = FALSE;
3057 pAssert(object != NULL);
3058 publicArea = &object->publicArea;
3059 sensitive = &object->sensitive;
3060 if(publicArea->type != sensitive->sensitiveType)
3061 return TPM_RC_TYPE;
3062 switch(publicArea->type)
3063 {
3064#ifdef TPM_ALG_RSA
3065 case TPM_ALG_RSA:
3066 isAsymmetric = TRUE;
3067 // The public and private key sizes need to be consistent
3068 if(sensitive->sensitive.rsa.t.size != publicArea->unique.rsa.t.size/2)
3069 result = TPM_RC_BINDING;
3070 else
3071 // Load key by computing the private exponent
3072 result = CryptLoadPrivateRSA(object);
3073 break;
3074#endif
3075#ifdef TPM_ALG_ECC
3076 // This function is called from ObjectLoad() which has already checked to
3077 // see that the public point is on the curve so no need to repeat that
3078 // check.
3079 case TPM_ALG_ECC:
3080 isAsymmetric = TRUE;
3081 if( publicArea->unique.ecc.x.t.size
3082 != sensitive->sensitive.ecc.t.size)
3083 result = TPM_RC_BINDING;
3084 else if(publicArea->nameAlg != TPM_ALG_NULL)
3085 {
3086 TPMS_ECC_POINT publicToCompare;
3087 // Compute ECC public key
3088 CryptEccPointMultiply(&publicToCompare,
3089 publicArea->parameters.eccDetail.curveID,
3090 &sensitive->sensitive.ecc, NULL);
3091 // Compare ECC public key
3092 if( (!Memory2BEqual(&publicArea->unique.ecc.x.b,
3093 &publicToCompare.x.b))
3094 || (!Memory2BEqual(&publicArea->unique.ecc.y.b,
3095 &publicToCompare.y.b)))
3096 result = TPM_RC_BINDING;
3097 }
3098 break;
3099//
3100#endif
3101 case TPM_ALG_KEYEDHASH:
3102 break;
3103 case TPM_ALG_SYMCIPHER:
Vadim Bendeburya49f9122015-10-27 16:32:54 -07003104 if( (publicArea->parameters.symDetail.sym.keyBits.sym + 7)/8
Vadim Bendebury56797522015-05-20 10:32:25 -07003105 != sensitive->sensitive.sym.t.size)
3106 result = TPM_RC_BINDING;
3107 break;
3108 default:
3109 // The choice here is an assert or a return of a bad type for the object
3110 pAssert(0);
3111 break;
3112 }
3113 // For asymmetric keys, the algorithm for validating the linkage between
3114 // the public and private areas is algorithm dependent. For symmetric keys
3115 // the linkage is based on hashing the symKey and obfuscation values.
3116 if( result == TPM_RC_SUCCESS && !isAsymmetric
3117 && publicArea->nameAlg != TPM_ALG_NULL)
3118 {
3119 TPM2B_DIGEST uniqueToCompare;
3120 // Compute unique for symmetric key
3121 CryptComputeSymmetricUnique(publicArea->nameAlg, sensitive,
3122 &uniqueToCompare);
3123 // Compare unique
3124 if(!Memory2BEqual(&publicArea->unique.sym.b,
3125 &uniqueToCompare.b))
3126 result = TPM_RC_BINDING;
3127 }
3128 return result;
3129}
3130//
3131//
3132// 10.2.9.15 CryptGetSignHashAlg()
3133//
3134// Get the hash algorithm of signature from a TPMT_SIGNATURE structure. It assumes the signature is not
3135// NULL This is a function for easy access
3136//
3137TPMI_ALG_HASH
3138CryptGetSignHashAlg(
3139 TPMT_SIGNATURE *auth // IN: signature
3140 )
3141{
3142 pAssert(auth->sigAlg != TPM_ALG_NULL);
3143 // Get authHash algorithm based on signing scheme
3144 switch(auth->sigAlg)
3145 {
3146#ifdef TPM_ALG_RSA
3147 case TPM_ALG_RSASSA:
3148 return auth->signature.rsassa.hash;
3149 case TPM_ALG_RSAPSS:
3150 return auth->signature.rsapss.hash;
3151 #endif //TPM_ALG_RSA
3152 #ifdef TPM_ALG_ECC
3153 case TPM_ALG_ECDSA:
3154 return auth->signature.ecdsa.hash;
3155 #endif //TPM_ALG_ECC
3156 case TPM_ALG_HMAC:
3157 return auth->signature.hmac.hashAlg;
3158 default:
3159 return TPM_ALG_NULL;
3160 }
3161}
3162//
3163//
3164// 10.2.9.16 CryptIsSplitSign()
3165//
3166// This function us used to determine if the signing operation is a split signing operation that required a
3167// TPM2_Commit().
3168//
3169BOOL
3170CryptIsSplitSign(
3171 TPM_ALG_ID scheme // IN: the algorithm selector
3172 )
3173{
3174 if( scheme != scheme
3175# ifdef TPM_ALG_ECDAA
3176 || scheme == TPM_ALG_ECDAA
3177# endif // TPM_ALG_ECDAA
3178 )
3179 return TRUE;
3180 return FALSE;
3181}
3182//
3183//
3184// 10.2.9.17 CryptIsSignScheme()
3185//
3186// This function indicates if a scheme algorithm is a sign algorithm.
3187//
3188BOOL
3189CryptIsSignScheme(
3190 TPMI_ALG_ASYM_SCHEME scheme
3191 )
3192{
3193 BOOL isSignScheme = FALSE;
3194 switch(scheme)
3195 {
3196#ifdef TPM_ALG_RSA
3197 // If RSA is implemented, then both signing schemes are required
3198 case TPM_ALG_RSASSA:
3199 case TPM_ALG_RSAPSS:
3200 isSignScheme = TRUE;
3201 break;
3202#endif //TPM_ALG_RSA
3203#ifdef TPM_ALG_ECC
3204 // If ECC is implemented ECDSA is required
3205 case TPM_ALG_ECDSA:
3206#ifdef TPM_ALG_ECDAA
3207 // ECDAA is optional
3208 case TPM_ALG_ECDAA:
3209#endif
3210#ifdef TPM_ALG_ECSCHNORR
3211 // Schnorr is also optional
3212 case TPM_ALG_ECSCHNORR:
3213#endif
3214#ifdef TPM_ALG_SM2
3215 case TPM_ALG_SM2:
3216#endif
3217 isSignScheme = TRUE;
3218 break;
3219#endif //TPM_ALG_ECC
3220 default:
3221 break;
3222 }
3223 return isSignScheme;
3224}
3225//
3226//
3227// 10.2.9.18 CryptIsDecryptScheme()
3228//
3229// This function indicate if a scheme algorithm is a decrypt algorithm.
3230//
3231BOOL
3232CryptIsDecryptScheme(
3233 TPMI_ALG_ASYM_SCHEME scheme
3234 )
3235{
3236 BOOL isDecryptScheme = FALSE;
3237 switch(scheme)
3238 {
3239#ifdef TPM_ALG_RSA
3240 // If RSA is implemented, then both decrypt schemes are required
3241 case TPM_ALG_RSAES:
3242 case TPM_ALG_OAEP:
3243 isDecryptScheme = TRUE;
3244 break;
3245#endif //TPM_ALG_RSA
3246#ifdef TPM_ALG_ECC
3247 // If ECC is implemented ECDH is required
3248 case TPM_ALG_ECDH:
3249#ifdef TPM_ALG_SM2
3250 case TPM_ALG_SM2:
3251#endif
3252#ifdef TPM_ALG_ECMQV
3253 case TPM_ALG_ECMQV:
3254#endif
3255 isDecryptScheme = TRUE;
3256 break;
3257#endif //TPM_ALG_ECC
3258 default:
3259 break;
3260 }
3261 return isDecryptScheme;
3262}
3263//
3264//
3265// 10.2.9.19 CryptSelectSignScheme()
3266//
3267// This function is used by the attestation and signing commands. It implements the rules for selecting the
3268// signature scheme to use in signing. This function requires that the signing key either be TPM_RH_NULL
3269// or be loaded.
3270// If a default scheme is defined in object, the default scheme should be chosen, otherwise, the input
3271// scheme should be chosen. In the case that both object and input scheme has a non-NULL scheme
3272// algorithm, if the schemes are compatible, the input scheme will be chosen.
3273//
3274//
3275//
3276//
3277// Error Returns Meaning
3278//
3279// TPM_RC_KEY key referenced by signHandle is not a signing key
3280// TPM_RC_SCHEME both scheme and key's default scheme are empty; or scheme is
3281// empty while key's default scheme requires explicit input scheme (split
3282// signing); or non-empty default key scheme differs from scheme
3283//
3284TPM_RC
3285CryptSelectSignScheme(
3286 TPMI_DH_OBJECT signHandle, // IN: handle of signing key
3287 TPMT_SIG_SCHEME *scheme // IN/OUT: signing scheme
3288 )
3289{
3290 OBJECT *signObject;
3291 TPMT_SIG_SCHEME *objectScheme;
3292 TPMT_PUBLIC *publicArea;
3293 TPM_RC result = TPM_RC_SUCCESS;
3294 // If the signHandle is TPM_RH_NULL, then the NULL scheme is used, regardless
3295 // of the setting of scheme
3296 if(signHandle == TPM_RH_NULL)
3297 {
3298 scheme->scheme = TPM_ALG_NULL;
3299 scheme->details.any.hashAlg = TPM_ALG_NULL;
3300 }
3301 else
3302 {
3303 // sign handle is not NULL so...
3304 // Get sign object pointer
3305 signObject = ObjectGet(signHandle);
3306 publicArea = &signObject->publicArea;
3307 // is this a signing key?
3308 if(!publicArea->objectAttributes.sign)
3309 result = TPM_RC_KEY;
3310 else
3311 {
3312 // "parms" defined to avoid long code lines.
3313 TPMU_PUBLIC_PARMS *parms = &publicArea->parameters;
3314 if(CryptIsAsymAlgorithm(publicArea->type))
3315 objectScheme = (TPMT_SIG_SCHEME *)&parms->asymDetail.scheme;
3316 else
3317 objectScheme = (TPMT_SIG_SCHEME *)&parms->keyedHashDetail.scheme;
3318 // If the object doesn't have a default scheme, then use the
3319 // input scheme.
3320 if(objectScheme->scheme == TPM_ALG_NULL)
3321 {
3322 // Input and default can't both be NULL
3323 if(scheme->scheme == TPM_ALG_NULL)
3324 result = TPM_RC_SCHEME;
3325 // Assume that the scheme is compatible with the key. If not,
3326 // we will generate an error in the signing operation.
3327 }
3328 else if(scheme->scheme == TPM_ALG_NULL)
3329 {
3330 // input scheme is NULL so use default
3331 // First, check to see if the default requires that the caller
3332 // provided scheme data
3333 if(CryptIsSplitSign(objectScheme->scheme))
3334 result = TPM_RC_SCHEME;
3335 else
3336 {
3337 scheme->scheme = objectScheme->scheme;
3338 scheme->details.any.hashAlg
3339 = objectScheme->details.any.hashAlg;
3340 }
3341 }
3342 else
3343 {
3344 // Both input and object have scheme selectors
3345 // If the scheme and the hash are not the same then...
3346 if( objectScheme->scheme != scheme->scheme
3347 || ( objectScheme->details.any.hashAlg
3348 != scheme->details.any.hashAlg))
3349 result = TPM_RC_SCHEME;
3350 }
3351 }
3352 }
3353 return result;
3354}
3355//
3356//
3357// 10.2.9.20 CryptSign()
3358//
3359// Sign a digest with asymmetric key or HMAC. This function is called by attestation commands and the
3360// generic TPM2_Sign() command. This function checks the key scheme and digest size. It does not check
3361// if the sign operation is allowed for restricted key. It should be checked before the function is called. The
3362// function will assert if the key is not a signing key.
3363//
3364// Error Returns Meaning
3365//
3366// TPM_RC_SCHEME signScheme is not compatible with the signing key type
3367// TPM_RC_VALUE digest value is greater than the modulus of signHandle or size of
3368// hashData does not match hash algorithm insignScheme (for an RSA
3369// key); invalid commit status or failed to generate r value (for an ECC
3370// key)
3371//
3372TPM_RC
3373CryptSign(
3374 TPMI_DH_OBJECT signHandle, // IN: The handle of sign key
3375 TPMT_SIG_SCHEME *signScheme, // IN: sign scheme.
3376 TPM2B_DIGEST *digest, // IN: The digest being signed
3377 TPMT_SIGNATURE *signature // OUT: signature
3378 )
3379{
3380 OBJECT *signKey = ObjectGet(signHandle);
3381 TPM_RC result = TPM_RC_SCHEME;
3382 // check if input handle is a sign key
3383 pAssert(signKey->publicArea.objectAttributes.sign == SET);
3384 // Must have the private portion loaded. This check is made during
3385 // authorization.
3386 pAssert(signKey->attributes.publicOnly == CLEAR);
3387 // Initialize signature scheme
3388 signature->sigAlg = signScheme->scheme;
3389 // If the signature algorithm is TPM_ALG_NULL, then we are done
3390 if(signature->sigAlg == TPM_ALG_NULL)
3391 return TPM_RC_SUCCESS;
3392 // All the schemes other than TPM_ALG_NULL have a hash algorithm
3393 TEST_HASH(signScheme->details.any.hashAlg);
3394 // Initialize signature hash
3395 // Note: need to do the check for alg null first because the null scheme
3396 // doesn't have a hashAlg member.
3397 signature->signature.any.hashAlg = signScheme->details.any.hashAlg;
3398 // perform sign operation based on different key type
3399 switch (signKey->publicArea.type)
3400 {
3401#ifdef TPM_ALG_RSA
3402 case TPM_ALG_RSA:
3403 result = CryptSignRSA(signKey, signScheme, digest, signature);
3404 break;
3405#endif //TPM_ALG_RSA
3406#ifdef TPM_ALG_ECC
3407 case TPM_ALG_ECC:
3408 result = CryptSignECC(signKey, signScheme, digest, signature);
3409 break;
3410#endif //TPM_ALG_ECC
3411 case TPM_ALG_KEYEDHASH:
3412 result = CryptSignHMAC(signKey, signScheme, digest, signature);
3413 break;
3414 default:
3415 break;
3416 }
3417 return result;
3418}
3419//
3420//
3421// 10.2.9.21 CryptVerifySignature()
3422//
3423// This function is used to verify a signature. It is called by TPM2_VerifySignature() and
3424// TPM2_PolicySigned().
3425// Since this operation only requires use of a public key, no consistency checks are necessary for the key to
3426// signature type because a caller can load any public key that they like with any scheme that they like. This
3427// routine simply makes sure that the signature is correct, whatever the type.
3428// This function requires that auth is not a NULL pointer.
3429//
3430// Error Returns Meaning
3431//
3432// TPM_RC_SIGNATURE the signature is not genuine
3433// TPM_RC_SCHEME the scheme is not supported
3434// TPM_RC_HANDLE an HMAC key was selected but the private part of the key is not
3435// loaded
3436//
3437TPM_RC
3438CryptVerifySignature(
3439 TPMI_DH_OBJECT keyHandle, // IN: The handle of sign key
3440 TPM2B_DIGEST *digest, // IN: The digest being validated
3441 TPMT_SIGNATURE *signature // IN: signature
3442 )
3443{
3444 // NOTE: ObjectGet will either return a pointer to a loaded object or
3445 // will assert. It will never return a non-valid value. This makes it save
3446 // to initialize 'publicArea' with the return value from ObjectGet() without
3447 // checking it first.
3448 OBJECT *authObject = ObjectGet(keyHandle);
3449 TPMT_PUBLIC *publicArea = &authObject->publicArea;
3450 TPM_RC result = TPM_RC_SCHEME;
3451 // The input unmarshaling should prevent any input signature from being
3452 // a NULL signature, but just in case
3453 if(signature->sigAlg == TPM_ALG_NULL)
3454 return TPM_RC_SIGNATURE;
3455 switch (publicArea->type)
3456 {
3457#ifdef TPM_ALG_RSA
3458 case TPM_ALG_RSA:
3459 result = CryptRSAVerifySignature(authObject, digest, signature);
3460 break;
3461#endif //TPM_ALG_RSA
3462#ifdef TPM_ALG_ECC
3463 case TPM_ALG_ECC:
3464 result = CryptECCVerifySignature(authObject, digest, signature);
3465 break;
3466#endif // TPM_ALG_ECC
3467 case TPM_ALG_KEYEDHASH:
3468 if(authObject->attributes.publicOnly)
Vadim Bendebury065e0d72015-10-16 09:35:42 -07003469 result = TPM_RC_HANDLE;
Vadim Bendebury56797522015-05-20 10:32:25 -07003470 else
3471 result = CryptHMACVerifySignature(authObject, digest, signature);
3472 break;
3473 default:
3474 break;
3475 }
3476 return result;
3477}
3478//
3479//
3480// 10.2.10 Math functions
3481//
3482// 10.2.10.1 CryptDivide()
3483//
3484// This function interfaces to the math library for large number divide.
3485//
3486// Error Returns Meaning
3487//
3488// TPM_RC_SIZE quotient or remainder is too small to receive the result
3489//
3490TPM_RC
3491CryptDivide(
3492 TPM2B *numerator, // IN: numerator
3493 TPM2B *denominator, // IN: denominator
3494 TPM2B *quotient, // OUT: quotient = numerator / denominator.
3495 TPM2B *remainder // OUT: numerator mod denominator.
3496 )
3497{
3498 pAssert( numerator != NULL && denominator!= NULL
3499 && (quotient != NULL || remainder != NULL)
3500 );
3501 // assume denominator is not 0
3502 pAssert(denominator->size != 0);
3503 return TranslateCryptErrors(_math__Div(numerator,
3504 denominator,
3505 quotient,
3506 remainder)
3507 );
3508}
3509//
3510//
3511// 10.2.10.2 CryptCompare()
3512//
3513// This function interfaces to the math library for large number, unsigned compare.
3514//
3515// Return Value Meaning
3516//
3517// 1 if a > b
3518// 0 if a = b
3519// -1 if a < b
3520//
3521LIB_EXPORT int
3522CryptCompare(
3523 const UINT32 aSize, // IN: size of a
3524 const BYTE *a, // IN: a buffer
3525 const UINT32 bSize, // IN: size of b
3526 const BYTE *b // IN: b buffer
3527 )
3528{
3529 return _math__uComp(aSize, a, bSize, b);
3530}
3531//
3532//
3533// 10.2.10.3 CryptCompareSigned()
3534//
3535// This function interfaces to the math library for large number, signed compare.
3536//
3537// Return Value Meaning
3538//
3539// 1 if a > b
3540// 0 if a = b
3541// -1 if a < b
3542//
3543int
3544CryptCompareSigned(
3545 UINT32 aSize, // IN: size of a
3546 BYTE *a, // IN: a buffer
3547 UINT32 bSize, // IN: size of b
3548 BYTE *b // IN: b buffer
3549 )
3550{
3551 return _math__Comp(aSize, a, bSize, b);
3552}
3553//
3554//
3555// 10.2.10.4 CryptGetTestResult
3556//
3557// This function returns the results of a self-test function.
3558//
3559// NOTE: the behavior in this function is NOT the correct behavior for a real TPM implementation. An artificial behavior is
3560// placed here due to the limitation of a software simulation environment. For the correct behavior, consult the
3561// part 3 specification for TPM2_GetTestResult().
3562//
3563TPM_RC
3564CryptGetTestResult(
3565 TPM2B_MAX_BUFFER *outData // OUT: test result data
3566 )
3567{
3568 outData->t.size = 0;
3569 return TPM_RC_SUCCESS;
3570}
3571//
3572//
3573// 10.2.11 Capability Support
3574//
3575// 10.2.11.1 CryptCapGetECCCurve()
3576//
3577// This function returns the list of implemented ECC curves.
3578//
3579// Return Value Meaning
3580//
3581// YES if no more ECC curve is available
3582// NO if there are more ECC curves not reported
3583//
3584#ifdef TPM_ALG_ECC //% 5
3585TPMI_YES_NO
3586CryptCapGetECCCurve(
3587 TPM_ECC_CURVE curveID, // IN: the starting ECC curve
3588 UINT32 maxCount, // IN: count of returned curve
3589 TPML_ECC_CURVE *curveList // OUT: ECC curve list
3590 )
3591{
3592 TPMI_YES_NO more = NO;
3593 UINT16 i;
3594 UINT32 count = _cpri__EccGetCurveCount();
3595 TPM_ECC_CURVE curve;
3596 // Initialize output property list
3597 curveList->count = 0;
3598 // The maximum count of curves we may return is MAX_ECC_CURVES
3599 if(maxCount > MAX_ECC_CURVES) maxCount = MAX_ECC_CURVES;
3600 // Scan the eccCurveValues array
3601 for(i = 0; i < count; i++)
3602 {
3603 curve = _cpri__GetCurveIdByIndex(i);
3604 // If curveID is less than the starting curveID, skip it
3605 if(curve < curveID)
3606 continue;
3607 if(curveList->count < maxCount)
3608 {
3609 // If we have not filled up the return list, add more curves to
3610 // it
3611 curveList->eccCurves[curveList->count] = curve;
3612 curveList->count++;
3613 }
3614 else
3615 {
3616 // If the return list is full but we still have curves
3617 // available, report this and stop iterating
3618 more = YES;
3619 break;
3620 }
3621 }
3622 return more;
3623}
3624//
3625//
3626// 10.2.11.2 CryptCapGetEccCurveNumber()
3627//
3628// This function returns the number of ECC curves supported by the TPM.
3629//
3630UINT32
3631CryptCapGetEccCurveNumber(
3632 void
3633 )
3634{
3635 // There is an array that holds the curve data. Its size divided by the
3636 // size of an entry is the number of values in the table.
3637 return _cpri__EccGetCurveCount();
3638}
3639#endif //TPM_ALG_ECC //% 5
3640//
3641//
3642// 10.2.11.3 CryptAreKeySizesConsistent()
3643//
3644// This function validates that the public key size values are consistent for an asymmetric key.
3645//
3646// NOTE: This is not a comprehensive test of the public key.
3647//
3648//
3649// Return Value Meaning
3650//
3651// TRUE sizes are consistent
3652// FALSE sizes are not consistent
3653//
3654BOOL
3655CryptAreKeySizesConsistent(
3656 TPMT_PUBLIC *publicArea // IN: the public area to check
3657 )
3658{
3659 BOOL consistent = FALSE;
3660 switch (publicArea->type)
3661 {
3662#ifdef TPM_ALG_RSA
3663 case TPM_ALG_RSA:
3664 // The key size in bits is filtered by the unmarshaling
3665 consistent = ( ((publicArea->parameters.rsaDetail.keyBits+7)/8)
3666 == publicArea->unique.rsa.t.size);
3667 break;
3668#endif //TPM_ALG_RSA
3669#ifdef TPM_ALG_ECC
3670 case TPM_ALG_ECC:
3671 {
3672 UINT16 keySizeInBytes;
3673 TPM_ECC_CURVE curveId = publicArea->parameters.eccDetail.curveID;
3674 keySizeInBytes = CryptEccGetKeySizeInBytes(curveId);
3675 consistent = keySizeInBytes > 0
3676 && publicArea->unique.ecc.x.t.size <= keySizeInBytes
3677 && publicArea->unique.ecc.y.t.size <= keySizeInBytes;
3678 }
3679 break;
3680#endif //TPM_ALG_ECC
3681 default:
3682 break;
3683 }
3684 return consistent;
3685}
3686//
3687//
3688// 10.2.11.4 CryptAlgSetImplemented()
3689//
3690// This function initializes the bit vector with one bit for each implemented algorithm. This function is called
3691// from _TPM_Init(). The vector of implemented algorithms should be generated by the part 2 parser so that
3692// the g_implementedAlgorithms vector can be a const. That's not how it is now
3693//
3694void
3695CryptAlgsSetImplemented(
3696 void
3697 )
3698{
3699 AlgorithmGetImplementedVector(&g_implementedAlgorithms);
3700}