• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/openssl-1.0.0q/crypto/whrlpool/
1/**
2 * The Whirlpool hashing function.
3 *
4 * <P>
5 * <b>References</b>
6 *
7 * <P>
8 * The Whirlpool algorithm was developed by
9 * <a href="mailto:pbarreto@scopus.com.br">Paulo S. L. M. Barreto</a> and
10 * <a href="mailto:vincent.rijmen@cryptomathic.com">Vincent Rijmen</a>.
11 *
12 * See
13 *      P.S.L.M. Barreto, V. Rijmen,
14 *      ``The Whirlpool hashing function,''
15 *      NESSIE submission, 2000 (tweaked version, 2001),
16 *      <https://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/whirlpool.zip>
17 *
18 * Based on "@version 3.0 (2003.03.12)" by Paulo S.L.M. Barreto and
19 * Vincent Rijmen. Lookup "reference implementations" on
20 * <http://planeta.terra.com.br/informatica/paulobarreto/>
21 *
22 * =============================================================================
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
25 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
34 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 *
36 */
37
38/*
39 * OpenSSL-specific implementation notes.
40 *
41 * WHIRLPOOL_Update as well as one-stroke WHIRLPOOL both expect
42 * number of *bytes* as input length argument. Bit-oriented routine
43 * as specified by authors is called WHIRLPOOL_BitUpdate[!] and
44 * does not have one-stroke counterpart.
45 *
46 * WHIRLPOOL_BitUpdate implements byte-oriented loop, essentially
47 * to serve WHIRLPOOL_Update. This is done for performance.
48 *
49 * Unlike authors' reference implementation, block processing
50 * routine whirlpool_block is designed to operate on multi-block
51 * input. This is done for perfomance.
52 */
53
54#include "wp_locl.h"
55#include <string.h>
56
57int WHIRLPOOL_Init	(WHIRLPOOL_CTX *c)
58	{
59	memset (c,0,sizeof(*c));
60	return(1);
61	}
62
63int WHIRLPOOL_Update	(WHIRLPOOL_CTX *c,const void *_inp,size_t bytes)
64	{
65	/* Well, largest suitable chunk size actually is
66	 * (1<<(sizeof(size_t)*8-3))-64, but below number
67	 * is large enough for not to care about excessive
68	 * calls to WHIRLPOOL_BitUpdate... */
69	size_t chunk = ((size_t)1)<<(sizeof(size_t)*8-4);
70	const unsigned char *inp = _inp;
71
72	while (bytes>=chunk)
73		{
74		WHIRLPOOL_BitUpdate(c,inp,chunk*8);
75		bytes -= chunk;
76		inp   += chunk;
77		}
78	if (bytes)
79		WHIRLPOOL_BitUpdate(c,inp,bytes*8);
80
81	return(1);
82	}
83
84void WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX *c,const void *_inp,size_t bits)
85	{
86	size_t		n;
87	unsigned int	bitoff = c->bitoff,
88			bitrem = bitoff%8,
89			inpgap = (8-(unsigned int)bits%8)&7;
90	const unsigned char *inp=_inp;
91
92	/* This 256-bit increment procedure relies on the size_t
93	 * being natural size of CPU register, so that we don't
94	 * have to mask the value in order to detect overflows. */
95	c->bitlen[0] += bits;
96	if (c->bitlen[0] < bits)	/* overflow */
97		{
98		n = 1;
99		do  { 	c->bitlen[n]++;
100		    } while(c->bitlen[n]==0
101		   	    && ++n<(WHIRLPOOL_COUNTER/sizeof(size_t)));
102		}
103
104#ifndef OPENSSL_SMALL_FOOTPRINT
105	reconsider:
106	if (inpgap==0 && bitrem==0)	/* byte-oriented loop */
107		{
108		while (bits)
109			{
110			if (bitoff==0 && (n=bits/WHIRLPOOL_BBLOCK))
111				{
112				whirlpool_block(c,inp,n);
113				inp  += n*WHIRLPOOL_BBLOCK/8;
114				bits %= WHIRLPOOL_BBLOCK;
115				}
116			else
117				{
118				unsigned int byteoff = bitoff/8;
119
120				bitrem = WHIRLPOOL_BBLOCK - bitoff;/* re-use bitrem */
121				if (bits >= bitrem)
122					{
123					bits -= bitrem;
124					bitrem /= 8;
125					memcpy(c->data+byteoff,inp,bitrem);
126					inp  += bitrem;
127					whirlpool_block(c,c->data,1);
128					bitoff = 0;
129					}
130				else
131					{
132					memcpy(c->data+byteoff,inp,bits/8);
133					bitoff += (unsigned int)bits;
134					bits = 0;
135					}
136				c->bitoff = bitoff;
137				}
138			}
139		}
140	else				/* bit-oriented loop */
141#endif
142		{
143		/*
144			   inp
145			   |
146			   +-------+-------+-------
147			      |||||||||||||||||||||
148			   +-------+-------+-------
149		+-------+-------+-------+-------+-------
150		||||||||||||||				c->data
151		+-------+-------+-------+-------+-------
152			|
153			c->bitoff/8
154		*/
155		while (bits)
156			{
157			unsigned int	byteoff	= bitoff/8;
158			unsigned char	b;
159
160#ifndef OPENSSL_SMALL_FOOTPRINT
161			if (bitrem==inpgap)
162				{
163				c->data[byteoff++] |= inp[0] & (0xff>>inpgap);
164				inpgap = 8-inpgap;
165				bitoff += inpgap;  bitrem = 0;	/* bitoff%8 */
166				bits   -= inpgap;  inpgap = 0;	/* bits%8   */
167				inp++;
168				if (bitoff==WHIRLPOOL_BBLOCK)
169					{
170					whirlpool_block(c,c->data,1);
171					bitoff = 0;
172					}
173				c->bitoff = bitoff;
174				goto reconsider;
175				}
176			else
177#endif
178			if (bits>=8)
179				{
180				b  = ((inp[0]<<inpgap) | (inp[1]>>(8-inpgap)));
181				b &= 0xff;
182				if (bitrem)	c->data[byteoff++] |= b>>bitrem;
183				else		c->data[byteoff++]  = b;
184				bitoff += 8;
185				bits   -= 8;
186				inp++;
187				if (bitoff>=WHIRLPOOL_BBLOCK)
188					{
189					whirlpool_block(c,c->data,1);
190					byteoff  = 0;
191					bitoff  %= WHIRLPOOL_BBLOCK;
192					}
193				if (bitrem)	c->data[byteoff] = b<<(8-bitrem);
194				}
195			else	/* remaining less than 8 bits */
196				{
197				b = (inp[0]<<inpgap)&0xff;
198				if (bitrem)	c->data[byteoff++] |= b>>bitrem;
199				else		c->data[byteoff++]  = b;
200				bitoff += (unsigned int)bits;
201				if (bitoff==WHIRLPOOL_BBLOCK)
202					{
203					whirlpool_block(c,c->data,1);
204					byteoff  = 0;
205			        	bitoff  %= WHIRLPOOL_BBLOCK;
206					}
207				if (bitrem)	c->data[byteoff] = b<<(8-bitrem);
208				bits = 0;
209				}
210			c->bitoff = bitoff;
211			}
212		}
213	}
214
215int WHIRLPOOL_Final	(unsigned char *md,WHIRLPOOL_CTX *c)
216	{
217	unsigned int	bitoff  = c->bitoff,
218			byteoff = bitoff/8;
219	size_t		i,j,v;
220	unsigned char  *p;
221
222	bitoff %= 8;
223	if (bitoff)	c->data[byteoff] |= 0x80>>bitoff;
224	else		c->data[byteoff]  = 0x80;
225	byteoff++;
226
227	/* pad with zeros */
228	if (byteoff > (WHIRLPOOL_BBLOCK/8-WHIRLPOOL_COUNTER))
229		{
230		if (byteoff<WHIRLPOOL_BBLOCK/8)
231			memset(&c->data[byteoff],0,WHIRLPOOL_BBLOCK/8-byteoff);
232		whirlpool_block(c,c->data,1);
233		byteoff = 0;
234		}
235	if (byteoff < (WHIRLPOOL_BBLOCK/8-WHIRLPOOL_COUNTER))
236		memset(&c->data[byteoff],0,
237			(WHIRLPOOL_BBLOCK/8-WHIRLPOOL_COUNTER)-byteoff);
238	/* smash 256-bit c->bitlen in big-endian order */
239	p = &c->data[WHIRLPOOL_BBLOCK/8-1];	/* last byte in c->data */
240	for(i=0;i<WHIRLPOOL_COUNTER/sizeof(size_t);i++)
241		for(v=c->bitlen[i],j=0;j<sizeof(size_t);j++,v>>=8)
242			*p-- = (unsigned char)(v&0xff);
243
244	whirlpool_block(c,c->data,1);
245
246	if (md)	{
247		memcpy(md,c->H.c,WHIRLPOOL_DIGEST_LENGTH);
248		memset(c,0,sizeof(*c));
249		return(1);
250		}
251	return(0);
252	}
253
254unsigned char *WHIRLPOOL(const void *inp, size_t bytes,unsigned char *md)
255	{
256	WHIRLPOOL_CTX ctx;
257	static unsigned char m[WHIRLPOOL_DIGEST_LENGTH];
258
259	if (md == NULL) md=m;
260	WHIRLPOOL_Init(&ctx);
261	WHIRLPOOL_Update(&ctx,inp,bytes);
262	WHIRLPOOL_Final(md,&ctx);
263	return(md);
264	}
265