]>
git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/whrlpool/wp_dgst.c
2 * Copyright 2005-2020 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.
56 * Whirlpool low level APIs are deprecated for public use, but still ok for
59 #include "internal/deprecated.h"
61 #include <openssl/crypto.h>
65 int WHIRLPOOL_Init(WHIRLPOOL_CTX
*c
)
67 memset(c
, 0, sizeof(*c
));
71 int WHIRLPOOL_Update(WHIRLPOOL_CTX
*c
, const void *_inp
, size_t bytes
)
74 * Well, largest suitable chunk size actually is
75 * (1<<(sizeof(size_t)*8-3))-64, but below number is large enough for not
76 * to care about excessive calls to WHIRLPOOL_BitUpdate...
78 size_t chunk
= ((size_t)1) << (sizeof(size_t) * 8 - 4);
79 const unsigned char *inp
= _inp
;
81 while (bytes
>= chunk
) {
82 WHIRLPOOL_BitUpdate(c
, inp
, chunk
* 8);
87 WHIRLPOOL_BitUpdate(c
, inp
, bytes
* 8);
92 void WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX
*c
, const void *_inp
, size_t bits
)
95 unsigned int bitoff
= c
->bitoff
,
96 bitrem
= bitoff
% 8, inpgap
= (8 - (unsigned int)bits
% 8) & 7;
97 const unsigned char *inp
= _inp
;
100 * This 256-bit increment procedure relies on the size_t being natural
101 * size of CPU register, so that we don't have to mask the value in order
102 * to detect overflows.
104 c
->bitlen
[0] += bits
;
105 if (c
->bitlen
[0] < bits
) { /* overflow */
109 } while (c
->bitlen
[n
] == 0
110 && ++n
< (WHIRLPOOL_COUNTER
/ sizeof(size_t)));
112 #ifndef OPENSSL_SMALL_FOOTPRINT
114 if (inpgap
== 0 && bitrem
== 0) { /* byte-oriented loop */
116 if (bitoff
== 0 && (n
= bits
/ WHIRLPOOL_BBLOCK
)) {
117 whirlpool_block(c
, inp
, n
);
118 inp
+= n
* WHIRLPOOL_BBLOCK
/ 8;
119 bits
%= WHIRLPOOL_BBLOCK
;
121 unsigned int byteoff
= bitoff
/ 8;
123 bitrem
= WHIRLPOOL_BBLOCK
- bitoff
; /* re-use bitrem */
124 if (bits
>= bitrem
) {
127 memcpy(c
->data
+ byteoff
, inp
, bitrem
);
129 whirlpool_block(c
, c
->data
, 1);
132 memcpy(c
->data
+ byteoff
, inp
, bits
/ 8);
133 bitoff
+= (unsigned int)bits
;
139 } else /* bit-oriented loop */
145 +-------+-------+-------
146 |||||||||||||||||||||
147 +-------+-------+-------
148 +-------+-------+-------+-------+-------
149 |||||||||||||| c->data
150 +-------+-------+-------+-------+-------
155 unsigned int byteoff
= bitoff
/ 8;
158 #ifndef OPENSSL_SMALL_FOOTPRINT
159 if (bitrem
== inpgap
) {
160 c
->data
[byteoff
++] |= inp
[0] & (0xff >> inpgap
);
163 bitrem
= 0; /* bitoff%8 */
165 inpgap
= 0; /* bits%8 */
167 if (bitoff
== WHIRLPOOL_BBLOCK
) {
168 whirlpool_block(c
, c
->data
, 1);
176 b
= ((inp
[0] << inpgap
) | (inp
[1] >> (8 - inpgap
)));
179 c
->data
[byteoff
++] |= b
>> bitrem
;
181 c
->data
[byteoff
++] = b
;
185 if (bitoff
>= WHIRLPOOL_BBLOCK
) {
186 whirlpool_block(c
, c
->data
, 1);
188 bitoff
%= WHIRLPOOL_BBLOCK
;
191 c
->data
[byteoff
] = b
<< (8 - bitrem
);
192 } else { /* remaining less than or equal to 8 bits */
194 b
= (inp
[0] << inpgap
) & 0xff;
196 c
->data
[byteoff
++] |= b
>> bitrem
;
198 c
->data
[byteoff
++] = b
;
199 bitoff
+= (unsigned int)bits
;
200 if (bitoff
== WHIRLPOOL_BBLOCK
) {
201 whirlpool_block(c
, c
->data
, 1);
203 bitoff
%= WHIRLPOOL_BBLOCK
;
206 c
->data
[byteoff
] = b
<< (8 - bitrem
);
214 int WHIRLPOOL_Final(unsigned char *md
, WHIRLPOOL_CTX
*c
)
216 unsigned int bitoff
= c
->bitoff
, byteoff
= bitoff
/ 8;
222 c
->data
[byteoff
] |= 0x80 >> bitoff
;
224 c
->data
[byteoff
] = 0x80;
228 if (byteoff
> (WHIRLPOOL_BBLOCK
/ 8 - WHIRLPOOL_COUNTER
)) {
229 if (byteoff
< WHIRLPOOL_BBLOCK
/ 8)
230 memset(&c
->data
[byteoff
], 0, WHIRLPOOL_BBLOCK
/ 8 - byteoff
);
231 whirlpool_block(c
, c
->data
, 1);
234 if (byteoff
< (WHIRLPOOL_BBLOCK
/ 8 - WHIRLPOOL_COUNTER
))
235 memset(&c
->data
[byteoff
], 0,
236 (WHIRLPOOL_BBLOCK
/ 8 - WHIRLPOOL_COUNTER
) - byteoff
);
237 /* smash 256-bit c->bitlen in big-endian order */
238 p
= &c
->data
[WHIRLPOOL_BBLOCK
/ 8 - 1]; /* last byte in c->data */
239 for (i
= 0; i
< WHIRLPOOL_COUNTER
/ sizeof(size_t); i
++)
240 for (v
= c
->bitlen
[i
], j
= 0; j
< sizeof(size_t); j
++, v
>>= 8)
241 *p
-- = (unsigned char)(v
& 0xff);
243 whirlpool_block(c
, c
->data
, 1);
246 memcpy(md
, c
->H
.c
, WHIRLPOOL_DIGEST_LENGTH
);
247 OPENSSL_cleanse(c
, sizeof(*c
));
253 unsigned char *WHIRLPOOL(const void *inp
, size_t bytes
, unsigned char *md
)
256 static unsigned char m
[WHIRLPOOL_DIGEST_LENGTH
];
260 WHIRLPOOL_Init(&ctx
);
261 WHIRLPOOL_Update(&ctx
, inp
, bytes
);
262 WHIRLPOOL_Final(md
, &ctx
);