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