#include "hmac_sha256.h"

#include <string.h>


void init_HMAC_SHA256( HMAC_SHA256 * hmac, const uint8_t* key, unsigned int keylength )
{
	uint8_t ipad [ SHA256_MESSAGE_BLOCK_LENGTH ];
	int i = 0;
	memset( ipad, 0, SHA256_MESSAGE_BLOCK_LENGTH );
	if( keylength > SHA256_MESSAGE_BLOCK_LENGTH )
	{
		initSHA256Hash( &hmac->hashCtx );
		updateSHA256Hash( &hmac->hashCtx, (uint8_t*)key, keylength );
		getResultAndResetSHA256Hash( &hmac->hashCtx, hmac->key );
		hmac->keyLength = SHA256_HASH_LENGTH;
	}
	else
	{
		memcpy( hmac->key, key, keylength );
		hmac->keyLength = keylength;
	}

	memcpy( ipad, hmac->key, hmac->keyLength );
	for( i = 0; i < SHA256_MESSAGE_BLOCK_LENGTH; ++i )
	{
		ipad[ i ] ^= 0x36;
	}

	initSHA256Hash( &hmac->hashCtx );
	updateSHA256Hash( &hmac->hashCtx, ipad, SHA256_MESSAGE_BLOCK_LENGTH );
}

void update_HMAC_SHA256( HMAC_SHA256 * hmac, const uint8_t* data, unsigned int datalength )
{
	updateSHA256Hash( &hmac->hashCtx, (uint8_t*)data, datalength );
}

void final_HMAC_SHA256( HMAC_SHA256 * hmac, uint8_t * mac )
{
	uint8_t opad [ SHA256_MESSAGE_BLOCK_LENGTH ];
	int i = 0;
	memset( opad, 0, SHA256_MESSAGE_BLOCK_LENGTH );

	getResultAndResetSHA256Hash( &hmac->hashCtx, mac );
	memcpy( opad, hmac->key, hmac->keyLength );
	for( i = 0; i < SHA256_MESSAGE_BLOCK_LENGTH; ++i )
	{
		opad[ i ] ^= 0x5C;
	}

	updateSHA256Hash( &hmac->hashCtx, opad, SHA256_MESSAGE_BLOCK_LENGTH );
	updateSHA256Hash( &hmac->hashCtx, mac, SHA256_HASH_LENGTH );
	getResultAndResetSHA256Hash( &hmac->hashCtx, mac );
	memset( hmac->key, 0, hmac->keyLength );
	hmac->keyLength = 0;
}

