/*
* Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
* ** IMPORTANT ** PublishedPartner API's in this file are published to 3rd party developers via the 
* Symbian website. Changes to these API's should be treated as PublishedAll API changes and the Security TA should be consulted.
* This header contains the definition of the message digest classes
*
*/




/**
 @file 
 @publishedAll
 @released
*/

#ifndef __HASH_H__
#define __HASH_H__

#include <e32base.h>


//Forward Declarations
class MSHA2Impl;

/**
 * Base class for message digests.
 */
class CMessageDigest:public CBase
	{
	public:
	/**
	 *	Enumeration to identify hash functions (aka message-digest algorithms).
	 */
	enum THashId
	{
		/** 
		 * Message Digest algorithm developed by Rivest for digital signature
		 * applications (and optimized for 8-bit machines). 
		 * 
		 * Takes a message of arbitrary length and produces a 128-bit message digest. 
		 *
		 * See RFC 1319
		 */
		EMD2,
		/** 
		 * Message Digest algorithm developed by Rivest for digital signature
		 * applications (and optimized for 32-bit machines). 
		 * 
		 * Takes a message of arbitrary length and produces a 128-bit message digest. 
		 * 
		 * See RFC 1321
		 */
		EMD5,
		/** 
		 * Secure Hash Algorithm (version 1) is a message digest algorithm developed by 
		 * NIST, along with the NSA, for use with the Digital Signature Standard (DSS).
		 * 
		 * It takes a message of less than 2^64 bits in length and produces
		 * a 160-bit message digest.
		 *
		 * See FIPS 180-1 and RFC 3174
		 */
		ESHA1,
		/** 
		 * HMAC - Hash function based Message Authentication Code is a mechanism
		 * for message authentication using cryptographic hash functions. (A checksum.)
		 * 
		 * It can be used with any iterative cryptographic hash function,
   		 * e.g., MD5, SHA-1, in combination with a secret shared key
   		 * to produce a checksum that is appended to the message.
   		 * The cryptographic strength of HMAC depends on the properties
   		 * of the underlying hash function.
		 *
		 * See RFC 2104 
		 */
		HMAC,
		/** 
		 * Message Digest algorithm developed by Rivest for digital signature
		 * applications (and optimized for 32-bit machines). 
		 * 
		 * Takes a message of arbitrary length and produces a 128-bit message digest. 
		 * 
		 * See RFC 1320
		 */
		EMD4,
		/** 
		 * Secure Hash Algorithm - 224 (version 2) is a message digest algorithm developed by 
		 * NIST, along with the NSA, for use with the Digital Signature Standard (DSS).
		 * 
		 * It takes a message of less than 2^64 bits in length and produces
		 * a 224-bit message digest.
		 *
		 * See FIPS 180-2 (with change notice), RFC3874 and FIPS 180-3
		 */
		ESHA224,
		/** 
		 * Secure Hash Algorithm - 256 (version 2) is a message digest algorithm developed by 
		 * NIST, along with the NSA, for use with the Digital Signature Standard (DSS).
		 * 
		 * It takes a message of less than 2^64 bits in length and produces
		 * a 256-bit message digest.
		 *
		 * See FIPS 180-2 and RFC 4634
		 */
		ESHA256,
		/** 
		 * Secure Hash Algorithm - 384 (version 2) is a message digest algorithm developed by 
		 * NIST, along with the NSA, for use with the Digital Signature Standard (DSS).
		 * 
		 * It takes a message of less than 2^128 bits in length and produces
		 * a 384-bit message digest.
		 *
		 * See FIPS 180-2 and RFC 4634
		 */
		ESHA384,
		/** 
		 * Secure Hash Algorithm - 512 (version 2) is a message digest algorithm developed by 
		 * NIST, along with the NSA, for use with the Digital Signature Standard (DSS).
		 * 
		 * It takes a message of less than 2^128 bits in length and produces
		 * a 512-bit message digest.
		 *
		 * See FIPS 180-2 and RFC 4634
		 */
		ESHA512
	};
	
	public:
		/** 
		 * Creates a brand new reset CMessageDigest object containing no state
		 * information from the current object.  
		 * 
		 * To make a copy of a message digest with its internal state intact,
		 * see CopyL().
		 *
		 * @return A pointer to the new reset CMessageDigest object
		 */
		IMPORT_C virtual CMessageDigest* ReplicateL(void)=0;		

		/** 
		 * Adds aMessage to the internal representation of data to be hashed,
		 * then returns a TPtrC8 of the finalised hash of all the previously
		 * appended messages.
		 * 
		 * @param aMessage	Data to be included in the hash.
		 * @return			A descriptor pointer to the buffer containing the
		 *					resulting hash.
		 */
		IMPORT_C virtual TPtrC8 Hash(const TDesC8& aMessage)=0;

		/** 
		 * Creates a new CMessageDigest object with the exact same state as
		 * the current object.  
		 *
		 * This function copies all internal state of the message digest.
		 * To create a new CMessageDigest object without the state of
		 * the current object, see ReplicateL().
		 *
		 * @return A pointer to the new CMessageDigest object
		 */
		IMPORT_C virtual CMessageDigest* CopyL(void)=0;
		
		/** 
		 * Gets the internal block size of the message digest.
		 * 
		 * @return	Internal block size of message digest in bytes.
		 */
		IMPORT_C virtual TInt BlockSize(void)=0;
		
		/** 
		 * Gets the size of the message digest output.
		 *
		 * @return	Output size of the message digest in bytes.
		 */
		IMPORT_C virtual TInt HashSize(void)=0;
		
		/** 
		 * Resets the internal state of the message digest.  
		 *
		 * A reset hash object loses all internal state representing the hashed
		 * data. A reset message digest is suitable to begin a new, distinct hash
		 * of different data.  Any previously returned TPtrC8 from a call to
		 * Final() remains valid until any subsequent call to Update() or
		 * Final().
		 */
		IMPORT_C virtual void Reset(void)=0;
		
		/**
		 * Destructor.
		 */		
		IMPORT_C ~CMessageDigest(void);
	public:
		/** 
		 * Adds data to the internal representation of messages to be hashed.
		 *
		 * @param aMessage	Data to be included in the hash.
		 * @since v8.0
		 */
		IMPORT_C virtual void Update(const TDesC8& aMessage)=0;
		
		/** 
		 * Adds aMessage to the internal representation of data to be hashed,
		 * returns a TPtrC8 of the finalised hash of all the previously
		 * appended messages, and calls Reset().
		 * 
		 * @param aMessage	Data to be included in the hash 
		 * @return			A descriptor pointer to the buffer containing the
		 *					resulting hash.
		 * @since v8.0
		 */
		IMPORT_C virtual TPtrC8 Final(const TDesC8& aMessage)=0;
		
		/** 
		 * Gets a TPtrC8 of the finalised hash of all the previously
		 * appended messages and then calls Reset().
		 * 
		 * @return	A descriptor pointer to the buffer containing the
		 * 			resulting hash.
		 * @since v8.0
		 */
		IMPORT_C virtual TPtrC8 Final(void)=0;
	public:
		/**
		 * Restores the internal state of the message digest
		 * to a previously stored state.
		 *
		 * @see StoreState()
		 */
		virtual void RestoreState() = 0;

		/**
		 * Stores the internal state of the message digest. 
		 */
		virtual void StoreState() = 0;
	protected:
		/**
		 * Constructor
		 */
		IMPORT_C CMessageDigest(void);

		/**
		 * Copy constructor
		 *
		 * @param aMD	A CMessageDigest object
		 */
		IMPORT_C CMessageDigest(const CMessageDigest& aMD);
	};

