///////////////////////////////////////////////////////////////////////////////
/// @file dePluginSHA1.cpp
///
/// @brief sha1 (fips-180-1 standard) secure hash plugin
///
/// @author Lightning
///
/// This file is the intellectual property of Novus Delta, LLC.. Usage of the
/// contents of this file is subject to the Destiny3D Member License which
/// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
///
/// This file is distributed "AS IS" without warranty of any kind.  Novus
/// Delta, LLC. does not guarantee the fitness of the contents of this file
/// for any particular purpose.
///
/// Copyright (C) 2001-2004 Novus Delta, LLC. All Rights Reserved.
///
/// <hr>
///                                 Change History
/// <hr>
///
/// @date Sep 2004
/// @author Lightning
/// @remarks Creation
///
///////////////////////////////////////////////////////////////////////////////

#include <windows.h>
#include "dePlugins_priv.hpp"
#include "SHA1/sha1.h"

//the sha1 secure hash plugin

//ID of sha1
#ifdef DE3D_CPU_LITTLE_ENDIAN
#define SHA1ID	0x00414853		//SHA\0, SHA1, version 0.0
#else
#define SHA1ID	0x53484100		//SHA\0, SHA1, version 0.0
#endif

dePluginSHA1::dePluginSHA1()
{
	//setup the defaults
}

dePluginSHA1::~dePluginSHA1()
{
	//clear out all the settings so no one knows what they are
}

void* dePluginSHA1::GetInterface(IdePlugin::interface_t i)
{
	if (i == IdePlugin::iface_IdePlugin)
		return (IdePlugin*)(this);
	else if (i == IdePlugin::iface_IdePluginSHA1)
		return (dePluginSHA1*)(this);
	return NULL;
}

int dePluginSHA1::Release()
{
	delete this;
	return 0;
}

deBoolean dePluginSHA1::EncodeData(void *Buffer, DWORD Length, void *NewBuffer, DWORD *NewLength)
{
	SHA1Instance	SHA1Inst;

	//if no valid pointers, return deFALSE
	if(!Buffer || !Length || !NewBuffer || !NewLength)
		return deFALSE;

	//verify that *NewLength is at least the size of the needed length
	if(*NewLength < MaxEncodeLength(Length))
		return deFALSE;

	//setup the beginning part of the buffer for the header
	((SHA1Header *)NewBuffer)->ID = SHA1ID;				//id that it is SHA1
	((SHA1Header *)NewBuffer)->OriginalSize = deByteOrderBE32(Length);	//original length
	
	//init the SHA1 hash
	SHA1Init(&SHA1Inst);

	//hash the data
	SHA1Process(&SHA1Inst, (unsigned char *)Buffer, Length);

	//finish it and get the hash
	SHA1Finish(&SHA1Inst, ((SHA1Header *)NewBuffer)->SHA1Hash, sizeof((SHA1Header *)NewBuffer)->SHA1Hash);

	//copy the original data into the buffer
	memcpy(&((BYTE *)NewBuffer)[sizeof(SHA1Header)], Buffer, Length);

	return deTRUE;
}

deBoolean dePluginSHA1::DecodeData(void *Buffer, DWORD Length, void *NewBuffer, DWORD *NewLength)
{
	SHA1Instance	SHA1Inst;
	BYTE			NewHash[20];

	//if no valid pointers, return deFALSE
	if(!Buffer || !Length || !NewBuffer || !NewLength)
		return deFALSE;

	//verify that the buffer is ours
	if(((SHA1Header *)Buffer)->ID != SHA1ID)
		return deFALSE;

	//verify that *NewLength is at least the size of the needed length
	if(*NewLength < ((SHA1Header *)Buffer)->OriginalSize)
		return deFALSE;

	//make sure newlength is proper
	*NewLength = deByteOrderBE32(((SHA1Header *)Buffer)->OriginalSize);

	//init the SHA1 hash
	SHA1Init(&SHA1Inst);

	//hash the data
	SHA1Process(&SHA1Inst, &((BYTE *)Buffer)[sizeof(SHA1Header)], *NewLength);

	//finish it and get the hash
	SHA1Finish(&SHA1Inst, NewHash, sizeof(NewHash));

	//see if the hashes match
	if(memcmp(NewHash, ((SHA1Header *)Buffer)->SHA1Hash, sizeof(NewHash)))
		return deFALSE;
	
	//everything matched, give them their data
	memcpy(NewBuffer, &((BYTE *)Buffer)[sizeof(SHA1Header)], *NewLength);

	return deTRUE;
}

DWORD dePluginSHA1::MaxEncodeLength(DWORD Length)
{
	//add the size of the header to the length
	return (Length + sizeof(SHA1Header));
}

DWORD dePluginSHA1::MaxDecodeLength(void *Buffer)
{
	//return the maximum length for the hash

	//if no buffer, return 0
	if(!Buffer)
		return 0;

	//verify the header
	if(((SHA1Header *)Buffer)->ID != SHA1ID)
		return 0;

	//return the original size
	return deByteOrderBE32(((SHA1Header *)Buffer)->OriginalSize);
}