• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Microsoft Reference Implementation for TPM 2.0
2  *
3  *  The copyright in this software is being made available under the BSD License,
4  *  included below. This software may be subject to other third party and
5  *  contributor rights, including patent rights, and no such rights are granted
6  *  under this license.
7  *
8  *  Copyright (c) Microsoft Corporation
9  *
10  *  All rights reserved.
11  *
12  *  BSD License
13  *
14  *  Redistribution and use in source and binary forms, with or without modification,
15  *  are permitted provided that the following conditions are met:
16  *
17  *  Redistributions of source code must retain the above copyright notice, this list
18  *  of conditions and the following disclaimer.
19  *
20  *  Redistributions in binary form must reproduce the above copyright notice, this
21  *  list of conditions and the following disclaimer in the documentation and/or
22  *  other materials provided with the distribution.
23  *
24  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28  *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29  *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31  *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 //** Introduction
36 //
37 //  This module contains the interfaces to the CryptoEngine and provides
38 //  miscellaneous cryptographic functions in support of the TPM.
39 //
40 
41 //** Includes
42 #include "Tpm.h"
43 
44 //****************************************************************************/
45 //**     Hash/HMAC Functions
46 //****************************************************************************/
47 
48 //*** CryptHmacSign()
49 // Sign a digest using an HMAC key. This an HMAC of a digest, not an HMAC of a
50 // message.
51 //  Return Type: TPM_RC
52 //      TPM_RC_HASH         not a valid hash
53 static TPM_RC
CryptHmacSign(TPMT_SIGNATURE * signature,OBJECT * signKey,TPM2B_DIGEST * hashData)54 CryptHmacSign(
55     TPMT_SIGNATURE      *signature,     // OUT: signature
56     OBJECT              *signKey,       // IN: HMAC key sign the hash
57     TPM2B_DIGEST        *hashData       // IN: hash to be signed
58     )
59 {
60     HMAC_STATE       hmacState;
61     UINT32           digestSize;
62 
63     digestSize = CryptHmacStart2B(&hmacState, signature->signature.any.hashAlg,
64                                   &signKey->sensitive.sensitive.bits.b);
65     CryptDigestUpdate2B(&hmacState.hashState, &hashData->b);
66     CryptHmacEnd(&hmacState, digestSize,
67                  (BYTE *)&signature->signature.hmac.digest);
68     return TPM_RC_SUCCESS;
69 }
70 
71 //*** CryptHMACVerifySignature()
72 // This function will verify a signature signed by a HMAC key.
73 // Note that a caller needs to prepare 'signature' with the signature algorithm
74 // (TPM_ALG_HMAC) and the hash algorithm to use. This function then builds a
75 // signature of that type.
76 //  Return Type: TPM_RC
77 //      TPM_RC_SCHEME           not the proper scheme for this key type
78 //      TPM_RC_SIGNATURE        if invalid input or signature is not genuine
79 static TPM_RC
CryptHMACVerifySignature(OBJECT * signKey,TPM2B_DIGEST * hashData,TPMT_SIGNATURE * signature)80 CryptHMACVerifySignature(
81     OBJECT              *signKey,       // IN: HMAC key signed the hash
82     TPM2B_DIGEST        *hashData,      // IN: digest being verified
83     TPMT_SIGNATURE      *signature      // IN: signature to be verified
84     )
85 {
86     TPMT_SIGNATURE           test;
87     TPMT_KEYEDHASH_SCHEME   *keyScheme =
88                          &signKey->publicArea.parameters.keyedHashDetail.scheme;
89 //
90     if((signature->sigAlg != TPM_ALG_HMAC)
91        || (signature->signature.hmac.hashAlg == TPM_ALG_NULL))
92         return TPM_RC_SCHEME;
93     // This check is not really needed for verification purposes. However, it does
94     // prevent someone from trying to validate a signature using a weaker hash
95     // algorithm than otherwise allowed by the key. That is, a key with a scheme
96     // other than TMP_ALG_NULL can only be used to validate signatures that have
97     // a matching scheme.
98     if((keyScheme->scheme != TPM_ALG_NULL)
99        && ((keyScheme->scheme != signature->sigAlg)
100            || (keyScheme->details.hmac.hashAlg
101                != signature->signature.any.hashAlg)))
102         return TPM_RC_SIGNATURE;
103     test.sigAlg = signature->sigAlg;
104     test.signature.hmac.hashAlg = signature->signature.hmac.hashAlg;
105 
106     CryptHmacSign(&test, signKey, hashData);
107 
108     // Compare digest
109     if(!MemoryEqual(&test.signature.hmac.digest,
110                     &signature->signature.hmac.digest,
111                     CryptHashGetDigestSize(signature->signature.any.hashAlg)))
112         return TPM_RC_SIGNATURE;
113 
114     return TPM_RC_SUCCESS;
115 }
116 
117 //*** CryptGenerateKeyedHash()
118 // This function creates a keyedHash object.
119 // Return type: TPM_RC
120 //      TPM_RC_NO_RESULT    cannot get values from random number generator
121 //      TPM_RC_SIZE         sensitive data size is larger than allowed for
122 //                          the scheme
123 static TPM_RC
CryptGenerateKeyedHash(TPMT_PUBLIC * publicArea,TPMT_SENSITIVE * sensitive,TPMS_SENSITIVE_CREATE * sensitiveCreate,RAND_STATE * rand)124 CryptGenerateKeyedHash(
125     TPMT_PUBLIC             *publicArea,        // IN/OUT: the public area template
126                                                 //     for the new key.
127     TPMT_SENSITIVE          *sensitive,         // OUT: sensitive area
128     TPMS_SENSITIVE_CREATE   *sensitiveCreate,   // IN: sensitive creation data
129     RAND_STATE              *rand               // IN: "entropy" source
130     )
131 {
132     TPMT_KEYEDHASH_SCHEME   *scheme;
133     TPM_ALG_ID               hashAlg;
134     UINT16                   digestSize;
135 
136     scheme = &publicArea->parameters.keyedHashDetail.scheme;
137 
138     if(publicArea->type != TPM_ALG_KEYEDHASH)
139         return TPM_RC_FAILURE;
140 
141     // Pick the limiting hash algorithm
142     if(scheme->scheme == TPM_ALG_NULL)
143         hashAlg = publicArea->nameAlg;
144     else if(scheme->scheme == TPM_ALG_XOR)
145         hashAlg = scheme->details.xor.hashAlg;
146     else
147         hashAlg = scheme->details.hmac.hashAlg;
148     digestSize = CryptHashGetDigestSize(hashAlg);
149 
150     // if this is a signing or a decryption key, then the limit
151     // for the data size is the block size of the hash. This limit
152     // is set because larger values have lower entropy because of the
153     // HMAC function. The lower limit is 1/2 the size of the digest
154     //
155     //If the user provided the key, check that it is a proper size
156     if(sensitiveCreate->data.t.size != 0)
157     {
158         if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)
159            || IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
160         {
161             if(sensitiveCreate->data.t.size > CryptHashGetBlockSize(hashAlg))
162                 return TPM_RC_SIZE;
163 #if 0   // May make this a FIPS-mode requirement
164             if(sensitiveCreate->data.t.size < (digestSize / 2))
165                 return TPM_RC_SIZE;
166 #endif
167         }
168         // If this is a data blob, then anything that will get past the unmarshaling
169         // is OK
170         MemoryCopy2B(&sensitive->sensitive.bits.b, &sensitiveCreate->data.b,
171                      sizeof(sensitive->sensitive.bits.t.buffer));
172     }
173     else
174     {
175         // The TPM is going to generate the data so set the size to be the
176         // size of the digest of the algorithm
177         sensitive->sensitive.bits.t.size =
178             DRBG_Generate(rand, sensitive->sensitive.bits.t.buffer, digestSize);
179         if(sensitive->sensitive.bits.t.size == 0)
180             return (g_inFailureMode) ? TPM_RC_FAILURE : TPM_RC_NO_RESULT;
181     }
182     return TPM_RC_SUCCESS;
183 }
184 
185 //*** CryptIsSchemeAnonymous()
186 // This function is used to test a scheme to see if it is an anonymous scheme
187 // The only anonymous scheme is ECDAA. ECDAA can be used to do things
188 // like U-Prove.
189 BOOL
CryptIsSchemeAnonymous(TPM_ALG_ID scheme)190 CryptIsSchemeAnonymous(
191     TPM_ALG_ID       scheme         // IN: the scheme algorithm to test
192     )
193 {
194     return scheme == TPM_ALG_ECDAA;
195 }
196 
197 //**** ************************************************************************
198 //** Symmetric Functions
199 //**** ************************************************************************
200 
201 //*** ParmDecryptSym()
202 //  This function performs parameter decryption using symmetric block cipher.
203 /*(See Part 1 specification)
204 // Symmetric parameter decryption
205 //      When parameter decryption uses a symmetric block cipher, a decryption
206 //      key and IV will be generated from:
207 //      KDFa(hash, sessionAuth, "CFB", nonceNewer, nonceOlder, bits)    (24)
208 //      Where:
209 //      hash            the hash function associated with the session
210 //      sessionAuth     the sessionAuth associated with the session
211 //      nonceNewer      nonceCaller for a command
212 //      nonceOlder      nonceTPM for a command
213 //      bits            the number of bits required for the symmetric key
214 //                      plus an IV
215 */
216 void
ParmDecryptSym(TPM_ALG_ID symAlg,TPM_ALG_ID hash,UINT16 keySizeInBits,TPM2B * key,TPM2B * nonceCaller,TPM2B * nonceTpm,UINT32 dataSize,BYTE * data)217 ParmDecryptSym(
218     TPM_ALG_ID       symAlg,        // IN: the symmetric algorithm
219     TPM_ALG_ID       hash,          // IN: hash algorithm for KDFa
220     UINT16           keySizeInBits, // IN: the key size in bits
221     TPM2B           *key,           // IN: KDF HMAC key
222     TPM2B           *nonceCaller,   // IN: nonce caller
223     TPM2B           *nonceTpm,      // IN: nonce TPM
224     UINT32           dataSize,      // IN: size of parameter buffer
225     BYTE            *data           // OUT: buffer to be decrypted
226     )
227 {
228     // KDF output buffer
229     // It contains parameters for the CFB encryption
230     // From MSB to LSB, they are the key and iv
231     BYTE             symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE];
232     // Symmetric key size in byte
233     UINT16           keySize = (keySizeInBits + 7) / 8;
234     TPM2B_IV         iv;
235 
236     iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits);
237     // If there is decryption to do...
238     if(iv.t.size > 0)
239     {
240         // Generate key and iv
241         CryptKDFa(hash, key, CFB_KEY, nonceCaller, nonceTpm,
242                   keySizeInBits + (iv.t.size * 8), symParmString, NULL, FALSE);
243         MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size);
244 
245         CryptSymmetricDecrypt(data, symAlg, keySizeInBits, symParmString,
246                               &iv, TPM_ALG_CFB, dataSize, data);
247     }
248     return;
249 }
250 
251 //*** ParmEncryptSym()
252 //  This function performs parameter encryption using symmetric block cipher.
253 /*(See part 1 specification)
254 //      When parameter decryption uses a symmetric block cipher, an encryption
255 //      key and IV will be generated from:
256 //      KDFa(hash, sessionAuth, "CFB", nonceNewer, nonceOlder, bits)    (24)
257 //      Where:
258 //      hash            the hash function associated with the session
259 //      sessionAuth     the sessionAuth associated with the session
260 //      nonceNewer      nonceTPM for a response
261 //      nonceOlder      nonceCaller for a response
262 //      bits            the number of bits required for the symmetric key
263 //                      plus an IV
264 */
265 void
ParmEncryptSym(TPM_ALG_ID symAlg,TPM_ALG_ID hash,UINT16 keySizeInBits,TPM2B * key,TPM2B * nonceCaller,TPM2B * nonceTpm,UINT32 dataSize,BYTE * data)266 ParmEncryptSym(
267     TPM_ALG_ID       symAlg,        // IN: symmetric algorithm
268     TPM_ALG_ID       hash,          // IN: hash algorithm for KDFa
269     UINT16           keySizeInBits, // IN: symmetric key size in bits
270     TPM2B           *key,           // IN: KDF HMAC key
271     TPM2B           *nonceCaller,   // IN: nonce caller
272     TPM2B           *nonceTpm,      // IN: nonce TPM
273     UINT32           dataSize,      // IN: size of parameter buffer
274     BYTE            *data           // OUT: buffer to be encrypted
275     )
276 {
277     // KDF output buffer
278     // It contains parameters for the CFB encryption
279     BYTE             symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE];
280 
281     // Symmetric key size in bytes
282     UINT16           keySize = (keySizeInBits + 7) / 8;
283 
284     TPM2B_IV         iv;
285 
286     iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits);
287     // See if there is any encryption to do
288     if(iv.t.size > 0)
289     {
290         // Generate key and iv
291         CryptKDFa(hash, key, CFB_KEY, nonceTpm, nonceCaller,
292                   keySizeInBits + (iv.t.size * 8), symParmString, NULL, FALSE);
293         MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size);
294 
295         CryptSymmetricEncrypt(data, symAlg, keySizeInBits, symParmString, &iv,
296                               TPM_ALG_CFB, dataSize, data);
297     }
298     return;
299 }
300 
301 //*** CryptGenerateKeySymmetric()
302 // This function generates a symmetric cipher key. The derivation process is
303 // determined by the type of the provided 'rand'
304 // Return type: TPM_RC
305 //      TPM_RC_NO_RESULT    cannot get a random value
306 //      TPM_RC_KEY_SIZE     key size in the public area does not match the size
307 //                          in the sensitive creation area
308 //      TPM_RC_KEY          provided key value is not allowed
309 static TPM_RC
CryptGenerateKeySymmetric(TPMT_PUBLIC * publicArea,TPMT_SENSITIVE * sensitive,TPMS_SENSITIVE_CREATE * sensitiveCreate,RAND_STATE * rand)310 CryptGenerateKeySymmetric(
311     TPMT_PUBLIC             *publicArea,        // IN/OUT: The public area template
312                                                 //     for the new key.
313     TPMT_SENSITIVE          *sensitive,         // OUT: sensitive area
314     TPMS_SENSITIVE_CREATE   *sensitiveCreate,   // IN: sensitive creation data
315     RAND_STATE              *rand               // IN: the "entropy" source for
316     )
317 {
318     UINT16           keyBits = publicArea->parameters.symDetail.sym.keyBits.sym;
319     TPM_RC           result;
320 //
321     // only do multiples of RADIX_BITS
322     if((keyBits % RADIX_BITS) != 0)
323         return TPM_RC_KEY_SIZE;
324     // If this is not a new key, then the provided key data must be the right size
325     if(sensitiveCreate->data.t.size != 0)
326     {
327         result = CryptSymKeyValidate(&publicArea->parameters.symDetail.sym,
328                                      (TPM2B_SYM_KEY *)&sensitiveCreate->data);
329         if(result == TPM_RC_SUCCESS)
330             MemoryCopy2B(&sensitive->sensitive.sym.b, &sensitiveCreate->data.b,
331                          sizeof(sensitive->sensitive.sym.t.buffer));
332     }
333 #if ALG_TDES
334     else if(publicArea->parameters.symDetail.sym.algorithm == TPM_ALG_TDES)
335     {
336         result = CryptGenerateKeyDes(publicArea, sensitive, rand);
337     }
338 #endif
339     else
340     {
341         sensitive->sensitive.sym.t.size =
342             DRBG_Generate(rand, sensitive->sensitive.sym.t.buffer,
343                           BITS_TO_BYTES(keyBits));
344         if(g_inFailureMode)
345             result = TPM_RC_FAILURE;
346         else if(sensitive->sensitive.sym.t.size == 0)
347             result = TPM_RC_NO_RESULT;
348         else
349             result = TPM_RC_SUCCESS;
350     }
351     return result;
352 }
353 
354 //*** CryptXORObfuscation()
355 // This function implements XOR obfuscation. It should not be called if the
356 // hash algorithm is not implemented. The only return value from this function
357 // is TPM_RC_SUCCESS.
358 void
CryptXORObfuscation(TPM_ALG_ID hash,TPM2B * key,TPM2B * contextU,TPM2B * contextV,UINT32 dataSize,BYTE * data)359 CryptXORObfuscation(
360     TPM_ALG_ID       hash,          // IN: hash algorithm for KDF
361     TPM2B           *key,           // IN: KDF key
362     TPM2B           *contextU,      // IN: contextU
363     TPM2B           *contextV,      // IN: contextV
364     UINT32           dataSize,      // IN: size of data buffer
365     BYTE            *data           // IN/OUT: data to be XORed in place
366     )
367 {
368     BYTE             mask[MAX_DIGEST_SIZE]; // Allocate a digest sized buffer
369     BYTE            *pm;
370     UINT32           i;
371     UINT32           counter = 0;
372     UINT16           hLen = CryptHashGetDigestSize(hash);
373     UINT32           requestSize = dataSize * 8;
374     INT32            remainBytes = (INT32)dataSize;
375 
376     pAssert((key != NULL) && (data != NULL) && (hLen != 0));
377 
378     // Call KDFa to generate XOR mask
379     for(; remainBytes > 0; remainBytes -= hLen)
380     {
381         // Make a call to KDFa to get next iteration
382         CryptKDFa(hash, key, XOR_KEY, contextU, contextV,
383                   requestSize, mask, &counter, TRUE);
384 
385     // XOR next piece of the data
386         pm = mask;
387         for(i = hLen < remainBytes ? hLen : remainBytes; i > 0; i--)
388             *data++ ^= *pm++;
389     }
390     return;
391 }
392 
393 //****************************************************************************
394 //** Initialization and shut down
395 //****************************************************************************
396 
397 //*** CryptInit()
398 // This function is called when the TPM receives a _TPM_Init indication.
399 //
400 // NOTE: The hash algorithms do not have to be tested, they just need to be
401 // available. They have to be tested before the TPM can accept HMAC authorization
402 // or return any result that relies on a hash algorithm.
403 //  Return Type: BOOL
404 //      TRUE(1)         initializations succeeded
405 //      FALSE(0)        initialization failed and caller should place the TPM into
406 //                      Failure Mode
407 BOOL
CryptInit(void)408 CryptInit(
409     void
410     )
411 {
412     BOOL         ok;
413     // Initialize the vector of implemented algorithms
414     AlgorithmGetImplementedVector(&g_implementedAlgorithms);
415 
416     // Indicate that all test are necessary
417     CryptInitializeToTest();
418 
419     // Do any library initializations that are necessary. If any fails,
420     // the caller should go into failure mode;
421     ok = SupportLibInit();
422     ok = ok && CryptSymInit();
423     ok = ok && CryptRandInit();
424     ok = ok && CryptHashInit();
425 #if ALG_RSA
426     ok = ok && CryptRsaInit();
427 #endif // ALG_RSA
428 #if ALG_ECC
429     ok = ok && CryptEccInit();
430 #endif // ALG_ECC
431     return ok;
432 }
433 
434 //*** CryptStartup()
435 // This function is called by TPM2_Startup() to initialize the functions in
436 // this cryptographic library and in the provided CryptoLibrary. This function
437 // and CryptUtilInit() are both provided so that the implementation may move the
438 // initialization around to get the best interaction.
439 //  Return Type: BOOL
440 //      TRUE(1)         startup succeeded
441 //      FALSE(0)        startup failed and caller should place the TPM into
442 //                      Failure Mode
443 BOOL
CryptStartup(STARTUP_TYPE type)444 CryptStartup(
445     STARTUP_TYPE     type           // IN: the startup type
446     )
447 {
448     BOOL            OK;
449     NOT_REFERENCED(type);
450 
451     OK = CryptSymStartup() && CryptRandStartup() && CryptHashStartup()
452 #if ALG_RSA
453         &&  CryptRsaStartup()
454 #endif // ALG_RSA
455 #if ALG_ECC
456         &&  CryptEccStartup()
457 #endif // ALG_ECC
458         ;
459 #if ALG_ECC
460     // Don't directly check for SU_RESET because that is the default
461     if(OK && (type != SU_RESTART) && (type != SU_RESUME))
462     {
463     // If the shutdown was orderly, then the values recovered from NV will
464     // be OK to use.
465         // Get a new  random commit nonce
466         gr.commitNonce.t.size = sizeof(gr.commitNonce.t.buffer);
467         CryptRandomGenerate(gr.commitNonce.t.size, gr.commitNonce.t.buffer);
468         // Reset the counter and commit array
469         gr.commitCounter = 0;
470         MemorySet(gr.commitArray, 0, sizeof(gr.commitArray));
471     }
472 #endif // ALG_ECC
473     return OK;
474 }
475 
476 //****************************************************************************
477 //** Algorithm-Independent Functions
478 //****************************************************************************
479 //*** Introduction
480 // These functions are used generically when a function of a general type
481 // (e.g., symmetric encryption) is required.  The functions will modify the
482 // parameters as required to interface to the indicated algorithms.
483 //
484 //*** CryptIsAsymAlgorithm()
485 // This function indicates if an algorithm is an asymmetric algorithm.
486 //  Return Type: BOOL
487 //      TRUE(1)         if it is an asymmetric algorithm
488 //      FALSE(0)        if it is not an asymmetric algorithm
489 BOOL
CryptIsAsymAlgorithm(TPM_ALG_ID algID)490 CryptIsAsymAlgorithm(
491     TPM_ALG_ID       algID          // IN: algorithm ID
492     )
493 {
494     switch(algID)
495     {
496 #if ALG_RSA
497         case TPM_ALG_RSA:
498 #endif
499 #if ALG_ECC
500         case TPM_ALG_ECC:
501 #endif
502             return TRUE;
503             break;
504         default:
505             break;
506     }
507     return FALSE;
508 }
509 
510 //*** CryptSecretEncrypt()
511 // This function creates a secret value and its associated secret structure using
512 // an asymmetric algorithm.
513 //
514 // This function is used by TPM2_Rewrap() TPM2_MakeCredential(),
515 // and TPM2_Duplicate().
516 //  Return Type: TPM_RC
517 //      TPM_RC_ATTRIBUTES   'keyHandle' does not reference a valid decryption key
518 //      TPM_RC_KEY          invalid ECC key (public point is not on the curve)
519 //      TPM_RC_SCHEME       RSA key with an unsupported padding scheme
520 //      TPM_RC_VALUE        numeric value of the data to be decrypted is greater
521 //                          than the RSA key modulus
522 TPM_RC
CryptSecretEncrypt(OBJECT * encryptKey,const TPM2B * label,TPM2B_DATA * data,TPM2B_ENCRYPTED_SECRET * secret)523 CryptSecretEncrypt(
524     OBJECT                  *encryptKey,    // IN: encryption key object
525     const TPM2B             *label,         // IN: a null-terminated string as L
526     TPM2B_DATA              *data,          // OUT: secret value
527     TPM2B_ENCRYPTED_SECRET  *secret         // OUT: secret structure
528     )
529 {
530     TPMT_RSA_DECRYPT         scheme;
531     TPM_RC                   result = TPM_RC_SUCCESS;
532 //
533     if(data == NULL || secret == NULL)
534         return TPM_RC_FAILURE;
535 
536     // The output secret value has the size of the digest produced by the nameAlg.
537     data->t.size = CryptHashGetDigestSize(encryptKey->publicArea.nameAlg);
538     // The encryption scheme is OAEP using the nameAlg of the encrypt key.
539     scheme.scheme = TPM_ALG_OAEP;
540     scheme.details.anySig.hashAlg = encryptKey->publicArea.nameAlg;
541 
542     if(!IS_ATTRIBUTE(encryptKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt))
543         return TPM_RC_ATTRIBUTES;
544     switch(encryptKey->publicArea.type)
545     {
546 #if ALG_RSA
547         case TPM_ALG_RSA:
548         {
549             // Create secret data from RNG
550             CryptRandomGenerate(data->t.size, data->t.buffer);
551 
552             // Encrypt the data by RSA OAEP into encrypted secret
553             result = CryptRsaEncrypt((TPM2B_PUBLIC_KEY_RSA *)secret, &data->b,
554                                      encryptKey, &scheme, label, NULL);
555         }
556         break;
557 #endif // ALG_RSA
558 
559 #if ALG_ECC
560         case TPM_ALG_ECC:
561         {
562             TPMS_ECC_POINT      eccPublic;
563             TPM2B_ECC_PARAMETER eccPrivate;
564             TPMS_ECC_POINT      eccSecret;
565             BYTE                *buffer = secret->t.secret;
566 
567             // Need to make sure that the public point of the key is on the
568             // curve defined by the key.
569             if(!CryptEccIsPointOnCurve(
570                 encryptKey->publicArea.parameters.eccDetail.curveID,
571                 &encryptKey->publicArea.unique.ecc))
572                 result = TPM_RC_KEY;
573             else
574             {
575                 // Call crypto engine to create an auxiliary ECC key
576                 // We assume crypt engine initialization should always success.
577                 // Otherwise, TPM should go to failure mode.
578 
579                 CryptEccNewKeyPair(&eccPublic, &eccPrivate,
580                                encryptKey->publicArea.parameters.eccDetail.curveID);
581                 // Marshal ECC public to secret structure. This will be used by the
582                 // recipient to decrypt the secret with their private key.
583                 secret->t.size = TPMS_ECC_POINT_Marshal(&eccPublic, &buffer, NULL);
584 
585                 // Compute ECDH shared secret which is R = [d]Q where d is the
586                 // private part of the ephemeral key and Q is the public part of a
587                 // TPM key. TPM_RC_KEY error return from CryptComputeECDHSecret
588                 // because the auxiliary ECC key is just created according to the
589                 // parameters of input ECC encrypt key.
590                 if(CryptEccPointMultiply(&eccSecret,
591                              encryptKey->publicArea.parameters.eccDetail.curveID,
592                              &encryptKey->publicArea.unique.ecc, &eccPrivate,
593                              NULL, NULL)
594                    != TPM_RC_SUCCESS)
595                     result = TPM_RC_KEY;
596                 else
597                 {
598                     // The secret value is computed from Z using KDFe as:
599                     // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits)
600                     // Where:
601                     //  HashID  the nameAlg of the decrypt key
602                     //  Z   the x coordinate (Px) of the product (P) of the point
603                     //      (Q) of the secret and the private x coordinate (de,V)
604                     //      of the decryption key
605                     //  Use a null-terminated string containing "SECRET"
606                     //  PartyUInfo  the x coordinate of the point in the secret
607                     //              (Qe,U )
608                     //  PartyVInfo  the x coordinate of the public key (Qs,V )
609                     //  bits    the number of bits in the digest of HashID
610                     // Retrieve seed from KDFe
611                     CryptKDFe(encryptKey->publicArea.nameAlg, &eccSecret.x.b,
612                               label, &eccPublic.x.b,
613                               &encryptKey->publicArea.unique.ecc.x.b,
614                               data->t.size * 8, data->t.buffer);
615                 }
616             }
617         }
618         break;
619 #endif // ALG_ECC
620         default:
621             FAIL(FATAL_ERROR_INTERNAL);
622             break;
623     }
624     return result;
625 }
626 
627 //*** CryptSecretDecrypt()
628 // Decrypt a secret value by asymmetric (or symmetric) algorithm
629 // This function is used for ActivateCredential and Import for asymmetric
630 // decryption, and StartAuthSession for both asymmetric and symmetric
631 // decryption process
632 //
633 //  Return Type: TPM_RC
634 //      TPM_RC_ATTRIBUTES        RSA key is not a decryption key
635 //      TPM_RC_BINDING           Invalid RSA key (public and private parts are not
636 //                               cryptographically bound.
637 //      TPM_RC_ECC_POINT         ECC point in the secret is not on the curve
638 //      TPM_RC_INSUFFICIENT      failed to retrieve ECC point from the secret
639 //      TPM_RC_NO_RESULT         multiplication resulted in ECC point at infinity
640 //      TPM_RC_SIZE              data to decrypt is not of the same size as RSA key
641 //      TPM_RC_VALUE             For RSA key, numeric value of the encrypted data is
642 //                               greater than the modulus, or the recovered data is
643 //                               larger than the output buffer.
644 //                               For keyedHash or symmetric key, the secret is
645 //                               larger than the size of the digest produced by
646 //                               the name algorithm.
647 //      TPM_RC_FAILURE           internal error
648 TPM_RC
CryptSecretDecrypt(OBJECT * decryptKey,TPM2B_NONCE * nonceCaller,const TPM2B * label,TPM2B_ENCRYPTED_SECRET * secret,TPM2B_DATA * data)649 CryptSecretDecrypt(
650     OBJECT                  *decryptKey,    // IN: decrypt key
651     TPM2B_NONCE             *nonceCaller,   // IN: nonceCaller.  It is needed for
652                                             //     symmetric decryption.  For
653                                             //     asymmetric decryption, this
654                                             //     parameter is NULL
655     const TPM2B             *label,         // IN: a value for L
656     TPM2B_ENCRYPTED_SECRET  *secret,        // IN: input secret
657     TPM2B_DATA              *data           // OUT: decrypted secret value
658     )
659 {
660     TPM_RC      result = TPM_RC_SUCCESS;
661 
662     // Decryption for secret
663     switch(decryptKey->publicArea.type)
664     {
665 #if ALG_RSA
666         case TPM_ALG_RSA:
667         {
668             TPMT_RSA_DECRYPT        scheme;
669             TPMT_RSA_SCHEME         *keyScheme
670                 = &decryptKey->publicArea.parameters.rsaDetail.scheme;
671             UINT16                   digestSize;
672 
673             scheme = *(TPMT_RSA_DECRYPT *)keyScheme;
674             // If the key scheme is TPM_ALG_NULL, set the scheme to OAEP and
675             // set the algorithm to the name algorithm.
676             if(scheme.scheme == TPM_ALG_NULL)
677             {
678                 // Use OAEP scheme
679                 scheme.scheme = TPM_ALG_OAEP;
680                 scheme.details.oaep.hashAlg = decryptKey->publicArea.nameAlg;
681             }
682             // use the digestSize as an indicator of whether or not the scheme
683             // is using a supported hash algorithm.
684             // Note: depending on the scheme used for encryption, a hashAlg might
685             // not be needed. However, the return value has to have some upper
686             // limit on the size. In this case, it is the size of the digest of the
687             // hash algorithm. It is checked after the decryption is done but, there
688             // is no point in doing the decryption if the size is going to be
689             // 'wrong' anyway.
690             digestSize = CryptHashGetDigestSize(scheme.details.oaep.hashAlg);
691             if(scheme.scheme != TPM_ALG_OAEP || digestSize == 0)
692                 return TPM_RC_SCHEME;
693 
694             // Set the output buffer capacity
695             data->t.size = sizeof(data->t.buffer);
696 
697             // Decrypt seed by RSA OAEP
698             result = CryptRsaDecrypt(&data->b, &secret->b,
699                                      decryptKey, &scheme, label);
700             if((result == TPM_RC_SUCCESS) && (data->t.size > digestSize))
701                 result = TPM_RC_VALUE;
702         }
703         break;
704 #endif // ALG_RSA
705 #if ALG_ECC
706         case TPM_ALG_ECC:
707         {
708             TPMS_ECC_POINT       eccPublic;
709             TPMS_ECC_POINT       eccSecret;
710             BYTE                *buffer = secret->t.secret;
711             INT32                size = secret->t.size;
712 
713             // Retrieve ECC point from secret buffer
714             result = TPMS_ECC_POINT_Unmarshal(&eccPublic, &buffer, &size);
715             if(result == TPM_RC_SUCCESS)
716             {
717                 result = CryptEccPointMultiply(&eccSecret,
718                               decryptKey->publicArea.parameters.eccDetail.curveID,
719                               &eccPublic, &decryptKey->sensitive.sensitive.ecc,
720                               NULL, NULL);
721                 if(result == TPM_RC_SUCCESS)
722                 {
723                     // Set the size of the "recovered" secret value to be the size
724                     // of the digest produced by the nameAlg.
725                     data->t.size =
726                         CryptHashGetDigestSize(decryptKey->publicArea.nameAlg);
727 
728                 // The secret value is computed from Z using KDFe as:
729                 // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits)
730                 // Where:
731                 //  HashID -- the nameAlg of the decrypt key
732                 //  Z --  the x coordinate (Px) of the product (P) of the point
733                 //        (Q) of the secret and the private x coordinate (de,V)
734                 //        of the decryption key
735                 //  Use -- a null-terminated string containing "SECRET"
736                 //  PartyUInfo -- the x coordinate of the point in the secret
737                 //              (Qe,U )
738                 //  PartyVInfo -- the x coordinate of the public key (Qs,V )
739                 //  bits -- the number of bits in the digest of HashID
740                 // Retrieve seed from KDFe
741                     CryptKDFe(decryptKey->publicArea.nameAlg, &eccSecret.x.b, label,
742                               &eccPublic.x.b,
743                               &decryptKey->publicArea.unique.ecc.x.b,
744                               data->t.size * 8, data->t.buffer);
745                 }
746             }
747         }
748         break;
749 #endif // ALG_ECC
750 #if     !ALG_KEYEDHASH
751 #   error   "KEYEDHASH support is required"
752 #endif
753         case TPM_ALG_KEYEDHASH:
754             // The seed size can not be bigger than the digest size of nameAlg
755             if(secret->t.size >
756                CryptHashGetDigestSize(decryptKey->publicArea.nameAlg))
757                 result = TPM_RC_VALUE;
758             else
759             {
760                 // Retrieve seed by XOR Obfuscation:
761                 //    seed = XOR(secret, hash, key, nonceCaller, nullNonce)
762                 //    where:
763                 //    secret  the secret parameter from the TPM2_StartAuthHMAC
764                 //            command that contains the seed value
765                 //    hash    nameAlg  of tpmKey
766                 //    key     the key or data value in the object referenced by
767                 //            entityHandle in the TPM2_StartAuthHMAC command
768                 //    nonceCaller the parameter from the TPM2_StartAuthHMAC command
769                 //    nullNonce   a zero-length nonce
770                 // XOR Obfuscation in place
771                 CryptXORObfuscation(decryptKey->publicArea.nameAlg,
772                                     &decryptKey->sensitive.sensitive.bits.b,
773                                     &nonceCaller->b, NULL,
774                                     secret->t.size, secret->t.secret);
775                 // Copy decrypted seed
776                 MemoryCopy2B(&data->b, &secret->b, sizeof(data->t.buffer));
777             }
778             break;
779         case TPM_ALG_SYMCIPHER:
780         {
781             TPM2B_IV                iv = {{0}};
782             TPMT_SYM_DEF_OBJECT     *symDef;
783             // The seed size can not be bigger than the digest size of nameAlg
784             if(secret->t.size >
785                CryptHashGetDigestSize(decryptKey->publicArea.nameAlg))
786                 result = TPM_RC_VALUE;
787             else
788             {
789                 symDef = &decryptKey->publicArea.parameters.symDetail.sym;
790                 iv.t.size = CryptGetSymmetricBlockSize(symDef->algorithm,
791                                                        symDef->keyBits.sym);
792                 if(iv.t.size == 0)
793                     return TPM_RC_FAILURE;
794                 if(nonceCaller->t.size >= iv.t.size)
795                 {
796                     MemoryCopy(iv.t.buffer, nonceCaller->t.buffer, iv.t.size);
797                 }
798                 else
799                 {
800                     if(nonceCaller->t.size > sizeof(iv.t.buffer))
801                         return TPM_RC_FAILURE;
802                     MemoryCopy(iv.b.buffer, nonceCaller->t.buffer,
803                                  nonceCaller->t.size);
804                 }
805                 // make sure secret will fit
806                 if(secret->t.size > data->t.size)
807                     return TPM_RC_FAILURE;
808                 data->t.size = secret->t.size;
809                 // CFB decrypt, using nonceCaller as iv
810                 CryptSymmetricDecrypt(data->t.buffer, symDef->algorithm,
811                                       symDef->keyBits.sym,
812                                       decryptKey->sensitive.sensitive.sym.t.buffer,
813                                       &iv, TPM_ALG_CFB, secret->t.size,
814                                       secret->t.secret);
815             }
816         }
817         break;
818         default:
819             FAIL(FATAL_ERROR_INTERNAL);
820             break;
821     }
822     return result;
823 }
824 
825 //*** CryptParameterEncryption()
826 // This function does in-place encryption of a response parameter.
827 void
CryptParameterEncryption(TPM_HANDLE handle,TPM2B * nonceCaller,UINT16 leadingSizeInByte,TPM2B_AUTH * extraKey,BYTE * buffer)828 CryptParameterEncryption(
829     TPM_HANDLE       handle,            // IN: encrypt session handle
830     TPM2B           *nonceCaller,       // IN: nonce caller
831     UINT16           leadingSizeInByte, // IN: the size of the leading size field in
832                                         //     bytes
833     TPM2B_AUTH      *extraKey,          // IN: additional key material other than
834                                         //     sessionAuth
835     BYTE            *buffer             // IN/OUT: parameter buffer to be encrypted
836     )
837 {
838     SESSION     *session = SessionGet(handle);  // encrypt session
839     TPM2B_TYPE(TEMP_KEY, (sizeof(extraKey->t.buffer)
840                           + sizeof(session->sessionKey.t.buffer)));
841     TPM2B_TEMP_KEY        key;               // encryption key
842     UINT32               cipherSize = 0;    // size of cipher text
843 //
844     // Retrieve encrypted data size.
845     if(leadingSizeInByte == 2)
846     {
847         // Extract the first two bytes as the size field as the data size
848         // encrypt
849         cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer);
850         // advance the buffer
851         buffer = &buffer[2];
852     }
853 #ifdef      TPM4B
854     else if(leadingSizeInByte == 4)
855     {
856         // use the first four bytes to indicate the number of bytes to encrypt
857         cipherSize = BYTE_ARRAY_TO_UINT32(buffer);
858         //advance pointer
859         buffer = &buffer[4];
860     }
861 #endif
862     else
863     {
864         FAIL(FATAL_ERROR_INTERNAL);
865     }
866 
867     // Compute encryption key by concatenating sessionKey with extra key
868     MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
869     MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer));
870 
871     if(session->symmetric.algorithm == TPM_ALG_XOR)
872 
873         // XOR parameter encryption formulation:
874         //    XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder)
875         CryptXORObfuscation(session->authHashAlg, &(key.b),
876                             &(session->nonceTPM.b),
877                             nonceCaller, cipherSize, buffer);
878     else
879         ParmEncryptSym(session->symmetric.algorithm, session->authHashAlg,
880                        session->symmetric.keyBits.aes, &(key.b),
881                        nonceCaller, &(session->nonceTPM.b),
882                        cipherSize, buffer);
883     return;
884 }
885 
886 //*** CryptParameterDecryption()
887 // This function does in-place decryption of a command parameter.
888 //  Return Type: TPM_RC
889 //      TPM_RC_SIZE             The number of bytes in the input buffer is less than
890 //                              the number of bytes to be decrypted.
891 TPM_RC
CryptParameterDecryption(TPM_HANDLE handle,TPM2B * nonceCaller,UINT32 bufferSize,UINT16 leadingSizeInByte,TPM2B_AUTH * extraKey,BYTE * buffer)892 CryptParameterDecryption(
893     TPM_HANDLE       handle,            // IN: encrypted session handle
894     TPM2B           *nonceCaller,       // IN: nonce caller
895     UINT32           bufferSize,        // IN: size of parameter buffer
896     UINT16           leadingSizeInByte, // IN: the size of the leading size field in
897                                         //     byte
898     TPM2B_AUTH      *extraKey,          // IN: the authValue
899     BYTE            *buffer             // IN/OUT: parameter buffer to be decrypted
900     )
901 {
902     SESSION         *session = SessionGet(handle);  // encrypt session
903     // The HMAC key is going to be the concatenation of the session key and any
904     // additional key material (like the authValue). The size of both of these
905     // is the size of the buffer which can contain a TPMT_HA.
906     TPM2B_TYPE(HMAC_KEY, (sizeof(extraKey->t.buffer)
907                           + sizeof(session->sessionKey.t.buffer)));
908     TPM2B_HMAC_KEY          key;            // decryption key
909     UINT32                  cipherSize = 0; // size of cipher text
910 //
911     // Retrieve encrypted data size.
912     if(leadingSizeInByte == 2)
913     {
914         // The first two bytes of the buffer are the size of the
915         // data to be decrypted
916         cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer);
917         buffer = &buffer[2];   // advance the buffer
918     }
919 #ifdef  TPM4B
920     else if(leadingSizeInByte == 4)
921     {
922         // the leading size is four bytes so get the four byte size field
923         cipherSize = BYTE_ARRAY_TO_UINT32(buffer);
924         buffer = &buffer[4];   //advance pointer
925     }
926 #endif
927     else
928     {
929         FAIL(FATAL_ERROR_INTERNAL);
930     }
931     if(cipherSize > bufferSize)
932         return TPM_RC_SIZE;
933 
934     // Compute decryption key by concatenating sessionAuth with extra input key
935     MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer));
936     MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer));
937 
938     if(session->symmetric.algorithm == TPM_ALG_XOR)
939         // XOR parameter decryption formulation:
940         //    XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder)
941         // Call XOR obfuscation function
942         CryptXORObfuscation(session->authHashAlg, &key.b, nonceCaller,
943                             &(session->nonceTPM.b), cipherSize, buffer);
944     else
945         // Assume that it is one of the symmetric block ciphers.
946         ParmDecryptSym(session->symmetric.algorithm, session->authHashAlg,
947                        session->symmetric.keyBits.sym,
948                        &key.b, nonceCaller, &session->nonceTPM.b,
949                        cipherSize, buffer);
950 
951     return TPM_RC_SUCCESS;
952 }
953 
954 //*** CryptComputeSymmetricUnique()
955 // This function computes the unique field in public area for symmetric objects.
956 void
CryptComputeSymmetricUnique(TPMT_PUBLIC * publicArea,TPMT_SENSITIVE * sensitive,TPM2B_DIGEST * unique)957 CryptComputeSymmetricUnique(
958     TPMT_PUBLIC     *publicArea,    // IN: the object's public area
959     TPMT_SENSITIVE  *sensitive,     // IN: the associated sensitive area
960     TPM2B_DIGEST    *unique         // OUT: unique buffer
961     )
962 {
963     // For parents (symmetric and derivation), use an HMAC to compute
964     // the 'unique' field
965     if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)
966        && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt))
967     {
968         // Unique field is HMAC(sensitive->seedValue, sensitive->sensitive)
969         HMAC_STATE      hmacState;
970         unique->b.size = CryptHmacStart2B(&hmacState, publicArea->nameAlg,
971                                           &sensitive->seedValue.b);
972         CryptDigestUpdate2B(&hmacState.hashState,
973                             &sensitive->sensitive.any.b);
974         CryptHmacEnd2B(&hmacState, &unique->b);
975     }
976     else
977     {
978         HASH_STATE  hashState;
979         // Unique := Hash(sensitive->seedValue || sensitive->sensitive)
980         unique->t.size = CryptHashStart(&hashState, publicArea->nameAlg);
981         CryptDigestUpdate2B(&hashState, &sensitive->seedValue.b);
982         CryptDigestUpdate2B(&hashState, &sensitive->sensitive.any.b);
983         CryptHashEnd2B(&hashState, &unique->b);
984     }
985     return;
986 }
987 
988 //*** CryptCreateObject()
989 // This function creates an object.
990 // For an asymmetric key, it will create a key pair and, for a parent key, a seed
991 // value for child protections.
992 //
993 // For an symmetric object, (TPM_ALG_SYMCIPHER or TPM_ALG_KEYEDHASH), it will
994 // create a secret key if the caller did not provide one. It will create a random
995 // secret seed value that is hashed with the secret value to create the public
996 // unique value.
997 //
998 // 'publicArea', 'sensitive', and 'sensitiveCreate' are the only required parameters
999 // and are the only ones that are used by TPM2_Create(). The other parameters
1000 // are optional and are used when the generated Object needs to be deterministic.
1001 // This is the case for both Primary Objects and Derived Objects.
1002 //
1003 // When a seed value is provided, a RAND_STATE will be populated and used for
1004 // all operations in the object generation that require a random number. In the
1005 // simplest case, TPM2_CreatePrimary() will use 'seed', 'label' and 'context' with
1006 // context being the hash of the template. If the Primary Object is in
1007 // the Endorsement hierarchy, it will also populate 'proof' with ehProof.
1008 //
1009 // For derived keys, 'seed' will be the secret value from the parent, 'label' and
1010 // 'context' will be set according to the parameters of TPM2_CreateLoaded() and
1011 // 'hashAlg' will be set which causes the RAND_STATE to be a KDF generator.
1012 //
1013 //  Return Type: TPM_RC
1014 //      TPM_RC_KEY          a provided key is not an allowed value
1015 //      TPM_RC_KEY_SIZE     key size in the public area does not match the size
1016 //                          in the sensitive creation area for a symmetric key
1017 //      TPM_RC_NO_RESULT    unable to get random values (only in derivation)
1018 //      TPM_RC_RANGE        for an RSA key, the exponent is not supported
1019 //      TPM_RC_SIZE         sensitive data size is larger than allowed for the
1020 //                          scheme for a keyed hash object
1021 //      TPM_RC_VALUE        exponent is not prime or could not find a prime using
1022 //                          the provided parameters for an RSA key;
1023 //                          unsupported name algorithm for an ECC key
1024 TPM_RC
CryptCreateObject(OBJECT * object,TPMS_SENSITIVE_CREATE * sensitiveCreate,RAND_STATE * rand)1025 CryptCreateObject(
1026     OBJECT                  *object,            // IN: new object structure pointer
1027     TPMS_SENSITIVE_CREATE   *sensitiveCreate,   // IN: sensitive creation
1028     RAND_STATE              *rand               // IN: the random number generator
1029                                                 //      to use
1030     )
1031 {
1032     TPMT_PUBLIC             *publicArea = &object->publicArea;
1033     TPMT_SENSITIVE          *sensitive = &object->sensitive;
1034     TPM_RC                   result = TPM_RC_SUCCESS;
1035 //
1036     // Set the sensitive type for the object
1037     sensitive->sensitiveType = publicArea->type;
1038 
1039     // For all objects, copy the initial authorization data
1040     sensitive->authValue = sensitiveCreate->userAuth;
1041 
1042     // If the TPM is the source of the data, set the size of the provided data to
1043     // zero so that there's no confusion about what to do.
1044     if(IS_ATTRIBUTE(publicArea->objectAttributes,
1045                     TPMA_OBJECT, sensitiveDataOrigin))
1046         sensitiveCreate->data.t.size = 0;
1047 
1048     // Generate the key and unique fields for the asymmetric keys and just the
1049     // sensitive value for symmetric object
1050     switch(publicArea->type)
1051     {
1052 #if ALG_RSA
1053         // Create RSA key
1054         case TPM_ALG_RSA:
1055             // RSA uses full object so that it has a place to put the private
1056             // exponent
1057             result = CryptRsaGenerateKey(publicArea, sensitive, rand);
1058             break;
1059 #endif // ALG_RSA
1060 
1061 #if ALG_ECC
1062         // Create ECC key
1063         case TPM_ALG_ECC:
1064             result = CryptEccGenerateKey(publicArea, sensitive, rand);
1065             break;
1066 #endif // ALG_ECC
1067         case TPM_ALG_SYMCIPHER:
1068             result = CryptGenerateKeySymmetric(publicArea, sensitive,
1069                                                sensitiveCreate, rand);
1070             break;
1071         case TPM_ALG_KEYEDHASH:
1072             result = CryptGenerateKeyedHash(publicArea, sensitive,
1073                                             sensitiveCreate, rand);
1074             break;
1075         default:
1076             FAIL(FATAL_ERROR_INTERNAL);
1077             break;
1078     }
1079     if(result != TPM_RC_SUCCESS)
1080         return result;
1081 // Create the sensitive seed value
1082     // If this is a primary key in the endorsement hierarchy, stir the DRBG state
1083     // This implementation uses both shProof and ehProof to make sure that there
1084     // is no leakage of either.
1085     if(object->attributes.primary && object->attributes.epsHierarchy)
1086     {
1087         DRBG_AdditionalData((DRBG_STATE *)rand, &gp.shProof.b);
1088         DRBG_AdditionalData((DRBG_STATE *)rand, &gp.ehProof.b);
1089     }
1090     // Generate a seedValue that is the size of the digest produced by nameAlg
1091     sensitive->seedValue.t.size =
1092         DRBG_Generate(rand, sensitive->seedValue.t.buffer,
1093                       CryptHashGetDigestSize(publicArea->nameAlg));
1094     if(g_inFailureMode)
1095         return TPM_RC_FAILURE;
1096     else if(sensitive->seedValue.t.size == 0)
1097         return TPM_RC_NO_RESULT;
1098     // For symmetric objects, need to compute the unique value for the public area
1099     if(publicArea->type == TPM_ALG_SYMCIPHER
1100        || publicArea->type == TPM_ALG_KEYEDHASH)
1101     {
1102         CryptComputeSymmetricUnique(publicArea, sensitive, &publicArea->unique.sym);
1103     }
1104     else
1105     {
1106         // if this is an asymmetric key and it isn't a parent, then
1107         // get rid of the seed.
1108         if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)
1109            || !IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
1110             memset(&sensitive->seedValue, 0, sizeof(sensitive->seedValue));
1111     }
1112     // Compute the name
1113     PublicMarshalAndComputeName(publicArea, &object->name);
1114     return result;
1115 }
1116 
1117 //*** CryptGetSignHashAlg()
1118 // Get the hash algorithm of signature from a TPMT_SIGNATURE structure.
1119 // It assumes the signature is not NULL
1120 //  This is a function for easy access
1121 TPMI_ALG_HASH
CryptGetSignHashAlg(TPMT_SIGNATURE * auth)1122 CryptGetSignHashAlg(
1123     TPMT_SIGNATURE  *auth           // IN: signature
1124     )
1125 {
1126     if(auth->sigAlg == TPM_ALG_NULL)
1127         FAIL(FATAL_ERROR_INTERNAL);
1128 
1129     // Get authHash algorithm based on signing scheme
1130     switch(auth->sigAlg)
1131     {
1132 #if ALG_RSA
1133     // If RSA is supported, both RSASSA and RSAPSS are required
1134 #   if !defined TPM_ALG_RSASSA || !defined TPM_ALG_RSAPSS
1135 #       error "RSASSA and RSAPSS are required for RSA"
1136 #   endif
1137         case TPM_ALG_RSASSA:
1138             return auth->signature.rsassa.hash;
1139         case TPM_ALG_RSAPSS:
1140             return auth->signature.rsapss.hash;
1141 #endif // ALG_RSA
1142 
1143 #if ALG_ECC
1144     // If ECC is defined, ECDSA is mandatory
1145 #   if !ALG_ECDSA
1146 #       error "ECDSA is requried for ECC"
1147 #   endif
1148         case TPM_ALG_ECDSA:
1149     // SM2 and ECSCHNORR are optional
1150 
1151 #   if      ALG_SM2
1152         case TPM_ALG_SM2:
1153 #   endif
1154 #   if  ALG_ECSCHNORR
1155         case TPM_ALG_ECSCHNORR:
1156 #   endif
1157         //all ECC signatures look the same
1158             return auth->signature.ecdsa.hash;
1159 
1160 #   if  ALG_ECDAA
1161         // Don't know how to verify an ECDAA signature
1162         case TPM_ALG_ECDAA:
1163             break;
1164 #   endif
1165 
1166 #endif // ALG_ECC
1167 
1168         case TPM_ALG_HMAC:
1169             return auth->signature.hmac.hashAlg;
1170 
1171         default:
1172             break;
1173     }
1174     return TPM_ALG_NULL;
1175 }
1176 
1177 //*** CryptIsSplitSign()
1178 // This function us used to determine if the signing operation is a split
1179 // signing operation that required a TPM2_Commit().
1180 //
1181 BOOL
CryptIsSplitSign(TPM_ALG_ID scheme)1182 CryptIsSplitSign(
1183     TPM_ALG_ID       scheme         // IN: the algorithm selector
1184     )
1185 {
1186     switch(scheme)
1187     {
1188 #   if  ALG_ECDAA
1189         case TPM_ALG_ECDAA:
1190             return TRUE;
1191             break;
1192 #   endif   // ALG_ECDAA
1193         default:
1194             return FALSE;
1195             break;
1196     }
1197 }
1198 
1199 //*** CryptIsAsymSignScheme()
1200 // This function indicates if a scheme algorithm is a sign algorithm.
1201 BOOL
CryptIsAsymSignScheme(TPMI_ALG_PUBLIC publicType,TPMI_ALG_ASYM_SCHEME scheme)1202 CryptIsAsymSignScheme(
1203     TPMI_ALG_PUBLIC          publicType,        // IN: Type of the object
1204     TPMI_ALG_ASYM_SCHEME     scheme             // IN: the scheme
1205     )
1206 {
1207     BOOL            isSignScheme = TRUE;
1208 
1209     switch(publicType)
1210     {
1211 #if ALG_RSA
1212         case TPM_ALG_RSA:
1213             switch(scheme)
1214             {
1215 #   if !ALG_RSASSA  || !ALG_RSAPSS
1216 #       error "RSASSA and PSAPSS required if RSA used."
1217 #   endif
1218                 case TPM_ALG_RSASSA:
1219                 case TPM_ALG_RSAPSS:
1220                     break;
1221                 default:
1222                     isSignScheme = FALSE;
1223                     break;
1224             }
1225             break;
1226 #endif // ALG_RSA
1227 
1228 #if ALG_ECC
1229         // If ECC is implemented ECDSA is required
1230         case TPM_ALG_ECC:
1231             switch(scheme)
1232             {
1233                 // Support for ECDSA is required for ECC
1234                 case TPM_ALG_ECDSA:
1235 #if ALG_ECDAA // ECDAA is optional
1236                 case TPM_ALG_ECDAA:
1237 #endif
1238 #if ALG_ECSCHNORR // Schnorr is also optional
1239                 case TPM_ALG_ECSCHNORR:
1240 #endif
1241 #if ALG_SM2 // SM2 is optional
1242                 case TPM_ALG_SM2:
1243 #endif
1244                     break;
1245                 default:
1246                     isSignScheme = FALSE;
1247                     break;
1248             }
1249             break;
1250 #endif // ALG_ECC
1251         default:
1252             isSignScheme = FALSE;
1253             break;
1254     }
1255     return isSignScheme;
1256 }
1257 
1258 //*** CryptIsAsymDecryptScheme()
1259 // This function indicate if a scheme algorithm is a decrypt algorithm.
1260 BOOL
CryptIsAsymDecryptScheme(TPMI_ALG_PUBLIC publicType,TPMI_ALG_ASYM_SCHEME scheme)1261 CryptIsAsymDecryptScheme(
1262     TPMI_ALG_PUBLIC          publicType,        // IN: Type of the object
1263     TPMI_ALG_ASYM_SCHEME     scheme             // IN: the scheme
1264     )
1265 {
1266     BOOL        isDecryptScheme = TRUE;
1267 
1268     switch(publicType)
1269     {
1270 #if ALG_RSA
1271         case TPM_ALG_RSA:
1272             switch(scheme)
1273             {
1274                 case TPM_ALG_RSAES:
1275                 case TPM_ALG_OAEP:
1276                     break;
1277                 default:
1278                     isDecryptScheme = FALSE;
1279                     break;
1280             }
1281             break;
1282 #endif // ALG_RSA
1283 
1284 #if ALG_ECC
1285         // If ECC is implemented ECDH is required
1286         case TPM_ALG_ECC:
1287             switch(scheme)
1288             {
1289 #if  !ALG_ECDH
1290 #   error "ECDH is required for ECC"
1291 #endif
1292                 case TPM_ALG_ECDH:
1293 #if ALG_SM2
1294                 case TPM_ALG_SM2:
1295 #endif
1296 #if ALG_ECMQV
1297                 case TPM_ALG_ECMQV:
1298 #endif
1299                     break;
1300                 default:
1301                     isDecryptScheme = FALSE;
1302                     break;
1303             }
1304             break;
1305 #endif // ALG_ECC
1306         default:
1307             isDecryptScheme = FALSE;
1308             break;
1309     }
1310     return isDecryptScheme;
1311 }
1312 
1313 //*** CryptSelectSignScheme()
1314 // This function is used by the attestation and signing commands.  It implements
1315 // the rules for selecting the signature scheme to use in signing. This function
1316 // requires that the signing key either be TPM_RH_NULL or be loaded.
1317 //
1318 // If a default scheme is defined in object, the default scheme should be chosen,
1319 // otherwise, the input scheme should be chosen.
1320 // In the case that  both object and input scheme has a non-NULL scheme
1321 // algorithm, if the schemes are compatible, the input scheme will be chosen.
1322 //
1323 // This function should not be called if 'signObject->publicArea.type' ==
1324 // ALG_SYMCIPHER.
1325 //
1326 //  Return Type: BOOL
1327 //      TRUE(1)         scheme selected
1328 //      FALSE(0)        both 'scheme' and key's default scheme are empty; or
1329 //                      'scheme' is empty while key's default scheme requires
1330 //                      explicit input scheme (split signing); or
1331 //                      non-empty default key scheme differs from 'scheme'
1332 BOOL
CryptSelectSignScheme(OBJECT * signObject,TPMT_SIG_SCHEME * scheme)1333 CryptSelectSignScheme(
1334     OBJECT              *signObject,    // IN: signing key
1335     TPMT_SIG_SCHEME     *scheme         // IN/OUT: signing scheme
1336     )
1337 {
1338     TPMT_SIG_SCHEME     *objectScheme;
1339     TPMT_PUBLIC         *publicArea;
1340     BOOL                 OK;
1341 
1342     // If the signHandle is TPM_RH_NULL, then the NULL scheme is used, regardless
1343     // of the setting of scheme
1344     if(signObject == NULL)
1345     {
1346         OK = TRUE;
1347         scheme->scheme = TPM_ALG_NULL;
1348         scheme->details.any.hashAlg = TPM_ALG_NULL;
1349     }
1350     else
1351     {
1352         // assignment to save typing.
1353         publicArea = &signObject->publicArea;
1354 
1355         // A symmetric cipher can be used to encrypt and decrypt but it can't
1356         // be used for signing
1357         if(publicArea->type == TPM_ALG_SYMCIPHER)
1358             return FALSE;
1359         // Point to the scheme object
1360         if(CryptIsAsymAlgorithm(publicArea->type))
1361             objectScheme =
1362             (TPMT_SIG_SCHEME *)&publicArea->parameters.asymDetail.scheme;
1363         else
1364             objectScheme =
1365             (TPMT_SIG_SCHEME *)&publicArea->parameters.keyedHashDetail.scheme;
1366 
1367     // If the object doesn't have a default scheme, then use the
1368     // input scheme.
1369         if(objectScheme->scheme == TPM_ALG_NULL)
1370         {
1371             // Input and default can't both be NULL
1372             OK = (scheme->scheme != TPM_ALG_NULL);
1373             // Assume that the scheme is compatible with the key. If not,
1374             // an error will be generated in the signing operation.
1375         }
1376         else if(scheme->scheme == TPM_ALG_NULL)
1377         {
1378             // input scheme is NULL so use default
1379 
1380             // First, check to see if the default requires that the caller
1381             // provided scheme data
1382             OK = !CryptIsSplitSign(objectScheme->scheme);
1383             if(OK)
1384             {
1385                 // The object has a scheme and the input is TPM_ALG_NULL so copy
1386                 // the object scheme as the final scheme. It is better to use a
1387                 // structure copy than a copy of the individual fields.
1388                 *scheme = *objectScheme;
1389             }
1390         }
1391         else
1392         {
1393             // Both input and object have scheme selectors
1394             // If the scheme and the hash are not the same then...
1395             // NOTE: the reason that there is no copy here is that the input
1396             // might contain extra data for a split signing scheme and that
1397             // data is not in the object so, it has to be preserved.
1398             OK = (objectScheme->scheme == scheme->scheme)
1399                 && (objectScheme->details.any.hashAlg
1400                     == scheme->details.any.hashAlg);
1401         }
1402     }
1403     return OK;
1404 }
1405 
1406 //*** CryptSign()
1407 // Sign a digest with asymmetric key or HMAC.
1408 // This function is called by attestation commands and the generic TPM2_Sign
1409 // command.
1410 // This function checks the key scheme and digest size.  It does not
1411 // check if the sign operation is allowed for restricted key.  It should be
1412 // checked before the function is called.
1413 // The function will assert if the key is not a signing key.
1414 //
1415 //  Return Type: TPM_RC
1416 //      TPM_RC_SCHEME      'signScheme' is not compatible with the signing key type
1417 //      TPM_RC_VALUE       'digest' value is greater than the modulus of
1418 //                         'signHandle' or size of 'hashData' does not match hash
1419 //                         algorithm in'signScheme' (for an RSA key);
1420 //                         invalid commit status or failed to generate "r" value
1421 //                         (for an ECC key)
1422 TPM_RC
CryptSign(OBJECT * signKey,TPMT_SIG_SCHEME * signScheme,TPM2B_DIGEST * digest,TPMT_SIGNATURE * signature)1423 CryptSign(
1424     OBJECT              *signKey,       // IN: signing key
1425     TPMT_SIG_SCHEME     *signScheme,    // IN: sign scheme.
1426     TPM2B_DIGEST        *digest,        // IN: The digest being signed
1427     TPMT_SIGNATURE      *signature      // OUT: signature
1428     )
1429 {
1430     TPM_RC               result = TPM_RC_SCHEME;
1431 
1432     // Initialize signature scheme
1433     signature->sigAlg = signScheme->scheme;
1434 
1435     // If the signature algorithm is TPM_ALG_NULL or the signing key is NULL,
1436     // then we are done
1437     if((signature->sigAlg == TPM_ALG_NULL) || (signKey == NULL))
1438         return TPM_RC_SUCCESS;
1439 
1440     // Initialize signature hash
1441     // Note: need to do the check for TPM_ALG_NULL first because the null scheme
1442     // doesn't have a hashAlg member.
1443     signature->signature.any.hashAlg = signScheme->details.any.hashAlg;
1444 
1445     // perform sign operation based on different key type
1446     switch(signKey->publicArea.type)
1447     {
1448 #if ALG_RSA
1449         case TPM_ALG_RSA:
1450             result = CryptRsaSign(signature, signKey, digest, NULL);
1451             break;
1452 #endif // ALG_RSA
1453 #if ALG_ECC
1454         case TPM_ALG_ECC:
1455             // The reason that signScheme is passed to CryptEccSign but not to the
1456             // other signing methods is that the signing for ECC may be split and
1457             // need the 'r' value that is in the scheme but not in the signature.
1458             result = CryptEccSign(signature, signKey, digest,
1459                                   (TPMT_ECC_SCHEME *)signScheme, NULL);
1460             break;
1461 #endif // ALG_ECC
1462         case TPM_ALG_KEYEDHASH:
1463             result = CryptHmacSign(signature, signKey, digest);
1464             break;
1465         default:
1466             FAIL(FATAL_ERROR_INTERNAL);
1467             break;
1468     }
1469     return result;
1470 }
1471 
1472 //*** CryptValidateSignature()
1473 // This function is used to verify a signature.  It is called by
1474 // TPM2_VerifySignature() and TPM2_PolicySigned.
1475 //
1476 // Since this operation only requires use of a public key, no consistency
1477 // checks are necessary for the key to signature type because a caller can load
1478 // any public key that they like with any scheme that they like. This routine
1479 // simply makes sure that the signature is correct, whatever the type.
1480 //
1481 //  Return Type: TPM_RC
1482 //      TPM_RC_SIGNATURE            the signature is not genuine
1483 //      TPM_RC_SCHEME               the scheme is not supported
1484 //      TPM_RC_HANDLE               an HMAC key was selected but the
1485 //                                  private part of the key is not loaded
1486 TPM_RC
CryptValidateSignature(TPMI_DH_OBJECT keyHandle,TPM2B_DIGEST * digest,TPMT_SIGNATURE * signature)1487 CryptValidateSignature(
1488     TPMI_DH_OBJECT   keyHandle,     // IN: The handle of sign key
1489     TPM2B_DIGEST    *digest,        // IN: The digest being validated
1490     TPMT_SIGNATURE  *signature      // IN: signature
1491     )
1492 {
1493     // NOTE: HandleToObject will either return a pointer to a loaded object or
1494     // will assert. It will never return a non-valid value. This makes it save
1495     // to initialize 'publicArea' with the return value from HandleToObject()
1496     // without checking it first.
1497     OBJECT              *signObject = HandleToObject(keyHandle);
1498     TPMT_PUBLIC         *publicArea = &signObject->publicArea;
1499     TPM_RC               result = TPM_RC_SCHEME;
1500 
1501     // The input unmarshaling should prevent any input signature from being
1502     // a NULL signature, but just in case
1503     if(signature->sigAlg == TPM_ALG_NULL)
1504         return TPM_RC_SIGNATURE;
1505 
1506     switch(publicArea->type)
1507     {
1508 #if ALG_RSA
1509         case TPM_ALG_RSA:
1510         {
1511     //
1512             // Call RSA code to verify signature
1513             result = CryptRsaValidateSignature(signature, signObject, digest);
1514             break;
1515         }
1516 #endif // ALG_RSA
1517 
1518 #if ALG_ECC
1519         case TPM_ALG_ECC:
1520             result = CryptEccValidateSignature(signature, signObject, digest);
1521             break;
1522 #endif // ALG_ECC
1523 
1524         case TPM_ALG_KEYEDHASH:
1525             if(signObject->attributes.publicOnly)
1526                 result = TPM_RCS_HANDLE;
1527             else
1528                 result = CryptHMACVerifySignature(signObject, digest, signature);
1529             break;
1530         default:
1531             break;
1532     }
1533     return result;
1534 }
1535 
1536 //*** CryptGetTestResult
1537 // This function returns the results of a self-test function.
1538 // Note: the behavior in this function is NOT the correct behavior for a real
1539 // TPM implementation.  An artificial behavior is placed here due to the
1540 // limitation of a software simulation environment.  For the correct behavior,
1541 // consult the part 3 specification for TPM2_GetTestResult().
1542 TPM_RC
CryptGetTestResult(TPM2B_MAX_BUFFER * outData)1543 CryptGetTestResult(
1544     TPM2B_MAX_BUFFER    *outData        // OUT: test result data
1545     )
1546 {
1547     outData->t.size = 0;
1548     return TPM_RC_SUCCESS;
1549 }
1550 
1551 //*** CryptValidateKeys()
1552 // This function is used to verify that the key material of and object is valid.
1553 // For a 'publicOnly' object, the key is verified for size and, if it is an ECC
1554 // key, it is verified to be on the specified curve. For a key with a sensitive
1555 // area, the binding between the public and private parts of the key are verified.
1556 // If the nameAlg of the key is TPM_ALG_NULL, then the size of the sensitive area
1557 // is verified but the public portion is not verified, unless the key is an RSA key.
1558 // For an RSA key, the reason for loading the sensitive area is to use it. The
1559 // only way to use a private RSA key is to compute the private exponent. To compute
1560 // the private exponent, the public modulus is used.
1561 //  Return Type: TPM_RC
1562 //      TPM_RC_BINDING      the public and private parts are not cryptographically
1563 //                          bound
1564 //      TPM_RC_HASH         cannot have a publicOnly key with nameAlg of TPM_ALG_NULL
1565 //      TPM_RC_KEY          the public unique is not valid
1566 //      TPM_RC_KEY_SIZE     the private area key is not valid
1567 //      TPM_RC_TYPE         the types of the sensitive and private parts do not match
1568 TPM_RC
CryptValidateKeys(TPMT_PUBLIC * publicArea,TPMT_SENSITIVE * sensitive,TPM_RC blamePublic,TPM_RC blameSensitive)1569 CryptValidateKeys(
1570     TPMT_PUBLIC      *publicArea,
1571     TPMT_SENSITIVE   *sensitive,
1572     TPM_RC            blamePublic,
1573     TPM_RC            blameSensitive
1574     )
1575 {
1576     TPM_RC               result;
1577     UINT16               keySizeInBytes;
1578     UINT16               digestSize = CryptHashGetDigestSize(publicArea->nameAlg);
1579     TPMU_PUBLIC_PARMS   *params = &publicArea->parameters;
1580     TPMU_PUBLIC_ID      *unique = &publicArea->unique;
1581 
1582     if(sensitive != NULL)
1583     {
1584         // Make sure that the types of the public and sensitive are compatible
1585         if(publicArea->type != sensitive->sensitiveType)
1586             return TPM_RCS_TYPE + blameSensitive;
1587         // Make sure that the authValue is not bigger than allowed
1588         // If there is no name algorithm, then the size just needs to be less than
1589         // the maximum size of the buffer used for authorization. That size check
1590         // was made during unmarshaling of the sensitive area
1591         if((sensitive->authValue.t.size) > digestSize && (digestSize > 0))
1592             return TPM_RCS_SIZE + blameSensitive;
1593     }
1594     switch(publicArea->type)
1595     {
1596 #if ALG_RSA
1597         case TPM_ALG_RSA:
1598             keySizeInBytes = BITS_TO_BYTES(params->rsaDetail.keyBits);
1599 
1600             // Regardless of whether there is a sensitive area, the public modulus
1601             // needs to have the correct size. Otherwise, it can't be used for
1602             // any public key operation nor can it be used to compute the private
1603             // exponent.
1604             // NOTE: This implementation only supports key sizes that are multiples
1605             // of 1024 bits which means that the MSb of the 0th byte will always be
1606             // SET in any prime and in the public modulus.
1607             if((unique->rsa.t.size != keySizeInBytes)
1608                 || (unique->rsa.t.buffer[0] < 0x80))
1609                 return TPM_RCS_KEY + blamePublic;
1610             if(params->rsaDetail.exponent != 0
1611                && params->rsaDetail.exponent < 7)
1612                 return TPM_RCS_VALUE + blamePublic;
1613             if(sensitive != NULL)
1614             {
1615                 // If there is a sensitive area, it has to be the correct size
1616                 // including having the correct high order bit SET.
1617                 if(((sensitive->sensitive.rsa.t.size * 2) != keySizeInBytes)
1618                    || (sensitive->sensitive.rsa.t.buffer[0] < 0x80))
1619                     return TPM_RCS_KEY_SIZE + blameSensitive;
1620             }
1621             break;
1622 #endif
1623 #if ALG_ECC
1624         case TPM_ALG_ECC:
1625         {
1626             TPMI_ECC_CURVE      curveId;
1627             curveId = params->eccDetail.curveID;
1628             keySizeInBytes = BITS_TO_BYTES(CryptEccGetKeySizeForCurve(curveId));
1629             if(sensitive == NULL)
1630             {
1631                 // Validate the public key size
1632                 if(unique->ecc.x.t.size != keySizeInBytes
1633                    || unique->ecc.y.t.size != keySizeInBytes)
1634                     return TPM_RCS_KEY + blamePublic;
1635                 if(publicArea->nameAlg != TPM_ALG_NULL)
1636                 {
1637                     if(!CryptEccIsPointOnCurve(curveId, &unique->ecc))
1638                         return TPM_RCS_ECC_POINT + blamePublic;
1639                 }
1640             }
1641             else
1642             {
1643                 // If the nameAlg is TPM_ALG_NULL, then only verify that the
1644                 // private part of the key is OK.
1645                 if(!CryptEccIsValidPrivateKey(&sensitive->sensitive.ecc,
1646                                                   curveId))
1647                         return TPM_RCS_KEY_SIZE;
1648                 if(publicArea->nameAlg != TPM_ALG_NULL)
1649                 {
1650                 // Full key load, verify that the public point belongs to the
1651                 // private key.
1652                     TPMS_ECC_POINT          toCompare;
1653                     result = CryptEccPointMultiply(&toCompare, curveId, NULL,
1654                                                    &sensitive->sensitive.ecc,
1655                                                    NULL, NULL);
1656                     if(result != TPM_RC_SUCCESS)
1657                         return TPM_RCS_BINDING;
1658                     else
1659                     {
1660                     // Make sure that the private key generated the public key.
1661                     // The input values and the values produced by the point
1662                     // multiply may not be the same size so adjust the computed
1663                     // value to match the size of the input value by adding or
1664                     // removing zeros.
1665                         AdjustNumberB(&toCompare.x.b, unique->ecc.x.t.size);
1666                         AdjustNumberB(&toCompare.y.b, unique->ecc.y.t.size);
1667                         if(!MemoryEqual2B(&unique->ecc.x.b, &toCompare.x.b)
1668                            || !MemoryEqual2B(&unique->ecc.y.b, &toCompare.y.b))
1669                             return TPM_RCS_BINDING;
1670                     }
1671                 }
1672             }
1673             break;
1674         }
1675 #endif
1676         default:
1677             // Checks for SYMCIPHER and KEYEDHASH are largely the same
1678             // If public area has a nameAlg, then validate the public area size
1679             // and if there is also a sensitive area, validate the binding
1680 
1681             // For consistency, if the object is public-only just make sure that
1682             // the unique field is consistent with the name algorithm
1683             if(sensitive == NULL)
1684             {
1685                 if(unique->sym.t.size != digestSize)
1686                     return TPM_RCS_KEY + blamePublic;
1687             }
1688             else
1689             {
1690                 // Make sure that the key size in the sensitive area is consistent.
1691                 if(publicArea->type == TPM_ALG_SYMCIPHER)
1692                 {
1693                     result = CryptSymKeyValidate(&params->symDetail.sym,
1694                                                 &sensitive->sensitive.sym);
1695                     if(result != TPM_RC_SUCCESS)
1696                         return result + blameSensitive;
1697                 }
1698                 else
1699                 {
1700                     // For a keyed hash object, the key has to be less than the
1701                     // smaller of the block size of the hash used in the scheme or
1702                     // 128 bytes. The worst case value is limited by the
1703                     // unmarshaling code so the only thing left to be checked is
1704                     // that it does not exceed the block size of the hash.
1705                     // by the hash algorithm of the scheme.
1706                     TPMT_KEYEDHASH_SCHEME       *scheme;
1707                     UINT16                       maxSize;
1708                     scheme = &params->keyedHashDetail.scheme;
1709                     if(scheme->scheme == TPM_ALG_XOR)
1710                     {
1711                         maxSize = CryptHashGetBlockSize(scheme->details.xor.hashAlg);
1712                     }
1713                     else if(scheme->scheme == TPM_ALG_HMAC)
1714                     {
1715                         maxSize = CryptHashGetBlockSize(scheme->details.hmac.hashAlg);
1716                     }
1717                     else if(scheme->scheme == TPM_ALG_NULL)
1718                     {
1719                         // Not signing or xor so must be a data block
1720                         maxSize = 128;
1721                     }
1722                     else
1723                         return TPM_RCS_SCHEME + blamePublic;
1724                     if(sensitive->sensitive.bits.t.size > maxSize)
1725                         return TPM_RCS_KEY_SIZE + blameSensitive;
1726                 }
1727                 // If there is a nameAlg, check the binding
1728                 if(publicArea->nameAlg != TPM_ALG_NULL)
1729                 {
1730                     TPM2B_DIGEST            compare;
1731                     if(sensitive->seedValue.t.size != digestSize)
1732                         return TPM_RCS_KEY_SIZE + blameSensitive;
1733 
1734                     CryptComputeSymmetricUnique(publicArea, sensitive, &compare);
1735                     if(!MemoryEqual2B(&unique->sym.b, &compare.b))
1736                         return TPM_RC_BINDING;
1737                 }
1738             }
1739             break;
1740     }
1741     // For a parent, need to check that the seedValue is the correct size for
1742     // protections. It should be at least half the size of the nameAlg
1743     if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)
1744        && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)
1745        && sensitive != NULL
1746        && publicArea->nameAlg != TPM_ALG_NULL)
1747     {
1748         if((sensitive->seedValue.t.size < (digestSize / 2))
1749            || (sensitive->seedValue.t.size > digestSize))
1750             return TPM_RCS_SIZE + blameSensitive;
1751     }
1752     return TPM_RC_SUCCESS;
1753 }
1754 
1755 //*** CryptSelectMac()
1756 // This function is used to set the MAC scheme based on the key parameters and
1757 // the input scheme.
1758 //  Return Type: TPM_RC
1759 //      TPM_RC_SCHEME       the scheme is not a valid mac scheme
1760 //      TPM_RC_TYPE         the input key is not a type that supports a mac
1761 //      TPM_RC_VALUE        the input scheme and the key scheme are not compatible
1762 TPM_RC
CryptSelectMac(TPMT_PUBLIC * publicArea,TPMI_ALG_MAC_SCHEME * inMac)1763 CryptSelectMac(
1764     TPMT_PUBLIC             *publicArea,
1765     TPMI_ALG_MAC_SCHEME     *inMac
1766 )
1767 {
1768     TPM_ALG_ID              macAlg = TPM_ALG_NULL;
1769     switch(publicArea->type)
1770     {
1771         case TPM_ALG_KEYEDHASH:
1772         {
1773             // Local value to keep lines from getting too long
1774             TPMT_KEYEDHASH_SCHEME   *scheme;
1775             scheme = &publicArea->parameters.keyedHashDetail.scheme;
1776             // Expect that the scheme is either HMAC or NULL
1777             if(scheme->scheme != TPM_ALG_NULL)
1778                 macAlg = scheme->details.hmac.hashAlg;
1779             break;
1780         }
1781         case TPM_ALG_SYMCIPHER:
1782         {
1783             TPMT_SYM_DEF_OBJECT     *scheme;
1784             scheme = &publicArea->parameters.symDetail.sym;
1785             // Expect that the scheme is either valid symmetric cipher or NULL
1786             if(scheme->algorithm != TPM_ALG_NULL)
1787                 macAlg = scheme->mode.sym;
1788             break;
1789         }
1790         default:
1791             return TPM_RCS_TYPE;
1792     }
1793     // If the input value is not TPM_ALG_NULL ...
1794     if(*inMac != TPM_ALG_NULL)
1795     {
1796         // ... then either the scheme in the key must be TPM_ALG_NULL or the input
1797         // value must match
1798         if((macAlg != TPM_ALG_NULL) && (*inMac != macAlg))
1799             return TPM_RCS_VALUE;
1800     }
1801     else
1802     {
1803         // Since the input value is TPM_ALG_NULL, then the key value can't be
1804         // TPM_ALG_NULL
1805         if(macAlg == TPM_ALG_NULL)
1806             return TPM_RCS_VALUE;
1807         *inMac = macAlg;
1808     }
1809     if(!CryptMacIsValidForKey(publicArea->type, *inMac, FALSE))
1810         return TPM_RCS_SCHEME;
1811     return TPM_RC_SUCCESS;
1812 }
1813 
1814 //*** CryptMacIsValidForKey()
1815 // Check to see if the key type is compatible with the mac type
1816 BOOL
CryptMacIsValidForKey(TPM_ALG_ID keyType,TPM_ALG_ID macAlg,BOOL flag)1817 CryptMacIsValidForKey(
1818     TPM_ALG_ID          keyType,
1819     TPM_ALG_ID          macAlg,
1820     BOOL                flag
1821 )
1822 {
1823     switch(keyType)
1824     {
1825         case TPM_ALG_KEYEDHASH:
1826             return CryptHashIsValidAlg(macAlg, flag);
1827             break;
1828         case TPM_ALG_SYMCIPHER:
1829             return CryptSmacIsValidAlg(macAlg, flag);
1830             break;
1831         default:
1832             break;
1833     }
1834     return FALSE;
1835 }
1836 
1837 //*** CryptSmacIsValidAlg()
1838 // This function is used to test if an algorithm is a supported SMAC algorithm. It
1839 // needs to be updated as new algorithms are added.
1840 BOOL
CryptSmacIsValidAlg(TPM_ALG_ID alg,BOOL FLAG)1841 CryptSmacIsValidAlg(
1842     TPM_ALG_ID      alg,
1843     BOOL            FLAG        // IN: Indicates if TPM_ALG_NULL is valid
1844 )
1845 {
1846     switch (alg)
1847     {
1848 #if ALG_CMAC
1849         case TPM_ALG_CMAC:
1850             return TRUE;
1851             break;
1852 #endif
1853         case TPM_ALG_NULL:
1854             return FLAG;
1855             break;
1856         default:
1857             return FALSE;
1858     }
1859 }
1860 
1861 //*** CryptSymModeIsValid()
1862 // Function checks to see if an algorithm ID is a valid, symmetric block cipher
1863 // mode for the TPM. If 'flag' is SET, them TPM_ALG_NULL is a valid mode.
1864 // not include the modes used for SMAC
1865 BOOL
CryptSymModeIsValid(TPM_ALG_ID mode,BOOL flag)1866 CryptSymModeIsValid(
1867     TPM_ALG_ID          mode,
1868     BOOL                flag
1869 )
1870 {
1871     switch(mode)
1872     {
1873 #if ALG_CTR
1874         case TPM_ALG_CTR:
1875 #endif // ALG_CTR
1876 #if ALG_OFB
1877         case TPM_ALG_OFB:
1878 #endif // ALG_OFB
1879 #if ALG_CBC
1880         case TPM_ALG_CBC:
1881 #endif // ALG_CBC
1882 #if ALG_CFB
1883         case TPM_ALG_CFB:
1884 #endif // ALG_CFB
1885 #if ALG_ECB
1886         case TPM_ALG_ECB:
1887 #endif // ALG_ECB
1888             return TRUE;
1889         case TPM_ALG_NULL:
1890             return flag;
1891             break;
1892         default:
1893             break;
1894     }
1895     return FALSE;
1896 }
1897 
1898 
1899 
1900