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 // Check authPolicy digest consistency 537 if( publicArea->authPolicy.t.size != 0 538 && ( publicArea->authPolicy.t.size 539 != CryptGetHashDigestSize(publicArea->nameAlg) 540 ) 541 ) 542 return TPM_RC_SIZE; 543 // If the parent is fixedTPM (including a Primary Object) the object must have 544 // the same value for fixedTPM and fixedParent 545 if( parentObject == NULL 546 || parentObject->publicArea.objectAttributes.fixedTPM == SET) 547 { 548 if( publicArea->objectAttributes.fixedParent 549 != publicArea->objectAttributes.fixedTPM 550 ) 551 return TPM_RC_ATTRIBUTES; 552 } 553 else 554 // The parent is not fixedTPM so the object can't be fixedTPM 555 if(publicArea->objectAttributes.fixedTPM == SET) 556 return TPM_RC_ATTRIBUTES; 557 // A restricted object cannot be both sign and decrypt and it can't be neither 558 // sign nor decrypt 559 if ( publicArea->objectAttributes.restricted == SET 560 && ( publicArea->objectAttributes.decrypt 561 == publicArea->objectAttributes.sign) 562 ) 563 return TPM_RC_ATTRIBUTES; 564 // A fixedTPM object can not have encryptedDuplication bit SET 565 if( publicArea->objectAttributes.fixedTPM == SET 566 && publicArea->objectAttributes.encryptedDuplication == SET) 567 return TPM_RC_ATTRIBUTES; 568 // If a parent object has fixedTPM CLEAR, the child must have the 569 // same encryptedDuplication value as its parent. 570 // Primary objects are considered to have a fixedTPM parent (the seeds). 571 if( ( parentObject != NULL 572 && parentObject->publicArea.objectAttributes.fixedTPM == CLEAR) 573 // Get here if parent is not fixed TPM 574 && ( publicArea->objectAttributes.encryptedDuplication 575 != parentObject->publicArea.objectAttributes.encryptedDuplication 576 ) 577 ) 578 return TPM_RC_ATTRIBUTES; 579 return SchemeChecks(load, parentHandle, publicArea); 580 } 581 // 582 // 583 // FillInCreationData() 584 // 585 // Fill in creation data for an object. 586 // 587 void 588 FillInCreationData( 589 TPMI_DH_OBJECT parentHandle, // IN: handle of parent 590 TPMI_ALG_HASH nameHashAlg, // IN: name hash algorithm 591 TPML_PCR_SELECTION *creationPCR, // IN: PCR selection 592 TPM2B_DATA *outsideData, // IN: outside data 593 TPM2B_CREATION_DATA *outCreation, // OUT: creation data for output 594 TPM2B_DIGEST *creationDigest // OUT: creation digest 595 // 596 ) 597 { 598 BYTE creationBuffer[sizeof(TPMS_CREATION_DATA)]; 599 BYTE *buffer; 600 INT32 bufferSize; 601 HASH_STATE hashState; 602 // Fill in TPMS_CREATION_DATA in outCreation 603 // Compute PCR digest 604 PCRComputeCurrentDigest(nameHashAlg, creationPCR, 605 &outCreation->t.creationData.pcrDigest); 606 // Put back PCR selection list 607 outCreation->t.creationData.pcrSelect = *creationPCR; 608 // Get locality 609 outCreation->t.creationData.locality 610 = LocalityGetAttributes(_plat__LocalityGet()); 611 outCreation->t.creationData.parentNameAlg = TPM_ALG_NULL; 612 // If the parent is is either a primary seed or TPM_ALG_NULL, then the Name 613 // and QN of the parent are the parent's handle. 614 if(HandleGetType(parentHandle) == TPM_HT_PERMANENT) 615 { 616 BYTE *buffer = &outCreation->t.creationData.parentName.t.name[0]; 617 INT32 bufferSize = sizeof(TPM_HANDLE); 618 outCreation->t.creationData.parentName.t.size = 619 TPM_HANDLE_Marshal(&parentHandle, &buffer, &bufferSize); 620 // Parent qualified name of a Temporary Object is the same as parent's 621 // name 622 MemoryCopy2B(&outCreation->t.creationData.parentQualifiedName.b, 623 &outCreation->t.creationData.parentName.b, 624 sizeof(outCreation->t.creationData.parentQualifiedName.t.name)); 625 } 626 else // Regular object 627 { 628 OBJECT *parentObject = ObjectGet(parentHandle); 629 // Set name algorithm 630 outCreation->t.creationData.parentNameAlg = 631 parentObject->publicArea.nameAlg; 632 // Copy parent name 633 outCreation->t.creationData.parentName = parentObject->name; 634 // Copy parent qualified name 635 outCreation->t.creationData.parentQualifiedName = 636 parentObject->qualifiedName; 637 } 638 // Copy outside information 639 outCreation->t.creationData.outsideInfo = *outsideData; 640 // Marshal creation data to canonical form 641 buffer = creationBuffer; 642 bufferSize = sizeof(TPMS_CREATION_DATA); 643 outCreation->t.size = TPMS_CREATION_DATA_Marshal(&outCreation->t.creationData, 644 &buffer, &bufferSize); 645 // Compute hash for creation field in public template 646 creationDigest->t.size = CryptStartHash(nameHashAlg, &hashState); 647 CryptUpdateDigest(&hashState, outCreation->t.size, creationBuffer); 648 CryptCompleteHash2B(&hashState, &creationDigest->b); 649 return; 650 } 651 // GetSeedForKDF() 652 // 653 // Get a seed for KDF. The KDF for encryption and HMAC key use the same seed. It returns a pointer to 654 // the seed 655 // 656 TPM2B_SEED* 657 GetSeedForKDF( 658 TPM_HANDLE protectorHandle, // IN: the protector handle 659 TPM2B_SEED *seedIn // IN: the optional input seed 660 ) 661 { 662 OBJECT *protector = NULL; // Pointer to the protector 663 // Get seed for encryption key. Use input seed if provided. 664 // Otherwise, using protector object's seedValue. TPM_RH_NULL is the only 665 // exception that we may not have a loaded object as protector. In such a 666 // case, use nullProof as seed. 667 if(seedIn != NULL) 668 { 669 return seedIn; 670 } 671 else 672 { 673 if(protectorHandle == TPM_RH_NULL) 674 { 675 return (TPM2B_SEED *) &gr.nullProof; 676 } 677 else 678 { 679 protector = ObjectGet(protectorHandle); 680 return (TPM2B_SEED *) &protector->sensitive.seedValue; 681 } 682 } 683 } 684 // 685 // 686 // ProduceOuterWrap() 687 // 688 // This function produce outer wrap for a buffer containing the sensitive data. It requires the sensitive data 689 // being marshaled to the outerBuffer, with the leading bytes reserved for integrity hash. If iv is used, iv 690 // space should be reserved at the beginning of the buffer. It assumes the sensitive data starts at address 691 // (outerBuffer + integrity size {+ iv size}). This function performs: 692 // a) Add IV before sensitive area if required 693 // b) encrypt sensitive data, if iv is required, encrypt by iv. otherwise, encrypted by a NULL iv 694 // c) add HMAC integrity at the beginning of the buffer It returns the total size of blob with outer wrap 695 // 696 UINT16 697 ProduceOuterWrap( 698 TPM_HANDLE protector, // IN: The handle of the object that provides 699 // protection. For object, it is parent 700 // handle. For credential, it is the handle 701 // of encrypt object. 702 TPM2B_NAME *name, // IN: the name of the object 703 TPM_ALG_ID hashAlg, // IN: hash algorithm for outer wrap 704 TPM2B_SEED *seed, // IN: an external seed may be provided for 705 // duplication blob. For non duplication 706 // blob, this parameter should be NULL 707 BOOL useIV, // IN: indicate if an IV is used 708 UINT16 dataSize, // IN: the size of sensitive data, excluding the 709 // leading integrity buffer size or the 710 // optional iv size 711 BYTE *outerBuffer // IN/OUT: outer buffer with sensitive data in 712 // it 713 ) 714 { 715 TPM_ALG_ID symAlg; 716 UINT16 keyBits; 717 TPM2B_SYM_KEY symKey; 718 TPM2B_IV ivRNG; // IV from RNG 719 TPM2B_IV *iv = NULL; 720 UINT16 ivSize = 0; // size of iv area, including the size field 721 BYTE *sensitiveData; // pointer to the sensitive data 722 TPM2B_DIGEST integrity; 723 UINT16 integritySize; 724 BYTE *buffer; // Auxiliary buffer pointer 725 INT32 bufferSize; 726 // Compute the beginning of sensitive data. The outer integrity should 727 // always exist if this function function is called to make an outer wrap 728 integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg); 729 sensitiveData = outerBuffer + integritySize; 730 // If iv is used, adjust the pointer of sensitive data and add iv before it 731 if(useIV) 732 { 733 ivSize = GetIV2BSize(protector); 734 // Generate IV from RNG. The iv data size should be the total IV area 735 // size minus the size of size field 736 ivRNG.t.size = ivSize - sizeof(UINT16); 737 CryptGenerateRandom(ivRNG.t.size, ivRNG.t.buffer); 738 // Marshal IV to buffer 739 buffer = sensitiveData; 740 bufferSize = sizeof(TPM2B_IV); 741 TPM2B_IV_Marshal(&ivRNG, &buffer, &bufferSize); 742 // adjust sensitive data starting after IV area 743 sensitiveData += ivSize; 744 // Use iv for encryption 745 iv = &ivRNG; 746 } 747 // Compute symmetric key parameters for outer buffer encryption 748 ComputeProtectionKeyParms(protector, hashAlg, name, seed, 749 &symAlg, &keyBits, &symKey); 750 // Encrypt inner buffer in place 751 CryptSymmetricEncrypt(sensitiveData, symAlg, keyBits, 752 TPM_ALG_CFB, symKey.t.buffer, iv, dataSize, 753 sensitiveData); 754 // Compute outer integrity. Integrity computation includes the optional IV 755 // area 756 ComputeOuterIntegrity(name, protector, hashAlg, seed, dataSize + ivSize, 757 outerBuffer + integritySize, &integrity); 758 // Add integrity at the beginning of outer buffer 759 buffer = outerBuffer; 760 bufferSize = sizeof(TPM2B_DIGEST); 761 TPM2B_DIGEST_Marshal(&integrity, &buffer, &bufferSize); 762 // return the total size in outer wrap 763 return dataSize + integritySize + ivSize; 764 } 765 // 766 // 767 // 768 // UnwrapOuter() 769 // 770 // This function remove the outer wrap of a blob containing sensitive data This function performs: 771 // a) check integrity of outer blob 772 // b) decrypt outer blob 773 // 774 // Error Returns Meaning 775 // 776 // TPM_RC_INSUFFICIENT error during sensitive data unmarshaling 777 // TPM_RC_INTEGRITY sensitive data integrity is broken 778 // TPM_RC_SIZE error during sensitive data unmarshaling 779 // TPM_RC_VALUE IV size for CFB does not match the encryption algorithm block size 780 // 781 TPM_RC 782 UnwrapOuter( 783 TPM_HANDLE protector, // IN: The handle of the object that provides 784 // protection. For object, it is parent 785 // handle. For credential, it is the handle 786 // of encrypt object. 787 TPM2B_NAME *name, // IN: the name of the object 788 TPM_ALG_ID hashAlg, // IN: hash algorithm for outer wrap 789 TPM2B_SEED *seed, // IN: an external seed may be provided for 790 // duplication blob. For non duplication 791 // blob, this parameter should be NULL. 792 BOOL useIV, // IN: indicates if an IV is used 793 UINT16 dataSize, // IN: size of sensitive data in outerBuffer, 794 // including the leading integrity buffer 795 // size, and an optional iv area 796 BYTE *outerBuffer // IN/OUT: sensitive data 797 ) 798 { 799 TPM_RC result; 800 TPM_ALG_ID symAlg = TPM_ALG_NULL; 801 TPM2B_SYM_KEY symKey; 802 UINT16 keyBits = 0; 803 TPM2B_IV ivIn; // input IV retrieved from input buffer 804 TPM2B_IV *iv = NULL; 805 BYTE *sensitiveData; // pointer to the sensitive data 806 TPM2B_DIGEST integrityToCompare; 807 TPM2B_DIGEST integrity; 808 INT32 size; 809 // Unmarshal integrity 810 sensitiveData = outerBuffer; 811 size = (INT32) dataSize; 812 result = TPM2B_DIGEST_Unmarshal(&integrity, &sensitiveData, &size); 813 if(result == TPM_RC_SUCCESS) 814 { 815 // Compute integrity to compare 816 ComputeOuterIntegrity(name, protector, hashAlg, seed, 817 (UINT16) size, sensitiveData, 818 &integrityToCompare); 819 // Compare outer blob integrity 820 if(!Memory2BEqual(&integrity.b, &integrityToCompare.b)) 821 return TPM_RC_INTEGRITY; 822 // Get the symmetric algorithm parameters used for encryption 823 ComputeProtectionKeyParms(protector, hashAlg, name, seed, 824 &symAlg, &keyBits, &symKey); 825 // Retrieve IV if it is used 826 if(useIV) 827 { 828 result = TPM2B_IV_Unmarshal(&ivIn, &sensitiveData, &size); 829 if(result == TPM_RC_SUCCESS) 830 { 831 // The input iv size for CFB must match the encryption algorithm 832 // block size 833 if(ivIn.t.size != CryptGetSymmetricBlockSize(symAlg, keyBits)) 834 result = TPM_RC_VALUE; 835 else 836 iv = &ivIn; 837 } 838 } 839 } 840 // If no errors, decrypt private in place 841 if(result == TPM_RC_SUCCESS) 842 CryptSymmetricDecrypt(sensitiveData, symAlg, keyBits, 843 TPM_ALG_CFB, symKey.t.buffer, iv, 844 (UINT16) size, sensitiveData); 845 return result; 846 } 847 // 848 // 849 // SensitiveToPrivate() 850 // 851 // This function prepare the private blob for off the chip storage The operations in this function: 852 // a) marshal TPM2B_SENSITIVE structure into the buffer of TPM2B_PRIVATE 853 // b) apply encryption to the sensitive area. 854 // c) apply outer integrity computation. 855 // 856 void 857 SensitiveToPrivate( 858 TPMT_SENSITIVE *sensitive, // IN: sensitive structure 859 TPM2B_NAME *name, // IN: the name of the object 860 TPM_HANDLE parentHandle, // IN: The parent's handle 861 TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. This 862 // parameter is used when parentHandle is 863 // NULL, in which case the object is 864 // temporary. 865 TPM2B_PRIVATE *outPrivate // OUT: output private structure 866 ) 867 { 868 BYTE *buffer; // Auxiliary buffer pointer 869 INT32 bufferSize; 870 BYTE *sensitiveData; // pointer to the sensitive data 871 UINT16 dataSize; // data blob size 872 TPMI_ALG_HASH hashAlg; // hash algorithm for integrity 873 UINT16 integritySize; 874 UINT16 ivSize; 875 pAssert(name != NULL && name->t.size != 0); 876 // Find the hash algorithm for integrity computation 877 if(parentHandle == TPM_RH_NULL) 878 { 879 // For Temporary Object, using self name algorithm 880 hashAlg = nameAlg; 881 } 882 else 883 { 884 // Otherwise, using parent's name algorithm 885 hashAlg = ObjectGetNameAlg(parentHandle); 886 } 887 // Starting of sensitive data without wrappers 888 sensitiveData = outPrivate->t.buffer; 889 // Compute the integrity size 890 integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg); 891 // Reserve space for integrity 892 sensitiveData += integritySize; 893 // Get iv size 894 ivSize = GetIV2BSize(parentHandle); 895 // Reserve space for iv 896 sensitiveData += ivSize; 897 // Marshal sensitive area, leaving the leading 2 bytes for size 898 buffer = sensitiveData + sizeof(UINT16); 899 bufferSize = sizeof(TPMT_SENSITIVE); 900 dataSize = TPMT_SENSITIVE_Marshal(sensitive, &buffer, &bufferSize); 901 // Adding size before the data area 902 buffer = sensitiveData; 903 bufferSize = sizeof(UINT16); 904 UINT16_Marshal(&dataSize, &buffer, &bufferSize); 905 // Adjust the dataSize to include the size field 906 dataSize += sizeof(UINT16); 907 // Adjust the pointer to inner buffer including the iv 908 sensitiveData = outPrivate->t.buffer + ivSize; 909 //Produce outer wrap, including encryption and HMAC 910 outPrivate->t.size = ProduceOuterWrap(parentHandle, name, hashAlg, NULL, 911 TRUE, dataSize, outPrivate->t.buffer); 912 return; 913 } 914 // 915 // 916 // PrivateToSensitive() 917 // 918 // Unwrap a input private area. Check the integrity, decrypt and retrieve data to a sensitive structure. The 919 // operations in this function: 920 // a) check the integrity HMAC of the input private area 921 // b) decrypt the private buffer 922 // c) unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE 923 // 924 // Error Returns Meaning 925 // 926 // TPM_RC_INTEGRITY if the private area integrity is bad 927 // TPM_RC_SENSITIVE unmarshal errors while unmarshaling TPMS_ENCRYPT from input 928 // private 929 // TPM_RC_VALUE outer wrapper does not have an iV of the correct size 930 // 931 TPM_RC 932 PrivateToSensitive( 933 TPM2B_PRIVATE *inPrivate, // IN: input private structure 934 TPM2B_NAME *name, // IN: the name of the object 935 TPM_HANDLE parentHandle, // IN: The parent's handle 936 TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. It is 937 // passed separately because we only pass 938 // name, rather than the whole public area 939 // of the object. This parameter is used in 940 // the following two cases: 1. primary 941 // objects. 2. duplication blob with inner 942 // wrap. In other cases, this parameter 943 // will be ignored 944 TPMT_SENSITIVE *sensitive // OUT: sensitive structure 945 ) 946 { 947 TPM_RC result; 948 BYTE *buffer; 949 INT32 size; 950 BYTE *sensitiveData; // pointer to the sensitive data 951 UINT16 dataSize; 952 UINT16 dataSizeInput; 953 TPMI_ALG_HASH hashAlg; // hash algorithm for integrity 954 OBJECT *parent = NULL; 955 UINT16 integritySize; 956 UINT16 ivSize; 957 // Make sure that name is provided 958 pAssert(name != NULL && name->t.size != 0); 959 // Find the hash algorithm for integrity computation 960 if(parentHandle == TPM_RH_NULL) 961 { 962 // For Temporary Object, using self name algorithm 963 hashAlg = nameAlg; 964 } 965 else 966 { 967 // Otherwise, using parent's name algorithm 968 hashAlg = ObjectGetNameAlg(parentHandle); 969 } 970 // unwrap outer 971 result = UnwrapOuter(parentHandle, name, hashAlg, NULL, TRUE, 972 inPrivate->t.size, inPrivate->t.buffer); 973 if(result != TPM_RC_SUCCESS) 974 return result; 975 // Compute the inner integrity size. 976 integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg); 977 // Get iv size 978 ivSize = GetIV2BSize(parentHandle); 979 // The starting of sensitive data and data size without outer wrapper 980 sensitiveData = inPrivate->t.buffer + integritySize + ivSize; 981 dataSize = inPrivate->t.size - integritySize - ivSize; 982 // Unmarshal input data size 983 buffer = sensitiveData; 984 size = (INT32) dataSize; 985 result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size); 986 if(result == TPM_RC_SUCCESS) 987 { 988 if((dataSizeInput + sizeof(UINT16)) != dataSize) 989 result = TPM_RC_SENSITIVE; 990 else 991 { 992 // Unmarshal sensitive buffer to sensitive structure 993 result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size); 994 if(result != TPM_RC_SUCCESS || size != 0) 995 { 996 pAssert( (parent == NULL) 997 || parent->publicArea.objectAttributes.fixedTPM == CLEAR); 998 result = TPM_RC_SENSITIVE; 999 } 1000 else 1001 { 1002 // Always remove trailing zeros at load so that it is not necessary 1003 // to check 1004 // each time auth is checked. 1005 MemoryRemoveTrailingZeros(&(sensitive->authValue)); 1006 } 1007 } 1008 } 1009 return result; 1010 } 1011 // 1012 // 1013 // SensitiveToDuplicate() 1014 // 1015 // This function prepare the duplication blob from the sensitive area. The operations in this function: 1016 // a) marshal TPMT_SENSITIVE structure into the buffer of TPM2B_PRIVATE 1017 // b) apply inner wrap to the sensitive area if required 1018 // c) apply outer wrap if required 1019 // 1020 void 1021 SensitiveToDuplicate( 1022 TPMT_SENSITIVE *sensitive, // IN: sensitive structure 1023 TPM2B_NAME *name, // IN: the name of the object 1024 TPM_HANDLE parentHandle, // IN: The new parent's handle 1025 TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. It 1026 // is passed separately because we 1027 // only pass name, rather than the 1028 // whole public area of the object. 1029 TPM2B_SEED *seed, // IN: the external seed. If external 1030 // seed is provided with size of 0, 1031 // no outer wrap should be applied 1032 // to duplication blob. 1033 TPMT_SYM_DEF_OBJECT *symDef, // IN: Symmetric key definition. If the 1034 // symmetric key algorithm is NULL, 1035 // no inner wrap should be applied. 1036 TPM2B_DATA *innerSymKey, // IN/OUT: a symmetric key may be 1037 // provided to encrypt the inner 1038 // wrap of a duplication blob. May 1039 // be generated here if needed. 1040 TPM2B_PRIVATE *outPrivate // OUT: output private structure 1041 ) 1042 { 1043 BYTE *buffer; // Auxiliary buffer pointer 1044 INT32 bufferSize; 1045 BYTE *sensitiveData; // pointer to the sensitive data 1046 TPMI_ALG_HASH outerHash = TPM_ALG_NULL;// The hash algorithm for outer wrap 1047 TPMI_ALG_HASH innerHash = TPM_ALG_NULL;// The hash algorithm for inner wrap 1048 UINT16 dataSize; // data blob size 1049 BOOL doInnerWrap = FALSE; 1050 BOOL doOuterWrap = FALSE; 1051 // Make sure that name is provided 1052 pAssert(name != NULL && name->t.size != 0); 1053 // Make sure symDef and innerSymKey are not NULL 1054 pAssert(symDef != NULL && innerSymKey != NULL); 1055 // Starting of sensitive data without wrappers 1056 sensitiveData = outPrivate->t.buffer; 1057 // Find out if inner wrap is required 1058 if(symDef->algorithm != TPM_ALG_NULL) 1059 { 1060 doInnerWrap = TRUE; 1061 // Use self nameAlg as inner hash algorithm 1062 innerHash = nameAlg; 1063 // Adjust sensitive data pointer 1064 sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(innerHash); 1065 } 1066 // Find out if outer wrap is required 1067 if(seed->t.size != 0) 1068 { 1069 doOuterWrap = TRUE; 1070 // Use parent nameAlg as outer hash algorithm 1071 outerHash = ObjectGetNameAlg(parentHandle); 1072 // Adjust sensitive data pointer 1073 sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(outerHash); 1074 } 1075 // Marshal sensitive area, leaving the leading 2 bytes for size 1076 buffer = sensitiveData + sizeof(UINT16); 1077 bufferSize = sizeof(TPMT_SENSITIVE); 1078 dataSize = TPMT_SENSITIVE_Marshal(sensitive, &buffer, &bufferSize); 1079 // Adding size before the data area 1080 buffer = sensitiveData; 1081 bufferSize = sizeof(UINT16); 1082 UINT16_Marshal(&dataSize, &buffer, &bufferSize); 1083 // Adjust the dataSize to include the size field 1084 dataSize += sizeof(UINT16); 1085 // Apply inner wrap for duplication blob. It includes both integrity and 1086 // encryption 1087 if(doInnerWrap) 1088 { 1089 BYTE *innerBuffer = NULL; 1090 BOOL symKeyInput = TRUE; 1091 innerBuffer = outPrivate->t.buffer; 1092 // Skip outer integrity space 1093 if(doOuterWrap) 1094 innerBuffer += sizeof(UINT16) + CryptGetHashDigestSize(outerHash); 1095 dataSize = ProduceInnerIntegrity(name, innerHash, dataSize, 1096 innerBuffer); 1097 // Generate inner encryption key if needed 1098 if(innerSymKey->t.size == 0) 1099 { 1100 innerSymKey->t.size = (symDef->keyBits.sym + 7) / 8; 1101 CryptGenerateRandom(innerSymKey->t.size, innerSymKey->t.buffer); 1102 // TPM generates symmetric encryption. Set the flag to FALSE 1103 symKeyInput = FALSE; 1104 } 1105 else 1106 { 1107 // assume the input key size should matches the symmetric definition 1108 pAssert(innerSymKey->t.size == (symDef->keyBits.sym + 7) / 8); 1109 } 1110 // Encrypt inner buffer in place 1111 CryptSymmetricEncrypt(innerBuffer, symDef->algorithm, 1112 symDef->keyBits.sym, TPM_ALG_CFB, 1113 innerSymKey->t.buffer, NULL, dataSize, 1114 innerBuffer); 1115 // If the symmetric encryption key is imported, clear the buffer for 1116 // output 1117 if(symKeyInput) 1118 innerSymKey->t.size = 0; 1119 } 1120 // Apply outer wrap for duplication blob. It includes both integrity and 1121 // encryption 1122 if(doOuterWrap) 1123 { 1124 dataSize = ProduceOuterWrap(parentHandle, name, outerHash, seed, FALSE, 1125 dataSize, outPrivate->t.buffer); 1126 } 1127 // Data size for output 1128 outPrivate->t.size = dataSize; 1129 return; 1130 } 1131 // 1132 // 1133 // DuplicateToSensitive() 1134 // 1135 // Unwrap a duplication blob. Check the integrity, decrypt and retrieve data to a sensitive structure. The 1136 // operations in this function: 1137 // a) check the integrity HMAC of the input private area 1138 // b) decrypt the private buffer 1139 // c) unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE 1140 // 1141 // Error Returns Meaning 1142 // 1143 // TPM_RC_INSUFFICIENT unmarshaling sensitive data from inPrivate failed 1144 // TPM_RC_INTEGRITY inPrivate data integrity is broken 1145 // TPM_RC_SIZE unmarshaling sensitive data from inPrivate failed 1146 // 1147 TPM_RC 1148 DuplicateToSensitive( 1149 TPM2B_PRIVATE *inPrivate, // IN: input private structure 1150 TPM2B_NAME *name, // IN: the name of the object 1151 TPM_HANDLE parentHandle, // IN: The parent's handle 1152 TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. 1153 TPM2B_SEED *seed, // IN: an external seed may be provided. 1154 // If external seed is provided with 1155 // size of 0, no outer wrap is 1156 // applied 1157 TPMT_SYM_DEF_OBJECT *symDef, // IN: Symmetric key definition. If the 1158 // symmetric key algorithm is NULL, 1159 // no inner wrap is applied 1160 TPM2B_DATA *innerSymKey, // IN: a symmetric key may be provided 1161 // to decrypt the inner wrap of a 1162 // duplication blob. 1163 TPMT_SENSITIVE *sensitive // OUT: sensitive structure 1164 ) 1165 { 1166 TPM_RC result; 1167 BYTE *buffer; 1168 INT32 size; 1169 BYTE *sensitiveData; // pointer to the sensitive data 1170 UINT16 dataSize; 1171 UINT16 dataSizeInput; 1172 // Make sure that name is provided 1173 pAssert(name != NULL && name->t.size != 0); 1174 // Make sure symDef and innerSymKey are not NULL 1175 pAssert(symDef != NULL && innerSymKey != NULL); 1176 // Starting of sensitive data 1177 sensitiveData = inPrivate->t.buffer; 1178 dataSize = inPrivate->t.size; 1179 // Find out if outer wrap is applied 1180 if(seed->t.size != 0) 1181 { 1182 TPMI_ALG_HASH outerHash = TPM_ALG_NULL; 1183 // Use parent nameAlg as outer hash algorithm 1184 outerHash = ObjectGetNameAlg(parentHandle); 1185 result = UnwrapOuter(parentHandle, name, outerHash, seed, FALSE, 1186 dataSize, sensitiveData); 1187 if(result != TPM_RC_SUCCESS) 1188 return result; 1189 // Adjust sensitive data pointer and size 1190 sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(outerHash); 1191 dataSize -= sizeof(UINT16) + CryptGetHashDigestSize(outerHash); 1192 } 1193 // Find out if inner wrap is applied 1194 if(symDef->algorithm != TPM_ALG_NULL) 1195 { 1196 TPMI_ALG_HASH innerHash = TPM_ALG_NULL; 1197 // assume the input key size should matches the symmetric definition 1198 pAssert(innerSymKey->t.size == (symDef->keyBits.sym + 7) / 8); 1199 // Decrypt inner buffer in place 1200 CryptSymmetricDecrypt(sensitiveData, symDef->algorithm, 1201 symDef->keyBits.sym, TPM_ALG_CFB, 1202 innerSymKey->t.buffer, NULL, dataSize, 1203 sensitiveData); 1204 // Use self nameAlg as inner hash algorithm 1205 innerHash = nameAlg; 1206 // Check inner integrity 1207 result = CheckInnerIntegrity(name, innerHash, dataSize, sensitiveData); 1208 if(result != TPM_RC_SUCCESS) 1209 return result; 1210 // Adjust sensitive data pointer and size 1211 sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(innerHash); 1212 dataSize -= sizeof(UINT16) + CryptGetHashDigestSize(innerHash); 1213 } 1214 // Unmarshal input data size 1215 buffer = sensitiveData; 1216 size = (INT32) dataSize; 1217 result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size); 1218 if(result == TPM_RC_SUCCESS) 1219 { 1220 if((dataSizeInput + sizeof(UINT16)) != dataSize) 1221 result = TPM_RC_SIZE; 1222 else 1223 { 1224 // Unmarshal sensitive buffer to sensitive structure 1225 result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size); 1226 // if the results is OK make sure that all the data was unmarshaled 1227 if(result == TPM_RC_SUCCESS && size != 0) 1228 result = TPM_RC_SIZE; 1229 } 1230 } 1231 // Always remove trailing zeros at load so that it is not necessary to check 1232 // each time auth is checked. 1233 if(result == TPM_RC_SUCCESS) 1234 MemoryRemoveTrailingZeros(&(sensitive->authValue)); 1235 return result; 1236 } 1237 // 1238 // 1239 // SecretToCredential() 1240 // 1241 // This function prepare the credential blob from a secret (a TPM2B_DIGEST) The operations in this 1242 // function: 1243 // a) marshal TPM2B_DIGEST structure into the buffer of TPM2B_ID_OBJECT 1244 // b) encrypt the private buffer, excluding the leading integrity HMAC area 1245 // c) compute integrity HMAC and append to the beginning of the buffer. 1246 // d) Set the total size of TPM2B_ID_OBJECT buffer 1247 // 1248 void 1249 SecretToCredential( 1250 TPM2B_DIGEST *secret, // IN: secret information 1251 TPM2B_NAME *name, // IN: the name of the object 1252 TPM2B_SEED *seed, // IN: an external seed. 1253 TPM_HANDLE protector, // IN: The protector's handle 1254 TPM2B_ID_OBJECT *outIDObject // OUT: output credential 1255 ) 1256 { 1257 BYTE *buffer; // Auxiliary buffer pointer 1258 INT32 bufferSize; 1259 BYTE *sensitiveData; // pointer to the sensitive data 1260 TPMI_ALG_HASH outerHash; // The hash algorithm for outer wrap 1261 UINT16 dataSize; // data blob size 1262 pAssert(secret != NULL && outIDObject != NULL); 1263 // use protector's name algorithm as outer hash 1264 outerHash = ObjectGetNameAlg(protector); 1265 // Marshal secret area to credential buffer, leave space for integrity 1266 sensitiveData = outIDObject->t.credential 1267 + sizeof(UINT16) + CryptGetHashDigestSize(outerHash); 1268 // Marshal secret area 1269 buffer = sensitiveData; 1270 bufferSize = sizeof(TPM2B_DIGEST); 1271 dataSize = TPM2B_DIGEST_Marshal(secret, &buffer, &bufferSize); 1272 // Apply outer wrap 1273 outIDObject->t.size = ProduceOuterWrap(protector, 1274 name, 1275 outerHash, 1276 seed, 1277 FALSE, 1278 dataSize, 1279 outIDObject->t.credential); 1280 return; 1281 } 1282 // 1283 // 1284 // CredentialToSecret() 1285 // 1286 // Unwrap a credential. Check the integrity, decrypt and retrieve data to a TPM2B_DIGEST structure. The 1287 // operations in this function: 1288 // a) check the integrity HMAC of the input credential area 1289 // b) decrypt the credential buffer 1290 // c) unmarshal TPM2B_DIGEST structure into the buffer of TPM2B_DIGEST 1291 // 1292 // Error Returns Meaning 1293 // 1294 // TPM_RC_INSUFFICIENT error during credential unmarshaling 1295 // TPM_RC_INTEGRITY credential integrity is broken 1296 // TPM_RC_SIZE error during credential unmarshaling 1297 // TPM_RC_VALUE IV size does not match the encryption algorithm block size 1298 // 1299 TPM_RC 1300 CredentialToSecret( 1301 TPM2B_ID_OBJECT *inIDObject, // IN: input credential blob 1302 TPM2B_NAME *name, // IN: the name of the object 1303 TPM2B_SEED *seed, // IN: an external seed. 1304 TPM_HANDLE protector, // IN: The protector's handle 1305 TPM2B_DIGEST *secret // OUT: secret information 1306 ) 1307 { 1308 TPM_RC result; 1309 BYTE *buffer; 1310 INT32 size; 1311 TPMI_ALG_HASH outerHash; // The hash algorithm for outer wrap 1312 BYTE *sensitiveData; // pointer to the sensitive data 1313 UINT16 dataSize; 1314 // use protector's name algorithm as outer hash 1315 outerHash = ObjectGetNameAlg(protector); 1316 // Unwrap outer, a TPM_RC_INTEGRITY error may be returned at this point 1317 result = UnwrapOuter(protector, name, outerHash, seed, FALSE, 1318 inIDObject->t.size, inIDObject->t.credential); 1319 if(result == TPM_RC_SUCCESS) 1320 { 1321 // Compute the beginning of sensitive data 1322 sensitiveData = inIDObject->t.credential 1323 + sizeof(UINT16) + CryptGetHashDigestSize(outerHash); 1324 dataSize = inIDObject->t.size 1325 - (sizeof(UINT16) + CryptGetHashDigestSize(outerHash)); 1326 // Unmarshal secret buffer to TPM2B_DIGEST structure 1327 buffer = sensitiveData; 1328 size = (INT32) dataSize; 1329 result = TPM2B_DIGEST_Unmarshal(secret, &buffer, &size); 1330 // If there were no other unmarshaling errors, make sure that the 1331 // expected amount of data was recovered 1332 if(result == TPM_RC_SUCCESS && size != 0) 1333 return TPM_RC_SIZE; 1334 } 1335 return result; 1336 } 1337