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