/**
 * The Whirlpool hashing function.
 *
 * <P>
 * <b>References</b>
 *
 * <P>
 * The Whirlpool algorithm was developed by
 * <a href="mailto:pbarreto@scopus.com.br">Paulo S. L. M. Barreto</a> and
 * <a href="mailto:vincent.rijmen@cryptomathic.com">Vincent Rijmen</a>.
 *
 * See
 *      P.S.L.M. Barreto, V. Rijmen,
 *      ``The Whirlpool hashing function,''
 *      NESSIE submission, 2000 (tweaked version, 2001),
 *      <https://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/whirlpool.zip>
 *
 * Based on "@version 3.0 (2003.03.12)" by Paulo S.L.M. Barreto and
 * Vincent Rijmen. Lookup "reference implementations" on
 * <http://planeta.terra.com.br/informatica/paulobarreto/>
 *
 * =============================================================================
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

/*
 * OpenSSL-specific implementation notes.
 *
 * WHIRLPOOL_Update as well as one-stroke WHIRLPOOL both expect
 * number of *bytes* as input length argument. Bit-oriented routine
 * as specified by authors is called WHIRLPOOL_BitUpdate[!] and
 * does not have one-stroke counterpart.
 *
 * WHIRLPOOL_BitUpdate implements byte-oriented loop, essentially
 * to serve WHIRLPOOL_Update. This is done for performance.
 *
 * Unlike authors' reference implementation, block processing
 * routine whirlpool_block is designed to operate on multi-block
 * input. This is done for perfomance.
 */

#include "wp_locl.h"
#include <string.h>

int WHIRLPOOL_Init	(WHIRLPOOL_CTX *c)
	{
	memset (c,0,sizeof(*c));
	return(1);
	}

int WHIRLPOOL_Update	(WHIRLPOOL_CTX *c,const void *_inp,size_t bytes)
	{
	/* Well, largest suitable chunk size actually is
	 * (1<<(sizeof(size_t)*8-3))-64, but below number
	 * is large enough for not to care about excessive
	 * calls to WHIRLPOOL_BitUpdate... */
	size_t chunk = ((size_t)1)<<(sizeof(size_t)*8-4);
	const unsigned char *inp = _inp;

	while (bytes>=chunk)
		{
		WHIRLPOOL_BitUpdate(c,inp,chunk*8);
		bytes -= chunk;
		inp   += chunk;
		}
	if (bytes)
		WHIRLPOOL_BitUpdate(c,inp,bytes*8);

	return(1);
	}

void WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX *c,const void *_inp,size_t bits)
	{
	size_t		n;
	unsigned int	bitoff = c->bitoff,
			bitrem = bitoff%8,
			inpgap = (8-(unsigned int)bits%8)&7;
	const unsigned char *inp=_inp;

	/* This 256-bit increment procedure relies on the size_t
	 * being natural size of CPU register, so that we don't
	 * have to mask the value in order to detect overflows. */
	c->bitlen[0] += bits;
	if (c->bitlen[0] < bits)	/* overflow */
		{
		n = 1;
		do  { 	c->bitlen[n]++;
		    } while(c->bitlen[n]==0
		   	    && ++n<(WHIRLPOOL_COUNTER/sizeof(size_t)));
		}

#ifndef OPENSSL_SMALL_FOOTPRINT
	reconsider:
	if (inpgap==0 && bitrem==0)	/* byte-oriented loop */
		{
		while (bits)
			{
			if (bitoff==0 && (n=bits/WHIRLPOOL_BBLOCK))
				{
				whirlpool_block(c,inp,n);
				inp  += n*WHIRLPOOL_BBLOCK/8;
				bits %= WHIRLPOOL_BBLOCK;
				}
			else
				{
				unsigned int byteoff = bitoff/8;

				bitrem = WHIRLPOOL_BBLOCK - bitoff;/* re-use bitrem */
				if (bits >= bitrem)
					{
					bits -= bitrem;
					bitrem /= 8;
					memcpy(c->data+byteoff,inp,bitrem);
					inp  += bitrem;
					whirlpool_block(c,c->data,1);
					bitoff = 0;
					}
				else
					{
					memcpy(c->data+byteoff,inp,bits/8);
					bitoff += (unsigned int)bits;
					bits = 0;
					}
				c->bitoff = bitoff;
				}
			}
		}
	else				/* bit-oriented loop */
#endif
		{
		/*
			   inp
			   |
			   +-------+-------+-------
			      |||||||||||||||||||||
			   +-------+-------+-------
		+-------+-------+-------+-------+-------
		||||||||||||||				c->data
		+-------+-------+-------+-------+-------
			|
			c->bitoff/8
		*/
		while (bits)
			{
			unsigned int	byteoff	= bitoff/8;
			unsigned char	b;

#ifndef OPENSSL_SMALL_FOOTPRINT
			if (bitrem==inpgap)
				{
				c->data[byteoff++] |= inp[0] & (0xff>>inpgap);
				inpgap = 8-inpgap;
				bitoff += inpgap;  bitrem = 0;	/* bitoff%8 */
				bits   -= inpgap;  inpgap = 0;	/* bits%8   */
				inp++;
				if (bitoff==WHIRLPOOL_BBLOCK)
					{
					whirlpool_block(c,c->data,1);
					bitoff = 0;
					}
				c->bitoff = bitoff;
				goto reconsider;
				}
			else
#endif
			if (bits>=8)
				{
				b  = ((inp[0]<<inpgap) | (inp[1]>>(8-inpgap)));
				b &= 0xff;
				if (bitrem)	c->data[byteoff++] |= b>>bitrem;
				else		c->data[byteoff++]  = b;
				bitoff += 8;
				bits   -= 8;
				inp++;
				if (bitoff>=WHIRLPOOL_BBLOCK)
					{
					whirlpool_block(c,c->data,1);
					byteoff  = 0;
					bitoff  %= WHIRLPOOL_BBLOCK;
					}
				if (bitrem)	c->data[byteoff] = b<<(8-bitrem);
				}
			else	/* remaining less than 8 bits */
				{
				b = (inp[0]<<inpgap)&0xff;
				if (bitrem)	c->data[byteoff++] |= b>>bitrem;
				else		c->data[byteoff++]  = b;
				bitoff += (unsigned int)bits;
				if (bitoff==WHIRLPOOL_BBLOCK)
					{
					whirlpool_block(c,c->data,1);
					byteoff  = 0;
			        	bitoff  %= WHIRLPOOL_BBLOCK;
					}
				if (bitrem)	c->data[byteoff] = b<<(8-bitrem);
				bits = 0;
				}
			c->bitoff = bitoff;
			}
		}
	}

int WHIRLPOOL_Final	(unsigned char *md,WHIRLPOOL_CTX *c)
	{
	unsigned int	bitoff  = c->bitoff,
			byteoff = bitoff/8;
	size_t		i,j,v;
	unsigned char  *p;

	bitoff %= 8;
	if (bitoff)	c->data[byteoff] |= 0x80>>bitoff;
	else		c->data[byteoff]  = 0x80;
	byteoff++;

	/* pad with zeros */
	if (byteoff > (WHIRLPOOL_BBLOCK/8-WHIRLPOOL_COUNTER))
		{
		if (byteoff<WHIRLPOOL_BBLOCK/8)
			memset(&c->data[byteoff],0,WHIRLPOOL_BBLOCK/8-byteoff);
		whirlpool_block(c,c->data,1);
		byteoff = 0;
		}
	if (byteoff < (WHIRLPOOL_BBLOCK/8-WHIRLPOOL_COUNTER))
		memset(&c->data[byteoff],0,
			(WHIRLPOOL_BBLOCK/8-WHIRLPOOL_COUNTER)-byteoff);
	/* smash 256-bit c->bitlen in big-endian order */
	p = &c->data[WHIRLPOOL_BBLOCK/8-1];	/* last byte in c->data */
	for(i=0;i<WHIRLPOOL_COUNTER/sizeof(size_t);i++)
		for(v=c->bitlen[i],j=0;j<sizeof(size_t);j++,v>>=8)
			*p-- = (unsigned char)(v&0xff);

	whirlpool_block(c,c->data,1);

	if (md)	{
		memcpy(md,c->H.c,WHIRLPOOL_DIGEST_LENGTH);
		memset(c,0,sizeof(*c));
		return(1);
		}
	return(0);
	}

unsigned char *WHIRLPOOL(const void *inp, size_t bytes,unsigned char *md)
	{
	WHIRLPOOL_CTX ctx;
	static unsigned char m[WHIRLPOOL_DIGEST_LENGTH];

	if (md == NULL) md=m;
	WHIRLPOOL_Init(&ctx);
	WHIRLPOOL_Update(&ctx,inp,bytes);
	WHIRLPOOL_Final(md,&ctx);
	return(md);
	}
