// SecureHash.h: interface for the CSecureHash class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_SECUREHASH_H__21E03927_8E4C_4589_99CA_B348C39D01FE__INCLUDED_)
#define AFX_SECUREHASH_H__21E03927_8E4C_4589_99CA_B348C39D01FE__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "KeyMakingDlg.h"

#define WM_KEY_MAKING_PROGRESS_DATA			WM_USER + 504
#define MAX_SAMPLE_NUM						262144

class CSha2Context
{
public:
	CSha2Context()
	{	
//		memset ( this , 0x0 , sizeof ( *this ) );
	}
	~CSha2Context()
	{
	}
	unsigned long	m_lTotal[2];		/*!< number of bytes processed  */
	unsigned long	m_lState[8];		/*!< intermediate digest state  */
	unsigned char	m_pBuffer[64];   /*!< data block being processed */

	unsigned char	m_byInPad[64];	/*!< HMAC: inner padding        */
	unsigned char	m_byOutPad[64];   /*!< HMAC: outer padding        */
	int				m_nHashType;		/*!< 0 => SHA-256, else SHA-224 */
};


class CSecureHash  
{
public:
	CSecureHash();
	~CSecureHash();

	void SetWnd(HWND hwnd);
	HWND			m_pHwnd;

	/**
	 * \brief          SHA-256 context setup
	 *
	 * \param pSha2Context      context to be initialized
	 * \param m_nType    0 = use SHA256, 1 = use SHA224
	 */
	void Starts ( int nHashType );

	/**
	 * \brief          SHA-256 process buffer
	 *
	 * \param pSha2Context      SHA-256 context
	 * \param pInput    buffer holding the  data
	 * \param nLength     length of the pInput data
	 */
	void Update ( unsigned char* pInput , int nLength );

	/**
	 * \brief          SHA-256 final digest
	 *
	 * \param pSha2Context      SHA-256 context
	 * \param pszOutput   SHA-224/256 checksum result
	 */
	void Finish ( unsigned char pszOutput[32] );

	/**
	 * \brief          Output = SHA-256( pInput buffer )
	 *
	 * \param pInput    buffer holding the  data
	 * \param nLength     length of the pInput data
	 * \param pszOutput   SHA-224/256 checksum result
	 * \param nHashType    0 = use SHA256, 1 = use SHA224
	 */
	void OneShot ( unsigned char* pInput , int nLength , 
						unsigned char pszOutput[32] , int nHashType );

	/**
	 * \brief          pszOutput = SHA-256( file contents )
	 *
	 * \param pszPath     pInput file name
	 * \param pszOutput   SHA-224/256 checksum result
	 * \param nHashType    0 = use SHA256, 1 = use SHA224
	 *
	 * \return         0 if successful, 1 if fopen failed,
	 *                 or 2 if fread failed
	 */
	int OneShotFromFile ( char* pszPath , unsigned char pszOutput[32] , int nHashType );

	int OneShotFromDirectory ( char* pszPath, int lSampleSize, int* lCurSize );

	/**
	 * \brief          SHA-256 HMAC context setup
	 *
	 * \param pSha2Context      HMAC context to be initialized
	 * \param pKey      HMAC secret key
	 * \param nKeyLength   length of the HMAC key
	 * \param nHashType    0 = use SHA256, 1 = use SHA224
	 */
	void HmacStarts ( unsigned char* pKey , int nKeyLength , int nHashType );

	/**
	 * \brief          SHA-256 HMAC process buffer
	 *
	 * \param pSha2Context      HMAC context
	 * \param pInput    buffer holding the  data
	 * \param nLength     length of the pInput data
	 */
	void HmacUpdate ( unsigned char *pInput , int nLength );

	/**
	 * \brief          SHA-256 HMAC final digest
	 *
	 * \param pSha2Context      HMAC context
	 * \param pszOutput   SHA-224/256 HMAC checksum result
	 */
	void HmacFinish ( unsigned char pszOutput[32] );

	/**
	 * \brief          pszOutput = HMAC-SHA-256( hmac key, pInput buffer )
	 *
	 * \param pKey      HMAC secret key
	 * \param nKeyLength   length of the HMAC key
	 * \param pInput    buffer holding the  data
	 * \param nLength     length of the pInput data
	 * \param pszOutput   HMAC-SHA-224/256 result
	 * \param nHashType    0 = use SHA256, 1 = use SHA224
	 */
	void HmacOneShot ( unsigned char* pKey , int nKeyLength ,
						unsigned char* pInput , int nLength ,
						unsigned char pszOutput[32] , int nHashType );

#if defined(POLARSSL_SELF_TEST)

	/**
	 * \brief          Checkup routine
	 *
	 * \return         0 if successful, or 1 if the test failed
	 */
	int SelfTest ( int verbose );
#endif
	void Process ( unsigned char data[64] );

	enum
	{
		HASHTYPE_SHA_256 = 0 ,
		HASHTYPE_SHA_224 ,
	};

	__forceinline void GetUlongBigEndian ( unsigned long& n , unsigned char* b , int i )
	{
		(n) = ( (unsigned long) (b)[(i)    ] << 24 )        
			| ( (unsigned long) (b)[(i) + 1] << 16 )        
			| ( (unsigned long) (b)[(i) + 2] <<  8 )        
			| ( (unsigned long) (b)[(i) + 3]       );       
	}

	__forceinline void PutUlongBigEndian ( unsigned long& n , unsigned char* b , int i )
	{
		(b)[(i)    ] = (unsigned char) ( (n) >> 24 );       
		(b)[(i) + 1] = (unsigned char) ( (n) >> 16 );     
		(b)[(i) + 2] = (unsigned char) ( (n) >>  8 );     
		(b)[(i) + 3] = (unsigned char) ( (n)       );     
	}

public:
	CSha2Context m_Context;
};

#endif // !defined(AFX_SECUREHASH_H__21E03927_8E4C_4589_99CA_B348C39D01FE__INCLUDED_)
