Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tpruvot
GitHub Repository: tpruvot/cpuminer-multi
Path: blob/linux/sha3/md_helper.c
1201 views
1
/* $Id: md_helper.c 216 2010-06-08 09:46:57Z tp $ */
2
/*
3
* This file contains some functions which implement the external data
4
* handling and padding for Merkle-Damgard hash functions which follow
5
* the conventions set out by MD4 (little-endian) or SHA-1 (big-endian).
6
*
7
* API: this file is meant to be included, not compiled as a stand-alone
8
* file. Some macros must be defined:
9
* RFUN name for the round function
10
* HASH "short name" for the hash function
11
* BE32 defined for big-endian, 32-bit based (e.g. SHA-1)
12
* LE32 defined for little-endian, 32-bit based (e.g. MD5)
13
* BE64 defined for big-endian, 64-bit based (e.g. SHA-512)
14
* LE64 defined for little-endian, 64-bit based (no example yet)
15
* PW01 if defined, append 0x01 instead of 0x80 (for Tiger)
16
* BLEN if defined, length of a message block (in bytes)
17
* PLW1 if defined, length is defined on one 64-bit word only (for Tiger)
18
* PLW4 if defined, length is defined on four 64-bit words (for WHIRLPOOL)
19
* SVAL if defined, reference to the context state information
20
*
21
* BLEN is used when a message block is not 16 (32-bit or 64-bit) words:
22
* this is used for instance for Tiger, which works on 64-bit words but
23
* uses 512-bit message blocks (eight 64-bit words). PLW1 and PLW4 are
24
* ignored if 32-bit words are used; if 64-bit words are used and PLW1 is
25
* set, then only one word (64 bits) will be used to encode the input
26
* message length (in bits), otherwise two words will be used (as in
27
* SHA-384 and SHA-512). If 64-bit words are used and PLW4 is defined (but
28
* not PLW1), four 64-bit words will be used to encode the message length
29
* (in bits). Note that regardless of those settings, only 64-bit message
30
* lengths are supported (in bits): messages longer than 2 Exabytes will be
31
* improperly hashed (this is unlikely to happen soon: 2 Exabytes is about
32
* 2 millions Terabytes, which is huge).
33
*
34
* If CLOSE_ONLY is defined, then this file defines only the sph_XXX_close()
35
* function. This is used for Tiger2, which is identical to Tiger except
36
* when it comes to the padding (Tiger2 uses the standard 0x80 byte instead
37
* of the 0x01 from original Tiger).
38
*
39
* The RFUN function is invoked with two arguments, the first pointing to
40
* aligned data (as a "const void *"), the second being state information
41
* from the context structure. By default, this state information is the
42
* "val" field from the context, and this field is assumed to be an array
43
* of words ("sph_u32" or "sph_u64", depending on BE32/LE32/BE64/LE64).
44
* from the context structure. The "val" field can have any type, except
45
* for the output encoding which assumes that it is an array of "sph_u32"
46
* values. By defining NO_OUTPUT, this last step is deactivated; the
47
* includer code is then responsible for writing out the hash result. When
48
* NO_OUTPUT is defined, the third parameter to the "close()" function is
49
* ignored.
50
*
51
* ==========================(LICENSE BEGIN)============================
52
*
53
* Copyright (c) 2007-2010 Projet RNRT SAPHIR
54
*
55
* Permission is hereby granted, free of charge, to any person obtaining
56
* a copy of this software and associated documentation files (the
57
* "Software"), to deal in the Software without restriction, including
58
* without limitation the rights to use, copy, modify, merge, publish,
59
* distribute, sublicense, and/or sell copies of the Software, and to
60
* permit persons to whom the Software is furnished to do so, subject to
61
* the following conditions:
62
*
63
* The above copyright notice and this permission notice shall be
64
* included in all copies or substantial portions of the Software.
65
*
66
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
67
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
68
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
69
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
70
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
71
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
72
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
73
*
74
* ===========================(LICENSE END)=============================
75
*
76
* @author Thomas Pornin <[email protected]>
77
*/
78
79
#ifdef _MSC_VER
80
#pragma warning (disable: 4146)
81
#endif
82
83
#undef SPH_XCAT
84
#define SPH_XCAT(a, b) SPH_XCAT_(a, b)
85
#undef SPH_XCAT_
86
#define SPH_XCAT_(a, b) a ## b
87
88
#undef SPH_BLEN
89
#undef SPH_WLEN
90
#if defined BE64 || defined LE64
91
#define SPH_BLEN 128U
92
#define SPH_WLEN 8U
93
#else
94
#define SPH_BLEN 64U
95
#define SPH_WLEN 4U
96
#endif
97
98
#ifdef BLEN
99
#undef SPH_BLEN
100
#define SPH_BLEN BLEN
101
#endif
102
103
#undef SPH_MAXPAD
104
#if defined PLW1
105
#define SPH_MAXPAD (SPH_BLEN - SPH_WLEN)
106
#elif defined PLW4
107
#define SPH_MAXPAD (SPH_BLEN - (SPH_WLEN << 2))
108
#else
109
#define SPH_MAXPAD (SPH_BLEN - (SPH_WLEN << 1))
110
#endif
111
112
#undef SPH_VAL
113
#undef SPH_NO_OUTPUT
114
#ifdef SVAL
115
#define SPH_VAL SVAL
116
#define SPH_NO_OUTPUT 1
117
#else
118
#define SPH_VAL sc->val
119
#endif
120
121
#ifndef CLOSE_ONLY
122
123
#ifdef SPH_UPTR
124
static void
125
SPH_XCAT(HASH, _short)(void *cc, const void *data, size_t len)
126
#else
127
void
128
SPH_XCAT(sph_, HASH)(void *cc, const void *data, size_t len)
129
#endif
130
{
131
SPH_XCAT(sph_, SPH_XCAT(HASH, _context)) *sc;
132
size_t current;
133
134
sc = cc;
135
#if SPH_64
136
current = (unsigned)sc->count & (SPH_BLEN - 1U);
137
#else
138
current = (unsigned)sc->count_low & (SPH_BLEN - 1U);
139
#endif
140
while (len > 0) {
141
size_t clen;
142
#if !SPH_64
143
sph_u32 clow, clow2;
144
#endif
145
146
clen = SPH_BLEN - current;
147
if (clen > len)
148
clen = len;
149
memcpy(sc->buf + current, data, clen);
150
data = (const unsigned char *)data + clen;
151
current += clen;
152
len -= clen;
153
if (current == SPH_BLEN) {
154
RFUN(sc->buf, SPH_VAL);
155
current = 0;
156
}
157
#if SPH_64
158
sc->count += clen;
159
#else
160
clow = sc->count_low;
161
clow2 = SPH_T32(clow + clen);
162
sc->count_low = clow2;
163
if (clow2 < clow)
164
sc->count_high ++;
165
#endif
166
}
167
}
168
169
#ifdef SPH_UPTR
170
void
171
SPH_XCAT(sph_, HASH)(void *cc, const void *data, size_t len)
172
{
173
SPH_XCAT(sph_, SPH_XCAT(HASH, _context)) *sc;
174
unsigned current;
175
size_t orig_len;
176
#if !SPH_64
177
sph_u32 clow, clow2;
178
#endif
179
180
if (len < (2 * SPH_BLEN)) {
181
SPH_XCAT(HASH, _short)(cc, data, len);
182
return;
183
}
184
sc = cc;
185
#if SPH_64
186
current = (unsigned)sc->count & (SPH_BLEN - 1U);
187
#else
188
current = (unsigned)sc->count_low & (SPH_BLEN - 1U);
189
#endif
190
if (current > 0) {
191
unsigned t;
192
193
t = SPH_BLEN - current;
194
SPH_XCAT(HASH, _short)(cc, data, t);
195
data = (const unsigned char *)data + t;
196
len -= t;
197
}
198
#if !SPH_UNALIGNED
199
if (((SPH_UPTR)data & (SPH_WLEN - 1U)) != 0) {
200
SPH_XCAT(HASH, _short)(cc, data, len);
201
return;
202
}
203
#endif
204
orig_len = len;
205
while (len >= SPH_BLEN) {
206
RFUN(data, SPH_VAL);
207
len -= SPH_BLEN;
208
data = (const unsigned char *)data + SPH_BLEN;
209
}
210
if (len > 0)
211
memcpy(sc->buf, data, len);
212
#if SPH_64
213
sc->count += (sph_u64)orig_len;
214
#else
215
clow = sc->count_low;
216
clow2 = SPH_T32(clow + orig_len);
217
sc->count_low = clow2;
218
if (clow2 < clow)
219
sc->count_high ++;
220
/*
221
* This code handles the improbable situation where "size_t" is
222
* greater than 32 bits, and yet we do not have a 64-bit type.
223
*/
224
orig_len >>= 12;
225
orig_len >>= 10;
226
orig_len >>= 10;
227
sc->count_high += orig_len;
228
#endif
229
}
230
#endif
231
232
#endif
233
234
/*
235
* Perform padding and produce result. The context is NOT reinitialized
236
* by this function.
237
*/
238
static void
239
SPH_XCAT(HASH, _addbits_and_close)(void *cc,
240
unsigned ub, unsigned n, void *dst, unsigned rnum)
241
{
242
SPH_XCAT(sph_, SPH_XCAT(HASH, _context)) *sc;
243
unsigned current, u;
244
#if !SPH_64
245
sph_u32 low, high;
246
#endif
247
248
sc = cc;
249
#if SPH_64
250
current = (unsigned)sc->count & (SPH_BLEN - 1U);
251
#else
252
current = (unsigned)sc->count_low & (SPH_BLEN - 1U);
253
#endif
254
#ifdef PW01
255
sc->buf[current ++] = (0x100 | (ub & 0xFF)) >> (8 - n);
256
#else
257
{
258
unsigned z;
259
260
z = 0x80 >> n;
261
sc->buf[current ++] = ((ub & -z) | z) & 0xFF;
262
}
263
#endif
264
if (current > SPH_MAXPAD) {
265
memset(sc->buf + current, 0, SPH_BLEN - current);
266
RFUN(sc->buf, SPH_VAL);
267
memset(sc->buf, 0, SPH_MAXPAD);
268
} else {
269
memset(sc->buf + current, 0, SPH_MAXPAD - current);
270
}
271
#if defined BE64
272
#if defined PLW1
273
sph_enc64be_aligned(sc->buf + SPH_MAXPAD,
274
SPH_T64(sc->count << 3) + (sph_u64)n);
275
#elif defined PLW4
276
memset(sc->buf + SPH_MAXPAD, 0, 2 * SPH_WLEN);
277
sph_enc64be_aligned(sc->buf + SPH_MAXPAD + 2 * SPH_WLEN,
278
sc->count >> 61);
279
sph_enc64be_aligned(sc->buf + SPH_MAXPAD + 3 * SPH_WLEN,
280
SPH_T64(sc->count << 3) + (sph_u64)n);
281
#else
282
sph_enc64be_aligned(sc->buf + SPH_MAXPAD, sc->count >> 61);
283
sph_enc64be_aligned(sc->buf + SPH_MAXPAD + SPH_WLEN,
284
SPH_T64(sc->count << 3) + (sph_u64)n);
285
#endif
286
#elif defined LE64
287
#if defined PLW1
288
sph_enc64le_aligned(sc->buf + SPH_MAXPAD,
289
SPH_T64(sc->count << 3) + (sph_u64)n);
290
#elif defined PLW1
291
sph_enc64le_aligned(sc->buf + SPH_MAXPAD,
292
SPH_T64(sc->count << 3) + (sph_u64)n);
293
sph_enc64le_aligned(sc->buf + SPH_MAXPAD + SPH_WLEN, sc->count >> 61);
294
memset(sc->buf + SPH_MAXPAD + 2 * SPH_WLEN, 0, 2 * SPH_WLEN);
295
#else
296
sph_enc64le_aligned(sc->buf + SPH_MAXPAD,
297
SPH_T64(sc->count << 3) + (sph_u64)n);
298
sph_enc64le_aligned(sc->buf + SPH_MAXPAD + SPH_WLEN, sc->count >> 61);
299
#endif
300
#else
301
#if SPH_64
302
#ifdef BE32
303
sph_enc64be_aligned(sc->buf + SPH_MAXPAD,
304
SPH_T64(sc->count << 3) + (sph_u64)n);
305
#else
306
sph_enc64le_aligned(sc->buf + SPH_MAXPAD,
307
SPH_T64(sc->count << 3) + (sph_u64)n);
308
#endif
309
#else
310
low = sc->count_low;
311
high = SPH_T32((sc->count_high << 3) | (low >> 29));
312
low = SPH_T32(low << 3) + (sph_u32)n;
313
#ifdef BE32
314
sph_enc32be(sc->buf + SPH_MAXPAD, high);
315
sph_enc32be(sc->buf + SPH_MAXPAD + SPH_WLEN, low);
316
#else
317
sph_enc32le(sc->buf + SPH_MAXPAD, low);
318
sph_enc32le(sc->buf + SPH_MAXPAD + SPH_WLEN, high);
319
#endif
320
#endif
321
#endif
322
RFUN(sc->buf, SPH_VAL);
323
#ifdef SPH_NO_OUTPUT
324
(void)dst;
325
(void)rnum;
326
(void)u;
327
#else
328
for (u = 0; u < rnum; u ++) {
329
#if defined BE64
330
sph_enc64be((unsigned char *)dst + 8 * u, sc->val[u]);
331
#elif defined LE64
332
sph_enc64le((unsigned char *)dst + 8 * u, sc->val[u]);
333
#elif defined BE32
334
sph_enc32be((unsigned char *)dst + 4 * u, sc->val[u]);
335
#else
336
sph_enc32le((unsigned char *)dst + 4 * u, sc->val[u]);
337
#endif
338
}
339
#endif
340
}
341
342
static void
343
SPH_XCAT(HASH, _close)(void *cc, void *dst, unsigned rnum)
344
{
345
SPH_XCAT(HASH, _addbits_and_close)(cc, 0, 0, dst, rnum);
346
}
347
348