/* Microsoft Reference Implementation for TPM 2.0
 *
 *  The copyright in this software is being made available under the BSD License,
 *  included below. This software may be subject to other third party and
 *  contributor rights, including patent rights, and no such rights are granted
 *  under this license.
 *
 *  Copyright (c) Microsoft Corporation
 *
 *  All rights reserved.
 *
 *  BSD License
 *
 *  Redistribution and use in source and binary forms, with or without modification,
 *  are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice, this list
 *  of conditions and the following disclaimer.
 *
 *  Redistributions in binary form must reproduce the above copyright notice, this
 *  list of conditions and the following disclaimer in the documentation and/or
 *  other materials provided with the distribution.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/*(Auto-generated)
 *  Created by TpmPrototypes; Version 3.0 July 18, 2017
 *  Date: Mar  7, 2020  Time: 07:06:44PM
 */

#ifndef _OBJECT_SPT_FP_H_
#define _OBJECT_SPT_FP_H_

//*** AdjustAuthSize()
// This function will validate that the input authValue is no larger than the
// digestSize for the nameAlg. It will then pad with zeros to the size of the
// digest.
BOOL AdjustAuthSize(TPM2B_AUTH*   auth,    // IN/OUT: value to adjust
                    TPMI_ALG_HASH nameAlg  // IN:
);

//*** AreAttributesForParent()
// This function is called by create, load, and import functions.
//
// Note: The 'isParent' attribute is SET when an object is loaded and it has
// attributes that are suitable for a parent object.
//  Return Type: BOOL
//      TRUE(1)         properties are those of a parent
//      FALSE(0)        properties are not those of a parent
BOOL ObjectIsParent(OBJECT* parentObject  // IN: parent handle
);

//*** CreateChecks()
// Attribute checks that are unique to creation.
//  Return Type: TPM_RC
//      TPM_RC_ATTRIBUTES       sensitiveDataOrigin is not consistent with the
//                              object type
//      other                   returns from PublicAttributesValidation()
TPM_RC
CreateChecks(OBJECT* parentObject, TPMT_PUBLIC* publicArea, UINT16 sensitiveDataSize);

//*** SchemeChecks
// This function is called by TPM2_LoadExternal() and PublicAttributesValidation().
// This function validates the schemes in the public area of an object.
//  Return Type: TPM_RC
//      TPM_RC_HASH         non-duplicable storage key and its parent have different
//                          name algorithm
//      TPM_RC_KDF          incorrect KDF specified for decrypting keyed hash object
//      TPM_RC_KEY          invalid key size values in an asymmetric key public area
//      TPM_RCS_SCHEME       inconsistent attributes 'decrypt', 'sign', 'restricted'
//                          and key's scheme ID; or hash algorithm is inconsistent
//                          with the scheme ID for keyed hash object
//      TPM_RC_SYMMETRIC    a storage key with no symmetric algorithm specified; or
//                          non-storage key with symmetric algorithm different from
//                          TPM_ALG_NULL
TPM_RC
SchemeChecks(OBJECT*      parentObject,  // IN: parent (null if primary seed)
             TPMT_PUBLIC* publicArea     // IN: public area of the object
);

//*** PublicAttributesValidation()
// This function validates the values in the public area of an object.
// This function is used in the processing of TPM2_Create, TPM2_CreatePrimary,
// TPM2_CreateLoaded(), TPM2_Load(),  TPM2_Import(), and TPM2_LoadExternal().
// For TPM2_Import() this is only used if the new parent has fixedTPM SET. For
// TPM2_LoadExternal(), this is not used for a public-only key
//  Return Type: TPM_RC
//      TPM_RC_ATTRIBUTES   'fixedTPM', 'fixedParent', or 'encryptedDuplication'
//                          attributes are inconsistent between themselves or with
//                          those of the parent object;
//                          inconsistent 'restricted', 'decrypt' and 'sign'
//                          attributes;
//                          attempt to inject sensitive data for an asymmetric key;
//                          attempt to create a symmetric cipher key that is not
//                          a decryption key
//      TPM_RC_HASH         nameAlg is TPM_ALG_NULL
//      TPM_RC_SIZE         'authPolicy' size does not match digest size of the name
//                          algorithm in 'publicArea'
//   other                  returns from SchemeChecks()
TPM_RC
PublicAttributesValidation(OBJECT*      parentObject,  // IN: input parent object
                           TPMT_PUBLIC* publicArea  // IN: public area of the object
);

