1// This file was extracted from the TCG Published
2// Trusted Platform Module Library
3// Part 4: Supporting Routines
4// Family "2.0"
5// Level 00 Revision 01.16
6// October 30, 2014
7
8#include        "TPM_Types.h"
9#include        "CryptoEngine.h"        // types shared by CryptUtil and CryptoEngine.
10                                       // Includes the function prototypes for the
11                                       // CryptoEngine functions.
12#include        "Global.h"
13#include        "InternalRoutines.h"
14#include        "MemoryLib_fp.h"
15//#include        "CryptSelfTest_fp.h"
16//
17//
18//     10.2.2     TranslateCryptErrors()
19//
20//     This function converts errors from the cryptographic library into TPM_RC_VALUES.
21//
22//     Error Returns                     Meaning
23//
24//     TPM_RC_VALUE                      CRYPT_FAIL
25//     TPM_RC_NO_RESULT                  CRYPT_NO_RESULT
26//     TPM_RC_SCHEME                     CRYPT_SCHEME
27//     TPM_RC_VALUE                      CRYPT_PARAMETER
28//     TPM_RC_SIZE                       CRYPT_UNDERFLOW
29//     TPM_RC_ECC_POINT                  CRYPT_POINT
30//     TPM_RC_CANCELLED                  CRYPT_CANCEL
31//
32static TPM_RC
33TranslateCryptErrors (
34      CRYPT_RESULT            retVal                 // IN: crypt error to evaluate
35)
36{
37      switch (retVal)
38      {
39      case CRYPT_SUCCESS:
40          return TPM_RC_SUCCESS;
41      case CRYPT_FAIL:
42          return TPM_RC_VALUE;
43      case CRYPT_NO_RESULT:
44          return TPM_RC_NO_RESULT;
45      case CRYPT_SCHEME:
46          return TPM_RC_SCHEME;
47      case CRYPT_PARAMETER:
48          return TPM_RC_VALUE;
49      case CRYPT_UNDERFLOW:
50          return TPM_RC_SIZE;
51      case CRYPT_POINT:
52          return TPM_RC_ECC_POINT;
53      case CRYPT_CANCEL:
54       return TPM_RC_CANCELED;
55   default: // Other unknown warnings
56       return TPM_RC_FAILURE;
57   }
58}
59//
60//
61//     10.2.3     Random Number Generation Functions
62//
63#ifdef TPM_ALG_NULL //%
64#ifdef _DRBG_STATE_SAVE //%
65//
66//
67//     10.2.3.1    CryptDrbgGetPutState()
68//
69//     Read or write the current state from the DRBG in the cryptoEngine.
70//
71void
72CryptDrbgGetPutState(
73   GET_PUT              direction         // IN: Get from or put to DRBG
74   )
75{
76   _cpri__DrbgGetPutState(direction,
77                          sizeof(go.drbgState),
78                          (BYTE *)&go.drbgState);
79}
80#else   //% 00
81//%#define CryptDrbgGetPutState(ignored)            // If not doing state save, turn this
82//%                                                  // into a null macro
83#endif //%
84//
85//
86//     10.2.3.2    CryptStirRandom()
87//
88//     Stir random entropy
89//
90void
91CryptStirRandom(
92   UINT32               entropySize,      // IN: size of entropy buffer
93   BYTE                *buffer            // IN: entropy buffer
94   )
95{
96   // RNG self testing code may be inserted here
97   // Call crypto engine random number stirring function
98   _cpri__StirRandom(entropySize, buffer);
99   return;
100}
101//
102//
103//     10.2.3.3    CryptGenerateRandom()
104//
105//     This is the interface to _cpri__GenerateRandom().
106//
107UINT16
108CryptGenerateRandom(
109   UINT16               randomSize,       // IN: size of random number
110   BYTE                *buffer            // OUT: buffer of random number
111   )
112{
113   UINT16               result;
114   pAssert(randomSize <= MAX_RSA_KEY_BYTES || randomSize <= PRIMARY_SEED_SIZE);
115   if(randomSize == 0)
116          return 0;
117    // Call crypto engine random number generation
118    result = _cpri__GenerateRandom(randomSize, buffer);
119    if(result != randomSize)
120        FAIL(FATAL_ERROR_INTERNAL);
121   return result;
122}
123#endif //TPM_ALG_NULL //%
124//
125//
126//      10.2.4     Hash/HMAC Functions
127//
128//      10.2.4.1    CryptGetContextAlg()
129//
130//      This function returns the hash algorithm associated with a hash context.
131//
132#ifdef TPM_ALG_KEYEDHASH                 //% 1
133TPM_ALG_ID
134CryptGetContextAlg(
135    void                *state                // IN: the context to check
136    )
137{
138    HASH_STATE *context = (HASH_STATE *)state;
139    return _cpri__GetContextAlg(&context->state);
140}
141//
142//
143//      10.2.4.2    CryptStartHash()
144//
145//      This function starts a hash and return the size, in bytes, of the digest.
146//
147//      Return Value                      Meaning
148//
149//      >0                                the digest size of the algorithm
150//      =0                                the hashAlg was TPM_ALG_NULL
151//
152UINT16
153CryptStartHash(
154    TPMI_ALG_HASH        hashAlg,             // IN: hash algorithm
155    HASH_STATE          *hashState            // OUT: the state of hash stack. It will be used
156                                              //     in hash update and completion
157    )
158{
159    CRYPT_RESULT            retVal = 0;
160    pAssert(hashState != NULL);
161    TEST_HASH(hashAlg);
162    hashState->type = HASH_STATE_EMPTY;
163    // Call crypto engine start hash function
164    if((retVal = _cpri__StartHash(hashAlg, FALSE, &hashState->state)) > 0)
165        hashState->type = HASH_STATE_HASH;
166    return retVal;
167}
168//
169//
170//
171//      10.2.4.3    CryptStartHashSequence()
172//
173//      Start a hash stack for a sequence object and return the size, in bytes, of the digest. This call uses the
174//      form of the hash state that requires context save and restored.
175//
176//      Return Value                    Meaning
177//
178//      >0                              the digest size of the algorithm
179//      =0                              the hashAlg was TPM_ALG_NULL
180//
181UINT16
182CryptStartHashSequence(
183    TPMI_ALG_HASH       hashAlg,            // IN: hash algorithm
184    HASH_STATE         *hashState           // OUT: the state of hash stack. It will be used
185                                            //     in hash update and completion
186    )
187{
188    CRYPT_RESULT      retVal = 0;
189    pAssert(hashState != NULL);
190    TEST_HASH(hashAlg);
191    hashState->type = HASH_STATE_EMPTY;
192    // Call crypto engine start hash function
193    if((retVal = _cpri__StartHash(hashAlg, TRUE, &hashState->state)) > 0)
194        hashState->type = HASH_STATE_HASH;
195    return retVal;
196}
197//
198//
199//      10.2.4.4    CryptStartHMAC()
200//
201//      This function starts an HMAC sequence and returns the size of the digest that will be produced.
202//      The caller must provide a block of memory in which the hash sequence state is kept. The caller should
203//      not alter the contents of this buffer until the hash sequence is completed or abandoned.
204//
205//      Return Value                    Meaning
206//
207//      >0                              the digest size of the algorithm
208//      =0                              the hashAlg was TPM_ALG_NULL
209//
210UINT16
211CryptStartHMAC(
212    TPMI_ALG_HASH       hashAlg,            //   IN: hash algorithm
213    UINT16              keySize,            //   IN: the size of HMAC key in byte
214    BYTE               *key,                //   IN: HMAC key
215    HMAC_STATE         *hmacState           //   OUT: the state of HMAC stack. It will be used
216                                            //       in HMAC update and completion
217    )
218{
219    HASH_STATE         *hashState = (HASH_STATE *)hmacState;
220    CRYPT_RESULT       retVal;
221    // This has to come before the pAssert in case we             all calling this function
222    // during testing. If so, the first instance will             have no arguments but the
223    // hash algorithm. The call from the test routine             will have arguments. When
224    // the second call is done, then we return to the             test dispatcher.
225    TEST_HASH(hashAlg);
226    pAssert(hashState != NULL);
227    hashState->type = HASH_STATE_EMPTY;
228    if((retVal =    _cpri__StartHMAC(hashAlg, FALSE, &hashState->state, keySize, key,
229                                     &hmacState->hmacKey.b)) > 0)
230          hashState->type = HASH_STATE_HMAC;
231    return retVal;
232}
233//
234//
235//      10.2.4.5    CryptStartHMACSequence()
236//
237//      This function starts an HMAC sequence and returns the size of the digest that will be produced.
238//      The caller must provide a block of memory in which the hash sequence state is kept. The caller should
239//      not alter the contents of this buffer until the hash sequence is completed or abandoned.
240//      This call is used to start a sequence HMAC that spans multiple TPM commands.
241//
242//      Return Value                      Meaning
243//
244//      >0                                the digest size of the algorithm
245//      =0                                the hashAlg was TPM_ALG_NULL
246//
247UINT16
248CryptStartHMACSequence(
249    TPMI_ALG_HASH       hashAlg,              //   IN: hash algorithm
250    UINT16              keySize,              //   IN: the size of HMAC key in byte
251    BYTE               *key,                  //   IN: HMAC key
252    HMAC_STATE         *hmacState             //   OUT: the state of HMAC stack. It will be used
253                                              //       in HMAC update and completion
254    )
255{
256    HASH_STATE         *hashState = (HASH_STATE *)hmacState;
257    CRYPT_RESULT       retVal;
258    TEST_HASH(hashAlg);
259    hashState->type = HASH_STATE_EMPTY;
260    if((retVal =    _cpri__StartHMAC(hashAlg, TRUE, &hashState->state,
261                                     keySize, key, &hmacState->hmacKey.b)) > 0)
262          hashState->type = HASH_STATE_HMAC;
263    return retVal;
264}
265//
266//
267//      10.2.4.6    CryptStartHMAC2B()
268//
269//      This function starts an HMAC and returns the size of the digest that will be produced.
270//      This function is provided to support the most common use of starting an HMAC with a TPM2B key.
271//      The caller must provide a block of memory in which the hash sequence state is kept. The caller should
272//      not alter the contents of this buffer until the hash sequence is completed or abandoned.
273//
274//
275//
276//
277//      Return Value                    Meaning
278//
279//      >0                              the digest size of the algorithm
280//      =0                              the hashAlg was TPM_ALG_NULL
281//
282LIB_EXPORT UINT16
283CryptStartHMAC2B(
284    TPMI_ALG_HASH       hashAlg,            // IN: hash algorithm
285    TPM2B              *key,                // IN: HMAC key
286    HMAC_STATE         *hmacState           // OUT: the state of HMAC stack. It will be used
287                                            //     in HMAC update and completion
288    )
289{
290    return CryptStartHMAC(hashAlg, key->size, key->buffer, hmacState);
291}
292//
293//
294//      10.2.4.7    CryptStartHMACSequence2B()
295//
296//      This function starts an HMAC sequence and returns the size of the digest that will be produced.
297//      This function is provided to support the most common use of starting an HMAC with a TPM2B key.
298//      The caller must provide a block of memory in which the hash sequence state is kept. The caller should
299//      not alter the contents of this buffer until the hash sequence is completed or abandoned.
300//
301//      Return Value                    Meaning
302//
303//      >0                              the digest size of the algorithm
304//      =0                              the hashAlg was TPM_ALG_NULL
305//
306UINT16
307CryptStartHMACSequence2B(
308    TPMI_ALG_HASH       hashAlg,            // IN: hash algorithm
309    TPM2B              *key,                // IN: HMAC key
310    HMAC_STATE         *hmacState           // OUT: the state of HMAC stack. It will be used
311                                            //     in HMAC update and completion
312    )
313{
314    return CryptStartHMACSequence(hashAlg, key->size, key->buffer, hmacState);
315}
316//
317//
318//      10.2.4.8    CryptUpdateDigest()
319//
320//      This function updates a digest (hash or HMAC) with an array of octets.
321//      This function can be used for both HMAC and hash functions so the digestState is void so that either
322//      state type can be passed.
323//
324LIB_EXPORT void
325CryptUpdateDigest(
326    void               *digestState,        // IN: the state of hash stack
327    UINT32              dataSize,           // IN: the size of data
328    BYTE               *data                // IN: data to be hashed
329    )
330{
331    HASH_STATE         *hashState = (HASH_STATE *)digestState;
332    pAssert(digestState != NULL);
333    if(hashState->type != HASH_STATE_EMPTY && data != NULL && dataSize != 0)
334    {
335          // Call crypto engine update hash function
336          _cpri__UpdateHash(&hashState->state, dataSize, data);
337    }
338    return;
339}
340//
341//
342//      10.2.4.9     CryptUpdateDigest2B()
343//
344//      This function updates a digest (hash or HMAC) with a TPM2B.
345//      This function can be used for both HMAC and hash functions so the digestState is void so that either
346//      state type can be passed.
347//
348LIB_EXPORT void
349CryptUpdateDigest2B(
350    void                *digestState,       // IN: the digest state
351    TPM2B               *bIn                // IN: 2B containing the data
352    )
353{
354    // Only compute the digest if a pointer to the 2B is provided.
355    // In CryptUpdateDigest(), if size is zero or buffer is NULL, then no change
356    // to the digest occurs. This function should not provide a buffer if bIn is
357    // not provided.
358    if(bIn != NULL)
359        CryptUpdateDigest(digestState, bIn->size, bIn->buffer);
360    return;
361}
362//
363//
364//      10.2.4.10 CryptUpdateDigestInt()
365//
366//      This function is used to include an integer value to a hash stack. The function marshals the integer into its
367//      canonical form before calling CryptUpdateHash().
368//
369LIB_EXPORT void
370CryptUpdateDigestInt(
371    void                *state,             // IN: the state of hash stack
372    UINT32               intSize,           // IN: the size of 'intValue' in byte
373    void                *intValue           // IN: integer value to be hashed
374    )
375{
376#if BIG_ENDIAN_TPM == YES
377   pAssert(    intValue != NULL && (intSize == 1 || intSize == 2
378           || intSize == 4 || intSize == 8));
379   CryptUpdateHash(state, inSize, (BYTE *)intValue);
380#else
381    BYTE        marshalBuffer[8];
382    // Point to the big end of an little-endian value
383    BYTE        *p = &((BYTE *)intValue)[intSize - 1];
384    // Point to the big end of an big-endian value
385    BYTE        *q = marshalBuffer;
386    pAssert(intValue != NULL);
387    switch (intSize)
388    {
389    case 8:
390        *q++ = *p--;
391        *q++ = *p--;
392        *q++ = *p--;
393        *q++ = *p--;
394    case 4:
395        *q++ = *p--;
396         *q++ = *p--;
397     case 2:
398         *q++ = *p--;
399     case 1:
400         *q = *p;
401         // Call update the hash
402         CryptUpdateDigest(state, intSize, marshalBuffer);
403         break;
404     default:
405         FAIL(0);
406     }
407#endif
408   return;
409}
410//
411//
412//      10.2.4.11 CryptCompleteHash()
413//
414//      This function completes a hash sequence and returns the digest.
415//      This function can be called to complete either an HMAC or hash sequence. The state type determines if
416//      the context type is a hash or HMAC. If an HMAC, then the call is forwarded to CryptCompleteHash().
417//      If digestSize is smaller than the digest size of hash/HMAC algorithm, the most significant bytes of
418//      required size will be returned
419//
420//      Return Value                     Meaning
421//
422//      >=0                              the number of bytes placed in digest
423//
424LIB_EXPORT UINT16
425CryptCompleteHash(
426     void               *state,             // IN: the state of hash stack
427     UINT16              digestSize,        // IN: size of digest buffer
428     BYTE               *digest             // OUT: hash digest
429     )
430{
431     HASH_STATE         *hashState = (HASH_STATE *)state;              // local value
432     // If the session type is HMAC, then could forward this to
433     // the HMAC processing and not cause an error. However, if no
434     // function calls this routine to forward it, then we can't get
435     // test coverage. The decision is to assert if this is called with
436     // the type == HMAC and fix anything that makes the wrong call.
437     pAssert(hashState->type == HASH_STATE_HASH);
438     // Set the state to empty so that it doesn't get used again
439     hashState->type = HASH_STATE_EMPTY;
440     // Call crypto engine complete hash function
441     return     _cpri__CompleteHash(&hashState->state, digestSize, digest);
442}
443//
444//
445//      10.2.4.12 CryptCompleteHash2B()
446//
447//      This function is the same as CypteCompleteHash() but the digest is placed in a TPM2B. This is the most
448//      common use and this is provided for specification clarity. 'digest.size' should be set to indicate the number
449//      of bytes to place in the buffer
450//
451//
452//
453//
454//      Return Value                      Meaning
455//
456//      >=0                               the number of bytes placed in 'digest.buffer'
457//
458LIB_EXPORT UINT16
459CryptCompleteHash2B(
460     void               *state,               // IN: the state of hash stack
461     TPM2B              *digest               // IN: the size of the buffer Out: requested
462                                              //     number of byte
463     )
464{
465     UINT16                  retVal = 0;
466     if(digest != NULL)
467         retVal = CryptCompleteHash(state, digest->size, digest->buffer);
468     return retVal;
469}
470//
471//
472//      10.2.4.13 CryptHashBlock()
473//
474//      Hash a block of data and return the results. If the digest is larger than retSize, it is truncated and with the
475//      least significant octets dropped.
476//
477//      Return Value                      Meaning
478//
479//      >=0                               the number of bytes placed in ret
480//
481LIB_EXPORT UINT16
482CryptHashBlock(
483     TPM_ALG_ID          algId,               //   IN: the hash algorithm to use
484     UINT16              blockSize,           //   IN: size of the data block
485     BYTE               *block,               //   IN: address of the block to hash
486     UINT16              retSize,             //   IN: size of the return buffer
487     BYTE               *ret                  //   OUT: address of the buffer
488     )
489{
490     TEST_HASH(algId);
491     return _cpri__HashBlock(algId, blockSize, block, retSize, ret);
492}
493//
494//
495//      10.2.4.14 CryptCompleteHMAC()
496//
497//      This function completes a HMAC sequence and returns the digest. If digestSize is smaller than the digest
498//      size of the HMAC algorithm, the most significant bytes of required size will be returned.
499//
500//      Return Value                      Meaning
501//
502//      >=0                               the number of bytes placed in digest
503//
504LIB_EXPORT UINT16
505CryptCompleteHMAC(
506     HMAC_STATE         *hmacState,           // IN: the state of HMAC stack
507     UINT32              digestSize,          // IN: size of digest buffer
508     BYTE               *digest               // OUT: HMAC digest
509     )
510{
511     HASH_STATE         *hashState;
512     pAssert(hmacState != NULL);
513     hashState = &hmacState->hashState;
514     pAssert(hashState->type == HASH_STATE_HMAC);
515     hashState->type = HASH_STATE_EMPTY;
516     return _cpri__CompleteHMAC(&hashState->state, &hmacState->hmacKey.b,
517                                digestSize, digest);
518}
519//
520//
521//      10.2.4.15 CryptCompleteHMAC2B()
522//
523//      This function is the same as CryptCompleteHMAC() but the HMAC result is returned in a TPM2B which is
524//      the most common use.
525//
526//      Return Value                     Meaning
527//
528//      >=0                              the number of bytes placed in digest
529//
530LIB_EXPORT UINT16
531CryptCompleteHMAC2B(
532     HMAC_STATE         *hmacState,           // IN: the state of HMAC stack
533     TPM2B              *digest               // OUT: HMAC
534     )
535{
536     UINT16               retVal = 0;
537     if(digest != NULL)
538         retVal = CryptCompleteHMAC(hmacState, digest->size, digest->buffer);
539     return retVal;
540}
541//
542//
543//      10.2.4.16 CryptHashStateImportExport()
544//
545//      This function is used to prepare a hash state context for LIB_EXPORT or to import it into the internal
546//      format. It is used by TPM2_ContextSave() and TPM2_ContextLoad() via SequenceDataImportExport().
547//      This is just a pass-through function to the crypto library.
548//
549void
550CryptHashStateImportExport(
551     HASH_STATE         *internalFmt,         // IN: state to LIB_EXPORT
552     HASH_STATE         *externalFmt,         // OUT: exported state
553     IMPORT_EXPORT       direction
554     )
555{
556     _cpri__ImportExportHashState(&internalFmt->state,
557                                  (EXPORT_HASH_STATE *)&externalFmt->state,
558                                  direction);
559}
560//
561//
562//      10.2.4.17 CryptGetHashDigestSize()
563//
564//      This function returns the digest size in bytes for a hash algorithm.
565//
566//      Return Value                     Meaning
567//
568//      0                                digest size for TPM_ALG_NULL
569//      >0                               digest size
570//
571LIB_EXPORT UINT16
572CryptGetHashDigestSize(
573    TPM_ALG_ID           hashAlg              // IN: hash algorithm
574    )
575{
576    return _cpri__GetDigestSize(hashAlg);
577}
578//
579//
580//      10.2.4.18 CryptGetHashBlockSize()
581//
582//      Get the digest size in byte of a hash algorithm.
583//
584//      Return Value                      Meaning
585//
586//      0                                 block size for TPM_ALG_NULL
587//      >0                                block size
588//
589LIB_EXPORT UINT16
590CryptGetHashBlockSize(
591    TPM_ALG_ID           hash                 // IN: hash algorithm to look up
592    )
593{
594    return _cpri__GetHashBlockSize(hash);
595}
596//
597//
598//      10.2.4.19 CryptGetHashAlgByIndex()
599//
600//      This function is used to iterate through the hashes. TPM_ALG_NULL is returned for all indexes that are
601//      not valid hashes. If the TPM implements 3 hashes, then an index value of 0 will return the first
602//      implemented hash and an index value of 2 will return the last implemented hash. All other index values
603//      will return TPM_ALG_NULL.
604//
605//      Return Value                      Meaning
606//
607//      TPM_ALG_xxx()                     a hash algorithm
608//      TPM_ALG_NULL                      this can be used as a stop value
609//
610LIB_EXPORT TPM_ALG_ID
611CryptGetHashAlgByIndex(
612    UINT32               index                // IN: the index
613    )
614{
615    return _cpri__GetHashAlgByIndex(index);
616}
617//
618//
619//      10.2.4.20 CryptSignHMAC()
620//
621//      Sign a digest using an HMAC key. This an HMAC of a digest, not an HMAC of a message.
622//
623//      Error Returns                     Meaning
624//
625static TPM_RC
626CryptSignHMAC(
627    OBJECT                   *signKey,              //   IN: HMAC key sign the hash
628    TPMT_SIG_SCHEME          *scheme,               //   IN: signing scheme
629    TPM2B_DIGEST             *hashData,             //   IN: hash to be signed
630    TPMT_SIGNATURE           *signature             //   OUT: signature
631    )
632{
633//
634   HMAC_STATE           hmacState;
635   UINT32               digestSize;
636   // HMAC algorithm self testing code may be inserted here
637   digestSize = CryptStartHMAC2B(scheme->details.hmac.hashAlg,
638                                 &signKey->sensitive.sensitive.bits.b,
639                                 &hmacState);
640   // The hash algorithm must be a valid one.
641   pAssert(digestSize > 0);
642   CryptUpdateDigest2B(&hmacState, &hashData->b);
643   CryptCompleteHMAC(&hmacState, digestSize,
644                     (BYTE *) &signature->signature.hmac.digest);
645   // Set HMAC algorithm
646   signature->signature.hmac.hashAlg = scheme->details.hmac.hashAlg;
647   return TPM_RC_SUCCESS;
648}
649//
650//
651//      10.2.4.21 CryptHMACVerifySignature()
652//
653//      This function will verify a signature signed by a HMAC key.
654//
655//      Error Returns                   Meaning
656//
657//      TPM_RC_SIGNATURE                if invalid input or signature is not genuine
658//
659static TPM_RC
660CryptHMACVerifySignature(
661   OBJECT              *signKey,            // IN: HMAC key signed the hash
662   TPM2B_DIGEST        *hashData,           // IN: digest being verified
663   TPMT_SIGNATURE      *signature           // IN: signature to be verified
664   )
665{
666   HMAC_STATE                hmacState;
667   TPM2B_DIGEST              digestToCompare;
668   digestToCompare.t.size = CryptStartHMAC2B(signature->signature.hmac.hashAlg,
669                            &signKey->sensitive.sensitive.bits.b, &hmacState);
670   CryptUpdateDigest2B(&hmacState, &hashData->b);
671   CryptCompleteHMAC2B(&hmacState, &digestToCompare.b);
672   // Compare digest
673   if(MemoryEqual(digestToCompare.t.buffer,
674                  (BYTE *) &signature->signature.hmac.digest,
675                  digestToCompare.t.size))
676       return TPM_RC_SUCCESS;
677   else
678       return TPM_RC_SIGNATURE;
679}
680//
681//
682//      10.2.4.22 CryptGenerateKeyedHash()
683//
684//      This function creates a keyedHash object.
685//
686//
687//
688//      Error Returns                     Meaning
689//
690//      TPM_RC_SIZE                       sensitive data size is larger than allowed for the scheme
691//      TPM_RC_VALUE                      the publicArea nameAlg is invalid
692//
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;
707   // Check parameter values
708   if(publicArea->nameAlg == TPM_ALG_NULL)
709   {
710       return TPM_RC_VALUE;
711   }
712   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)
718       hashAlg = scheme->details.xor_.hashAlg;
719   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//
750//      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}
771#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.
960   // The hash algorithm match has to be verified for OAEP.
961   // 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.
964   else if (keyScheme->scheme == scheme->scheme
965            && ((keyScheme->scheme != TPM_ALG_OAEP) ||
966                (keyScheme->details.anySig.hashAlg == scheme->details.anySig.hashAlg)))
967   {
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//
1253//      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);
1557   TPM2B_8B                cntr = {.b.size = 8};
1558   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
1936//       TPM_RC_VALUE                      the publicArea nameAlg is invalid
1937//
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{
1949   // Check parameter values
1950   if(publicArea->nameAlg == TPM_ALG_NULL)
1951   {
1952       return TPM_RC_VALUE;
1953   }
1954   // 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)
1958           != publicArea->parameters.symDetail.sym.keyBits.sym)
1959           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
1963       if(publicArea->parameters.symDetail.sym.keyBits.sym % 8 != 0)
1964           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
1970           = publicArea->parameters.symDetail.sym.keyBits.sym / 8;
1971       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{
2179   TPM2B_IV                 defaultIv = {};
2180   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
2420             result = CryptEncryptRSA(&secret->t.size, secret->t.secret,
2421                                      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;
2432           BYTE                   *buffer = secret->t.secret;
2433           INT32                  bufferSize = sizeof(TPMS_ECC_POINT);
2434             // 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.
2449                  secret->t.size = TPMS_ECC_POINT_Marshal(&eccPublic, &buffer, &bufferSize);
2450                  // 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,
2541                                       secret->t.size, secret->t.secret,label);
2542             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;
2554           BYTE                     *buffer = secret->t.secret;
2555           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,
2614                                     secret->t.size, secret->t.secret);
2615                // Copy decrypted seed
2616                MemoryCopy2B(&data->b, &secret->b, sizeof(data->t.buffer));
2617            }
2618            break;
2619        case TPM_ALG_SYMCIPHER:
2620            {
2621                TPM2B_IV                 iv = {};
2622                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                {
2629                    symDef = &decryptKey->publicArea.parameters.symDetail.sym;
2630                    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
2640                       CryptSymmetricDecrypt(secret->t.secret, symDef->algorithm,
2641                                          symDef->keyBits.sym, TPM_ALG_CFB,
2642                                          decryptKey->sensitive.sensitive.sym.t.buffer,
2643                                          &iv, secret->t.size, secret->t.secret);
2644                       // 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
2885//                                         key; unsupported name algorithm for symmetric algorithms
2886//
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:
3116       if(    (publicArea->parameters.symDetail.sym.keyBits.sym + 7)/8
3117           != 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{
3186    if(   0
3187#    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)
3481             result = TPM_RC_HANDLE;
3482        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}
3713