GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/whrlpool/wp_dgst.c Lines: 49 100 49.0 %
Date: 2017-11-07 Branches: 20 58 34.5 %

Line Branch Exec Source
1
/* $OpenBSD: wp_dgst.c,v 1.4 2014/07/12 11:25:25 miod Exp $ */
2
/**
3
 * The Whirlpool hashing function.
4
 *
5
 * <P>
6
 * <b>References</b>
7
 *
8
 * <P>
9
 * The Whirlpool algorithm was developed by
10
 * <a href="mailto:pbarreto@scopus.com.br">Paulo S. L. M. Barreto</a> and
11
 * <a href="mailto:vincent.rijmen@cryptomathic.com">Vincent Rijmen</a>.
12
 *
13
 * See
14
 *      P.S.L.M. Barreto, V. Rijmen,
15
 *      ``The Whirlpool hashing function,''
16
 *      NESSIE submission, 2000 (tweaked version, 2001),
17
 *      <https://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/whirlpool.zip>
18
 *
19
 * Based on "@version 3.0 (2003.03.12)" by Paulo S.L.M. Barreto and
20
 * Vincent Rijmen. Lookup "reference implementations" on
21
 * <http://planeta.terra.com.br/informatica/paulobarreto/>
22
 *
23
 * =============================================================================
24
 *
25
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
26
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
29
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
32
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
34
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
 *
37
 */
38
39
/*
40
 * OpenSSL-specific implementation notes.
41
 *
42
 * WHIRLPOOL_Update as well as one-stroke WHIRLPOOL both expect
43
 * number of *bytes* as input length argument. Bit-oriented routine
44
 * as specified by authors is called WHIRLPOOL_BitUpdate[!] and
45
 * does not have one-stroke counterpart.
46
 *
47
 * WHIRLPOOL_BitUpdate implements byte-oriented loop, essentially
48
 * to serve WHIRLPOOL_Update. This is done for performance.
49
 *
50
 * Unlike authors' reference implementation, block processing
51
 * routine whirlpool_block is designed to operate on multi-block
52
 * input. This is done for performance.
53
 */
54
55
#include "wp_locl.h"
56
#include <openssl/crypto.h>
57
#include <string.h>
58
59
int WHIRLPOOL_Init(WHIRLPOOL_CTX *c)
60
	{
61
24
	memset (c,0,sizeof(*c));
62
12
	return(1);
63
	}
64
65
int WHIRLPOOL_Update	(WHIRLPOOL_CTX *c,const void *_inp,size_t bytes)
66
	{
67
	/* Well, largest suitable chunk size actually is
68
	 * (1<<(sizeof(size_t)*8-3))-64, but below number
69
	 * is large enough for not to care about excessive
70
	 * calls to WHIRLPOOL_BitUpdate... */
71
	size_t chunk = ((size_t)1)<<(sizeof(size_t)*8-4);
72
	const unsigned char *inp = _inp;
73
74
42
	while (bytes>=chunk)
75
		{
76
		WHIRLPOOL_BitUpdate(c,inp,chunk*8);
77
		bytes -= chunk;
78
		inp   += chunk;
79
		}
80
14
	if (bytes)
81
14
		WHIRLPOOL_BitUpdate(c,inp,bytes*8);
82
83
14
	return(1);
84
	}