//*** FillInCreationData()
// Fill in creation data for an object.
//  Return Type: void
void FillInCreationData(
    TPMI_DH_OBJECT       parentHandle,   // IN: handle of parent
    TPMI_ALG_HASH        nameHashAlg,    // IN: name hash algorithm
    TPML_PCR_SELECTION*  creationPCR,    // IN: PCR selection
    TPM2B_DATA*          outsideData,    // IN: outside data
    TPM2B_CREATION_DATA* outCreation,    // OUT: creation data for output
    TPM2B_DIGEST*        creationDigest  // OUT: creation digest
);

//*** GetSeedForKDF()
// Get a seed for KDF.  The KDF for encryption and HMAC key use the same seed.
const TPM2B* GetSeedForKDF(OBJECT* protector  // IN: the protector handle
);

//*** ProduceOuterWrap()
// This function produce outer wrap for a buffer containing the sensitive data.
// It requires the sensitive data being marshaled to the outerBuffer, with the
// leading bytes reserved for integrity hash.  If iv is used, iv space should
// be reserved at the beginning of the buffer.  It assumes the sensitive data
// starts at address (outerBuffer + integrity size @).
// This function:
//  a) adds IV before sensitive area if required;
//  b) encrypts sensitive data with IV or a NULL IV as required;
//  c) adds HMAC integrity at the beginning of the buffer; and
//  d) returns the total size of blob with outer wrap.
UINT16
ProduceOuterWrap(OBJECT* protector,   // IN: The handle of the object that provides
                                      //     protection.  For object, it is parent
                                      //     handle. For credential, it is the handle
                                      //     of encrypt object.
                 TPM2B*     name,     // IN: the name of the object
                 TPM_ALG_ID hashAlg,  // IN: hash algorithm for outer wrap
                 TPM2B*     seed,     // IN: an external seed may be provided for
                                      //     duplication blob. For non duplication
                                      //     blob, this parameter should be NULL
                 BOOL   useIV,        // IN: indicate if an IV is used
                 UINT16 dataSize,     // IN: the size of sensitive data, excluding the
                                      //     leading integrity buffer size or the
                                      //     optional iv size
                 BYTE* outerBuffer    // IN/OUT: outer buffer with sensitive data in
                                      //     it
);

//*** UnwrapOuter()
// This function remove the outer wrap of a blob containing sensitive data
// This function:
//  a) checks integrity of outer blob; and
//  b) decrypts the outer blob.
//
//  Return Type: TPM_RC
//      TPM_RCS_INSUFFICIENT     error during sensitive data unmarshaling
//      TPM_RCS_INTEGRITY        sensitive data integrity is broken
//      TPM_RCS_SIZE             error during sensitive data unmarshaling
//      TPM_RCS_VALUE            IV size for CFB does not match the encryption
//                               algorithm block size
TPM_RC
UnwrapOuter(OBJECT* protector,   // IN: The object that provides
                                 //     protection.  For object, it is parent
                                 //     handle. For credential, it is the
                                 //     encrypt object.
            TPM2B*     name,     // IN: the name of the object
            TPM_ALG_ID hashAlg,  // IN: hash algorithm for outer wrap
            TPM2B*     seed,     // IN: an external seed may be provided for
                                 //     duplication blob. For non duplication
                                 //     blob, this parameter should be NULL.
            BOOL   useIV,        // IN: indicates if an IV is used
            UINT16 dataSize,     // IN: size of sensitive data in outerBuffer,
                                 //     including the leading integrity buffer
                                 //     size, and an optional iv area
            BYTE* outerBuffer    // IN/OUT: sensitive data
);