/** 
 * The MD2 block size (in bytes) 
 * 
 * @internalTechnology 
 */
const TInt MD2_BLOCK=16;

/** The size (in bytes) of the MD2 message digest */
const TInt MD2_HASH=16;

/**
 * An MD2 message digest
 */
class CMD2:public CMessageDigest

	{
	public:
		/**
		 * Creates a new MD2 object.
		 *
		 * @return	A pointer to the new CMD2 object
		 */
		IMPORT_C static CMD2* NewL(void);
		IMPORT_C CMessageDigest* ReplicateL(void);
		IMPORT_C TPtrC8 Hash(const TDesC8& aMessage);
		/** Destructor */
		IMPORT_C ~CMD2(void);
		IMPORT_C CMessageDigest* CopyL(void);
		IMPORT_C TInt BlockSize(void);
		IMPORT_C TInt HashSize(void);
		IMPORT_C void Reset(void);
		IMPORT_C void Update(const TDesC8& aMessage);
		IMPORT_C TPtrC8 Final(const TDesC8& aMessage);
		IMPORT_C TPtrC8 Final();
	public:
		void RestoreState();
		void StoreState();
	private:
		void DoUpdate(const TUint8* aData,TUint aLength);
		void DoFinal(void);
		void Block(const TUint8* aData);
	private:
		CMD2(void);
		CMD2(const CMD2& aMD2);
	private:
		TBuf8<MD2_HASH> iHash;
		TInt iNum;
		TUint8 iData[MD2_BLOCK];
		TUint iChecksum[MD2_BLOCK];
		TUint iState[MD2_BLOCK];
	private:
		TBuf8<MD2_HASH> iHashBuf;
		TUint8 iDataTemp[MD2_BLOCK];
		TUint iChecksumTemp[MD2_BLOCK];
		TUint iStateTemp[MD2_BLOCK];
	};

