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(¶ms->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 = ¶ms->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