]>
Commit | Line | Data |
---|---|---|
4f22f405 | 1 | /* |
da1c088f | 2 | * Copyright 2005-2023 The OpenSSL Project Authors. All Rights Reserved. |
4f22f405 | 3 | * |
677c7ab9 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
4f22f405 RS |
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 | |
8 | */ | |
9 | ||
d1593e6b AP |
10 | /** |
11 | * The Whirlpool hashing function. | |
12 | * | |
d1593e6b AP |
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 | |
0d4fb843 | 52 | * input. This is done for performance. |
d1593e6b AP |
53 | */ |
54 | ||
7c3aa39f P |
55 | /* |
56 | * Whirlpool low level APIs are deprecated for public use, but still ok for | |
57 | * internal use. | |
58 | */ | |
59 | #include "internal/deprecated.h" | |
60 | ||
3ce2fdab | 61 | #include <openssl/crypto.h> |
706457b7 | 62 | #include "wp_local.h" |
d1593e6b AP |
63 | #include <string.h> |
64 | ||
0f113f3e MC |
65 | int WHIRLPOOL_Init(WHIRLPOOL_CTX *c) |
66 | { | |
67 | memset(c, 0, sizeof(*c)); | |
208fb891 | 68 | return 1; |
0f113f3e | 69 | } |
d1593e6b | 70 | |
0f113f3e MC |
71 | int WHIRLPOOL_Update(WHIRLPOOL_CTX *c, const void *_inp, size_t bytes) |
72 | { | |
73 | /* | |
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... | |
77 | */ | |
78 | size_t chunk = ((size_t)1) << (sizeof(size_t) * 8 - 4); | |
79 | const unsigned char *inp = _inp; | |
d1593e6b | 80 | |
0f113f3e MC |
81 | while (bytes >= chunk) { |
82 | WHIRLPOOL_BitUpdate(c, inp, chunk * 8); | |
83 | bytes -= chunk; | |
84 | inp += chunk; | |
85 | } | |
86 | if (bytes) | |
87 | WHIRLPOOL_BitUpdate(c, inp, bytes * 8); | |
137db78b | 88 | |
208fb891 | 89 | return 1; |
0f113f3e | 90 | } |
d1593e6b | 91 | |
0f113f3e MC |
92 | void WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX *c, const void *_inp, size_t bits) |
93 | { | |
94 | size_t n; | |
95 | unsigned int bitoff = c->bitoff, | |
96 | bitrem = bitoff % 8, inpgap = (8 - (unsigned int)bits % 8) & 7; | |
97 | const unsigned char *inp = _inp; | |
d1593e6b | 98 | |
0f113f3e MC |
99 | /* |
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. | |
103 | */ | |
104 | c->bitlen[0] += bits; | |
105 | if (c->bitlen[0] < bits) { /* overflow */ | |
106 | n = 1; | |
107 | do { | |
108 | c->bitlen[n]++; | |
109 | } while (c->bitlen[n] == 0 | |
110 | && ++n < (WHIRLPOOL_COUNTER / sizeof(size_t))); | |
111 | } | |
d1593e6b | 112 | #ifndef OPENSSL_SMALL_FOOTPRINT |
0f113f3e MC |
113 | reconsider: |
114 | if (inpgap == 0 && bitrem == 0) { /* byte-oriented loop */ | |
115 | while (bits) { | |
116 | if (bitoff == 0 && (n = bits / WHIRLPOOL_BBLOCK)) { | |
117 | whirlpool_block(c, inp, n); | |
118 | inp += n * WHIRLPOOL_BBLOCK / 8; | |
119 | bits %= WHIRLPOOL_BBLOCK; | |
120 | } else { | |
121 | unsigned int byteoff = bitoff / 8; | |
d1593e6b | 122 | |
a024ab98 | 123 | bitrem = WHIRLPOOL_BBLOCK - bitoff; /* reuse bitrem */ |
0f113f3e MC |
124 | if (bits >= bitrem) { |
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 | } else { | |
132 | memcpy(c->data + byteoff, inp, bits / 8); | |
133 | bitoff += (unsigned int)bits; | |
134 | bits = 0; | |
135 | } | |
136 | c->bitoff = bitoff; | |
137 | } | |
138 | } | |
139 | } else /* bit-oriented loop */ | |
d1593e6b | 140 | #endif |
0f113f3e | 141 | { |
50e735f9 MC |
142 | /*- |
143 | inp | |
144 | | | |
145 | +-------+-------+------- | |
146 | ||||||||||||||||||||| | |
147 | +-------+-------+------- | |
148 | +-------+-------+-------+-------+------- | |
149 | |||||||||||||| c->data | |
150 | +-------+-------+-------+-------+------- | |
151 | | | |
152 | c->bitoff/8 | |
153 | */ | |
0f113f3e MC |
154 | while (bits) { |
155 | unsigned int byteoff = bitoff / 8; | |
156 | unsigned char b; | |
d1593e6b AP |
157 | |
158 | #ifndef OPENSSL_SMALL_FOOTPRINT | |
0f113f3e MC |
159 | if (bitrem == inpgap) { |
160 | c->data[byteoff++] |= inp[0] & (0xff >> inpgap); | |
161 | inpgap = 8 - inpgap; | |
162 | bitoff += inpgap; | |
163 | bitrem = 0; /* bitoff%8 */ | |
164 | bits -= inpgap; | |
165 | inpgap = 0; /* bits%8 */ | |
166 | inp++; | |
167 | if (bitoff == WHIRLPOOL_BBLOCK) { | |
168 | whirlpool_block(c, c->data, 1); | |
169 | bitoff = 0; | |
170 | } | |
171 | c->bitoff = bitoff; | |
172 | goto reconsider; | |
173 | } else | |
d1593e6b | 174 | #endif |
0b20ad12 | 175 | if (bits > 8) { |
0f113f3e MC |
176 | b = ((inp[0] << inpgap) | (inp[1] >> (8 - inpgap))); |
177 | b &= 0xff; | |
178 | if (bitrem) | |
179 | c->data[byteoff++] |= b >> bitrem; | |
180 | else | |
181 | c->data[byteoff++] = b; | |
182 | bitoff += 8; | |
183 | bits -= 8; | |
184 | inp++; | |
185 | if (bitoff >= WHIRLPOOL_BBLOCK) { | |
186 | whirlpool_block(c, c->data, 1); | |
187 | byteoff = 0; | |
188 | bitoff %= WHIRLPOOL_BBLOCK; | |
189 | } | |
190 | if (bitrem) | |
191 | c->data[byteoff] = b << (8 - bitrem); | |
0b20ad12 | 192 | } else { /* remaining less than or equal to 8 bits */ |
0f113f3e MC |
193 | |
194 | b = (inp[0] << inpgap) & 0xff; | |
195 | if (bitrem) | |
196 | c->data[byteoff++] |= b >> bitrem; | |
197 | else | |
198 | c->data[byteoff++] = b; | |
199 | bitoff += (unsigned int)bits; | |
200 | if (bitoff == WHIRLPOOL_BBLOCK) { | |
201 | whirlpool_block(c, c->data, 1); | |
202 | byteoff = 0; | |
203 | bitoff %= WHIRLPOOL_BBLOCK; | |
204 | } | |
205 | if (bitrem) | |
206 | c->data[byteoff] = b << (8 - bitrem); | |
207 | bits = 0; | |
208 | } | |
209 | c->bitoff = bitoff; | |
210 | } | |
211 | } | |
212 | } | |
d1593e6b | 213 | |
0f113f3e MC |
214 | int WHIRLPOOL_Final(unsigned char *md, WHIRLPOOL_CTX *c) |
215 | { | |
216 | unsigned int bitoff = c->bitoff, byteoff = bitoff / 8; | |
217 | size_t i, j, v; | |
218 | unsigned char *p; | |
d1593e6b | 219 | |
0f113f3e MC |
220 | bitoff %= 8; |
221 | if (bitoff) | |
222 | c->data[byteoff] |= 0x80 >> bitoff; | |
223 | else | |
224 | c->data[byteoff] = 0x80; | |
225 | byteoff++; | |
d1593e6b | 226 | |
0f113f3e MC |
227 | /* pad with zeros */ |
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); | |
232 | byteoff = 0; | |
233 | } | |
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); | |
d1593e6b | 242 | |
0f113f3e | 243 | whirlpool_block(c, c->data, 1); |
d1593e6b | 244 | |
0f113f3e MC |
245 | if (md) { |
246 | memcpy(md, c->H.c, WHIRLPOOL_DIGEST_LENGTH); | |
3ce2fdab | 247 | OPENSSL_cleanse(c, sizeof(*c)); |
208fb891 | 248 | return 1; |
0f113f3e | 249 | } |
26a7d938 | 250 | return 0; |
0f113f3e | 251 | } |
d1593e6b | 252 | |
0f113f3e MC |
253 | unsigned char *WHIRLPOOL(const void *inp, size_t bytes, unsigned char *md) |
254 | { | |
255 | WHIRLPOOL_CTX ctx; | |
256 | static unsigned char m[WHIRLPOOL_DIGEST_LENGTH]; | |
d1593e6b | 257 | |
0f113f3e MC |
258 | if (md == NULL) |
259 | md = m; | |
260 | WHIRLPOOL_Init(&ctx); | |
261 | WHIRLPOOL_Update(&ctx, inp, bytes); | |
262 | WHIRLPOOL_Final(md, &ctx); | |
26a7d938 | 263 | return md; |
0f113f3e | 264 | } |