/* 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. */ //** Introduction // This header contains the hash structure definitions used in the TPM code // to define the amount of space to be reserved for the hash state. This allows // the TPM code to not have to import all of the symbols used by the hash // computations. This lets the build environment of the TPM code not to have // include the header files associated with the CryptoEngine code. #ifndef _CRYPT_HASH_H #define _CRYPT_HASH_H //** Hash-related Structures union SMAC_STATES; // These definitions add the high-level methods for processing state that may be // an SMAC typedef void(* SMAC_DATA_METHOD)( union SMAC_STATES *state, UINT32 size, const BYTE *buffer ); typedef UINT16(* SMAC_END_METHOD)( union SMAC_STATES *state, UINT32 size, BYTE *buffer ); typedef struct sequenceMethods { SMAC_DATA_METHOD data; SMAC_END_METHOD end; } SMAC_METHODS; #define SMAC_IMPLEMENTED (CC_MAC || CC_MAC_Start) // These definitions are here because the SMAC state is in the union of hash states. typedef struct tpmCmacState { TPM_ALG_ID symAlg; UINT16 keySizeBits; INT16 bcount; // current count of bytes accumulated in IV TPM2B_IV iv; // IV buffer TPM2B_SYM_KEY symKey; } tpmCmacState_t; typedef union SMAC_STATES { #if ALG_CMAC tpmCmacState_t cmac; #endif UINT64 pad; } SMAC_STATES; typedef struct SMAC_STATE { SMAC_METHODS smacMethods; SMAC_STATES state; } SMAC_STATE; #if ALG_SHA1 # define IF_IMPLEMENTED_SHA1(op) op(SHA1, Sha1) #else # define IF_IMPLEMENTED_SHA1(op) #endif #if ALG_SHA256 # define IF_IMPLEMENTED_SHA256(op) op(SHA256, Sha256) #else # define IF_IMPLEMENTED_SHA256(op) #endif #if ALG_SHA384 # define IF_IMPLEMENTED_SHA384(op) op(SHA384, Sha384) #else # define IF_IMPLEMENTED_SHA384(op) #endif #if ALG_SHA512 # define IF_IMPLEMENTED_SHA512(op) op(SHA512, Sha512) #else # define IF_IMPLEMENTED_SHA512(op) #endif #if ALG_SM3_256 # define IF_IMPLEMENTED_SM3_256(op) op(SM3_256, Sm3_256) #else # define IF_IMPLEMENTED_SM3_256(op) #endif #if ALG_SHA3_256 # define IF_IMPLEMENTED_SHA3_256(op) op(SHA3_256, Sha3_256) #else # define IF_IMPLEMENTED_SHA3_256(op) #endif #if ALG_SHA3_384 # define IF_IMPLEMENTED_SHA3_384(op) op(SHA3_384, Sha3_384) #else # define IF_IMPLEMENTED_SHA3_384(op) #endif #if ALG_SHA3_512 # define IF_IMPLEMENTED_SHA3_512(op) op(SHA3_512, Sha3_512) #else # define IF_IMPLEMENTED_SHA3_512(op) #endif #define FOR_EACH_HASH(op) \ IF_IMPLEMENTED_SHA1(op) \ IF_IMPLEMENTED_SHA256(op) \ IF_IMPLEMENTED_SHA384(op) \ IF_IMPLEMENTED_SM3_256(op) \ IF_IMPLEMENTED_SHA3_256(op) \ IF_IMPLEMENTED_SHA3_384(op) \ IF_IMPLEMENTED_SHA3_512(op) #define HASH_TYPE(HASH, Hash) tpmHashState##HASH##_t Hash; typedef union { FOR_EACH_HASH(HASH_TYPE) // Additions for symmetric block cipher MAC #if SMAC_IMPLEMENTED SMAC_STATE smac; #endif // to force structure alignment to be no worse than HASH_ALIGNMENT #if HASH_ALIGNMENT == 8 uint64_t align; #else uint32_t align; #endif } ANY_HASH_STATE; typedef ANY_HASH_STATE *PANY_HASH_STATE; typedef const ANY_HASH_STATE *PCANY_HASH_STATE; #define ALIGNED_SIZE(x, b) ((((x) + (b) - 1) / (b)) * (b)) // MAX_HASH_STATE_SIZE will change with each implementation. It is assumed that // a hash state will not be larger than twice the block size plus some // overhead (in this case, 16 bytes). The overall size needs to be as // large as any of the hash contexts. The structure needs to start on an // alignment boundary and be an even multiple of the alignment #define MAX_HASH_STATE_SIZE ((2 * MAX_HASH_BLOCK_SIZE) + 16) #define MAX_HASH_STATE_SIZE_ALIGNED \ ALIGNED_SIZE(MAX_HASH_STATE_SIZE, HASH_ALIGNMENT) // This is an aligned byte array that will hold any of the hash contexts. typedef ANY_HASH_STATE ALIGNED_HASH_STATE; // The header associated with the hash library is expected to define the methods // which include the calling sequence. When not compiling CryptHash.c, the methods // are not defined so we need placeholder functions for the structures #ifndef HASH_START_METHOD_DEF # define HASH_START_METHOD_DEF void (HASH_START_METHOD)(void) #endif #ifndef HASH_DATA_METHOD_DEF # define HASH_DATA_METHOD_DEF void (HASH_DATA_METHOD)(void) #endif #ifndef HASH_END_METHOD_DEF # define HASH_END_METHOD_DEF void (HASH_END_METHOD)(void) #endif #ifndef HASH_STATE_COPY_METHOD_DEF # define HASH_STATE_COPY_METHOD_DEF void (HASH_STATE_COPY_METHOD)(void) #endif #ifndef HASH_STATE_EXPORT_METHOD_DEF # define HASH_STATE_EXPORT_METHOD_DEF void (HASH_STATE_EXPORT_METHOD)(void) #endif #ifndef HASH_STATE_IMPORT_METHOD_DEF # define HASH_STATE_IMPORT_METHOD_DEF void (HASH_STATE_IMPORT_METHOD)(void) #endif // Define the prototypical function call for each of the methods. This defines the // order in which the parameters are passed to the underlying function. typedef HASH_START_METHOD_DEF; typedef HASH_DATA_METHOD_DEF; typedef HASH_END_METHOD_DEF; typedef HASH_STATE_COPY_METHOD_DEF; typedef HASH_STATE_EXPORT_METHOD_DEF; typedef HASH_STATE_IMPORT_METHOD_DEF; typedef struct _HASH_METHODS { HASH_START_METHOD *start; HASH_DATA_METHOD *data; HASH_END_METHOD *end; HASH_STATE_COPY_METHOD *copy; // Copy a hash block HASH_STATE_EXPORT_METHOD *copyOut; // Copy a hash block from a hash // context HASH_STATE_IMPORT_METHOD *copyIn; // Copy a hash block to a proper hash // context } HASH_METHODS, *PHASH_METHODS; #define HASH_TPM2B(HASH, Hash) TPM2B_TYPE(HASH##_DIGEST, HASH##_DIGEST_SIZE); FOR_EACH_HASH(HASH_TPM2B) // When the TPM implements RSA, the hash-dependent OID pointers are part of the // HASH_DEF. These macros conditionally add the OID reference to the HASH_DEF and the // HASH_DEF_TEMPLATE. #if ALG_RSA #define PKCS1_HASH_REF const BYTE *PKCS1; #define PKCS1_OID(NAME) , OID_PKCS1_##NAME #else #define PKCS1_HASH_REF #define PKCS1_OID(NAME) #endif // When the TPM implements ECC, the hash-dependent OID pointers are part of the // HASH_DEF. These macros conditionally add the OID reference to the HASH_DEF and the // HASH_DEF_TEMPLATE. #if ALG_ECDSA #define ECDSA_HASH_REF const BYTE *ECDSA; #define ECDSA_OID(NAME) , OID_ECDSA_##NAME #else #define ECDSA_HASH_REF #define ECDSA_OID(NAME) #endif typedef const struct HASH_DEF { HASH_METHODS method; uint16_t blockSize; uint16_t digestSize; uint16_t contextSize; uint16_t hashAlg; const BYTE *OID; PKCS1_HASH_REF // PKCS1 OID ECDSA_HASH_REF // ECDSA OID } HASH_DEF, *PHASH_DEF; // Macro to fill in the HASH_DEF for an algorithm. For SHA1, the instance would be: // HASH_DEF_TEMPLATE(Sha1, SHA1) // This handles the difference in capitalization for the various pieces. #define HASH_DEF_TEMPLATE(HASH, Hash) \ HASH_DEF Hash##_Def= { \ {(HASH_START_METHOD *)&tpmHashStart_##HASH, \ (HASH_DATA_METHOD *)&tpmHashData_##HASH, \ (HASH_END_METHOD *)&tpmHashEnd_##HASH, \ (HASH_STATE_COPY_METHOD *)&tpmHashStateCopy_##HASH, \ (HASH_STATE_EXPORT_METHOD *)&tpmHashStateExport_##HASH, \ (HASH_STATE_IMPORT_METHOD *)&tpmHashStateImport_##HASH, \ }, \ HASH##_BLOCK_SIZE, /*block size */ \ HASH##_DIGEST_SIZE, /*data size */ \ sizeof(tpmHashState##HASH##_t), \ TPM_ALG_##HASH, OID_##HASH \ PKCS1_OID(HASH) ECDSA_OID(HASH)}; // These definitions are for the types that can be in a hash state structure. // These types are used in the cryptographic utilities. This is a define rather than // an enum so that the size of this field can be explicit. typedef BYTE HASH_STATE_TYPE; #define HASH_STATE_EMPTY ((HASH_STATE_TYPE) 0) #define HASH_STATE_HASH ((HASH_STATE_TYPE) 1) #define HASH_STATE_HMAC ((HASH_STATE_TYPE) 2) #if CC_MAC || CC_MAC_Start #define HASH_STATE_SMAC ((HASH_STATE_TYPE) 3) #endif // This is the structure that is used for passing a context into the hashing // functions. It should be the same size as the function context used within // the hashing functions. This is checked when the hash function is initialized. // This version uses a new layout for the contexts and a different definition. The // state buffer is an array of HASH_UNIT values so that a decent compiler will put // the structure on a HASH_UNIT boundary. If the structure is not properly aligned, // the code that manipulates the structure will copy to a properly aligned // structure before it is used and copy the result back. This just makes things // slower. // NOTE: This version of the state had the pointer to the update method in the // state. This is to allow the SMAC functions to use the same structure without // having to replicate the entire HASH_DEF structure. typedef struct _HASH_STATE { HASH_STATE_TYPE type; // type of the context TPM_ALG_ID hashAlg; PHASH_DEF def; ANY_HASH_STATE state; } HASH_STATE, *PHASH_STATE; typedef const HASH_STATE *PCHASH_STATE; //** HMAC State Structures // An HMAC_STATE structure contains an opaque HMAC stack state. A caller would // use this structure when performing incremental HMAC operations. This structure // contains a hash state and an HMAC key and allows slightly better stack // optimization than adding an HMAC key to each hash state. typedef struct hmacState { HASH_STATE hashState; // the hash state TPM2B_HASH_BLOCK hmacKey; // the HMAC key } HMAC_STATE, *PHMAC_STATE; // This is for the external hash state. This implementation assumes that the size // of the exported hash state is no larger than the internal hash state. typedef struct { BYTE buffer[sizeof(HASH_STATE)]; } EXPORT_HASH_STATE, *PEXPORT_HASH_STATE; typedef const EXPORT_HASH_STATE *PCEXPORT_HASH_STATE; #endif // _CRYPT_HASH_H