/** 
 * The MD5 block size (in bytes)
 * 
 * @internalTechnology 
 */
const TUint MD5_LBLOCK=16;

/** The size (in bytes) of the MD5 message digest */
const TUint MD5_HASH=16;

/**
 * An MD5 message digest
 *
 * Takes a message of arbitrary length as input and produces a 128-bit message digest. 
 *
 * The length of input data should not be longer than 2^32 in bits(2^31 in bytes)
 * which is roughly half a gig.
 *
 */
class CMD5:public CMessageDigest
	{
	public:
		/**
		 * Creates a new MD5 object.
		 *
		 * @return	A pointer to the new CMD5 object
		 */
		IMPORT_C static CMD5* NewL(void);
		IMPORT_C CMessageDigest* ReplicateL(void);
		IMPORT_C TPtrC8 Hash(const TDesC8& aMessage);
		/** Destructor */
		IMPORT_C ~CMD5(void);
		IMPORT_C CMessageDigest* CopyL(void);
		IMPORT_C TInt BlockSize(void);
		IMPORT_C TInt HashSize(void);
		IMPORT_C void Reset(void);
		IMPORT_C void Update(const TDesC8& aMessage);
		IMPORT_C TPtrC8 Final(const TDesC8& aMessage);
		IMPORT_C TPtrC8 Final();
	public:
		void RestoreState();
		void StoreState();
	private:
		CMD5(void);
		CMD5(const CMD5& aMD5);
	private:
		void DoUpdate(const TUint8* aData,TUint aLength);
		void DoFinal(void);
		void Block();
	private:
		TBuf8<MD5_HASH> iHash;
	private:
		TUint iA;
		TUint iB;
		TUint iC;
		TUint iD;
		TUint iNl;
		TUint iNh;
		TUint iData[MD5_LBLOCK];
	private:
		TUint iACopy;
		TUint iBCopy;
		TUint iCCopy;
		TUint iDCopy;
		TUint iNlCopy;
		TUint iNhCopy;
		TUint iDataCopy[MD5_LBLOCK];
	};

/** 
 * The SHA-1 block size (in bytes) 
 * 
 * @internalTechnology 
 */
const TUint SHA1_LBLOCK=16;

/** The size (in bytes) of the SHA-1 message digest */
const TUint SHA1_HASH=20;

/** The size (in bytes) of the SHA message digest */
const TUint SHA_HASH=SHA1_HASH;

/**
 * A SHA-1 message digest
 */
class CSHA1:public CMessageDigest
	{
	public:
		/**
		 * Creates a new SHA-1 object.
		 *
		 * @return	A pointer to the new SHA-1 object
		 */
		IMPORT_C static CSHA1* NewL(void);
		IMPORT_C CMessageDigest* ReplicateL(void);
		IMPORT_C TPtrC8 Hash(const TDesC8& aMessage);
		/** Destructor */
		IMPORT_C ~CSHA1(void);
		IMPORT_C CMessageDigest* CopyL(void);
		IMPORT_C TInt BlockSize(void);
		IMPORT_C TInt HashSize(void);
		IMPORT_C void Reset(void);
		IMPORT_C void Update(const TDesC8& aMessage);
		IMPORT_C TPtrC8 Final(const TDesC8& aMessage);
		IMPORT_C TPtrC8 Final();
	public:
		void RestoreState();
		void StoreState();
	private:
		CSHA1(void);
		CSHA1(const CSHA1& aSHA1);
		void ConstructL(void);
	private:
		void DoUpdate(const TUint8* aData,TUint aLength);
		void DoFinal(void);
		void Block();
	private:
		TBuf8<SHA1_HASH> iHash;
		TUint iA;
		TUint iB;
		TUint iC;
		TUint iD;
		TUint iE;
		TUint iNl;
		TUint iNh;
		TUint iData[SHA1_LBLOCK*5];
	private:
		TUint iACopy;
		TUint iBCopy;
		TUint iCCopy;
		TUint iDCopy;
		TUint iECopy;
		TUint iNlCopy;
		TUint iNhCopy;	
		TUint iDataCopy[SHA1_LBLOCK*5];
	};

