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