15679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// This file was extracted from the TCG Published
25679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// Trusted Platform Module Library
35679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// Part 4: Supporting Routines
45679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// Family "2.0"
55679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// Level 00 Revision 01.16
65679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// October 30, 2014
75679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
85679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#include "InternalRoutines.h"
95679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#include "Object_spt_fp.h"
10fe7bde4f6f18efd7a80611108290bf2981cbd726Vadim Bendebury#include "Platform.h"
115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//          Local Functions
155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//          EqualCryptSet()
175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     Check if the crypto sets in two public areas are equal
195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     Error Returns                     Meaning
215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     TPM_RC_ASYMMETRIC                 mismatched parameters
235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     TPM_RC_HASH                       mismatched name algorithm
245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     TPM_RC_TYPE                       mismatched type
255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
265679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic TPM_RC
275679752bf24c21135884e987c4077e2f7184897Vadim BendeburyEqualCryptSet(
285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMT_PUBLIC         *publicArea1,        // IN: public area 1
295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMT_PUBLIC         *publicArea2         // IN: public area 2
305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16                   size1;
335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16                   size2;
345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BYTE                     params1[sizeof(TPMU_PUBLIC_PARMS)];
355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BYTE                     params2[sizeof(TPMU_PUBLIC_PARMS)];
365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BYTE                     *buffer;
3732be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr   INT32                    bufferSize;
385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Compare name hash
395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(publicArea1->nameAlg != publicArea2->nameAlg)
405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return TPM_RC_HASH;
415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Compare algorithm
425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(publicArea1->type != publicArea2->type)
435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return TPM_RC_TYPE;
445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // TPMU_PUBLIC_PARMS field should be identical
455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   buffer = params1;
4632be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr   bufferSize = sizeof(TPMU_PUBLIC_PARMS);
475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   size1 = TPMU_PUBLIC_PARMS_Marshal(&publicArea1->parameters, &buffer,
4832be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr                                     &bufferSize, publicArea1->type);
495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   buffer = params2;
5032be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr   bufferSize = sizeof(TPMU_PUBLIC_PARMS);
515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   size2 = TPMU_PUBLIC_PARMS_Marshal(&publicArea2->parameters, &buffer,
5232be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr                                     &bufferSize, publicArea2->type);
535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(size1 != size2 || !MemoryEqual(params1, params2, size1))
545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return TPM_RC_ASYMMETRIC;
555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return TPM_RC_SUCCESS;
565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//          GetIV2BSize()
605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     Get the size of TPM2B_IV in canonical form that will be append to the start of the sensitive data. It
625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     includes both size of size field and size of iv data
635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     Return Value                      Meaning
655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
665679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic UINT16
675679752bf24c21135884e987c4077e2f7184897Vadim BendeburyGetIV2BSize(
685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_HANDLE            protectorHandle           // IN: the protector handle
695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   OBJECT                   *protector = NULL; // Pointer to the protector object
725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ALG_ID               symAlg;
735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16                    keyBits;
755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Determine the symmetric algorithm and size of key
765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(protectorHandle == TPM_RH_NULL)
775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Use the context encryption algorithm and key size
795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       symAlg = CONTEXT_ENCRYPT_ALG;
805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       keyBits = CONTEXT_ENCRYPT_KEY_BITS;
815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   else
835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       protector = ObjectGet(protectorHandle);
855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       symAlg = protector->publicArea.parameters.asymDetail.symmetric.algorithm;
865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       keyBits= protector->publicArea.parameters.asymDetail.symmetric.keyBits.sym;
875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // The IV size is a UINT16 size field plus the block size of the symmetric
895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // algorithm
905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return sizeof(UINT16) + CryptGetSymmetricBlockSize(symAlg, keyBits);
915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//         ComputeProtectionKeyParms()
955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     This function retrieves the symmetric protection key parameters for the sensitive data The parameters
975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     retrieved from this function include encryption algorithm, key size in bit, and a TPM2B_SYM_KEY
985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     containing the key material as well as the key size in bytes This function is used for any action that
995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     requires encrypting or decrypting of the sensitive area of an object or a credential blob
1005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
1015679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic void
1025679752bf24c21135884e987c4077e2f7184897Vadim BendeburyComputeProtectionKeyParms(
1035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_HANDLE          protectorHandle,       //   IN: the protector handle
1045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ALG_ID          hashAlg,               //   IN: hash algorithm for KDFa
1055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_NAME         *name,                  //   IN: name of the object
1065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_SEED         *seedIn,                //   IN: optional seed for duplication blob.
1075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                              //       For non duplication blob, this
1085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                              //       parameter should be NULL
1095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ALG_ID         *symAlg,                //   OUT: the symmetric algorithm
1105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16             *keyBits,               //   OUT: the symmetric key size in bits
1115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_SYM_KEY      *symKey                 //   OUT: the symmetric key
1125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
1135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
1145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_SEED                *seed = NULL;
1155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   OBJECT                    *protector = NULL; // Pointer to the protector
1165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Determine the algorithms for the KDF and the encryption/decryption
1175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // For TPM_RH_NULL, using context settings
1185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(protectorHandle == TPM_RH_NULL)
1195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
1205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Use the context encryption algorithm and key size
1215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       *symAlg = CONTEXT_ENCRYPT_ALG;
1225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       symKey->t.size = CONTEXT_ENCRYPT_KEY_BYTES;
1235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       *keyBits = CONTEXT_ENCRYPT_KEY_BITS;
1245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
1255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   else
1265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
1275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       TPMT_SYM_DEF_OBJECT *symDef;
1285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       protector = ObjectGet(protectorHandle);
1295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       symDef = &protector->publicArea.parameters.asymDetail.symmetric;
1305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       *symAlg = symDef->algorithm;
1315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       *keyBits= symDef->keyBits.sym;
1325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       symKey->t.size = (*keyBits + 7) / 8;
1335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
1345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Get seed for KDF
1355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   seed = GetSeedForKDF(protectorHandle, seedIn);
1365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // KDFa to generate symmetric key and IV value
1375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   KDFa(hashAlg, (TPM2B *)seed, "STORAGE", (TPM2B *)name, NULL,
1385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        symKey->t.size * 8, symKey->t.buffer, NULL);
1395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return;
1405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
1415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
1425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
1435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//           ComputeOuterIntegrity()
1445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
1455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      The sensitive area parameter is a buffer that holds a space for the integrity value and the marshaled
1465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      sensitive area. The caller should skip over the area set aside for the integrity value and compute the hash
1475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      of the remainder of the object. The size field of sensitive is in unmarshaled form and the sensitive area
1485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      contents is an array of bytes.
1495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
1505679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic void
1515679752bf24c21135884e987c4077e2f7184897Vadim BendeburyComputeOuterIntegrity(
1525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_NAME          *name,                   //   IN: the name of the object
1535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_HANDLE           protectorHandle,        //   IN: The handle of the object that
1545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                //       provides protection. For object, it
1555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                //       is parent handle. For credential, it
1565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                //       is the handle of encrypt object. For
1575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                //       a Temporary Object, it is TPM_RH_NULL
1585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMI_ALG_HASH        hashAlg,                //   IN: algorithm to use for integrity
1595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_SEED          *seedIn,                 //   IN: an external seed may be provided for
1605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                //       duplication blob. For non duplication
1615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                //       blob, this parameter should be NULL
1625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT32               sensitiveSize,          //   IN: size of the marshaled sensitive data
1635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BYTE                *sensitiveData,          //   IN: sensitive area
1645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_DIGEST        *integrity               //   OUT: integrity
1655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
1665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
1675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   HMAC_STATE               hmacState;
1685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_DIGEST             hmacKey;
1695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_SEED               *seed = NULL;
1705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Get seed for KDF
1715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   seed = GetSeedForKDF(protectorHandle, seedIn);
1725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Determine the HMAC key bits
1735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   hmacKey.t.size = CryptGetHashDigestSize(hashAlg);
1745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // KDFa to generate HMAC key
1755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   KDFa(hashAlg, (TPM2B *)seed, "INTEGRITY", NULL, NULL,
1765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        hmacKey.t.size * 8, hmacKey.t.buffer, NULL);
1775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Start HMAC and get the size of the digest which will become the integrity
1785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   integrity->t.size = CryptStartHMAC2B(hashAlg, &hmacKey.b, &hmacState);
1795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Adding the marshaled sensitive area to the integrity value
1805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   CryptUpdateDigest(&hmacState, sensitiveSize, sensitiveData);
1815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Adding name
1825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   CryptUpdateDigest2B(&hmacState, (TPM2B *)name);
1835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Compute HMAC
1845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   CryptCompleteHMAC2B(&hmacState, &integrity->b);
1855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return;
1865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
1875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
1885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
1895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//           ComputeInnerIntegrity()
1905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
1915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function computes the integrity of an inner wrap
1925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
1935679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic void
1945679752bf24c21135884e987c4077e2f7184897Vadim BendeburyComputeInnerIntegrity(
1955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_ALG_ID           hashAlg,           //   IN: hash algorithm for inner wrap
1965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_NAME          *name,              //   IN: the name of the object
1975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    UINT16               dataSize,          //   IN: the size of sensitive data
1985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BYTE                *sensitiveData,     //   IN: sensitive data
1995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_DIGEST        *integrity          //   OUT: inner integrity
2005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
2015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
2025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    HASH_STATE          hashState;
2035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Start hash and get the size of the digest which will become the integrity
2045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    integrity->t.size = CryptStartHash(hashAlg, &hashState);
2055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Adding the marshaled sensitive area to the integrity value
2065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    CryptUpdateDigest(&hashState, dataSize, sensitiveData);
2075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Adding name
2085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    CryptUpdateDigest2B(&hashState, &name->b);
2095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Compute hash
2105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    CryptCompleteHash2B(&hashState, &integrity->b);
2115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    return;
2125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
2135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//           ProduceInnerIntegrity()
2165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function produces an inner integrity for regular private, credential or duplication blob It requires the
2185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      sensitive data being marshaled to the innerBuffer, with the leading bytes reserved for integrity hash. It
2195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      assume the sensitive data starts at address (innerBuffer + integrity size). This function integrity at the
2205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      beginning of the inner buffer It returns the total size of buffer with the inner wrap
2215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2225679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic UINT16
2235679752bf24c21135884e987c4077e2f7184897Vadim BendeburyProduceInnerIntegrity(
2245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_NAME          *name,              //   IN: the name of the object
2255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_ALG_ID           hashAlg,           //   IN: hash algorithm for inner wrap
2265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    UINT16               dataSize,          //   IN: the size of sensitive data, excluding the
2275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                            //       leading integrity buffer size
2285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BYTE                *innerBuffer        //   IN/OUT: inner buffer with sensitive data in
2295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                            //       it. At input, the leading bytes of this
2305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                            //       buffer is reserved for integrity
2315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
2325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
2335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BYTE                     *sensitiveData; // pointer to the sensitive data
2345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_DIGEST             integrity;
2355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    UINT16                   integritySize;
2365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BYTE                     *buffer;             // Auxiliary buffer pointer
23732be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr    INT32                    bufferSize;
2385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // sensitiveData points to the beginning of sensitive data in innerBuffer
2395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg);
2405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    sensitiveData = innerBuffer + integritySize;
2415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    ComputeInnerIntegrity(hashAlg, name, dataSize, sensitiveData, &integrity);
2425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Add integrity at the beginning of inner buffer
2435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    buffer = innerBuffer;
24432be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr    bufferSize = sizeof(TPM2B_DIGEST);
24532be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr    TPM2B_DIGEST_Marshal(&integrity, &buffer, &bufferSize);
2465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    return dataSize + integritySize;
2475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
2485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//           CheckInnerIntegrity()
2515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function check integrity of inner blob
2535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Error Returns                     Meaning
2555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_INTEGRITY                  if the outer blob integrity is bad
2575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      unmarshal errors                  unmarshal errors while unmarshaling integrity
2585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2595679752bf24c21135884e987c4077e2f7184897Vadim Bendeburystatic TPM_RC
2605679752bf24c21135884e987c4077e2f7184897Vadim BendeburyCheckInnerIntegrity(
2615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_NAME          *name,                //   IN: the name of the object
2625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_ALG_ID           hashAlg,             //   IN: hash algorithm for inner wrap
2635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    UINT16               dataSize,            //   IN: the size of sensitive data, including the
2645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                              //       leading integrity buffer size
2655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BYTE                *innerBuffer          //   IN/OUT: inner buffer with sensitive data in
2665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                              //       it
2675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
2685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
2695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_RC              result;
2705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_DIGEST        integrity;
2715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_DIGEST        integrityToCompare;
2725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BYTE                *buffer;                          // Auxiliary buffer pointer
2735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    INT32               size;
2745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Unmarshal integrity
2755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    buffer = innerBuffer;
2765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    size = (INT32) dataSize;
2775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size);
2785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(result == TPM_RC_SUCCESS)
2795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    {
2805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Compute integrity to compare
2815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        ComputeInnerIntegrity(hashAlg, name, (UINT16) size, buffer,
2825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                              &integrityToCompare);
2835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // Compare outer blob integrity
2845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         if(!Memory2BEqual(&integrity.b, &integrityToCompare.b))
2855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             result = TPM_RC_INTEGRITY;
2865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    }
2875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    return result;
2885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
2895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//           Public Functions
2925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//           AreAttributesForParent()
2945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function is called by create, load, and import functions.
2965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Return Value                      Meaning
2985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
2995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TRUE                              properties are those of a parent
3005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      FALSE                             properties are not those of a parent
3015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
3025679752bf24c21135884e987c4077e2f7184897Vadim BendeburyBOOL
3035679752bf24c21135884e987c4077e2f7184897Vadim BendeburyAreAttributesForParent(
3045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   OBJECT             *parentObject        // IN: parent handle
3055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
3065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
3075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // This function is only called when a parent is needed. Any
3085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // time a "parent" is used, it must be authorized. When
3095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // the authorization is checked, both the public and sensitive
3105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // areas must be loaded. Just make sure...
3115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(parentObject->attributes.publicOnly == CLEAR);
3125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(ObjectDataIsStorage(&parentObject->publicArea))
3135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return TRUE;
3145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   else
3155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return FALSE;
3165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
3175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
3185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
3195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//          SchemeChecks()
3205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
3215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function validates the schemes in the public area of an object. This function is called by
3225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM2_LoadExternal() and PublicAttributesValidation().
3235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
3245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Error Returns                   Meaning
3255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
3265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_ASYMMETRIC               non-duplicable storage key and its parent have different public
3275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                      parameters
3285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_ATTRIBUTES               attempt to inject sensitive data for an asymmetric key; or attempt to
3295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                      create a symmetric cipher key that is not a decryption key
3305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_HASH                     non-duplicable storage key and its parent have different name
3315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                      algorithm
3325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_KDF                      incorrect KDF specified for decrypting keyed hash object
3335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_KEY                      invalid key size values in an asymmetric key public area
3345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_SCHEME                   inconsistent attributes decrypt, sign, restricted and key's scheme ID;
3355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                      or hash algorithm is inconsistent with the scheme ID for keyed hash
3365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                      object
3375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_SYMMETRIC                a storage key with no symmetric algorithm specified; or non-storage
3385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                      key with symmetric algorithm different from TPM_ALG_NULL
3395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_TYPE                     unexpected object type; or non-duplicable storage key and its parent
3405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                      have different types
3415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
3425679752bf24c21135884e987c4077e2f7184897Vadim BendeburyTPM_RC
3435679752bf24c21135884e987c4077e2f7184897Vadim BendeburySchemeChecks(
3445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BOOL                load,               // IN: TRUE if load checks, FALSE if
3455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                           //     TPM2_Create()
3465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMI_DH_OBJECT      parentHandle,       // IN: input parent handle
3475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMT_PUBLIC        *publicArea          // IN: public area of the object
3485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
3495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
3505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Checks for an asymmetric key
3515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(CryptIsAsymAlgorithm(publicArea->type))
3525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
3535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       TPMT_ASYM_SCHEME        *keyScheme;
3545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       keyScheme = &publicArea->parameters.asymDetail.scheme;
3555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // An asymmetric key can't be injected
3565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // This is only checked when creating an object
3575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         if(!load && (publicArea->objectAttributes.sensitiveDataOrigin == CLEAR))
3585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             return TPM_RC_ATTRIBUTES;
3595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         if(load && !CryptAreKeySizesConsistent(publicArea))
3605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             return TPM_RC_KEY;
3615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // Keys that are both signing and decrypting must have TPM_ALG_NULL
3625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // for scheme
3635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         if(     publicArea->objectAttributes.sign == SET
3645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             && publicArea->objectAttributes.decrypt == SET
3655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             && keyScheme->scheme != TPM_ALG_NULL)
3665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              return TPM_RC_SCHEME;
3675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // A restrict sign key must have a non-NULL scheme
3685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         if(     publicArea->objectAttributes.restricted == SET
3695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             && publicArea->objectAttributes.sign == SET
3705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             && keyScheme->scheme == TPM_ALG_NULL)
3715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             return TPM_RC_SCHEME;
3725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // Keys must have a valid sign or decrypt scheme, or a TPM_ALG_NULL
3735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // scheme
3745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // NOTE: The unmarshaling for a public area will unmarshal based on the
3755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // object type. If the type is an RSA key, then only RSA schemes will be
3765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // allowed because a TPMI_ALG_RSA_SCHEME will be unmarshaled and it
3775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // consists only of those algorithms that are allowed with an RSA key.
3785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // This means that there is no need to again make sure that the algorithm
3795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // is compatible with the object type.
3805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         if(    keyScheme->scheme != TPM_ALG_NULL
3815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             && (    (    publicArea->objectAttributes.sign == SET
3825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                       && !CryptIsSignScheme(keyScheme->scheme)
3835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                     )
3845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  || (    publicArea->objectAttributes.decrypt == SET
3855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                       && !CryptIsDecryptScheme(keyScheme->scheme)
3865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                     )
3875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                )
3885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           )
3895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              return TPM_RC_SCHEME;
3905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Special checks for an ECC key
3915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef TPM_ALG_ECC
3925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(publicArea->type == TPM_ALG_ECC)
3935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       {
3945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           TPM_ECC_CURVE        curveID = publicArea->parameters.eccDetail.curveID;
3955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           const TPMT_ECC_SCHEME *curveScheme = CryptGetCurveSignScheme(curveID);
3965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           // The curveId must be valid or the unmarshaling is busted.
3975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           pAssert(curveScheme != NULL);
3985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             // If the curveID requires a specific scheme, then the key must select
3995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             // the same scheme
4005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             if(curveScheme->scheme != TPM_ALG_NULL)
4015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             {
4025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                 if(keyScheme->scheme != curveScheme->scheme)
4035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                      return TPM_RC_SCHEME;
4045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                 // The scheme can allow any hash, or not...
405a49f9129735985d8851e38da0f2ca4380a51e388Vadim Bendebury                 if(    curveScheme->details.anySig.hashAlg != TPM_ALG_NULL
4065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                     && (   keyScheme->details.anySig.hashAlg
407a49f9129735985d8851e38da0f2ca4380a51e388Vadim Bendebury                         != curveScheme->details.anySig.hashAlg
4085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                        )
4095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                   )
4105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                      return TPM_RC_SCHEME;
4115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             }
4125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             // For now, the KDF must be TPM_ALG_NULL
4135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             if(publicArea->parameters.eccDetail.kdf.scheme != TPM_ALG_NULL)
4145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                 return TPM_RC_KDF;
4155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         }
4165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
4175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // Checks for a storage key (restricted + decryption)
4185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         if(   publicArea->objectAttributes.restricted == SET
4195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              && publicArea->objectAttributes.decrypt == SET)
4205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        {
4215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // A storage key must have a valid protection key
4225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              if(    publicArea->parameters.asymDetail.symmetric.algorithm
4235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  == TPM_ALG_NULL)
4245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                   return TPM_RC_SYMMETRIC;
4255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // A storage key must have a null scheme
4265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              if(publicArea->parameters.asymDetail.scheme.scheme != TPM_ALG_NULL)
4275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  return TPM_RC_SCHEME;
4285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // A storage key must match its parent algorithms unless
4295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // it is duplicable or a primary (including Temporary Primary Objects)
4305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              if(    HandleGetType(parentHandle) != TPM_HT_PERMANENT
4315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  && publicArea->objectAttributes.fixedParent == SET
4325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                )
4335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              {
4345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                   // If the object to be created is a storage key, and is fixedParent,
4355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                   // its crypto set has to match its parent's crypto set. TPM_RC_TYPE,
4365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                   // TPM_RC_HASH or TPM_RC_ASYMMETRIC may be returned at this point
4375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                   return EqualCryptSet(publicArea,
4385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                        &(ObjectGet(parentHandle)->publicArea));
4395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              }
4405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        }
4415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        else
4425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        {
4435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // Non-storage keys must have TPM_ALG_NULL for the symmetric algorithm
4445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              if(    publicArea->parameters.asymDetail.symmetric.algorithm
4455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  != TPM_ALG_NULL)
4465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                   return TPM_RC_SYMMETRIC;
4475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       }// End of asymmetric decryption key checks
4485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   } // End of asymmetric checks
4495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Check for bit attributes
4505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   else if(publicArea->type == TPM_ALG_KEYEDHASH)
4515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
4525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       TPMT_KEYEDHASH_SCHEME    *scheme
4535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           = &publicArea->parameters.keyedHashDetail.scheme;
4545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // If both sign and decrypt are set the scheme must be TPM_ALG_NULL
4555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // and the scheme selected when the key is used.
4565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // If neither sign nor decrypt is set, the scheme must be TPM_ALG_NULL
4575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // because this is a data object.
4585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(      publicArea->objectAttributes.sign
4595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           == publicArea->objectAttributes.decrypt)
4605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       {
4615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           if(scheme->scheme != TPM_ALG_NULL)
4625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                return TPM_RC_SCHEME;
4635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           return TPM_RC_SUCCESS;
4645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       }
4655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // If this is a decryption key, make sure that is is XOR and that there
4665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // is a KDF
4675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       else if(publicArea->objectAttributes.decrypt)
4685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       {
4695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           if(    scheme->scheme != TPM_ALG_XOR
4702d0870476357df22a81109512c0e8c3d5ecacfa6Jocelyn Bohr               || scheme->details.xor_.hashAlg == TPM_ALG_NULL)
4715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                return TPM_RC_SCHEME;
4722d0870476357df22a81109512c0e8c3d5ecacfa6Jocelyn Bohr           if(scheme->details.xor_.kdf == TPM_ALG_NULL)
4735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                return TPM_RC_KDF;
4745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           return TPM_RC_SUCCESS;
4755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        }
4765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // only supported signing scheme for keyedHash object is HMAC
4775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(    scheme->scheme != TPM_ALG_HMAC
4785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            || scheme->details.hmac.hashAlg == TPM_ALG_NULL)
4795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             return TPM_RC_SCHEME;
4805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // end of the checks for keyedHash
4815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         return TPM_RC_SUCCESS;
4825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
4835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   else if (publicArea->type == TPM_ALG_SYMCIPHER)
4845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
4855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Must be a decrypting key and may not be a signing key
4865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(    publicArea->objectAttributes.decrypt == CLEAR
4875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           || publicArea->objectAttributes.sign == SET
4885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         )
4895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            return TPM_RC_ATTRIBUTES;
4905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
4915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   else
4925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return TPM_RC_TYPE;
4935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return TPM_RC_SUCCESS;
4945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
4955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
4965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
4975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//          PublicAttributesValidation()
4985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
4995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function validates the values in the public area of an object. This function is called by
5005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM2_Create(), TPM2_Load(), and TPM2_CreatePrimary()
5015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
5025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Error Returns                     Meaning
5035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
5045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_ASYMMETRIC                 non-duplicable storage key and its parent have different public
5055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                        parameters
5065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_ATTRIBUTES                 fixedTPM, fixedParent, or encryptedDuplication attributes are
5075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                        inconsistent between themselves or with those of the parent object;
5085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                        inconsistent restricted, decrypt and sign attributes; attempt to inject
5095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                        sensitive data for an asymmetric key; attempt to create a symmetric
5105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                        cipher key that is not a decryption key
5115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_HASH                       non-duplicable storage key and its parent have different name
5125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                        algorithm
5135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_KDF                        incorrect KDF specified for decrypting keyed hash object
5145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_KEY                        invalid key size values in an asymmetric key public area
5155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_SCHEME                     inconsistent attributes decrypt, sign, restricted and key's scheme ID;
5165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                        or hash algorithm is inconsistent with the scheme ID for keyed hash
5175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                        object
5185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_SIZE                       authPolicy size does not match digest size of the name algorithm in
5195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                        publicArea
5205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_SYMMETRIC                  a storage key with no symmetric algorithm specified; or non-storage
5215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                        key with symmetric algorithm different from TPM_ALG_NULL
5225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_TYPE                       unexpected object type; or non-duplicable storage key and its parent
5235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                        have different types
5245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
5255679752bf24c21135884e987c4077e2f7184897Vadim BendeburyTPM_RC
5265679752bf24c21135884e987c4077e2f7184897Vadim BendeburyPublicAttributesValidation(
5275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BOOL                load,                 // IN: TRUE if load checks, FALSE if
5285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                             //     TPM2_Create()
5295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMI_DH_OBJECT      parentHandle,         // IN: input parent handle
5305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMT_PUBLIC        *publicArea            // IN: public area of the object
5315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
5325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
5335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   OBJECT                  *parentObject = NULL;
5345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(HandleGetType(parentHandle) != TPM_HT_PERMANENT)
5355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       parentObject = ObjectGet(parentHandle);
5365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Check authPolicy digest consistency
5375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(   publicArea->authPolicy.t.size != 0
5385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       && (    publicArea->authPolicy.t.size
5395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            != CryptGetHashDigestSize(publicArea->nameAlg)
5405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          )
5415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      )
5425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        return TPM_RC_SIZE;
5435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // If the parent is fixedTPM (including a Primary Object) the object must have
5445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // the same value for fixedTPM and fixedParent
5455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(     parentObject == NULL
5465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        || parentObject->publicArea.objectAttributes.fixedTPM == SET)
5475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    {
5485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(    publicArea->objectAttributes.fixedParent
5495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            != publicArea->objectAttributes.fixedTPM
5505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          )
5515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             return TPM_RC_ATTRIBUTES;
5525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    }
5535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    else
5545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // The parent is not fixedTPM so the object can't be fixedTPM
5555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(publicArea->objectAttributes.fixedTPM == SET)
5565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             return TPM_RC_ATTRIBUTES;
5575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // A restricted object cannot be both sign and decrypt and it can't be neither
5585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // sign nor decrypt
5595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if (    publicArea->objectAttributes.restricted == SET
5605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         && (    publicArea->objectAttributes.decrypt
5615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              == publicArea->objectAttributes.sign)
5625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       )
5635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         return TPM_RC_ATTRIBUTES;
5645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // A fixedTPM object can not have encryptedDuplication bit SET
5655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(    publicArea->objectAttributes.fixedTPM == SET
5665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        && publicArea->objectAttributes.encryptedDuplication == SET)
5675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        return TPM_RC_ATTRIBUTES;
5685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // If a parent object has fixedTPM CLEAR, the child must have the
5695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // same encryptedDuplication value as its parent.
5705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Primary objects are considered to have a fixedTPM parent (the seeds).
5715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(       (   parentObject != NULL
5725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              && parentObject->publicArea.objectAttributes.fixedTPM == CLEAR)
5735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Get here if parent is not fixed TPM
5745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       && (     publicArea->objectAttributes.encryptedDuplication
5755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             != parentObject->publicArea.objectAttributes.encryptedDuplication
5765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury           )
5775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      )
5785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        return TPM_RC_ATTRIBUTES;
5795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return SchemeChecks(load, parentHandle, publicArea);
5805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
5815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
5825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
5835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//            FillInCreationData()
5845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
5855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Fill in creation data for an object.
5865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
5875679752bf24c21135884e987c4077e2f7184897Vadim Bendeburyvoid
5885679752bf24c21135884e987c4077e2f7184897Vadim BendeburyFillInCreationData(
5895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMI_DH_OBJECT                     parentHandle,    //   IN: handle of parent
5905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMI_ALG_HASH                      nameHashAlg,     //   IN: name hash algorithm
5915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPML_PCR_SELECTION                *creationPCR,     //   IN: PCR selection
5925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_DATA                        *outsideData,     //   IN: outside data
5935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_CREATION_DATA               *outCreation,     //   OUT: creation data for output
5945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_DIGEST                      *creationDigest   //   OUT: creation digest
5955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
5965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
5975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
5985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BYTE                     creationBuffer[sizeof(TPMS_CREATION_DATA)];
5995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BYTE                    *buffer;
60032be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr   INT32                    bufferSize;
6015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   HASH_STATE               hashState;
6025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Fill in TPMS_CREATION_DATA in outCreation
6035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Compute PCR digest
6045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   PCRComputeCurrentDigest(nameHashAlg, creationPCR,
6055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                           &outCreation->t.creationData.pcrDigest);
6065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Put back PCR selection list
6075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   outCreation->t.creationData.pcrSelect = *creationPCR;
6085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Get locality
6095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   outCreation->t.creationData.locality
6105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       = LocalityGetAttributes(_plat__LocalityGet());
6115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   outCreation->t.creationData.parentNameAlg = TPM_ALG_NULL;
6125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // If the parent is is either a primary seed or TPM_ALG_NULL, then the Name
6135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // and QN of the parent are the parent's handle.
6145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(HandleGetType(parentHandle) == TPM_HT_PERMANENT)
6155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
616e85c65bf85bc6251895cdfe6bb6213d125cc2366ChromeOS Developer       BYTE         *buffer = &outCreation->t.creationData.parentName.t.name[0];
6175aac5855889e6b7785c34026d00504be2448ad1bJocelyn Bohr       INT32         bufferSize = sizeof(TPM_HANDLE);
6185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       outCreation->t.creationData.parentName.t.size =
61932be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr            TPM_HANDLE_Marshal(&parentHandle, &buffer, &bufferSize);
6205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // Parent qualified name of a Temporary Object is the same as parent's
6215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // name
6225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         MemoryCopy2B(&outCreation->t.creationData.parentQualifiedName.b,
6235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                      &outCreation->t.creationData.parentName.b,
624e85c65bf85bc6251895cdfe6bb6213d125cc2366ChromeOS Developer                     sizeof(outCreation->t.creationData.parentQualifiedName.t.name));
6255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
6265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   else           // Regular object
6275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
6285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       OBJECT              *parentObject = ObjectGet(parentHandle);
6295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // Set name algorithm
6305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         outCreation->t.creationData.parentNameAlg =
6315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             parentObject->publicArea.nameAlg;
6325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // Copy parent name
6335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         outCreation->t.creationData.parentName = parentObject->name;
6345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // Copy parent qualified name
6355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         outCreation->t.creationData.parentQualifiedName =
6365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             parentObject->qualifiedName;
6375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
6385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Copy outside information
6395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   outCreation->t.creationData.outsideInfo = *outsideData;
6405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Marshal creation data to canonical form
6415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   buffer = creationBuffer;
64232be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr   bufferSize = sizeof(TPMS_CREATION_DATA);
6435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   outCreation->t.size = TPMS_CREATION_DATA_Marshal(&outCreation->t.creationData,
64432be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr                         &buffer, &bufferSize);
6455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Compute hash for creation field in public template
6465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   creationDigest->t.size = CryptStartHash(nameHashAlg, &hashState);
6475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   CryptUpdateDigest(&hashState, outCreation->t.size, creationBuffer);
6485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   CryptCompleteHash2B(&hashState, &creationDigest->b);
6495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return;
6505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
6515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//           GetSeedForKDF()
6525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
6535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Get a seed for KDF. The KDF for encryption and HMAC key use the same seed. It returns a pointer to
6545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      the seed
6555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
6565679752bf24c21135884e987c4077e2f7184897Vadim BendeburyTPM2B_SEED*
6575679752bf24c21135884e987c4077e2f7184897Vadim BendeburyGetSeedForKDF(
6585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_HANDLE           protectorHandle,          // IN: the protector handle
6595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_SEED          *seedIn                    // IN: the optional input seed
6605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
6615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
6625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    OBJECT                   *protector = NULL; // Pointer to the protector
6635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Get seed for encryption key. Use input seed if provided.
6645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Otherwise, using protector object's seedValue. TPM_RH_NULL is the only
6655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // exception that we may not have a loaded object as protector. In such a
6665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // case, use nullProof as seed.
6675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(seedIn != NULL)
6685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    {
6695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        return seedIn;
6705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    }
6715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    else
6725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    {
6735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(protectorHandle == TPM_RH_NULL)
6745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        {
6755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             return (TPM2B_SEED *) &gr.nullProof;
6765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        }
6775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        else
6785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        {
6795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             protector = ObjectGet(protectorHandle);
6805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             return (TPM2B_SEED *) &protector->sensitive.seedValue;
6815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        }
6825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    }
6835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
6845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
6855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
6865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//           ProduceOuterWrap()
6875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
6885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function produce outer wrap for a buffer containing the sensitive data. It requires the sensitive data
6895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      being marshaled to the outerBuffer, with the leading bytes reserved for integrity hash. If iv is used, iv
6905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      space should be reserved at the beginning of the buffer. It assumes the sensitive data starts at address
6915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      (outerBuffer + integrity size {+ iv size}). This function performs:
6925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      a) Add IV before sensitive area if required
6935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      b) encrypt sensitive data, if iv is required, encrypt by iv. otherwise, encrypted by a NULL iv
6945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      c) add HMAC integrity at the beginning of the buffer It returns the total size of blob with outer wrap
6955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
6965679752bf24c21135884e987c4077e2f7184897Vadim BendeburyUINT16
6975679752bf24c21135884e987c4077e2f7184897Vadim BendeburyProduceOuterWrap(
6985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_HANDLE           protector,          //   IN: The handle of the object that provides
6995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                             //       protection. For object, it is parent
7005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                             //       handle. For credential, it is the handle
7015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                             //       of encrypt object.
7025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_NAME          *name,               //   IN: the name of the object
7035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_ALG_ID           hashAlg,            //   IN: hash algorithm for outer wrap
7045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_SEED          *seed,               //   IN: an external seed may be provided for
7055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                             //       duplication blob. For non duplication
7065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                             //       blob, this parameter should be NULL
7075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BOOL                 useIV,              //   IN: indicate if an IV is used
7085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    UINT16               dataSize,           //   IN: the size of sensitive data, excluding the
7095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                             //       leading integrity buffer size or the
7105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                             //       optional iv size
7115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BYTE                *outerBuffer         //   IN/OUT: outer buffer with sensitive data in
7125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                       //     it
7135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
7145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
7155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ALG_ID         symAlg;
7165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16             keyBits;
7175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_SYM_KEY      symKey;
7185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_IV           ivRNG;           // IV from RNG
7195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_IV           *iv = NULL;
7205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16             ivSize = 0;      // size of iv area, including the size field
7215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BYTE               *sensitiveData; // pointer to the sensitive data
7225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_DIGEST       integrity;
7235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16             integritySize;
7245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BYTE               *buffer;         // Auxiliary buffer pointer
72532be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr   INT32              bufferSize;
7265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Compute the beginning of sensitive data. The outer integrity should
7275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // always exist if this function function is called to make an outer wrap
7285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg);
7295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   sensitiveData = outerBuffer + integritySize;
7305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // If iv is used, adjust the pointer of sensitive data and add iv before it
7315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(useIV)
7325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
7335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       ivSize = GetIV2BSize(protector);
7345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // Generate IV from RNG. The iv data size should be the total IV area
7355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // size minus the size of size field
7365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         ivRNG.t.size = ivSize - sizeof(UINT16);
7375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         CryptGenerateRandom(ivRNG.t.size, ivRNG.t.buffer);
7385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // Marshal IV to buffer
7395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         buffer = sensitiveData;
7405aac5855889e6b7785c34026d00504be2448ad1bJocelyn Bohr         bufferSize = sizeof(TPM2B_IV);
74132be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr         TPM2B_IV_Marshal(&ivRNG, &buffer, &bufferSize);
7425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // adjust sensitive data starting after IV area
7435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         sensitiveData += ivSize;
7445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // Use iv for encryption
7455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         iv = &ivRNG;
7465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
7475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Compute symmetric key parameters for outer buffer encryption
7485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   ComputeProtectionKeyParms(protector, hashAlg, name, seed,
7495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                             &symAlg, &keyBits, &symKey);
7505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Encrypt inner buffer in place
7515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   CryptSymmetricEncrypt(sensitiveData, symAlg, keyBits,
7525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                         TPM_ALG_CFB, symKey.t.buffer, iv, dataSize,
7535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                         sensitiveData);
7545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Compute outer integrity. Integrity computation includes the optional IV
7555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // area
7565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   ComputeOuterIntegrity(name, protector, hashAlg, seed, dataSize + ivSize,
7575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                         outerBuffer + integritySize, &integrity);
7585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Add integrity at the beginning of outer buffer
7595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   buffer = outerBuffer;
7605aac5855889e6b7785c34026d00504be2448ad1bJocelyn Bohr   bufferSize = sizeof(TPM2B_DIGEST);
76132be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr   TPM2B_DIGEST_Marshal(&integrity, &buffer, &bufferSize);
7625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // return the total size in outer wrap
7635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return dataSize + integritySize + ivSize;
7645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
7655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
7665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
7675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
7685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//           UnwrapOuter()
7695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
7705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function remove the outer wrap of a blob containing sensitive data This function performs:
7715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      a) check integrity of outer blob
7725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      b) decrypt outer blob
7735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
7745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Error Returns                      Meaning
7755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
7765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_INSUFFICIENT                error during sensitive data unmarshaling
7775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_INTEGRITY                   sensitive data integrity is broken
7785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_SIZE                        error during sensitive data unmarshaling
7795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_VALUE                       IV size for CFB does not match the encryption algorithm block size
7805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
7815679752bf24c21135884e987c4077e2f7184897Vadim BendeburyTPM_RC
7825679752bf24c21135884e987c4077e2f7184897Vadim BendeburyUnwrapOuter(
7835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_HANDLE           protector,             //   IN: The handle of the object that provides
7845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                               //       protection. For object, it is parent
7855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                               //       handle. For credential, it is the handle
7865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                               //       of encrypt object.
7875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_NAME          *name,                  //   IN: the name of the object
7885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ALG_ID           hashAlg,               //   IN: hash algorithm for outer wrap
7895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_SEED          *seed,                  //   IN: an external seed may be provided for
7905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                               //       duplication blob. For non duplication
7915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                               //       blob, this parameter should be NULL.
7925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BOOL                 useIV,                 //   IN: indicates if an IV is used
7935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16               dataSize,              //   IN: size of sensitive data in outerBuffer,
7945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                               //       including the leading integrity buffer
7955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                               //       size, and an optional iv area
7965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BYTE                *outerBuffer            //   IN/OUT: sensitive data
7975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
7985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
7995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_RC              result;
8005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ALG_ID          symAlg = TPM_ALG_NULL;
8015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_SYM_KEY       symKey;
8025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16              keyBits = 0;
8035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_IV            ivIn;               // input IV retrieved from input buffer
8045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_IV            *iv = NULL;
8055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BYTE                *sensitiveData;               // pointer to the sensitive data
8065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_DIGEST        integrityToCompare;
8075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_DIGEST        integrity;
8085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   INT32               size;
8095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Unmarshal integrity
8105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   sensitiveData = outerBuffer;
8115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   size = (INT32) dataSize;
8125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   result = TPM2B_DIGEST_Unmarshal(&integrity, &sensitiveData, &size);
8135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(result == TPM_RC_SUCCESS)
8145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
8155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Compute integrity to compare
8165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       ComputeOuterIntegrity(name, protector, hashAlg, seed,
8175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                             (UINT16) size, sensitiveData,
8185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                             &integrityToCompare);
8195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // Compare outer blob integrity
8205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         if(!Memory2BEqual(&integrity.b, &integrityToCompare.b))
8215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             return TPM_RC_INTEGRITY;
8225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // Get the symmetric algorithm parameters used for encryption
8235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         ComputeProtectionKeyParms(protector, hashAlg, name, seed,
8245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                          &symAlg, &keyBits, &symKey);
8255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // Retrieve IV if it is used
8265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         if(useIV)
8275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         {
8285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             result = TPM2B_IV_Unmarshal(&ivIn, &sensitiveData, &size);
8295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             if(result == TPM_RC_SUCCESS)
8305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             {
8315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                 // The input iv size for CFB must match the encryption algorithm
8325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                 // block size
8335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                 if(ivIn.t.size != CryptGetSymmetricBlockSize(symAlg, keyBits))
8345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                     result = TPM_RC_VALUE;
8355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                 else
8365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                     iv = &ivIn;
8375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             }
8385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         }
8395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    }
8405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // If no errors, decrypt private in place
8415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(result == TPM_RC_SUCCESS)
8425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        CryptSymmetricDecrypt(sensitiveData, symAlg, keyBits,
8435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                              TPM_ALG_CFB, symKey.t.buffer, iv,
8445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                              (UINT16) size, sensitiveData);
8455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    return result;
8465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
8475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
8485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
8495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//           SensitiveToPrivate()
8505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
8515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function prepare the private blob for off the chip storage The operations in this function:
8525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      a) marshal TPM2B_SENSITIVE structure into the buffer of TPM2B_PRIVATE
8535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      b) apply encryption to the sensitive area.
8545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      c) apply outer integrity computation.
8555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
8565679752bf24c21135884e987c4077e2f7184897Vadim Bendeburyvoid
8575679752bf24c21135884e987c4077e2f7184897Vadim BendeburySensitiveToPrivate(
8585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMT_SENSITIVE      *sensitive,         //   IN: sensitive structure
8595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_NAME          *name,              //   IN: the name of the object
8605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_HANDLE           parentHandle,      //   IN: The parent's handle
8615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_ALG_ID           nameAlg,           //   IN: hash algorithm in public area. This
8625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                            //       parameter is used when parentHandle is
8635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                            //       NULL, in which case the object is
8645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                            //       temporary.
8655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_PRIVATE       *outPrivate         //   OUT: output private structure
8665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
8675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
8685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BYTE                     *buffer;                  //   Auxiliary buffer pointer
86932be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr    INT32                    bufferSize;
8705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BYTE                     *sensitiveData;           //   pointer to the sensitive data
8715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    UINT16                   dataSize;                 //   data blob size
8725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMI_ALG_HASH            hashAlg;                  //   hash algorithm for integrity
8735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    UINT16                   integritySize;
8745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    UINT16                   ivSize;
8755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    pAssert(name != NULL && name->t.size != 0);
8765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Find the hash algorithm for integrity computation
8775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    if(parentHandle == TPM_RH_NULL)
8785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    {
8795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // For Temporary Object, using self name algorithm
8805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        hashAlg = nameAlg;
8815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    }
8825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    else
8835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
8845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         // Otherwise, using parent's name algorithm
8855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury         hashAlg = ObjectGetNameAlg(parentHandle);
8865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
8875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Starting of sensitive data without wrappers
8885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   sensitiveData = outPrivate->t.buffer;
8895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Compute the integrity size
8905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg);
8915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Reserve space for integrity
8925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   sensitiveData += integritySize;
8935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Get iv size
8945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   ivSize = GetIV2BSize(parentHandle);
8955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Reserve space for iv
8965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   sensitiveData += ivSize;
8975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Marshal sensitive area, leaving the leading 2 bytes for size
8985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   buffer = sensitiveData + sizeof(UINT16);
89932be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr   bufferSize = sizeof(TPMT_SENSITIVE);
90032be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr   dataSize = TPMT_SENSITIVE_Marshal(sensitive, &buffer, &bufferSize);
9015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Adding size before the data area
9025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   buffer = sensitiveData;
90332be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr   bufferSize = sizeof(UINT16);
90432be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr   UINT16_Marshal(&dataSize, &buffer, &bufferSize);
9055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Adjust the dataSize to include the size field
9065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   dataSize += sizeof(UINT16);
9075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Adjust the pointer to inner buffer including the iv
9085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   sensitiveData = outPrivate->t.buffer + ivSize;
9095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   //Produce outer wrap, including encryption and HMAC
9105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   outPrivate->t.size = ProduceOuterWrap(parentHandle, name, hashAlg, NULL,
9115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                         TRUE, dataSize, outPrivate->t.buffer);
9125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return;
9135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
9145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
9155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
9165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//           PrivateToSensitive()
9175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
9185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Unwrap a input private area. Check the integrity, decrypt and retrieve data to a sensitive structure. The
9195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      operations in this function:
9205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      a) check the integrity HMAC of the input private area
9215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      b) decrypt the private buffer
9225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      c) unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE
9235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
9245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      Error Returns                   Meaning
9255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
9265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_INTEGRITY                if the private area integrity is bad
9275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_SENSITIVE                unmarshal errors while unmarshaling TPMS_ENCRYPT from input
9285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                      private
9295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      TPM_RC_VALUE                    outer wrapper does not have an iV of the correct size
9305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
9315679752bf24c21135884e987c4077e2f7184897Vadim BendeburyTPM_RC
9325679752bf24c21135884e987c4077e2f7184897Vadim BendeburyPrivateToSensitive(
9335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_PRIVATE       *inPrivate,          // IN: input private structure
9345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_NAME          *name,               // IN: the name of the object
9355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_HANDLE          parentHandle,    // IN: The parent's handle
9365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ALG_ID          nameAlg,         // IN: hash algorithm in public area. It is
9375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                        //     passed separately because we only pass
9385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                        //     name, rather than the whole public area
9395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                        //     of the object. This parameter is used in
9405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                        //     the following two cases: 1. primary
9415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                        //     objects. 2. duplication blob with inner
9425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                        //     wrap. In other cases, this parameter
9435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                        //     will be ignored
9445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMT_SENSITIVE     *sensitive        // OUT: sensitive structure
9455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
9465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
9475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_RC             result;
9485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BYTE               *buffer;
9495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   INT32              size;
9505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BYTE               *sensitiveData; // pointer to the sensitive data
9515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16             dataSize;
9525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16             dataSizeInput;
9535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMI_ALG_HASH      hashAlg;        // hash algorithm for integrity
9545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   OBJECT             *parent = NULL;
9555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16             integritySize;
9565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16             ivSize;
9575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Make sure that name is provided
9585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(name != NULL && name->t.size != 0);
9595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Find the hash algorithm for integrity computation
9605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(parentHandle == TPM_RH_NULL)
9615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
9625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // For Temporary Object, using self name algorithm
9635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       hashAlg = nameAlg;
9645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
9655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   else
9665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
9675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Otherwise, using parent's name algorithm
9685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       hashAlg = ObjectGetNameAlg(parentHandle);
9695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
9705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // unwrap outer
9715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   result = UnwrapOuter(parentHandle, name, hashAlg, NULL, TRUE,
9725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                        inPrivate->t.size, inPrivate->t.buffer);
9735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(result != TPM_RC_SUCCESS)
9745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return result;
9755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Compute the inner integrity size.
9765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   integritySize = sizeof(UINT16) + CryptGetHashDigestSize(hashAlg);
9775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Get iv size
9785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   ivSize = GetIV2BSize(parentHandle);
9795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // The starting of sensitive data and data size without outer wrapper
9805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   sensitiveData = inPrivate->t.buffer + integritySize + ivSize;
9815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   dataSize = inPrivate->t.size - integritySize - ivSize;
9825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Unmarshal input data size
9835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   buffer = sensitiveData;
9845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   size = (INT32) dataSize;
9855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size);
9865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(result == TPM_RC_SUCCESS)
9875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
9885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if((dataSizeInput + sizeof(UINT16)) != dataSize)
9895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            result = TPM_RC_SENSITIVE;
9905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       else
9915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       {
9925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // Unmarshal sensitive buffer to sensitive structure
9935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size);
9945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              if(result != TPM_RC_SUCCESS || size != 0)
9955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              {
9965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  pAssert(    (parent == NULL)
9975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                           || parent->publicArea.objectAttributes.fixedTPM == CLEAR);
9985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  result = TPM_RC_SENSITIVE;
9995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              }
10005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              else
10015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              {
10025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  // Always remove trailing zeros at load so that it is not necessary
10035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  // to check
10045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  // each time auth is checked.
10055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  MemoryRemoveTrailingZeros(&(sensitive->authValue));
10065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              }
10075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        }
10085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    }
10095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    return result;
10105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
10115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
10125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
10135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//          SensitiveToDuplicate()
10145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
10155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      This function prepare the duplication blob from the sensitive area. The operations in this function:
10165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      a) marshal TPMT_SENSITIVE structure into the buffer of TPM2B_PRIVATE
10175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      b) apply inner wrap to the sensitive area if required
10185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//      c) apply outer wrap if required
10195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
10205679752bf24c21135884e987c4077e2f7184897Vadim Bendeburyvoid
10215679752bf24c21135884e987c4077e2f7184897Vadim BendeburySensitiveToDuplicate(
10225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMT_SENSITIVE                *sensitive,          //   IN: sensitive structure
10235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_NAME                    *name,               //   IN: the name of the object
10245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_HANDLE                     parentHandle,       //   IN: The new parent's handle
10255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM_ALG_ID                     nameAlg,            //   IN: hash algorithm in public area. It
10265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       is passed separately because we
10275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       only pass name, rather than the
10285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       whole public area of the object.
10295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_SEED                    *seed,               //   IN: the external seed. If external
10305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       seed is provided with size of 0,
10315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       no outer wrap should be applied
10325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       to duplication blob.
10335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMT_SYM_DEF_OBJECT           *symDef,             //   IN: Symmetric key definition. If the
10345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       symmetric key algorithm is NULL,
10355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       no inner wrap should be applied.
10365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_DATA                    *innerSymKey,        //   IN/OUT: a symmetric key may be
10375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       provided to encrypt the inner
10385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       wrap of a duplication blob. May
10395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       be generated here if needed.
10405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPM2B_PRIVATE                 *outPrivate          //   OUT: output private structure
10415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    )
10425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
10435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BYTE                *buffer;        // Auxiliary buffer pointer
104432be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr    INT32               bufferSize;
10455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BYTE                *sensitiveData; // pointer to the sensitive data
10465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMI_ALG_HASH       outerHash = TPM_ALG_NULL;// The hash algorithm for outer wrap
10475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    TPMI_ALG_HASH       innerHash = TPM_ALG_NULL;// The hash algorithm for inner wrap
10485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    UINT16              dataSize;       // data blob size
10495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BOOL                doInnerWrap = FALSE;
10505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    BOOL                doOuterWrap = FALSE;
10515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Make sure that name is provided
10525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    pAssert(name != NULL && name->t.size != 0);
10535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // Make sure symDef and innerSymKey are not NULL
10545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(symDef != NULL && innerSymKey != NULL);
10555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Starting of sensitive data without wrappers
10565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   sensitiveData = outPrivate->t.buffer;
10575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Find out if inner wrap is required
10585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(symDef->algorithm != TPM_ALG_NULL)
10595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
10605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       doInnerWrap = TRUE;
10615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Use self nameAlg as inner hash algorithm
10625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       innerHash = nameAlg;
10635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Adjust sensitive data pointer
10645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(innerHash);
10655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
10665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Find out if outer wrap is required
10675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(seed->t.size != 0)
10685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
10695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       doOuterWrap = TRUE;
10705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Use parent nameAlg as outer hash algorithm
10715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       outerHash = ObjectGetNameAlg(parentHandle);
10725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Adjust sensitive data pointer
10735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(outerHash);
10745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
10755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Marshal sensitive area, leaving the leading 2 bytes for size
10765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   buffer = sensitiveData + sizeof(UINT16);
107732be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr   bufferSize = sizeof(TPMT_SENSITIVE);
107832be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr   dataSize = TPMT_SENSITIVE_Marshal(sensitive, &buffer, &bufferSize);
10795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Adding size before the data area
10805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   buffer = sensitiveData;
108132be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr   bufferSize = sizeof(UINT16);
108232be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr   UINT16_Marshal(&dataSize, &buffer, &bufferSize);
10835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Adjust the dataSize to include the size field
10845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   dataSize += sizeof(UINT16);
10855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Apply inner wrap for duplication blob. It includes both integrity and
10865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // encryption
10875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(doInnerWrap)
10885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
10895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       BYTE             *innerBuffer = NULL;
10905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       BOOL             symKeyInput = TRUE;
10915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       innerBuffer = outPrivate->t.buffer;
10925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Skip outer integrity space
10935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if(doOuterWrap)
10945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            innerBuffer += sizeof(UINT16) + CryptGetHashDigestSize(outerHash);
10955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       dataSize = ProduceInnerIntegrity(name, innerHash, dataSize,
10965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                         innerBuffer);
10975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Generate inner encryption key if needed
10985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(innerSymKey->t.size == 0)
10995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        {
11005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            innerSymKey->t.size = (symDef->keyBits.sym + 7) / 8;
11015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            CryptGenerateRandom(innerSymKey->t.size, innerSymKey->t.buffer);
11025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             // TPM generates symmetric encryption.   Set the flag to FALSE
11035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             symKeyInput = FALSE;
11045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        }
11055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        else
11065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        {
11075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             // assume the input key size should matches the symmetric definition
11085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury             pAssert(innerSymKey->t.size == (symDef->keyBits.sym + 7) / 8);
11095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        }
11105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Encrypt inner buffer in place
11115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          CryptSymmetricEncrypt(innerBuffer, symDef->algorithm,
11125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                symDef->keyBits.sym, TPM_ALG_CFB,
11135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                innerSymKey->t.buffer, NULL, dataSize,
11145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                innerBuffer);
11155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          // If the symmetric encryption key is imported, clear the buffer for
11165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          // output
11175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          if(symKeyInput)
11185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              innerSymKey->t.size = 0;
11195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
11205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Apply outer wrap for duplication blob. It includes both integrity and
11215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // encryption
11225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(doOuterWrap)
11235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
11245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       dataSize = ProduceOuterWrap(parentHandle, name, outerHash, seed, FALSE,
11255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                   dataSize, outPrivate->t.buffer);
11265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
11275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Data size for output
11285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   outPrivate->t.size = dataSize;
11295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return;
11305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
11315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
11325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
11335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//           DuplicateToSensitive()
11345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
11355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       Unwrap a duplication blob. Check the integrity, decrypt and retrieve data to a sensitive structure. The
11365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       operations in this function:
11375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       a) check the integrity HMAC of the input private area
11385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       b) decrypt the private buffer
11395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       c) unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE
11405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
11415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       Error Returns                   Meaning
11425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
11435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       TPM_RC_INSUFFICIENT             unmarshaling sensitive data from inPrivate failed
11445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       TPM_RC_INTEGRITY                inPrivate data integrity is broken
11455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       TPM_RC_SIZE                     unmarshaling sensitive data from inPrivate failed
11465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
11475679752bf24c21135884e987c4077e2f7184897Vadim BendeburyTPM_RC
11485679752bf24c21135884e987c4077e2f7184897Vadim BendeburyDuplicateToSensitive(
11495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_PRIVATE                 *inPrivate,           //   IN: input private structure
11505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_NAME                    *name,                //   IN: the name of the object
11515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_HANDLE                     parentHandle,        //   IN: The parent's handle
11525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_ALG_ID                     nameAlg,             //   IN: hash algorithm in public area.
11535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_SEED                    *seed,                //   IN: an external seed may be provided.
11545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       If external seed is provided with
11555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       size of 0, no outer wrap is
11565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       applied
11575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMT_SYM_DEF_OBJECT           *symDef,              //   IN: Symmetric key definition. If the
11585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       symmetric key algorithm is NULL,
11595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       no inner wrap is applied
11605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_DATA                    *innerSymKey,         //   IN: a symmetric key may be provided
11615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       to decrypt the inner wrap of a
11625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                                       //       duplication blob.
11635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMT_SENSITIVE                *sensitive            //   OUT: sensitive structure
11645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
11655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
11665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_RC              result;
11675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BYTE               *buffer;
11685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   INT32              size;
11695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BYTE               *sensitiveData; // pointer to the sensitive data
11705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16             dataSize;
11715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16             dataSizeInput;
11725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Make sure that name is provided
11735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(name != NULL && name->t.size != 0);
11745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Make sure symDef and innerSymKey are not NULL
11755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(symDef != NULL && innerSymKey != NULL);
11765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Starting of sensitive data
11775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   sensitiveData = inPrivate->t.buffer;
11785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   dataSize = inPrivate->t.size;
11795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Find out if outer wrap is applied
11805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(seed->t.size != 0)
11815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
11825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       TPMI_ALG_HASH   outerHash = TPM_ALG_NULL;
11835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Use parent nameAlg as outer hash algorithm
11845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        outerHash = ObjectGetNameAlg(parentHandle);
11855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        result = UnwrapOuter(parentHandle, name, outerHash, seed, FALSE,
11865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                             dataSize, sensitiveData);
11875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(result != TPM_RC_SUCCESS)
11885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            return result;
11895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Adjust sensitive data pointer and size
11905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(outerHash);
11915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        dataSize -= sizeof(UINT16) + CryptGetHashDigestSize(outerHash);
11925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
11935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Find out if inner wrap is applied
11945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(symDef->algorithm != TPM_ALG_NULL)
11955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
11965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       TPMI_ALG_HASH   innerHash = TPM_ALG_NULL;
11975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // assume the input key size should matches the symmetric definition
11985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        pAssert(innerSymKey->t.size == (symDef->keyBits.sym + 7) / 8);
11995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Decrypt inner buffer in place
12005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        CryptSymmetricDecrypt(sensitiveData, symDef->algorithm,
12015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                              symDef->keyBits.sym, TPM_ALG_CFB,
12025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                              innerSymKey->t.buffer, NULL, dataSize,
12035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                              sensitiveData);
12045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Use self nameAlg as inner hash algorithm
12055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        innerHash = nameAlg;
12065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Check inner integrity
12075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        result = CheckInnerIntegrity(name, innerHash, dataSize, sensitiveData);
12085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        if(result != TPM_RC_SUCCESS)
12095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            return result;
12105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        // Adjust sensitive data pointer and size
12115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        sensitiveData += sizeof(UINT16) + CryptGetHashDigestSize(innerHash);
12125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury        dataSize -= sizeof(UINT16) + CryptGetHashDigestSize(innerHash);
12135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
12145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Unmarshal input data size
12155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   buffer = sensitiveData;
12165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   size = (INT32) dataSize;
12175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size);
12185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(result == TPM_RC_SUCCESS)
12195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
12205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       if((dataSizeInput + sizeof(UINT16)) != dataSize)
12215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              result = TPM_RC_SIZE;
12225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          else
12235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          {
12245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // Unmarshal sensitive buffer to sensitive structure
12255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size);
12265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              // if the results is OK make sure that all the data was unmarshaled
12275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              if(result == TPM_RC_SUCCESS && size != 0)
12285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  result = TPM_RC_SIZE;
12295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       }
12305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
12315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Always remove trailing zeros at load so that it is not necessary to check
12325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // each time auth is checked.
12335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(result == TPM_RC_SUCCESS)
12345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       MemoryRemoveTrailingZeros(&(sensitive->authValue));
12355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return result;
12365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
12375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//           SecretToCredential()
12405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       This function prepare the credential blob from a secret (a TPM2B_DIGEST) The operations in this
12425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       function:
12435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       a) marshal TPM2B_DIGEST structure into the buffer of TPM2B_ID_OBJECT
12445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       b) encrypt the private buffer, excluding the leading integrity HMAC area
12455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       c) compute integrity HMAC and append to the beginning of the buffer.
12465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       d) Set the total size of TPM2B_ID_OBJECT buffer
12475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12485679752bf24c21135884e987c4077e2f7184897Vadim Bendeburyvoid
12495679752bf24c21135884e987c4077e2f7184897Vadim BendeburySecretToCredential(
12505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_DIGEST              *secret,          //   IN: secret information
12515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_NAME                *name,            //   IN: the name of the object
12525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_SEED                *seed,            //   IN: an external seed.
12535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_HANDLE                 protector,       //   IN: The protector's handle
12545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ID_OBJECT           *outIDObject      //   OUT: output credential
12555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
12565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
12575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BYTE                      *buffer;          //   Auxiliary buffer pointer
125832be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr   INT32                      bufferSize;
12595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BYTE                      *sensitiveData;   //   pointer to the sensitive data
12605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMI_ALG_HASH              outerHash;       //   The hash algorithm for outer wrap
12615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16                     dataSize;        //   data blob size
12625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   pAssert(secret != NULL && outIDObject != NULL);
12635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // use protector's name algorithm as outer hash
12645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   outerHash = ObjectGetNameAlg(protector);
12655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Marshal secret area to credential buffer, leave space for integrity
1266e85c65bf85bc6251895cdfe6bb6213d125cc2366ChromeOS Developer   sensitiveData = outIDObject->t.credential
12675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                   + sizeof(UINT16) + CryptGetHashDigestSize(outerHash);
12685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Marshal secret area
12695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   buffer = sensitiveData;
127032be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr   bufferSize = sizeof(TPM2B_DIGEST);
127132be40450906cd2c80dee4a83204931f7f3a2daaJocelyn Bohr   dataSize = TPM2B_DIGEST_Marshal(secret, &buffer, &bufferSize);
12725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Apply outer wrap
12735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   outIDObject->t.size = ProduceOuterWrap(protector,
12745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                          name,
12755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                          outerHash,
12765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                          seed,
12775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                          FALSE,
12785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                          dataSize,
1279e85c65bf85bc6251895cdfe6bb6213d125cc2366ChromeOS Developer                                          outIDObject->t.credential);
12805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return;
12815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
12825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//            CredentialToSecret()
12855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       Unwrap a credential. Check the integrity, decrypt and retrieve data to a TPM2B_DIGEST structure. The
12875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       operations in this function:
12885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       a) check the integrity HMAC of the input credential area
12895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       b) decrypt the credential buffer
12905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       c) unmarshal TPM2B_DIGEST structure into the buffer of TPM2B_DIGEST
12915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       Error Returns                      Meaning
12935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       TPM_RC_INSUFFICIENT                error during credential unmarshaling
12955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       TPM_RC_INTEGRITY                   credential integrity is broken
12965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       TPM_RC_SIZE                        error during credential unmarshaling
12975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//       TPM_RC_VALUE                       IV size does not match the encryption algorithm block size
12985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
12995679752bf24c21135884e987c4077e2f7184897Vadim BendeburyTPM_RC
13005679752bf24c21135884e987c4077e2f7184897Vadim BendeburyCredentialToSecret(
13015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ID_OBJECT          *inIDObject,             //   IN: input credential blob
13025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_NAME               *name,                   //   IN: the name of the object
13035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_SEED               *seed,                   //   IN: an external seed.
13045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_HANDLE                protector,              //   IN: The protector's handle
13055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_DIGEST             *secret                  //   OUT: secret information
13065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
13075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
13085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_RC                           result;
13095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BYTE                            *buffer;
13105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   INT32                            size;
13115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMI_ALG_HASH                    outerHash;     // The hash algorithm for outer wrap
13125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   BYTE                            *sensitiveData; // pointer to the sensitive data
13135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   UINT16                           dataSize;
13145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // use protector's name algorithm as outer hash
13155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   outerHash = ObjectGetNameAlg(protector);
13165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Unwrap outer, a TPM_RC_INTEGRITY error may be returned at this point
13175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   result = UnwrapOuter(protector, name, outerHash, seed, FALSE,
1318e85c65bf85bc6251895cdfe6bb6213d125cc2366ChromeOS Developer                        inIDObject->t.size, inIDObject->t.credential);
13195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(result == TPM_RC_SUCCESS)
13205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   {
13215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       // Compute the beginning of sensitive data
1322e85c65bf85bc6251895cdfe6bb6213d125cc2366ChromeOS Developer       sensitiveData = inIDObject->t.credential
13235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                       + sizeof(UINT16) + CryptGetHashDigestSize(outerHash);
13245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       dataSize = inIDObject->t.size
13255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                  - (sizeof(UINT16) + CryptGetHashDigestSize(outerHash));
13265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          // Unmarshal secret buffer to TPM2B_DIGEST structure
13275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          buffer = sensitiveData;
13285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          size = (INT32) dataSize;
13295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          result = TPM2B_DIGEST_Unmarshal(secret, &buffer, &size);
13305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          // If there were no other unmarshaling errors, make sure that the
13315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          // expected amount of data was recovered
13325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          if(result == TPM_RC_SUCCESS && size != 0)
13335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury              return TPM_RC_SIZE;
13345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   }
13355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return result;
13365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
1337