enum TSH2Algo
	{
	E224Bit,
	E256Bit,
	E384Bit,
	E512Bit
	};
	
/**
 * A SHA-2 message digest
 * 
 * SHA-2 comprises of SHA-224, SHA256, SHA384 and SHA512
 */
class CSHA2 : public CMessageDigest
	{
public:
	//NewL & NewLC	
	IMPORT_C static CSHA2* NewL(TSH2Algo aAlgorithmId);
	IMPORT_C static CSHA2* NewLC(TSH2Algo aAlgorithmId);
	
	/** Destructor */
	IMPORT_C ~CSHA2(void);
	
	//From CMessageDigest
	IMPORT_C CMessageDigest* ReplicateL(void);
	IMPORT_C TPtrC8 Hash(const TDesC8& aMessage);
	IMPORT_C CMessageDigest* CopyL(void);
	IMPORT_C TInt BlockSize(void);
	IMPORT_C TInt HashSize(void);
	IMPORT_C void Reset(void);
	IMPORT_C void Update(const TDesC8& aMessage);
	IMPORT_C TPtrC8 Final(const TDesC8& aMessage);
	IMPORT_C TPtrC8 Final();

public:
	void RestoreState();
	void StoreState();
	
private:
	//Constructors
	void ConstructL(TSH2Algo aAlgorithmId);
	void ConstructL(const CSHA2& aSHA512);
	
private:
	MSHA2Impl*	iImplementation;
	const TAny*	iInitValues;
	TSH2Algo	iAlgorithmType;
	TUint		iHashSize;
	};	
	
/**
 * A SHA message digest
 *
 * @deprecated Replaced by CSHA1
 */
class CSHA:public CMessageDigest
	{
	public:
		/**
		 * Creates a new SHA object.
		 *
		 * @return	A pointer to the new SHA object
		 */
		IMPORT_C static CSHA* NewL(void);
		IMPORT_C CMessageDigest* ReplicateL(void);
		IMPORT_C TPtrC8 Hash(const TDesC8& aMessage);
		/** Destructor */
		IMPORT_C ~CSHA(void);
		IMPORT_C CMessageDigest* CopyL(void);
		IMPORT_C TInt BlockSize(void);
		IMPORT_C TInt HashSize(void);
		IMPORT_C void Reset(void);
		IMPORT_C void Update(const TDesC8& aMessage);
		IMPORT_C TPtrC8 Final(const TDesC8& aMessage);
		IMPORT_C TPtrC8 Final();
	public:
		void RestoreState();
		void StoreState();
	};

/**
 * This is the maximum block size currently supported by HMAC implementation.
 */ 
	const TUint KMaxBlockSize=128;

/**
 * An HMAC (Hashed Message Authentication Code)
 */
	class CHMAC:public CMessageDigest

	{
	public:
		/**
		 * Creates a new HMAC object from a specified type of message digest 
		 * and authentication key.
		 * 
		 * @param aKey		Authentication key.
		 * @param aDigest	A message digest to construct the HMAC from.
		 * @return			A pointer to the new CHMAC object. 
		 *					The resulting HMAC object takes ownership of aDigest
		 *					and is responsible for its deletion.
		 */
		IMPORT_C static CHMAC* NewL(const TDesC8& aKey,CMessageDigest* aDigest);
		IMPORT_C CMessageDigest* ReplicateL(void);
		IMPORT_C TPtrC8 Hash(const TDesC8& aMessage);
		/** Destructor */
		IMPORT_C ~CHMAC(void);
		IMPORT_C CMessageDigest* CopyL(void);
		IMPORT_C TInt BlockSize(void);
		IMPORT_C TInt HashSize(void);
		IMPORT_C void Reset(void);
		IMPORT_C void Update(const TDesC8& aMessage);
		IMPORT_C TPtrC8 Final(const TDesC8& aMessage);
		IMPORT_C TPtrC8 Final();
	public:
		void RestoreState();
		void StoreState();
	private:
		CHMAC(void);
		CHMAC(CMessageDigest* aDigest);
		CHMAC(const CHMAC& aHMAC);
		void InitialiseL(const TDesC8& aKey);
		void InitBlockSizeL();
		
	private:
		CMessageDigest* iDigest;
		TBuf8<KMaxBlockSize> iInnerPad;
		TBuf8<KMaxBlockSize> iOuterPad;
		TBuf8<KMaxBlockSize> iInnerPadCopy;
		TBuf8<KMaxBlockSize> iOuterPadCopy;		
		TInt iBlockSize;
	};
	
