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 "InternalRoutines.h" 9 #include "Object_spt_fp.h" 10 #include "Platform.h" 11 // 12 // 13 // 14 // Local Functions 15 // 16 // EqualCryptSet() 17 // 18 // Check if the crypto sets in two public areas are equal 19 // 20 // Error Returns Meaning 21 // 22 // TPM_RC_ASYMMETRIC mismatched parameters 23 // TPM_RC_HASH mismatched name algorithm 24 // TPM_RC_TYPE mismatched type 25 // 26 static TPM_RC 27 EqualCryptSet( 28 TPMT_PUBLIC *publicArea1, // IN: public area 1 29 TPMT_PUBLIC *publicArea2 // IN: public area 2 30 ) 31 { 32 UINT16 size1; 33 UINT16 size2; 34 BYTE params1[sizeof(TPMU_PUBLIC_PARMS)]; 35 BYTE params2[sizeof(TPMU_PUBLIC_PARMS)]; 36 BYTE *buffer; 37 INT32 bufferSize; 38 // Compare name hash 39 if(publicArea1->nameAlg != publicArea2->nameAlg) 40 return TPM_RC_HASH; 41 // Compare algorithm 42 if(publicArea1->type != publicArea2->type) 43 return TPM_RC_TYPE; 44 // TPMU_PUBLIC_PARMS field should be identical 45 buffer = params1; 46 bufferSize = sizeof(TPMU_PUBLIC_PARMS); 47 size1 = TPMU_PUBLIC_PARMS_Marshal(&publicArea1->parameters, &buffer, 48 &bufferSize, publicArea1->type); 49 buffer = params2; 50 bufferSize = sizeof(TPMU_PUBLIC_PARMS); 51 size2 = TPMU_PUBLIC_PARMS_Marshal(&publicArea2->parameters, &buffer, 52 &bufferSize, publicArea2->type); 53 if(size1 != size2 || !MemoryEqual(params1, params2, size1)) 54 return TPM_RC_ASYMMETRIC; 55 return TPM_RC_SUCCESS; 56 } 57 // 58 // 59 // GetIV2BSize() 60 // 61 // Get the size of TPM2B_IV in canonical form that will be append to the start of the sensitive data. It 62 // includes both size of size field and size of iv data 63 // 64 // Return Value Meaning 65 // 66 static UINT16 67 GetIV2BSize( 68 TPM_HANDLE protectorHandle // IN: the protector handle 69 ) 70 { 71 OBJECT *protector = NULL; // Pointer to the protector object 72 TPM_ALG_ID symAlg; 73 // 74 UINT16 keyBits; 75 // Determine the symmetric algorithm and size of key 76 if(protectorHandle == TPM_RH_NULL) 77 { 78 // Use the context encryption algorithm and key size 79 symAlg = CONTEXT_ENCRYPT_ALG; 80 keyBits = CONTEXT_ENCRYPT_KEY_BITS; 81 } 82 else 83 { 84 protector = ObjectGet(protectorHandle); 85 symAlg = protector->publicArea.parameters.asymDetail.symmetric.algorithm; 86 keyBits= protector->publicArea.parameters.asymDetail.symmetric.keyBits.sym; 87 } 88 // The IV size is a UINT16 size field plus the block size of the symmetric 89 // algorithm 90 return sizeof(UINT16) + CryptGetSymmetricBlockSize(symAlg, keyBits); 91 } 92 // 93 // 94 // ComputeProtectionKeyParms() 95 // 96 // This function retrieves the symmetric protection key parameters for the sensitive data The parameters 97 // retrieved from this function include encryption algorithm, key size in bit, and a TPM2B_SYM_KEY 98 // containing the key material as well as the key size in bytes This function is used for any action that 99 // requires encrypting or decrypting of the sensitive area of an object or a credential blob 100 // 101 static void 102 ComputeProtectionKeyParms( 103 TPM_HANDLE protectorHandle, // IN: the protector handle 104 TPM_ALG_ID hashAlg, // IN: hash algorithm for KDFa 105 TPM2B_NAME *name, // IN: name of the object 106 TPM2B_SEED *seedIn, // IN: optional seed for duplication blob. 107 // For non duplication blob, this 108 // parameter should be NULL 109 TPM_ALG_ID *symAlg, // OUT: the symmetric algorithm 110 UINT16 *keyBits, // OUT: the symmetric key size in bits 111 TPM2B_SYM_KEY *symKey // OUT: the symmetric key 112 ) 113 { 114 TPM2B_SEED *seed = NULL; 115 OBJECT *protector = NULL; // Pointer to the protector 116 // Determine the algorithms for the KDF and the encryption/decryption 117 // For TPM_RH_NULL, using context settings 118 if(protectorHandle == TPM_RH_NULL) 119 { 120 // Use the context encryption algorithm and key size 121 *symAlg = CONTEXT_ENCRYPT_ALG; 122 symKey->t.size = CONTEXT_ENCRYPT_KEY_BYTES; 123 *keyBits = CONTEXT_ENCRYPT_KEY_BITS; 124 } 125 else 126 { 127 TPMT_SYM_DEF_OBJECT *symDef; 128 protector = ObjectGet(protectorHandle); 129 symDef = &protector->publicArea.parameters.asymDetail.symmetric; 130 *symAlg = symDef->algorithm; 131 *keyBits= symDef->keyBits.sym; 132 symKey->t.size = (*keyBits + 7) / 8; 133 } 134 // Get seed for KDF 135 seed = GetSeedForKDF(protectorHandle, seedIn); 136 // KDFa to generate symmetric key and IV value 137 KDFa(hashAlg, (TPM2B *)seed, "STORAGE", (TPM2B *)name, NULL, 138 symKey->t.size * 8, symKey->t.buffer, NULL); 139 return; 140 } 141 // 142 // 143 // ComputeOuterIntegrity() 144 // 145 // The sensitive area parameter is a buffer that holds a space for the integrity value and the marshaled 146 // sensitive area. The caller should skip over the area set aside for the integrity value and compute the hash 147 // of the remainder of the object. The size field of sensitive is in unmarshaled form and the sensitive area 148 // contents is an array of bytes. 149 // 150 static void 151 ComputeOuterIntegrity( 152 TPM2B_NAME *name, // IN: the name of the object 153 TPM_HANDLE protectorHandle, // IN: The handle of the object that 154 // provides protection. For object, it 155 // is parent handle. For credential, it 156 // is the handle of encrypt object. For 157 // a Temporary Object, it is TPM_RH_NULL 158 TPMI_ALG_HASH hashAlg, // IN: algorithm to use for integrity 159 TPM2B_SEED *seedIn, // IN: an external seed may be provided for 160 // duplication blob. For non duplication 161 // blob, this parameter should be NULL 162 UINT32 sensitiveSize, // IN: size of the marshaled sensitive data 163 BYTE *sensitiveData, // IN: sensitive area 164 TPM2B_DIGEST *integrity // OUT: integrity 165 ) 166 { 167 HMAC_STATE hmacState; 168 TPM2B_DIGEST hmacKey; 169 TPM2B_SEED *seed = NULL; 170 // Get seed for KDF 171 seed = GetSeedForKDF(protectorHandle, seedIn); 172 // Determine the HMAC key bits 173 hmacKey.t.size = CryptGetHashDigestSize(hashAlg); 174 // KDFa to generate HMAC key 175 KDFa(hashAlg, (TPM2B *)seed, "INTEGRITY", NULL, NULL, 176 hmacKey.t.size * 8, hmacKey.t.buffer, NULL); 177 // Start HMAC and get the size of the digest which will become the integrity 178 integrity->t.size = CryptStartHMAC2B(hashAlg, &hmacKey.b, &hmacState); 179 // Adding the marshaled sensitive area to the integrity value 180 CryptUpdateDigest(&hmacState, sensitiveSize, sensitiveData); 181 // Adding name 182 CryptUpdateDigest2B(&hmacState, (TPM2B *)name); 183 // Compute HMAC 184 CryptCompleteHMAC2B(&hmacState, &integrity->b); 185 return; 186 } 187 // 188 // 189 // ComputeInnerIntegrity() 190 // 191 // This function computes the integrity of an inner wrap 192 // 193 static void 194 ComputeInnerIntegrity( 195 TPM_ALG_ID hashAlg, // IN: hash algorithm for inner wrap 196 TPM2B_NAME *name, // IN: the name of the object 197 UINT16 dataSize, // IN: the size of sensitive data 198 BYTE *sensitiveData, // IN: sensitive data 199 TPM2B_DIGEST *integrity // OUT: inner integrity 200 ) 201 { 202 HASH_STATE hashState; 203 // Start hash and get the size of the digest which will become the integrity 204 integrity->t.size = CryptStartHash(hashAlg, &hashState); 205 // Adding the marshaled sensitive area to the integrity value 206 CryptUpdateDigest(&hashState, dataSize, sensitiveData); 207 // Adding name 208 CryptUpdateDigest2B(&hashState, &name->b); 209 // Compute hash 210 CryptCompleteHash2B(&hashState, &integrity->b); 211 return; 212 } 213 // 214 // 215 // ProduceInnerIntegrity() 216 // 217 // This function produces an inner integrity for regular private, credential or duplication blob It requires the 218 // sensitive data being marshaled to the innerBuffer, with the leading bytes reserved for integrity hash. It 219 // assume the sensitive data starts at address (innerBuffer + integrity size). This function integrity at the 220 // beginning of the inner buffer It returns the total size of buffer with the inner wrap 221 // 222 static UINT16 223 ProduceInnerIntegrity( 224 TPM2B_NAME *name, // IN: the name of the object 225 TPM_ALG_ID hashAlg, // IN: hash algorithm for inner wrap 226 UINT16 dataSize, // IN: the size of sensitive data, excluding the 227 // leading integrity buffer size 228 BYTE *innerBuffer // IN/OUT: inner buffer with sensitive data in 229 // it. At input, the leading bytes of this 230 // buffer is reserved for integrity 231 ) 232 { 233 BYTE *sensitiveData; // pointer to the sensitive data 234 TPM2B_DIGEST integrity; 235 UINT16 integritySize; 236 BYTE *buffer; // Auxiliary buffer pointer 237 INT32 bufferSize; 238 // sensitiveData points to the beginning of sensitive data in innerBuffer 239 integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg); 240 sensitiveData = innerBuffer + integritySize; 241 ComputeInnerIntegrity(hashAlg, name, dataSize, sensitiveData, &integrity); 242 // Add integrity at the beginning of inner buffer 243 buffer = innerBuffer; 244 bufferSize = sizeof(TPM2B_DIGEST); 245 TPM2B_DIGEST_Marshal(&integrity, &buffer, &bufferSize); 246 return dataSize + integritySize; 247 } 248 // 249 // 250 // CheckInnerIntegrity() 251 // 252 // This function check integrity of inner blob 253 // 254 // Error Returns Meaning 255 // 256 // TPM_RC_INTEGRITY if the outer blob integrity is bad 257 // unmarshal errors unmarshal errors while unmarshaling integrity 258 // 259 static TPM_RC 260 CheckInnerIntegrity( 261 TPM2B_NAME *name, // IN: the name of the object 262 TPM_ALG_ID hashAlg, // IN: hash algorithm for inner wrap 263 UINT16 dataSize, // IN: the size of sensitive data, including the 264 // leading integrity buffer size 265 BYTE *innerBuffer // IN/OUT: inner buffer with sensitive data in 266 // it 267 ) 268 { 269 TPM_RC result; 270 TPM2B_DIGEST integrity; 271 TPM2B_DIGEST integrityToCompare; 272 BYTE *buffer; // Auxiliary buffer pointer 273 INT32 size; 274 // Unmarshal integrity 275 buffer = innerBuffer; 276 size = (INT32) dataSize; 277 result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size); 278 if(result == TPM_RC_SUCCESS) 279 { 280 // Compute integrity to compare 281 ComputeInnerIntegrity(hashAlg, name, (UINT16) size, buffer, 282 &integrityToCompare); 283 // Compare outer blob integrity 284 if(!Memory2BEqual(&integrity.b, &integrityToCompare.b)) 285 result = TPM_RC_INTEGRITY; 286 } 287 return result; 288 } 289 // 290 // 291 // Public Functions 292 // 293 // AreAttributesForParent() 294 // 295 // This function is called by create, load, and import functions. 296 // 297 // Return Value Meaning 298 // 299 // TRUE properties are those of a parent 300 // FALSE properties are not those of a parent 301 // 302 BOOL 303 AreAttributesForParent( 304 OBJECT *parentObject // IN: parent handle 305 ) 306 { 307 // This function is only called when a parent is needed. Any 308 // time a "parent" is used, it must be authorized. When 309 // the authorization is checked, both the public and sensitive 310 // areas must be loaded. Just make sure... 311 pAssert(parentObject->attributes.publicOnly == CLEAR); 312 if(ObjectDataIsStorage(&parentObject->publicArea)) 313 return TRUE; 314 else 315 return FALSE; 316 } 317 // 318 // 319 // SchemeChecks() 320 // 321 // This function validates the schemes in the public area of an object. This function is called by 322 // TPM2_LoadExternal() and PublicAttributesValidation(). 323 // 324 // Error Returns Meaning 325 // 326 // TPM_RC_ASYMMETRIC non-duplicable storage key and its parent have different public 327 // parameters 328 // TPM_RC_ATTRIBUTES attempt to inject sensitive data for an asymmetric key; or attempt to 329 // create a symmetric cipher key that is not a decryption key 330 // TPM_RC_HASH non-duplicable storage key and its parent have different name 331 // algorithm 332 // TPM_RC_KDF incorrect KDF specified for decrypting keyed hash object 333 // TPM_RC_KEY invalid key size values in an asymmetric key public area 334 // TPM_RC_SCHEME inconsistent attributes decrypt, sign, restricted and key's scheme ID; 335 // or hash algorithm is inconsistent with the scheme ID for keyed hash 336 // object 337 // TPM_RC_SYMMETRIC a storage key with no symmetric algorithm specified; or non-storage 338 // key with symmetric algorithm different from TPM_ALG_NULL 339 // TPM_RC_TYPE unexpected object type; or non-duplicable storage key and its parent 340 // have different types 341 // 342 TPM_RC 343 SchemeChecks( 344 BOOL load, // IN: TRUE if load checks, FALSE if 345 // TPM2_Create() 346 TPMI_DH_OBJECT parentHandle, // IN: input parent handle 347 TPMT_PUBLIC *publicArea // IN: public area of the object 348 ) 349 { 350 // Checks for an asymmetric key 351 if(CryptIsAsymAlgorithm(publicArea->type)) 352 { 353 TPMT_ASYM_SCHEME *keyScheme; 354 keyScheme = &publicArea->parameters.asymDetail.scheme; 355 // An asymmetric key can't be injected 356 // This is only checked when creating an object 357 if(!load && (publicArea->objectAttributes.sensitiveDataOrigin == CLEAR)) 358 return TPM_RC_ATTRIBUTES; 359 if(load && !CryptAreKeySizesConsistent(publicArea)) 360 return TPM_RC_KEY; 361 // Keys that are both signing and decrypting must have TPM_ALG_NULL 362 // for scheme 363 if( publicArea->objectAttributes.sign == SET 364 && publicArea->objectAttributes.decrypt == SET 365 && keyScheme->scheme != TPM_ALG_NULL) 366 return TPM_RC_SCHEME; 367 // A restrict sign key must have a non-NULL scheme 368 if( publicArea->objectAttributes.restricted == SET 369 && publicArea->objectAttributes.sign == SET 370 && keyScheme->scheme == TPM_ALG_NULL) 371 return TPM_RC_SCHEME; 372 // Keys must have a valid sign or decrypt scheme, or a TPM_ALG_NULL 373 // scheme 374 // NOTE: The unmarshaling for a public area will unmarshal based on the 375 // object type. If the type is an RSA key, then only RSA schemes will be 376 // allowed because a TPMI_ALG_RSA_SCHEME will be unmarshaled and it 377 // consists only of those algorithms that are allowed with an RSA key. 378 // This means that there is no need to again make sure that the algorithm 379 // is compatible with the object type. 380 if( keyScheme->scheme != TPM_ALG_NULL 381 && ( ( publicArea->objectAttributes.sign == SET 382 && !CryptIsSignScheme(keyScheme->scheme) 383 ) 384 || ( publicArea->objectAttributes.decrypt == SET 385 && !CryptIsDecryptScheme(keyScheme->scheme) 386 ) 387 ) 388 ) 389 return TPM_RC_SCHEME; 390 // Special checks for an ECC key 391 #ifdef TPM_ALG_ECC 392 if(publicArea->type == TPM_ALG_ECC) 393 { 394 TPM_ECC_CURVE curveID = publicArea->parameters.eccDetail.curveID; 395 const TPMT_ECC_SCHEME *curveScheme = CryptGetCurveSignScheme(curveID); 396 // The curveId must be valid or the unmarshaling is busted. 397 pAssert(curveScheme != NULL); 398 // If the curveID requires a specific scheme, then the key must select 399 // the same scheme 400 if(curveScheme->scheme != TPM_ALG_NULL) 401 { 402 if(keyScheme->scheme != curveScheme->scheme) 403 return TPM_RC_SCHEME; 404 // The scheme can allow any hash, or not... 405 if( curveScheme->details.anySig.hashAlg != TPM_ALG_NULL 406 && ( keyScheme->details.anySig.hashAlg 407 != curveScheme->details.anySig.hashAlg 408 ) 409 ) 410 return TPM_RC_SCHEME; 411 } 412 // For now, the KDF must be TPM_ALG_NULL 413 if(publicArea->parameters.eccDetail.kdf.scheme != TPM_ALG_NULL) 414 return TPM_RC_KDF; 415 } 416 #endif 417 // Checks for a storage key (restricted + decryption) 418 if( publicArea->objectAttributes.restricted == SET 419 && publicArea->objectAttributes.decrypt == SET) 420 { 421 // A storage key must have a valid protection key 422 if( publicArea->parameters.asymDetail.symmetric.algorithm 423 == TPM_ALG_NULL) 424 return TPM_RC_SYMMETRIC; 425 // A storage key must have a null scheme 426 if(publicArea->parameters.asymDetail.scheme.scheme != TPM_ALG_NULL) 427 return TPM_RC_SCHEME; 428 // A storage key must match its parent algorithms unless 429 // it is duplicable or a primary (including Temporary Primary Objects) 430 if( HandleGetType(parentHandle) != TPM_HT_PERMANENT 431 && publicArea->objectAttributes.fixedParent == SET 432 ) 433 { 434 // If the object to be created is a storage key, and is fixedParent, 435 // its crypto set has to match its parent's crypto set. TPM_RC_TYPE, 436 // TPM_RC_HASH or TPM_RC_ASYMMETRIC may be returned at this point 437 return EqualCryptSet(publicArea, 438 &(ObjectGet(parentHandle)->publicArea)); 439 } 440 } 441 else 442 { 443 // Non-storage keys must have TPM_ALG_NULL for the symmetric algorithm 444 if( publicArea->parameters.asymDetail.symmetric.algorithm 445 != TPM_ALG_NULL) 446 return TPM_RC_SYMMETRIC; 447 }// End of asymmetric decryption key checks 448 } // End of asymmetric checks 449 // Check for bit attributes 450 else if(publicArea->type == TPM_ALG_KEYEDHASH) 451 { 452 TPMT_KEYEDHASH_SCHEME *scheme 453 = &publicArea->parameters.keyedHashDetail.scheme; 454 // If both sign and decrypt are set the scheme must be TPM_ALG_NULL 455 // and the scheme selected when the key is used. 456 // If neither sign nor decrypt is set, the scheme must be TPM_ALG_NULL 457 // because this is a data object. 458 if( publicArea->objectAttributes.sign 459 == publicArea->objectAttributes.decrypt) 460 { 461 if(scheme->scheme != TPM_ALG_NULL) 462 return TPM_RC_SCHEME; 463 return TPM_RC_SUCCESS; 464 } 465 // If this is a decryption key, make sure that is is XOR and that there 466 // is a KDF 467 else if(publicArea->objectAttributes.decrypt) 468 { 469 if( scheme->scheme != TPM_ALG_XOR 470 || scheme->details.xor_.hashAlg == TPM_ALG_NULL) 471 return TPM_RC_SCHEME; 472 if(scheme->details.xor_.kdf == TPM_ALG_NULL) 473 return TPM_RC_KDF; 474 return TPM_RC_SUCCESS; 475 } 476 // only supported signing scheme for keyedHash object is HMAC 477 if( scheme->scheme != TPM_ALG_HMAC 478 || scheme->details.hmac.hashAlg == TPM_ALG_NULL) 479 return TPM_RC_SCHEME; 480 // end of the checks for keyedHash 481 return TPM_RC_SUCCESS; 482 } 483 else if (publicArea->type == TPM_ALG_SYMCIPHER) 484 { 485 // Must be a decrypting key and may not be a signing key 486 if( publicArea->objectAttributes.decrypt == CLEAR 487 || publicArea->objectAttributes.sign == SET 488 ) 489 return TPM_RC_ATTRIBUTES; 490 } 491 else 492 return TPM_RC_TYPE; 493 return TPM_RC_SUCCESS; 494 } 495 // 496 // 497 // PublicAttributesValidation() 498 // 499 // This function validates the values in the public area of an object. This function is called by 500 // TPM2_Create(), TPM2_Load(), and TPM2_CreatePrimary() 501 // 502 // Error Returns Meaning 503 // 504 // TPM_RC_ASYMMETRIC non-duplicable storage key and its parent have different public 505 // parameters 506 // TPM_RC_ATTRIBUTES fixedTPM, fixedParent, or encryptedDuplication attributes are 507 // inconsistent between themselves or with those of the parent object; 508 // inconsistent restricted, decrypt and sign attributes; attempt to inject 509 // sensitive data for an asymmetric key; attempt to create a symmetric 510 // cipher key that is not a decryption key 511 // TPM_RC_HASH non-duplicable storage key and its parent have different name 512 // algorithm 513 // TPM_RC_KDF incorrect KDF specified for decrypting keyed hash object 514 // TPM_RC_KEY invalid key size values in an asymmetric key public area 515 // TPM_RC_SCHEME inconsistent attributes decrypt, sign, restricted and key's scheme ID; 516 // or hash algorithm is inconsistent with the scheme ID for keyed hash 517 // object 518 // TPM_RC_SIZE authPolicy size does not match digest size of the name algorithm in 519 // publicArea 520 // TPM_RC_SYMMETRIC a storage key with no symmetric algorithm specified; or non-storage 521 // key with symmetric algorithm different from TPM_ALG_NULL 522 // TPM_RC_TYPE unexpected object type; or non-duplicable storage key and its parent 523 // have different types 524 // 525 TPM_RC 526 PublicAttributesValidation( 527 BOOL load, // IN: TRUE if load checks, FALSE if 528 // TPM2_Create() 529 TPMI_DH_OBJECT parentHandle, // IN: input parent handle 530 TPMT_PUBLIC *publicArea // IN: public area of the object 531 ) 532 { 533 OBJECT *parentObject = NULL; 534 if(HandleGetType(parentHandle) != TPM_HT_PERMANENT) 535 parentObject = ObjectGet(parentHandle); 536 if (publicArea->nameAlg == TPM_ALG_NULL) 537 return TPM_RC_HASH; 538 // Check authPolicy digest consistency 539 if( publicArea->authPolicy.t.size != 0 540 && ( publicArea->authPolicy.t.size 541 != CryptGetHashDigestSize(publicArea->nameAlg) 542 ) 543 ) 544 return TPM_RC_SIZE; 545 // If the parent is fixedTPM (including a Primary Object) the object must have 546 // the same value for fixedTPM and fixedParent 547 if( parentObject == NULL 548 || parentObject->publicArea.objectAttributes.fixedTPM == SET) 549 { 550 if( publicArea->objectAttributes.fixedParent 551 != publicArea->objectAttributes.fixedTPM 552 ) 553 return TPM_RC_ATTRIBUTES; 554 } 555 else 556 // The parent is not fixedTPM so the object can't be fixedTPM 557 if(publicArea->objectAttributes.fixedTPM == SET) 558 return TPM_RC_ATTRIBUTES; 559 // A restricted object cannot be both sign and decrypt and it can't be neither 560 // sign nor decrypt 561 if ( publicArea->objectAttributes.restricted == SET 562 && ( publicArea->objectAttributes.decrypt 563 == publicArea->objectAttributes.sign) 564 ) 565 return TPM_RC_ATTRIBUTES; 566 // A fixedTPM object can not have encryptedDuplication bit SET 567 if( publicArea->objectAttributes.fixedTPM == SET 568 && publicArea->objectAttributes.encryptedDuplication == SET) 569 return TPM_RC_ATTRIBUTES; 570 // If a parent object has fixedTPM CLEAR, the child must have the 571 // same encryptedDuplication value as its parent. 572 // Primary objects are considered to have a fixedTPM parent (the seeds). 573 if( ( parentObject != NULL 574 && parentObject->publicArea.objectAttributes.fixedTPM == CLEAR) 575 // Get here if parent is not fixed TPM 576 && ( publicArea->objectAttributes.encryptedDuplication 577 != parentObject->publicArea.objectAttributes.encryptedDuplication 578 ) 579 ) 580 return TPM_RC_ATTRIBUTES; 581 return SchemeChecks(load, parentHandle, publicArea); 582 } 583 // 584 // 585 // FillInCreationData() 586 // 587 // Fill in creation data for an object. 588 // 589 void 590 FillInCreationData( 591 TPMI_DH_OBJECT parentHandle, // IN: handle of parent 592 TPMI_ALG_HASH nameHashAlg, // IN: name hash algorithm 593 TPML_PCR_SELECTION *creationPCR, // IN: PCR selection 594 TPM2B_DATA *outsideData, // IN: outside data 595 TPM2B_CREATION_DATA *outCreation, // OUT: creation data for output 596 TPM2B_DIGEST *creationDigest // OUT: creation digest 597 // 598 ) 599 { 600 BYTE creationBuffer[sizeof(TPMS_CREATION_DATA)]; 601 BYTE *buffer; 602 INT32 bufferSize; 603 HASH_STATE hashState; 604 // Fill in TPMS_CREATION_DATA in outCreation 605 // Compute PCR digest 606 PCRComputeCurrentDigest(nameHashAlg, creationPCR, 607 &outCreation->t.creationData.pcrDigest); 608 // Put back PCR selection list 609 outCreation->t.creationData.pcrSelect = *creationPCR; 610 // Get locality 611 outCreation->t.creationData.locality 612 = LocalityGetAttributes(_plat__LocalityGet()); 613 outCreation->t.creationData.parentNameAlg = TPM_ALG_NULL; 614 // If the parent is is either a primary seed or TPM_ALG_NULL, then the Name 615 // and QN of the parent are the parent's handle. 616 if(HandleGetType(parentHandle) == TPM_HT_PERMANENT) 617 { 618 BYTE *buffer = &outCreation->t.creationData.parentName.t.name[0]; 619 INT32 bufferSize = sizeof(TPM_HANDLE); 620 outCreation->t.creationData.parentName.t.size = 621 TPM_HANDLE_Marshal(&parentHandle, &buffer, &bufferSize); 622 // Parent qualified name of a Temporary Object is the same as parent's 623 // name 624 MemoryCopy2B(&outCreation->t.creationData.parentQualifiedName.b, 625 &outCreation->t.creationData.parentName.b, 626 sizeof(outCreation->t.creationData.parentQualifiedName.t.name)); 627 } 628 else // Regular object 629 { 630 OBJECT *parentObject = ObjectGet(parentHandle); 631 // Set name algorithm 632 outCreation->t.creationData.parentNameAlg = 633 parentObject->publicArea.nameAlg; 634 // Copy parent name 635 outCreation->t.creationData.parentName = parentObject->name; 636 // Copy parent qualified name 637 outCreation->t.creationData.parentQualifiedName = 638 parentObject->qualifiedName; 639 } 640 // Copy outside information 641 outCreation->t.creationData.outsideInfo = *outsideData; 642 // Marshal creation data to canonical form 643 buffer = creationBuffer; 644 bufferSize = sizeof(TPMS_CREATION_DATA); 645 outCreation->t.size = TPMS_CREATION_DATA_Marshal(&outCreation->t.creationData, 646 &buffer, &bufferSize); 647 // Compute hash for creation field in public template 648 creationDigest->t.size = CryptStartHash(nameHashAlg, &hashState); 649 CryptUpdateDigest(&hashState, outCreation->t.size, creationBuffer); 650 CryptCompleteHash2B(&hashState, &creationDigest->b); 651 return; 652 } 653 // GetSeedForKDF() 654 // 655 // Get a seed for KDF. The KDF for encryption and HMAC key use the same seed. It returns a pointer to 656 // the seed 657 // 658 TPM2B_SEED* 659 GetSeedForKDF( 660 TPM_HANDLE protectorHandle, // IN: the protector handle 661 TPM2B_SEED *seedIn // IN: the optional input seed 662 ) 663 { 664 OBJECT *protector = NULL; // Pointer to the protector 665 // Get seed for encryption key. Use input seed if provided. 666 // Otherwise, using protector object's seedValue. TPM_RH_NULL is the only 667 // exception that we may not have a loaded object as protector. In such a 668 // case, use nullProof as seed. 669 if(seedIn != NULL) 670 { 671 return seedIn; 672 } 673 else 674 { 675 if(protectorHandle == TPM_RH_NULL) 676 { 677 return (TPM2B_SEED *) &gr.nullProof; 678 } 679 else 680 { 681 protector = ObjectGet(protectorHandle); 682 return (TPM2B_SEED *) &protector->sensitive.seedValue; 683 } 684 } 685 } 686 // 687 // 688 // ProduceOuterWrap() 689 // 690 // This function produce outer wrap for a buffer containing the sensitive data. It requires the sensitive data 691 // being marshaled to the outerBuffer, with the leading bytes reserved for integrity hash. If iv is used, iv 692 // space should be reserved at the beginning of the buffer. It assumes the sensitive data starts at address 693 // (outerBuffer + integrity size {+ iv size}). This function performs: 694 // a) Add IV before sensitive area if required 695 // b) encrypt sensitive data, if iv is required, encrypt by iv. otherwise, encrypted by a NULL iv 696 // c) add HMAC integrity at the beginning of the buffer It returns the total size of blob with outer wrap 697 // 698 UINT16 699 ProduceOuterWrap( 700 TPM_HANDLE protector, // IN: The handle of the object that provides 701 // protection. For object, it is parent 702 // handle. For credential, it is the handle 703 // of encrypt object. 704 TPM2B_NAME *name, // IN: the name of the object 705 TPM_ALG_ID hashAlg, // IN: hash algorithm for outer wrap 706 TPM2B_SEED *seed, // IN: an external seed may be provided for 707 // duplication blob. For non duplication 708 // blob, this parameter should be NULL 709 BOOL useIV, // IN: indicate if an IV is used 710 UINT16 dataSize, // IN: the size of sensitive data, excluding the 711 // leading integrity buffer size or the 712 // optional iv size 713 BYTE *outerBuffer // IN/OUT: outer buffer with sensitive data in 714 // it 715 ) 716 { 717 TPM_ALG_ID symAlg; 718 UINT16 keyBits; 719 TPM2B_SYM_KEY symKey; 720 TPM2B_IV ivRNG; // IV from RNG 721 TPM2B_IV *iv = NULL; 722 UINT16 ivSize = 0; // size of iv area, including the size field 723 BYTE *sensitiveData; // pointer to the sensitive data 724 TPM2B_DIGEST integrity; 725 UINT16 integritySize; 726 BYTE *buffer; // Auxiliary buffer pointer 727 INT32 bufferSize; 728 // Compute the beginning of sensitive data. The outer integrity should 729 // always exist if this function function is called to make an outer wrap 730 integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg); 731 sensitiveData = outerBuffer + integritySize; 732 // If iv is used, adjust the pointer of sensitive data and add iv before it 733 if(useIV) 734 { 735 ivSize = GetIV2BSize(protector); 736 // Generate IV from RNG. The iv data size should be the total IV area 737 // size minus the size of size field 738 ivRNG.t.size = ivSize - sizeof(UINT16); 739 CryptGenerateRandom(ivRNG.t.size, ivRNG.t.buffer); 740 // Marshal IV to buffer 741 buffer = sensitiveData; 742 bufferSize = sizeof(TPM2B_IV); 743 TPM2B_IV_Marshal(&ivRNG, &buffer, &bufferSize); 744 // adjust sensitive data starting after IV area 745 sensitiveData += ivSize; 746 // Use iv for encryption 747 iv = &ivRNG; 748 } 749 // Compute symmetric key parameters for outer buffer encryption 750 ComputeProtectionKeyParms(protector, hashAlg, name, seed, 751 &symAlg, &keyBits, &symKey); 752 // Encrypt inner buffer in place 753 CryptSymmetricEncrypt(sensitiveData, symAlg, keyBits, 754 TPM_ALG_CFB, symKey.t.buffer, iv, dataSize, 755 sensitiveData); 756 // Compute outer integrity. Integrity computation includes the optional IV 757 // area 758 ComputeOuterIntegrity(name, protector, hashAlg, seed, dataSize + ivSize, 759 outerBuffer + integritySize, &integrity); 760 // Add integrity at the beginning of outer buffer 761 buffer = outerBuffer; 762 bufferSize = sizeof(TPM2B_DIGEST); 763 TPM2B_DIGEST_Marshal(&integrity, &buffer, &bufferSize); 764 // return the total size in outer wrap 765 return dataSize + integritySize + ivSize; 766 } 767 // 768 // 769 // 770 // UnwrapOuter() 771 // 772 // This function remove the outer wrap of a blob containing sensitive data This function performs: 773 // a) check integrity of outer blob 774 // b) decrypt outer blob 775 // 776 // Error Returns Meaning 777 // 778 // TPM_RC_INSUFFICIENT error during sensitive data unmarshaling 779 // TPM_RC_INTEGRITY sensitive data integrity is broken 780 // TPM_RC_SIZE error during sensitive data unmarshaling 781 // TPM_RC_VALUE IV size for CFB does not match the encryption algorithm block size 782 // 783 TPM_RC 784 UnwrapOuter( 785 TPM_HANDLE protector, // IN: The handle of the object that provides 786 // protection. For object, it is parent 787 // handle. For credential, it is the handle 788 // of encrypt object. 789 TPM2B_NAME *name, // IN: the name of the object 790 TPM_ALG_ID hashAlg, // IN: hash algorithm for outer wrap 791 TPM2B_SEED *seed, // IN: an external seed may be provided for 792 // duplication blob. For non duplication 793 // blob, this parameter should be NULL. 794 BOOL useIV, // IN: indicates if an IV is used 795 UINT16 dataSize, // IN: size of sensitive data in outerBuffer, 796 // including the leading integrity buffer 797 // size, and an optional iv area 798 BYTE *outerBuffer // IN/OUT: sensitive data 799 ) 800 { 801 TPM_RC result; 802 TPM_ALG_ID symAlg = TPM_ALG_NULL; 803 TPM2B_SYM_KEY symKey; 804 UINT16 keyBits = 0; 805 TPM2B_IV ivIn; // input IV retrieved from input buffer 806 TPM2B_IV *iv = NULL; 807 BYTE *sensitiveData; // pointer to the sensitive data 808 TPM2B_DIGEST integrityToCompare; 809 TPM2B_DIGEST integrity; 810 INT32 size; 811 // Unmarshal integrity 812 sensitiveData = outerBuffer; 813 size = (INT32) dataSize; 814 result = TPM2B_DIGEST_Unmarshal(&integrity, &sensitiveData, &size); 815 if(result == TPM_RC_SUCCESS) 816 { 817 // Compute integrity to compare 818 ComputeOuterIntegrity(name, protector, hashAlg, seed, 819 (UINT16) size, sensitiveData, 820 &integrityToCompare); 821 // Compare outer blob integrity 822 if(!Memory2BEqual(&integrity.b, &integrityToCompare.b)) 823 return TPM_RC_INTEGRITY; 824 // Get the symmetric algorithm parameters used for encryption 825 ComputeProtectionKeyParms(protector, hashAlg, name, seed, 826 &symAlg, &keyBits, &symKey); 827 // Retrieve IV if it is used 828 if(useIV) 829 { 830 result = TPM2B_IV_Unmarshal(&ivIn, &sensitiveData, &size); 831 if(result == TPM_RC_SUCCESS) 832 { 833 // The input iv size for CFB must match the encryption algorithm 834 // block size 835 if(ivIn.t.size != CryptGetSymmetricBlockSize(symAlg, keyBits)) 836 result = TPM_RC_VALUE; 837 else 838 iv = &ivIn; 839 } 840 } 841 } 842 // If no errors, decrypt private in place 843 if(result == TPM_RC_SUCCESS) 844 CryptSymmetricDecrypt(sensitiveData, symAlg, keyBits, 845 TPM_ALG_CFB, symKey.t.buffer, iv, 846 (UINT16) size, sensitiveData); 847 return result; 848 } 849 // 850 // 851 // SensitiveToPrivate() 852 // 853 // This function prepare the private blob for off the chip storage The operations in this function: 854 // a) marshal TPM2B_SENSITIVE structure into the buffer of TPM2B_PRIVATE 855 // b) apply encryption to the sensitive area. 856 // c) apply outer integrity computation. 857 // 858 void 859 SensitiveToPrivate( 860 TPMT_SENSITIVE *sensitive, // IN: sensitive structure 861 TPM2B_NAME *name, // IN: the name of the object 862 TPM_HANDLE parentHandle, // IN: The parent's handle 863 TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. This 864 // parameter is used when parentHandle is 865 // NULL, in which case the object is 866 // temporary. 867 TPM2B_PRIVATE *outPrivate // OUT: output private structure 868 ) 869 { 870 BYTE *buffer; // Auxiliary buffer pointer 871 INT32 bufferSize; 872 BYTE *sensitiveData; // pointer to the sensitive data 873 UINT16 dataSize; // data blob size 874 TPMI_ALG_HASH hashAlg; // hash algorithm for integrity 875 UINT16 integritySize; 876 UINT16 ivSize; 877 pAssert(name != NULL && name->t.size != 0); 878 // Find the hash algorithm for integrity computation 879 if(parentHandle == TPM_RH_NULL) 880 { 881 // For Temporary Object, using self name algorithm 882 hashAlg = nameAlg; 883 } 884 else 885 { 886 // Otherwise, using parent's name algorithm 887 hashAlg = ObjectGetNameAlg(parentHandle); 888 } 889 // Starting of sensitive data without wrappers 890 sensitiveData = outPrivate->t.buffer; 891 // Compute the integrity size 892 integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg); 893 // Reserve space for integrity 894 sensitiveData += integritySize; 895 // Get iv size 896 ivSize = GetIV2BSize(parentHandle); 897 // Reserve space for iv 898 sensitiveData += ivSize; 899 // Marshal sensitive area, leaving the leading 2 bytes for size 900 buffer = sensitiveData + sizeof(UINT16); 901 bufferSize = sizeof(TPMT_SENSITIVE); 902 dataSize = TPMT_SENSITIVE_Marshal(sensitive, &buffer, &bufferSize); 903 // Adding size before the data area 904 buffer = sensitiveData; 905 bufferSize = sizeof(UINT16); 906 UINT16_Marshal(&dataSize, &buffer, &bufferSize); 907 // Adjust the dataSize to include the size field 908 dataSize += sizeof(UINT16); 909 // Adjust the pointer to inner buffer including the iv 910 sensitiveData = outPrivate->t.buffer + ivSize; 911 //Produce outer wrap, including encryption and HMAC 912 outPrivate->t.size = ProduceOuterWrap(parentHandle, name, hashAlg, NULL, 913 TRUE, dataSize, outPrivate->t.buffer); 914 return; 915 } 916 // 917 // 918 // PrivateToSensitive() 919 // 920 // Unwrap a input private area. Check the integrity, decrypt and retrieve data to a sensitive structure. The 921 // operations in this function: 922 // a) check the integrity HMAC of the input private area 923 // b) decrypt the private buffer 924 // c) unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE 925 // 926 // Error Returns Meaning 927 // 928 // TPM_RC_INTEGRITY if the private area integrity is bad 929 // TPM_RC_SENSITIVE unmarshal errors while unmarshaling TPMS_ENCRYPT from input 930 // private 931 // TPM_RC_VALUE outer wrapper does not have an iV of the correct size 932 // 933 TPM_RC 934 PrivateToSensitive( 935 TPM2B_PRIVATE *inPrivate, // IN: input private structure 936 TPM2B_NAME *name, // IN: the name of the object 937 TPM_HANDLE parentHandle, // IN: The parent's handle 938 TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. It is 939 // passed separately because we only pass 940 // name, rather than the whole public area 941 // of the object. This parameter is used in 942 // the following two cases: 1. primary 943 // objects. 2. duplication blob with inner 944 // wrap. In other cases, this parameter 945 // will be ignored 946 TPMT_SENSITIVE *sensitive // OUT: sensitive structure 947 ) 948 { 949 TPM_RC result; 950 BYTE *buffer; 951 INT32 size; 952 BYTE *sensitiveData; // pointer to the sensitive data 953 UINT16 dataSize; 954 UINT16 dataSizeInput; 955 TPMI_ALG_HASH hashAlg; // hash algorithm for integrity 956 OBJECT *parent = NULL; 957 UINT16 integritySize; 958 UINT16 ivSize; 959 // Make sure that name is provided 960 pAssert(name != NULL && name->t.size != 0); 961 // Find the hash algorithm for integrity computation 962 if(parentHandle == TPM_RH_NULL) 963 { 964 // For Temporary Object, using self name algorithm 965 hashAlg = nameAlg; 966 } 967 else 968 { 969 // Otherwise, using parent's name algorithm 970 hashAlg = ObjectGetNameAlg(parentHandle); 971 } 972 // unwrap outer 973 result = UnwrapOuter(parentHandle, name, hashAlg, NULL, TRUE, 974 inPrivate->t.size, inPrivate->t.buffer); 975 if(result != TPM_RC_SUCCESS) 976 return result; 977 // Compute the inner integrity size. 978 integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg); 979 // Get iv size 980 ivSize = GetIV2BSize(parentHandle); 981 // The starting of sensitive data and data size without outer wrapper 982 sensitiveData = inPrivate->t.buffer + integritySize + ivSize; 983 dataSize = inPrivate->t.size - integritySize - ivSize; 984 // Unmarshal input data size 985 buffer = sensitiveData; 986 size = (INT32) dataSize; 987 result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size); 988 if(result == TPM_RC_SUCCESS) 989 { 990 if((dataSizeInput + sizeof(UINT16)) != dataSize) 991 result = TPM_RC_SENSITIVE; 992 else 993 { 994 // Unmarshal sensitive buffer to sensitive structure 995 result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size); 996 if(result != TPM_RC_SUCCESS || size != 0) 997 { 998 pAssert( (parent == NULL) 999 || parent->publicArea.objectAttributes.fixedTPM == CLEAR); 1000 result = TPM_RC_SENSITIVE; 1001 } 1002 else 1003 { 1004 // Always remove trailing zeros at load so that it is not necessary 1005 // to check 1006 // each time auth is checked. 1007 MemoryRemoveTrailingZeros(&(sensitive->authValue)); 1008 } 1009 } 1010 } 1011 return result; 1012 } 1013 // 1014 // 1015 // SensitiveToDuplicate() 1016 // 1017 // This function prepare the duplication blob from the sensitive area. The operations in this function: 1018 // a) marshal TPMT_SENSITIVE structure into the buffer of TPM2B_PRIVATE 1019 // b) apply inner wrap to the sensitive area if required 1020 // c) apply outer wrap if required 1021 // 1022 void 1023 SensitiveToDuplicate( 1024 TPMT_SENSITIVE *sensitive, // IN: sensitive structure 1025 TPM2B_NAME *name, // IN: the name of the object 1026 TPM_HANDLE parentHandle, // IN: The new parent's handle 1027 TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. It 1028 // is passed separately because we 1029 // only pass name, rather than the 1030 // whole public area of the object. 1031 TPM2B_SEED *seed, // IN: the external seed. If external 1032 // seed is provided with size of 0, 1033 // no outer wrap should be applied 1034 // to duplication blob. 1035 TPMT_SYM_DEF_OBJECT *symDef, // IN: Symmetric key definition. If the 1036 // symmetric key algorithm is NULL, 1037 // no inner wrap should be applied. 1038 TPM2B_DATA *innerSymKey, // IN/OUT: a symmetric key may be 1039 // provided to encrypt the inner 1040 // wrap of a duplication blob. May 1041 // be generated here if needed. 1042 TPM2B_PRIVATE *outPrivate // OUT: output private structure 1043 ) 1044 { 1045 BYTE *buffer; // Auxiliary buffer pointer 1046 INT32 bufferSize; 1047 BYTE *sensitiveData; // pointer to the sensitive data 1048 TPMI_ALG_HASH outerHash = TPM_ALG_NULL;// The hash algorithm for outer wrap 1049 TPMI_ALG_HASH innerHash = TPM_ALG_NULL;// The hash algorithm for inner wrap 1050 UINT16 dataSize; // data blob size 1051 BOOL doInnerWrap = FALSE; 1052 BOOL doOuterWrap = FALSE; 1053 // Make sure that name is provided 1054 pAssert(name != NULL && name->t.size != 0); 1055 // Make sure symDef and innerSymKey are not NULL 1056 pAssert(symDef != NULL && innerSymKey != NULL); 1057 // Starting of sensitive data without wrappers 1058 sensitiveData = outPrivate->t.buffer; 1059 // Find out if inner wrap is required 1060 if(symDef->algorithm != TPM_ALG_NULL) 1061 { 1062 doInnerWrap = TRUE; 1063 // Use self nameAlg as inner hash algorithm 1064 innerHash = nameAlg; 1065 // Adjust sensitive data pointer 1066 sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(innerHash); 1067 } 1068 // Find out if outer wrap is required 1069 if(seed->t.size != 0) 1070 { 1071 doOuterWrap = TRUE; 1072 // Use parent nameAlg as outer hash algorithm 1073 outerHash = ObjectGetNameAlg(parentHandle); 1074 // Adjust sensitive data pointer 1075 sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(outerHash); 1076 } 1077 // Marshal sensitive area, leaving the leading 2 bytes for size 1078 buffer = sensitiveData + sizeof(UINT16); 1079 bufferSize = sizeof(TPMT_SENSITIVE); 1080 dataSize = TPMT_SENSITIVE_Marshal(sensitive, &buffer, &bufferSize); 1081 // Adding size before the data area 1082 buffer = sensitiveData; 1083 bufferSize = sizeof(UINT16); 1084 UINT16_Marshal(&dataSize, &buffer, &bufferSize); 1085 // Adjust the dataSize to include the size field 1086 dataSize += sizeof(UINT16); 1087 // Apply inner wrap for duplication blob. It includes both integrity and 1088 // encryption 1089 if(doInnerWrap) 1090 { 1091 BYTE *innerBuffer = NULL; 1092 BOOL symKeyInput = TRUE; 1093 innerBuffer = outPrivate->t.buffer; 1094 // Skip outer integrity space 1095 if(doOuterWrap) 1096 innerBuffer += sizeof(UINT16) + CryptGetHashDigestSize(outerHash); 1097 dataSize = ProduceInnerIntegrity(name, innerHash, dataSize, 1098 innerBuffer); 1099 // Generate inner encryption key if needed 1100 if(innerSymKey->t.size == 0) 1101 { 1102 innerSymKey->t.size = (symDef->keyBits.sym + 7) / 8; 1103 CryptGenerateRandom(innerSymKey->t.size, innerSymKey->t.buffer); 1104 // TPM generates symmetric encryption. Set the flag to FALSE 1105 symKeyInput = FALSE; 1106 } 1107 else 1108 { 1109 // assume the input key size should matches the symmetric definition 1110 pAssert(innerSymKey->t.size == (symDef->keyBits.sym + 7) / 8); 1111 } 1112 // Encrypt inner buffer in place 1113 CryptSymmetricEncrypt(innerBuffer, symDef->algorithm, 1114 symDef->keyBits.sym, TPM_ALG_CFB, 1115 innerSymKey->t.buffer, NULL, dataSize, 1116 innerBuffer); 1117 // If the symmetric encryption key is imported, clear the buffer for 1118 // output 1119 if(symKeyInput) 1120 innerSymKey->t.size = 0; 1121 } 1122 // Apply outer wrap for duplication blob. It includes both integrity and 1123 // encryption 1124 if(doOuterWrap) 1125 { 1126 dataSize = ProduceOuterWrap(parentHandle, name, outerHash, seed, FALSE, 1127 dataSize, outPrivate->t.buffer); 1128 } 1129 // Data size for output 1130 outPrivate->t.size = dataSize; 1131 return; 1132 } 1133 // 1134 // 1135 // DuplicateToSensitive() 1136 // 1137 // Unwrap a duplication blob. Check the integrity, decrypt and retrieve data to a sensitive structure. The 1138 // operations in this function: 1139 // a) check the integrity HMAC of the input private area 1140 // b) decrypt the private buffer 1141 // c) unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE 1142 // 1143 // Error Returns Meaning 1144 // 1145 // TPM_RC_INSUFFICIENT unmarshaling sensitive data from inPrivate failed 1146 // TPM_RC_INTEGRITY inPrivate data integrity is broken 1147 // TPM_RC_SIZE unmarshaling sensitive data from inPrivate failed 1148 // 1149 TPM_RC 1150 DuplicateToSensitive( 1151 TPM2B_PRIVATE *inPrivate, // IN: input private structure 1152 TPM2B_NAME *name, // IN: the name of the object 1153 TPM_HANDLE parentHandle, // IN: The parent's handle 1154 TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. 1155 TPM2B_SEED *seed, // IN: an external seed may be provided. 1156 // If external seed is provided with 1157 // size of 0, no outer wrap is 1158 // applied 1159 TPMT_SYM_DEF_OBJECT *symDef, // IN: Symmetric key definition. If the 1160 // symmetric key algorithm is NULL, 1161 // no inner wrap is applied 1162 TPM2B_DATA *innerSymKey, // IN: a symmetric key may be provided 1163 // to decrypt the inner wrap of a 1164 // duplication blob. 1165 TPMT_SENSITIVE *sensitive // OUT: sensitive structure 1166 ) 1167 { 1168 TPM_RC result; 1169 BYTE *buffer; 1170 INT32 size; 1171 BYTE *sensitiveData; // pointer to the sensitive data 1172 UINT16 dataSize; 1173 UINT16 dataSizeInput; 1174 // Make sure that name is provided 1175 pAssert(name != NULL && name->t.size != 0); 1176 // Make sure symDef and innerSymKey are not NULL 1177 pAssert(symDef != NULL && innerSymKey != NULL); 1178 // Starting of sensitive data 1179 sensitiveData = inPrivate->t.buffer; 1180 dataSize = inPrivate->t.size; 1181 // Find out if outer wrap is applied 1182 if(seed->t.size != 0) 1183 { 1184 TPMI_ALG_HASH outerHash = TPM_ALG_NULL; 1185 // Use parent nameAlg as outer hash algorithm 1186 outerHash = ObjectGetNameAlg(parentHandle); 1187 result = UnwrapOuter(parentHandle, name, outerHash, seed, FALSE, 1188 dataSize, sensitiveData); 1189 if(result != TPM_RC_SUCCESS) 1190 return result; 1191 // Adjust sensitive data pointer and size 1192 sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(outerHash); 1193 dataSize -= sizeof(UINT16) + CryptGetHashDigestSize(outerHash); 1194 } 1195 // Find out if inner wrap is applied 1196 if(symDef->algorithm != TPM_ALG_NULL) 1197 { 1198 TPMI_ALG_HASH innerHash = TPM_ALG_NULL; 1199 // assume the input key size should matches the symmetric definition 1200 pAssert(innerSymKey->t.size == (symDef->keyBits.sym + 7) / 8); 1201 // Decrypt inner buffer in place 1202 CryptSymmetricDecrypt(sensitiveData, symDef->algorithm, 1203 symDef->keyBits.sym, TPM_ALG_CFB, 1204 innerSymKey->t.buffer, NULL, dataSize, 1205 sensitiveData); 1206 // Use self nameAlg as inner hash algorithm 1207 innerHash = nameAlg; 1208 // Check inner integrity 1209 result = CheckInnerIntegrity(name, innerHash, dataSize, sensitiveData); 1210 if(result != TPM_RC_SUCCESS) 1211 return result; 1212 // Adjust sensitive data pointer and size 1213 sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(innerHash); 1214 dataSize -= sizeof(UINT16) + CryptGetHashDigestSize(innerHash); 1215 } 1216 // Unmarshal input data size 1217 buffer = sensitiveData; 1218 size = (INT32) dataSize; 1219 result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size); 1220 if(result == TPM_RC_SUCCESS) 1221 { 1222 if((dataSizeInput + sizeof(UINT16)) != dataSize) 1223 result = TPM_RC_SIZE; 1224 else 1225 { 1226 // Unmarshal sensitive buffer to sensitive structure 1227 result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size); 1228 // if the results is OK make sure that all the data was unmarshaled 1229 if(result == TPM_RC_SUCCESS && size != 0) 1230 result = TPM_RC_SIZE; 1231 } 1232 } 1233 // Always remove trailing zeros at load so that it is not necessary to check 1234 // each time auth is checked. 1235 if(result == TPM_RC_SUCCESS) 1236 MemoryRemoveTrailingZeros(&(sensitive->authValue)); 1237 return result; 1238 } 1239 // 1240 // 1241 // SecretToCredential() 1242 // 1243 // This function prepare the credential blob from a secret (a TPM2B_DIGEST) The operations in this 1244 // function: 1245 // a) marshal TPM2B_DIGEST structure into the buffer of TPM2B_ID_OBJECT 1246 // b) encrypt the private buffer, excluding the leading integrity HMAC area 1247 // c) compute integrity HMAC and append to the beginning of the buffer. 1248 // d) Set the total size of TPM2B_ID_OBJECT buffer 1249 // 1250 void 1251 SecretToCredential( 1252 TPM2B_DIGEST *secret, // IN: secret information 1253 TPM2B_NAME *name, // IN: the name of the object 1254 TPM2B_SEED *seed, // IN: an external seed. 1255 TPM_HANDLE protector, // IN: The protector's handle 1256 TPM2B_ID_OBJECT *outIDObject // OUT: output credential 1257 ) 1258 { 1259 BYTE *buffer; // Auxiliary buffer pointer 1260 INT32 bufferSize; 1261 BYTE *sensitiveData; // pointer to the sensitive data 1262 TPMI_ALG_HASH outerHash; // The hash algorithm for outer wrap 1263 UINT16 dataSize; // data blob size 1264 pAssert(secret != NULL && outIDObject != NULL); 1265 // use protector's name algorithm as outer hash 1266 outerHash = ObjectGetNameAlg(protector); 1267 // Marshal secret area to credential buffer, leave space for integrity 1268 sensitiveData = outIDObject->t.credential 1269 + sizeof(UINT16) + CryptGetHashDigestSize(outerHash); 1270 // Marshal secret area 1271 buffer = sensitiveData; 1272 bufferSize = sizeof(TPM2B_DIGEST); 1273 dataSize = TPM2B_DIGEST_Marshal(secret, &buffer, &bufferSize); 1274 // Apply outer wrap 1275 outIDObject->t.size = ProduceOuterWrap(protector, 1276 name, 1277 outerHash, 1278 seed, 1279 FALSE, 1280 dataSize, 1281 outIDObject->t.credential); 1282 return; 1283 } 1284 // 1285 // 1286 // CredentialToSecret() 1287 // 1288 // Unwrap a credential. Check the integrity, decrypt and retrieve data to a TPM2B_DIGEST structure. The 1289 // operations in this function: 1290 // a) check the integrity HMAC of the input credential area 1291 // b) decrypt the credential buffer 1292 // c) unmarshal TPM2B_DIGEST structure into the buffer of TPM2B_DIGEST 1293 // 1294 // Error Returns Meaning 1295 // 1296 // TPM_RC_INSUFFICIENT error during credential unmarshaling 1297 // TPM_RC_INTEGRITY credential integrity is broken 1298 // TPM_RC_SIZE error during credential unmarshaling 1299 // TPM_RC_VALUE IV size does not match the encryption algorithm block size 1300 // 1301 TPM_RC 1302 CredentialToSecret( 1303 TPM2B_ID_OBJECT *inIDObject, // IN: input credential blob 1304 TPM2B_NAME *name, // IN: the name of the object 1305 TPM2B_SEED *seed, // IN: an external seed. 1306 TPM_HANDLE protector, // IN: The protector's handle 1307 TPM2B_DIGEST *secret // OUT: secret information 1308 ) 1309 { 1310 TPM_RC result; 1311 BYTE *buffer; 1312 INT32 size; 1313 TPMI_ALG_HASH outerHash; // The hash algorithm for outer wrap 1314 BYTE *sensitiveData; // pointer to the sensitive data 1315 UINT16 dataSize; 1316 // use protector's name algorithm as outer hash 1317 outerHash = ObjectGetNameAlg(protector); 1318 // Unwrap outer, a TPM_RC_INTEGRITY error may be returned at this point 1319 result = UnwrapOuter(protector, name, outerHash, seed, FALSE, 1320 inIDObject->t.size, inIDObject->t.credential); 1321 if(result == TPM_RC_SUCCESS) 1322 { 1323 // Compute the beginning of sensitive data 1324 sensitiveData = inIDObject->t.credential 1325 + sizeof(UINT16) + CryptGetHashDigestSize(outerHash); 1326 dataSize = inIDObject->t.size 1327 - (sizeof(UINT16) + CryptGetHashDigestSize(outerHash)); 1328 // Unmarshal secret buffer to TPM2B_DIGEST structure 1329 buffer = sensitiveData; 1330 size = (INT32) dataSize; 1331 result = TPM2B_DIGEST_Unmarshal(secret, &buffer, &size); 1332 // If there were no other unmarshaling errors, make sure that the 1333 // expected amount of data was recovered 1334 if(result == TPM_RC_SUCCESS && size != 0) 1335 return TPM_RC_SIZE; 1336 } 1337 return result; 1338 } 1339