]>
git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/whrlpool/wp_dgst.c
2 * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 * The Whirlpool hashing function.
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>
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/>
23 * =============================================================================
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.
40 * OpenSSL-specific implementation notes.
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.
47 * WHIRLPOOL_BitUpdate implements byte-oriented loop, essentially
48 * to serve WHIRLPOOL_Update. This is done for performance.
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.
55 #include <openssl/crypto.h>
59 int WHIRLPOOL_Init(WHIRLPOOL_CTX
*c
)
61 memset(c
, 0, sizeof(*c
));
65 int WHIRLPOOL_Update(WHIRLPOOL_CTX
*c
, const void *_inp
, size_t bytes
)
68 * Well, largest suitable chunk size actually is
69 * (1<<(sizeof(size_t)*8-3))-64, but below number is large enough for not
70 * to care about excessive calls to WHIRLPOOL_BitUpdate...
72 size_t chunk
= ((size_t)1) << (sizeof(size_t) * 8 - 4);
73 const unsigned char *inp
= _inp
;
75 while (bytes
>= chunk
) {
76 WHIRLPOOL_BitUpdate(c
, inp
, chunk
* 8);
81 WHIRLPOOL_BitUpdate(c
, inp
, bytes
* 8);
86 void WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX
*c
, const void *_inp
, size_t bits
)
89 unsigned int bitoff
= c
->bitoff
,
90 bitrem
= bitoff
% 8, inpgap
= (8 - (unsigned int)bits
% 8) & 7;
91 const unsigned char *inp
= _inp
;
94 * This 256-bit increment procedure relies on the size_t being natural
95 * size of CPU register, so that we don't have to mask the value in order
96 * to detect overflows.
99 if (c
->bitlen
[0] < bits
) { /* overflow */
103 } while (c
->bitlen
[n
] == 0
104 && ++n
< (WHIRLPOOL_COUNTER
/ sizeof(size_t)));
106 #ifndef OPENSSL_SMALL_FOOTPRINT
108 if (inpgap
== 0 && bitrem
== 0) { /* byte-oriented loop */
110 if (bitoff
== 0 && (n
= bits
/ WHIRLPOOL_BBLOCK
)) {
111 whirlpool_block(c
, inp
, n
);
112 inp
+= n
* WHIRLPOOL_BBLOCK
/ 8;
113 bits
%= WHIRLPOOL_BBLOCK
;
115 unsigned int byteoff
= bitoff
/ 8;
117 bitrem
= WHIRLPOOL_BBLOCK
- bitoff
; /* re-use bitrem */
118 if (bits
>= bitrem
) {
121 memcpy(c
->data
+ byteoff
, inp
, bitrem
);
123 whirlpool_block(c
, c
->data
, 1);
126 memcpy(c
->data
+ byteoff
, inp
, bits
/ 8);
127 bitoff
+= (unsigned int)bits
;
133 } else /* bit-oriented loop */
139 +-------+-------+-------
140 |||||||||||||||||||||
141 +-------+-------+-------
142 +-------+-------+-------+-------+-------
143 |||||||||||||| c->data
144 +-------+-------+-------+-------+-------
149 unsigned int byteoff
= bitoff
/ 8;
152 #ifndef OPENSSL_SMALL_FOOTPRINT
153 if (bitrem
== inpgap
) {
154 c
->data
[byteoff
++] |= inp
[0] & (0xff >> inpgap
);
157 bitrem
= 0; /* bitoff%8 */
159 inpgap
= 0; /* bits%8 */
161 if (bitoff
== WHIRLPOOL_BBLOCK
) {
162 whirlpool_block(c
, c
->data
, 1);
170 b
= ((inp
[0] << inpgap
) | (inp
[1] >> (8 - inpgap
)));
173 c
->data
[byteoff
++] |= b
>> bitrem
;
175 c
->data
[byteoff
++] = b
;
179 if (bitoff
>= WHIRLPOOL_BBLOCK
) {
180 whirlpool_block(c
, c
->data
, 1);
182 bitoff
%= WHIRLPOOL_BBLOCK
;
185 c
->data
[byteoff
] = b
<< (8 - bitrem
);
186 } else { /* remaining less than or equal to 8 bits */
188 b
= (inp
[0] << inpgap
) & 0xff;
190 c
->data
[byteoff
++] |= b
>> bitrem
;
192 c
->data
[byteoff
++] = b
;
193 bitoff
+= (unsigned int)bits
;
194 if (bitoff
== WHIRLPOOL_BBLOCK
) {
195 whirlpool_block(c
, c
->data
, 1);
197 bitoff
%= WHIRLPOOL_BBLOCK
;
200 c
->data
[byteoff
] = b
<< (8 - bitrem
);
208 int WHIRLPOOL_Final(unsigned char *md
, WHIRLPOOL_CTX
*c
)
210 unsigned int bitoff
= c
->bitoff
, byteoff
= bitoff
/ 8;
216 c
->data
[byteoff
] |= 0x80 >> bitoff
;
218 c
->data
[byteoff
] = 0x80;
222 if (byteoff
> (WHIRLPOOL_BBLOCK
/ 8 - WHIRLPOOL_COUNTER
)) {
223 if (byteoff
< WHIRLPOOL_BBLOCK
/ 8)
224 memset(&c
->data
[byteoff
], 0, WHIRLPOOL_BBLOCK
/ 8 - byteoff
);
225 whirlpool_block(c
, c
->data
, 1);
228 if (byteoff
< (WHIRLPOOL_BBLOCK
/ 8 - WHIRLPOOL_COUNTER
))
229 memset(&c
->data
[byteoff
], 0,
230 (WHIRLPOOL_BBLOCK
/ 8 - WHIRLPOOL_COUNTER
) - byteoff
);
231 /* smash 256-bit c->bitlen in big-endian order */
232 p
= &c
->data
[WHIRLPOOL_BBLOCK
/ 8 - 1]; /* last byte in c->data */
233 for (i
= 0; i
< WHIRLPOOL_COUNTER
/ sizeof(size_t); i
++)
234 for (v
= c
->bitlen
[i
], j
= 0; j
< sizeof(size_t); j
++, v
>>= 8)
235 *p
-- = (unsigned char)(v
& 0xff);
237 whirlpool_block(c
, c
->data
, 1);
240 memcpy(md
, c
->H
.c
, WHIRLPOOL_DIGEST_LENGTH
);
241 OPENSSL_cleanse(c
, sizeof(*c
));
247 unsigned char *WHIRLPOOL(const void *inp
, size_t bytes
, unsigned char *md
)
250 static unsigned char m
[WHIRLPOOL_DIGEST_LENGTH
];
254 WHIRLPOOL_Init(&ctx
);
255 WHIRLPOOL_Update(&ctx
, inp
, bytes
);
256 WHIRLPOOL_Final(md
, &ctx
);