]>
git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/whrlpool/wp_dgst.c
2 * The Whirlpool hashing function.
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>.
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>
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/>
22 * =============================================================================
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.
39 * OpenSSL-specific implementation notes.
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.
46 * WHIRLPOOL_BitUpdate implements byte-oriented loop, essentially
47 * to serve WHIRLPOOL_Update. This is done for performance.
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.
57 int WHIRLPOOL_Init(WHIRLPOOL_CTX
*c
)
59 memset(c
, 0, sizeof(*c
));
63 int WHIRLPOOL_Update(WHIRLPOOL_CTX
*c
, const void *_inp
, size_t bytes
)
66 * Well, largest suitable chunk size actually is
67 * (1<<(sizeof(size_t)*8-3))-64, but below number is large enough for not
68 * to care about excessive calls to WHIRLPOOL_BitUpdate...
70 size_t chunk
= ((size_t)1) << (sizeof(size_t) * 8 - 4);
71 const unsigned char *inp
= _inp
;
73 while (bytes
>= chunk
) {
74 WHIRLPOOL_BitUpdate(c
, inp
, chunk
* 8);
79 WHIRLPOOL_BitUpdate(c
, inp
, bytes
* 8);
84 void WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX
*c
, const void *_inp
, size_t bits
)
87 unsigned int bitoff
= c
->bitoff
,
88 bitrem
= bitoff
% 8, inpgap
= (8 - (unsigned int)bits
% 8) & 7;
89 const unsigned char *inp
= _inp
;
92 * This 256-bit increment procedure relies on the size_t being natural
93 * size of CPU register, so that we don't have to mask the value in order
94 * to detect overflows.
97 if (c
->bitlen
[0] < bits
) { /* overflow */
101 } while (c
->bitlen
[n
] == 0
102 && ++n
< (WHIRLPOOL_COUNTER
/ sizeof(size_t)));
104 #ifndef OPENSSL_SMALL_FOOTPRINT
106 if (inpgap
== 0 && bitrem
== 0) { /* byte-oriented loop */
108 if (bitoff
== 0 && (n
= bits
/ WHIRLPOOL_BBLOCK
)) {
109 whirlpool_block(c
, inp
, n
);
110 inp
+= n
* WHIRLPOOL_BBLOCK
/ 8;
111 bits
%= WHIRLPOOL_BBLOCK
;
113 unsigned int byteoff
= bitoff
/ 8;
115 bitrem
= WHIRLPOOL_BBLOCK
- bitoff
; /* re-use bitrem */
116 if (bits
>= bitrem
) {
119 memcpy(c
->data
+ byteoff
, inp
, bitrem
);
121 whirlpool_block(c
, c
->data
, 1);
124 memcpy(c
->data
+ byteoff
, inp
, bits
/ 8);
125 bitoff
+= (unsigned int)bits
;
131 } else /* bit-oriented loop */
137 +-------+-------+-------
138 |||||||||||||||||||||
139 +-------+-------+-------
140 +-------+-------+-------+-------+-------
141 |||||||||||||| c->data
142 +-------+-------+-------+-------+-------
147 unsigned int byteoff
= bitoff
/ 8;
150 #ifndef OPENSSL_SMALL_FOOTPRINT
151 if (bitrem
== inpgap
) {
152 c
->data
[byteoff
++] |= inp
[0] & (0xff >> inpgap
);
155 bitrem
= 0; /* bitoff%8 */
157 inpgap
= 0; /* bits%8 */
159 if (bitoff
== WHIRLPOOL_BBLOCK
) {
160 whirlpool_block(c
, c
->data
, 1);
168 b
= ((inp
[0] << inpgap
) | (inp
[1] >> (8 - inpgap
)));
171 c
->data
[byteoff
++] |= b
>> bitrem
;
173 c
->data
[byteoff
++] = b
;
177 if (bitoff
>= WHIRLPOOL_BBLOCK
) {
178 whirlpool_block(c
, c
->data
, 1);
180 bitoff
%= WHIRLPOOL_BBLOCK
;
183 c
->data
[byteoff
] = b
<< (8 - bitrem
);
184 } else { /* remaining less than 8 bits */
186 b
= (inp
[0] << inpgap
) & 0xff;
188 c
->data
[byteoff
++] |= b
>> bitrem
;
190 c
->data
[byteoff
++] = b
;
191 bitoff
+= (unsigned int)bits
;
192 if (bitoff
== WHIRLPOOL_BBLOCK
) {
193 whirlpool_block(c
, c
->data
, 1);
195 bitoff
%= WHIRLPOOL_BBLOCK
;
198 c
->data
[byteoff
] = b
<< (8 - bitrem
);
206 int WHIRLPOOL_Final(unsigned char *md
, WHIRLPOOL_CTX
*c
)
208 unsigned int bitoff
= c
->bitoff
, byteoff
= bitoff
/ 8;
214 c
->data
[byteoff
] |= 0x80 >> bitoff
;
216 c
->data
[byteoff
] = 0x80;
220 if (byteoff
> (WHIRLPOOL_BBLOCK
/ 8 - WHIRLPOOL_COUNTER
)) {
221 if (byteoff
< WHIRLPOOL_BBLOCK
/ 8)
222 memset(&c
->data
[byteoff
], 0, WHIRLPOOL_BBLOCK
/ 8 - byteoff
);
223 whirlpool_block(c
, c
->data
, 1);
226 if (byteoff
< (WHIRLPOOL_BBLOCK
/ 8 - WHIRLPOOL_COUNTER
))
227 memset(&c
->data
[byteoff
], 0,
228 (WHIRLPOOL_BBLOCK
/ 8 - WHIRLPOOL_COUNTER
) - byteoff
);
229 /* smash 256-bit c->bitlen in big-endian order */
230 p
= &c
->data
[WHIRLPOOL_BBLOCK
/ 8 - 1]; /* last byte in c->data */
231 for (i
= 0; i
< WHIRLPOOL_COUNTER
/ sizeof(size_t); i
++)
232 for (v
= c
->bitlen
[i
], j
= 0; j
< sizeof(size_t); j
++, v
>>= 8)
233 *p
-- = (unsigned char)(v
& 0xff);
235 whirlpool_block(c
, c
->data
, 1);
238 memcpy(md
, c
->H
.c
, WHIRLPOOL_DIGEST_LENGTH
);
239 memset(c
, 0, sizeof(*c
));
245 unsigned char *WHIRLPOOL(const void *inp
, size_t bytes
, unsigned char *md
)
248 static unsigned char m
[WHIRLPOOL_DIGEST_LENGTH
];
252 WHIRLPOOL_Init(&ctx
);
253 WHIRLPOOL_Update(&ctx
, inp
, bytes
);
254 WHIRLPOOL_Final(md
, &ctx
);