/** 
 * The MD4 block size 
 * @internalTechnology 
 */
 const TUint MD4_LBLOCK=16;

/** The size (in bytes) of the MD4 message digest */
 const TUint MD4_HASH=16;


/**
 * An MD4 message digest Algorithm.
 *
 * Takes a message of arbitrary length as input and produces a 128-bit message digest. 
 *
 * The total input length of data should not be longer than 2^32 in bits(2^31 in bytes)
 * which is roughly half a gig.
 *
 */
class CMD4:public CMessageDigest
	{
	public:
		/**
		 * Creates a new MD4 object.
		 *
		 * @return	A pointer to the new CMD4 object
		 */
		IMPORT_C static CMD4* NewL(void);
		IMPORT_C CMessageDigest* ReplicateL(void);
		IMPORT_C TPtrC8 Hash(const TDesC8& aMessage);
		/** Destructor */
		IMPORT_C ~CMD4(void);
		IMPORT_C CMessageDigest* CopyL(void);
		IMPORT_C TInt BlockSize(void);
		IMPORT_C TInt HashSize(void);
		IMPORT_C void Reset(void);
		IMPORT_C void Update(const TDesC8& aMessage);
		IMPORT_C TPtrC8 Final(const TDesC8& aMessage);
		IMPORT_C TPtrC8 Final();
	public:
		virtual void RestoreState();
		virtual void StoreState();
	private:
		CMD4(void);
		CMD4(const CMD4& aMD4);
	private:
	   /**
		* Divides the message into blocks of 512 bits and performs the
		* Block operation on them.
		*/
		void DoUpdate(const TUint8* aData,TUint aLength);
	   /**
		* Performs the Block operation on the last 512 bit block.
		* This function does the padding on the last 512 bit block
		* and also appends the length of the message to the last 64-bits
		* of the block.
		*/
		void DoFinal(void);
	   /**
		* Performs the Block operation on the 512 bit blocks
		*/
		void Block();
	private:
		/*Holds the generated 128-bit Message Digest*/
		TBuf8<MD4_HASH> iHash;
	private:
		TUint iA;
		TUint iB;
		TUint iC;
		TUint iD;
		TUint iNl;
		TUint iNh;
		TUint iData[MD4_LBLOCK];
	private:
		TUint iACopy;
		TUint iBCopy;
		TUint iCCopy;
		TUint iDCopy;
		TUint iNlCopy;
		TUint iNhCopy;
		TUint iDataCopy[MD4_LBLOCK];
	};


/**
 *	Factory to create a CMessageDigest derived object according to the identity of the hash algorithm.
 */
class CMessageDigestFactory : public CBase
{
public:
	/**
	 * Creates a CMessageDigest derived object according to the specified type of hash algorithm.
	 *
	 * @param aHashId	The identity of the hash algorithm
	 * @return			A pointer to a CMessageDigest object
	 */
	IMPORT_C static CMessageDigest* NewDigestL(CMessageDigest::THashId aHashId);

	/**
	 * Creates a CMessageDigest derived object according to the specified type of hash algorithm.
	 * 
	 * The returned pointer is put onto the cleanup stack.
	 *
	 * @param aHashId	The identity of the hash algorithm
	 * @return			A pointer to a CMessageDigest object
	 */
	IMPORT_C static CMessageDigest* NewDigestLC(CMessageDigest::THashId aHashId);

	/**
	 * Creates a CMessageDigest derived object according to the specified type of hash algorithm
	 * and authentication key.
	 *
	 * @param aHashId	The identity of the hash algorithm
	 * @param aKey		The authentication key 
	 * @return			A pointer to a CMessageDigest object
	 */
	IMPORT_C static CMessageDigest* NewHMACL(CMessageDigest::THashId aHashId, const TDesC8& aKey);

	/**
	 * Creates a CMessageDigest derived object according to the specified type of hash algorithm
	 * and authentication key.
	 * 
	 * The returned pointer is put onto the cleanup stack.
	 *
	 * @param aHashId	The identity of the hash algorithm
	 * @param aKey		The authentication key 
	 * @return			A pointer to a CMessageDigest object
	 */
	IMPORT_C static CMessageDigest* NewHMACLC(CMessageDigest::THashId aHashId, const TDesC8& aKey);
};

#endif // __HASH_H__
