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