/*
* Creation date : Fri Mar 02 10:54:21 2007
* Last modified : %modify_time%
*/
/** @file
* \brief This file contains implementation of 
* LLF_HMAC() function. 
*
* \version LLF_HMAC.c#1:csrc:1
* \author Pavel Sasunkevich
* \remarks Copyright (C) 2007 by Discretix Technologies Ltd.
* All Rights reserved
*/

/************************ Include Files ***********************/

#include "LLF_HMAC.h"
#include "tomcrypt.h"

/************************ Defines *****************************/
/************************ Enums *******************************/
/************************ Typedefs ****************************/
/************************ Global Data *************************/
/************************ Private function prototype **********/
/************************ Private Functions *******************/
/************************ Public Functions ********************/

/**
****************************************************************
* Function Name: 
*  LLF_HMAC
*
* Inputs:
* @param OperationMode [in] - The operation mode:
*                  SHA1, SHA224, SHA256, SHA384, SHA512, MD5;
* @param key_ptr [in] - The pointer to the user's key buffer;
* @param keySize [in] - The size of the received key;
* @param DataIn_ptr [in] - A pointer to the buffer that stores the data to be hashed;
* @param DataSize [in] - The size of the data to be hashed, in bytes;
* @param HmacResultBuff [out] - A pointer to the target buffer where the 
*                   HMAC result stored in the context is loaded to;
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*   The function allocates an internal HASH Context, it initializes the 
* HASH Context with the cryptographic attributes that are needed for 
* the HASH block operation (initializes H's value for the HASH algorithm).
* Next the function loads the engine with the initializing values, 
* and then processes the data block, calculating the hash.
* Finally, the function return the message digest of the data buffer .
*
* \b
* Algorithm:
*  -# Initialize HASH machine;
*  -# Perform hash operation.
***************************************************************/
CE2Error_t LLF_HMAC    ( CE2_HASH_OperationMode_t  OperationMode,	/* in */
                         DxUint8_t                 *key_ptr,		/* in */
                         DxUint16_t                keySize,			/* in */
                         DxUint8_t                 *DataIn_ptr,		/* in */
                         DxUint32_t                DataSize,		/* in */
                         CE2_HASH_Result_t         HmacResultBuff )	/* out */
{
	int hash_index;
	int error_code;
	hmac_state hmac;
	unsigned long HmacResultBuffSize = sizeof(CE2_HASH_Result_t);

	/* Which mode to use:
	SHA1, SHA224, SHA256, SHA384, SHA512, MD5. */
	switch(OperationMode)
	{
	case CE2_HASH_SHA1_mode:
		if (register_hash(&sha1_desc) == -1) 
			return CE2_LLF_HMAC_MODULE_ERROR_BASE;
		hash_index = find_hash("sha1");
		break;
    case CE2_HASH_SHA224_mode:
		if (register_hash(&sha224_desc) == -1) 
			return CE2_LLF_HMAC_MODULE_ERROR_BASE;
		hash_index = find_hash("sha224");
		break;
    case CE2_HASH_SHA256_mode:
		if (register_hash(&sha256_desc) == -1) 
			return CE2_LLF_HMAC_MODULE_ERROR_BASE;
		hash_index = find_hash("sha256");
		break;
    case CE2_HASH_SHA384_mode:
		if (register_hash(&sha384_desc) == -1) 
			return CE2_LLF_HMAC_MODULE_ERROR_BASE;
		hash_index = find_hash("sha384");
		break;
    case CE2_HASH_SHA512_mode:
		if (register_hash(&sha512_desc) == -1) 
			return CE2_LLF_HMAC_MODULE_ERROR_BASE;
		hash_index = find_hash("sha512");
		break;
    case CE2_HASH_MD5_mode:
		if (register_hash(&md5_desc) == -1) 
			return CE2_LLF_HMAC_MODULE_ERROR_BASE;
		hash_index = find_hash("md5");
		break;
	default:
		return CE2_LLF_HMAC_MODULE_ERROR_BASE;
	}

	if (hash_index == -1)
		return CE2_LLF_HMAC_MODULE_ERROR_BASE;

	if (DataIn_ptr == DX_NULL)
	{
		/* Initialize HASH machine with key. */
		error_code = hmac_init(&hmac, hash_index, key_ptr, keySize);
		if (error_code != CRYPT_OK)
			return CE2_LLF_HMAC_MODULE_ERROR_BASE;

		/* Get HMAC result to our output buffer. */
		error_code = hmac_done(&hmac, (unsigned char*)HmacResultBuff, &HmacResultBuffSize);
	}
	else
		error_code = hmac_memory(hash_index, key_ptr, keySize, DataIn_ptr, DataSize,
			(unsigned char *)HmacResultBuff, &HmacResultBuffSize);

	return (error_code != CRYPT_OK) ? (CE2_LLF_HMAC_MODULE_ERROR_BASE) : (CE2_OK);
} /* End of LLF_HMAC */
