Raven Core  3.0.0
P2P Digital Currency
md_helper.c
Go to the documentation of this file.
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 <thomas.pornin@cryptolog.com>
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 }
sph_u32 high
Definition: keccak.c:370
#define SPH_T32(x)
Definition: sph_types.h:932
#define SPH_BLEN
Definition: md_helper.c:94
#define SPH_XCAT(a, b)
Definition: md_helper.c:84
void * memcpy(void *a, const void *b, size_t c)
#define HASH
Definition: sph_sha2.c:654
sph_u32 low
Definition: keccak.c:370
unsigned long sph_u32
Definition: sph_types.h:870
#define SPH_VAL
Definition: md_helper.c:118
#define RFUN
Definition: sph_sha2.c:653
#define SPH_MAXPAD
Definition: md_helper.c:109
#define SPH_WLEN
Definition: md_helper.c:95