85
86
void WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX *c,const void *_inp,size_t bits)
87
	{
88
	size_t		n;
89
28
	unsigned int	bitoff = c->bitoff,
90
14
			bitrem = bitoff%8,
91
14
			inpgap = (8-(unsigned int)bits%8)&7;
92
	const unsigned char *inp=_inp;
93
94
	/* This 256-bit increment procedure relies on the size_t
95
	 * being natural size of CPU register, so that we don't
96
	 * have to mask the value in order to detect overflows. */
97
14
	c->bitlen[0] += bits;
98
14
	if (c->bitlen[0] < bits)	/* overflow */
99
		{
100
		n = 1;
101
		do  { 	c->bitlen[n]++;
102
		    } while(c->bitlen[n]==0
103
		   	    && ++n<(WHIRLPOOL_COUNTER/sizeof(size_t)));
104
		}
105
106
#ifndef OPENSSL_SMALL_FOOTPRINT
107
	reconsider:
108
14
	if (inpgap==0 && bitrem==0)	/* byte-oriented loop */
109
		{
110
28
		while (bits)
111
			{
112

28
			if (bitoff==0 && (n=bits/WHIRLPOOL_BBLOCK))
113
				{
114
10
				whirlpool_block(c,inp,n);
115
10
				inp  += n*WHIRLPOOL_BBLOCK/8;
116
10
				bits %= WHIRLPOOL_BBLOCK;
117
10
				}
118
			else
119
				{
120
4
				unsigned int byteoff = bitoff/8;
121
122
4
				bitrem = WHIRLPOOL_BBLOCK - bitoff;/* re-use bitrem */
123
4
				if (bits >= bitrem)
124
					{
125
					bits -= bitrem;
126
					bitrem /= 8;
127
					memcpy(c->data+byteoff,inp,bitrem);
128
					inp  += bitrem;
129
					whirlpool_block(c,c->data,1);
130
					bitoff = 0;
131
					}
132
				else
133
					{
134
4
					memcpy(c->data+byteoff,inp,bits/8);
135
4
					bitoff += (unsigned int)bits;
136
					bits = 0;
137
					}
138
4
				c->bitoff = bitoff;
139
				}
140
			}
141
		}
142
	else				/* bit-oriented loop */
143
#endif
144
		{
145
		/*
146
			   inp
147
			   |
148
			   +-------+-------+-------
149
			      |||||||||||||||||||||
150
			   +-------+-------+-------
151
		+-------+-------+-------+-------+-------
152
		||||||||||||||				c->data
153
		+-------+-------+-------+-------+-------
154
			|
155
			c->bitoff/8
156
		*/
157
		while (bits)
158
			{
159
			unsigned int	byteoff	= bitoff/8;
160
			unsigned char	b;
161
162
#ifndef OPENSSL_SMALL_FOOTPRINT
163
			if (bitrem==inpgap)
164
				{
165
				c->data[byteoff++] |= inp[0] & (0xff>>inpgap);
166
				inpgap = 8-inpgap;
167
				bitoff += inpgap;  bitrem = 0;	/* bitoff%8 */
168
				bits   -= inpgap;  inpgap = 0;	/* bits%8   */
169
				inp++;
170
				if (bitoff==WHIRLPOOL_BBLOCK)
171
					{
172
					whirlpool_block(c,c->data,1);
173
					bitoff = 0;
174
					}
175
				c->bitoff = bitoff;
176
				goto reconsider;
177
				}
178
			else
179
#endif
180
			if (bits>=8)
181
				{
182
				b  = ((inp[0]<<inpgap) | (inp[1]>>(8-inpgap)));
183
				b &= 0xff;
184
				if (bitrem)	c->data[byteoff++] |= b>>bitrem;
185
				else		c->data[byteoff++]  = b;
186
				bitoff += 8;
187
				bits   -= 8;
188
				inp++;
189
				if (bitoff>=WHIRLPOOL_BBLOCK)
190
					{
191
					whirlpool_block(c,c->data,1);
192
					byteoff  = 0;
193
					bitoff  %= WHIRLPOOL_BBLOCK;
194
					}
195
				if (bitrem)	c->data[byteoff] = b<<(8-bitrem);
196
				}
197
			else	/* remaining less than 8 bits */
198
				{
199
				b = (inp[0]<<inpgap)&0xff;
200
				if (bitrem)	c->data[byteoff++] |= b>>bitrem;
201
				else		c->data[byteoff++]  = b;
202
				bitoff += (unsigned int)bits;
203
				if (bitoff==WHIRLPOOL_BBLOCK)
204
					{
205
					whirlpool_block(c,c->data,1);
206
					byteoff  = 0;
207
			        	bitoff  %= WHIRLPOOL_BBLOCK;
208
					}
209
				if (bitrem)	c->data[byteoff] = b<<(8-bitrem);
210
				bits = 0;
211
				}
212
			c->bitoff = bitoff;
213
			}
214
		}
215
14
	}
216
217
int WHIRLPOOL_Final	(unsigned char *md,WHIRLPOOL_CTX *c)
218
	{
219
12
	unsigned int	bitoff  = c->bitoff,
220
6
			byteoff = bitoff/8;
221
	size_t		i,j,v;
222
	unsigned char  *p;
223
224
6
	bitoff %= 8;
225
6
	if (bitoff)	c->data[byteoff] |= 0x80>>bitoff;
226
6
	else		c->data[byteoff]  = 0x80;
227
6
	byteoff++;
228
229
	/* pad with zeros */
230
6
	if (byteoff > (WHIRLPOOL_BBLOCK/8-WHIRLPOOL_COUNTER))
231
		{
232
4
		if (byteoff<WHIRLPOOL_BBLOCK/8)
233
4
			memset(&c->data[byteoff],0,WHIRLPOOL_BBLOCK/8-byteoff);
234
4
		whirlpool_block(c,c->data,1);
235
		byteoff = 0;
236
4
		}
237
6
	if (byteoff < (WHIRLPOOL_BBLOCK/8-WHIRLPOOL_COUNTER))
238
12
		memset(&c->data[byteoff],0,
239
6
			(WHIRLPOOL_BBLOCK/8-WHIRLPOOL_COUNTER)-byteoff);
240
	/* smash 256-bit c->bitlen in big-endian order */
241
6
	p = &c->data[WHIRLPOOL_BBLOCK/8-1];	/* last byte in c->data */
242
60
	for(i=0;i<WHIRLPOOL_COUNTER/sizeof(size_t);i++)
243
432
		for(v=c->bitlen[i],j=0;j<sizeof(size_t);j++,v>>=8)
244
192
			*p-- = (unsigned char)(v&0xff);
245
246
6
	whirlpool_block(c,c->data,1);
247
248
6
	if (md)	{
249
6
		memcpy(md,c->H.c,WHIRLPOOL_DIGEST_LENGTH);
250
6
		memset(c,0,sizeof(*c));
251
6
		return(1);
252
		}
253
	return(0);
254
6
	}
255
256
unsigned char *WHIRLPOOL(const void *inp, size_t bytes,unsigned char *md)
257
	{
258
	WHIRLPOOL_CTX ctx;
259
	static unsigned char m[WHIRLPOOL_DIGEST_LENGTH];
260
261
	if (md == NULL) md=m;
262
	WHIRLPOOL_Init(&ctx);
263
	WHIRLPOOL_Update(&ctx,inp,bytes);
264
	WHIRLPOOL_Final(md,&ctx);
265
	return(md);
266
	}