//*** SensitiveToPrivate()
// This function prepare the private blob for off the chip storage
// This function:
//  a) marshals TPM2B_SENSITIVE structure into the buffer of TPM2B_PRIVATE
//  b) applies encryption to the sensitive area; and
//  c) applies outer integrity computation.
void SensitiveToPrivate(
    TPMT_SENSITIVE* sensitive,  // IN: sensitive structure
    TPM2B_NAME*     name,       // IN: the name of the object
    OBJECT*         parent,     // IN: The parent object
    TPM_ALG_ID      nameAlg,    // IN: hash algorithm in public area.  This
                                //     parameter is used when parentHandle is
                                //     NULL, in which case the object is
                                //     temporary.
    TPM2B_PRIVATE* outPrivate   // OUT: output private structure
);

//*** PrivateToSensitive()
// Unwrap a input private area.  Check the integrity, decrypt and retrieve data
// to a sensitive structure.
// This function:
//  a) checks the integrity HMAC of the input private area;
//  b) decrypts the private buffer; and
//  c) unmarshals TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE.
//  Return Type: TPM_RC
//      TPM_RCS_INTEGRITY       if the private area integrity is bad
//      TPM_RC_SENSITIVE        unmarshal errors while unmarshaling TPMS_ENCRYPT
//                              from input private
//      TPM_RCS_SIZE            error during sensitive data unmarshaling
//      TPM_RCS_VALUE           outer wrapper does not have an iV of the correct
//                              size
TPM_RC
PrivateToSensitive(TPM2B*     inPrivate,  // IN: input private structure
                   TPM2B*     name,       // IN: the name of the object
                   OBJECT*    parent,     // IN: parent object
                   TPM_ALG_ID nameAlg,    // IN: hash algorithm in public area.  It is
                   //     passed separately because we only pass
                   //     name, rather than the whole public area
                   //     of the object.  This parameter is used in
                   //     the following two cases: 1. primary
                   //     objects. 2. duplication blob with inner
                   //     wrap.  In other cases, this parameter
                   //     will be ignored
                   TPMT_SENSITIVE* sensitive  // OUT: sensitive structure
);

//*** SensitiveToDuplicate()
// This function prepare the duplication blob from the sensitive area.
// This function:
//  a) marshals TPMT_SENSITIVE structure into the buffer of TPM2B_PRIVATE;
//  b) applies inner wrap to the sensitive area if required; and
//  c) applies outer wrap if required.
void SensitiveToDuplicate(
    TPMT_SENSITIVE* sensitive,    // IN: sensitive structure
    TPM2B*          name,         // IN: the name of the object
    OBJECT*         parent,       // IN: The new parent object
    TPM_ALG_ID      nameAlg,      // IN: hash algorithm in public area. It
                                  //     is passed separately because we
                                  //     only pass name, rather than the
                                  //     whole public area of the object.
    TPM2B* seed,                  // IN: the external seed. If external
                                  //     seed is provided with size of 0,
                                  //     no outer wrap should be applied
                                  //     to duplication blob.
    TPMT_SYM_DEF_OBJECT* symDef,  // IN: Symmetric key definition. If the
                                  //     symmetric key algorithm is NULL,
                                  //     no inner wrap should be applied.
    TPM2B_DATA* innerSymKey,      // IN/OUT: a symmetric key may be
                                  //     provided to encrypt the inner
                                  //     wrap of a duplication blob. May
                                  //     be generated here if needed.
    TPM2B_PRIVATE* outPrivate     // OUT: output private structure
);

//*** DuplicateToSensitive()
// Unwrap a duplication blob.  Check the integrity, decrypt and retrieve data
// to a sensitive structure.
// This function:
//  a) checks the integrity HMAC of the input private area;
//  b) decrypts the private buffer; and
//  c) unmarshals TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE.
//
//  Return Type: TPM_RC
//      TPM_RC_INSUFFICIENT      unmarshaling sensitive data from 'inPrivate' failed
//      TPM_RC_INTEGRITY         'inPrivate' data integrity is broken
//      TPM_RC_SIZE              unmarshaling sensitive data from 'inPrivate' failed
TPM_RC
DuplicateToSensitive(
    TPM2B*     inPrivate,         // IN: input private structure
    TPM2B*     name,              // IN: the name of the object
    OBJECT*    parent,            // IN: the parent
    TPM_ALG_ID nameAlg,           // IN: hash algorithm in public area.
    TPM2B*     seed,              // IN: an external seed may be provided.
                                  //     If external seed is provided with
                                  //     size of 0, no outer wrap is
                                  //     applied
    TPMT_SYM_DEF_OBJECT* symDef,  // IN: Symmetric key definition. If the
                                  //     symmetric key algorithm is NULL,
                                  //     no inner wrap is applied
    TPM2B* innerSymKey,           // IN: a symmetric key may be provided
                                  //     to decrypt the inner wrap of a
                                  //     duplication blob.
    TPMT_SENSITIVE* sensitive     // OUT: sensitive structure
);

//*** SecretToCredential()
// This function prepare the credential blob from a secret (a TPM2B_DIGEST)
// This function:
//  a) marshals TPM2B_DIGEST structure into the buffer of TPM2B_ID_OBJECT;
//  b) encrypts the private buffer, excluding the leading integrity HMAC area;
//  c) computes integrity HMAC and append to the beginning of the buffer; and
//  d) sets the total size of TPM2B_ID_OBJECT buffer.
void SecretToCredential(TPM2B_DIGEST*    secret,      // IN: secret information
                        TPM2B*           name,        // IN: the name of the object
                        TPM2B*           seed,        // IN: an external seed.
                        OBJECT*          protector,   // IN: the protector
                        TPM2B_ID_OBJECT* outIDObject  // OUT: output credential
);

//*** CredentialToSecret()
// Unwrap a credential.  Check the integrity, decrypt and retrieve data
// to a TPM2B_DIGEST structure.
// This function:
//  a) checks the integrity HMAC of the input credential area;
//  b) decrypts the credential buffer; and
//  c) unmarshals TPM2B_DIGEST structure into the buffer of TPM2B_DIGEST.
//
//  Return Type: TPM_RC
//      TPM_RC_INSUFFICIENT      error during credential unmarshaling
//      TPM_RC_INTEGRITY         credential integrity is broken
//      TPM_RC_SIZE              error during credential unmarshaling
//      TPM_RC_VALUE             IV size does not match the encryption algorithm
//                               block size
TPM_RC
CredentialToSecret(TPM2B*        inIDObject,  // IN: input credential blob
                   TPM2B*        name,        // IN: the name of the object
                   TPM2B*        seed,        // IN: an external seed.
                   OBJECT*       protector,   // IN: the protector
                   TPM2B_DIGEST* secret       // OUT: secret information
);

//*** MemoryRemoveTrailingZeros()
// This function is used to adjust the length of an authorization value.
// It adjusts the size of the TPM2B so that it does not include octets
// at the end of the buffer that contain zero.
//
// This function returns the number of non-zero octets in the buffer.
UINT16
MemoryRemoveTrailingZeros(TPM2B_AUTH* auth  // IN/OUT: value to adjust
);

//*** SetLabelAndContext()
// This function sets the label and context for a derived key. It is possible
// that 'label' or 'context' can end up being an Empty Buffer.
TPM_RC
SetLabelAndContext(TPMS_DERIVE* labelContext,       // IN/OUT: the recovered label and
                                                    //      context
                   TPM2B_SENSITIVE_DATA* sensitive  // IN: the sensitive data
);

//*** UnmarshalToPublic()
// Support function to unmarshal the template. This is used because the
// Input may be a TPMT_TEMPLATE and that structure does not have the same
// size as a TPMT_PUBLIC because of the difference between the 'unique' and
// 'seed' fields.
//
// If 'derive' is not NULL, then the 'seed' field is assumed to contain
// a 'label' and 'context' that are unmarshaled into 'derive'.
TPM_RC
UnmarshalToPublic(TPMT_PUBLIC*    tOut,  // OUT: output
                  TPM2B_TEMPLATE* tIn,   // IN:
                  BOOL derivation,       // IN: indicates if this is for a derivation
                  TPMS_DERIVE* labelContext  // OUT: label and context if derivation
);

//*** ObjectSetExternal()
// Set the external attributes for an object.
void ObjectSetExternal(OBJECT* object);

#endif  // _OBJECT_SPT_FP_H_
