/src/sleuthkit/tsk/base/sha1c.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * The Sleuth Kit |
3 | | * |
4 | | */ |
5 | | |
6 | | /* sha1c.c : Implementation of the Secure Hash Algorithm */ |
7 | | |
8 | | /* SHA: NIST's Secure Hash Algorithm */ |
9 | | |
10 | | /* This version written November 2000 by David Ireland of |
11 | | DI Management Services Pty Limited <code@di-mgt.com.au> |
12 | | |
13 | | Adapted from code in the Python Cryptography Toolkit, |
14 | | version 1.0.0 by A.M. Kuchling 1995. |
15 | | */ |
16 | | |
17 | | /* AM Kuchling's posting:- |
18 | | Based on SHA code originally posted to sci.crypt by Peter Gutmann |
19 | | in message <30ajo5$oe8@ccu2.auckland.ac.nz>. |
20 | | Modified to test for endianness on creation of SHA objects by AMK. |
21 | | Also, the original specification of SHA was found to have a weakness |
22 | | by NSA/NIST. This code implements the fixed version of SHA. |
23 | | */ |
24 | | |
25 | | /* Here's the first paragraph of Peter Gutmann's posting: |
26 | | |
27 | | The following is my SHA (FIPS 180) code updated to allow use of the "fixed" |
28 | | SHA, thanks to Jim Gillogly and an anonymous contributor for the information on |
29 | | what's changed in the new version. The fix is a simple change which involves |
30 | | adding a single rotate in the initial expansion function. It is unknown |
31 | | whether this is an optimal solution to the problem which was discovered in the |
32 | | SHA or whether it's simply a bandaid which fixes the problem with a minimum of |
33 | | effort (for example the reengineering of a great many Capstone chips). |
34 | | */ |
35 | | |
36 | | /** \file sha1c.c |
37 | | * Local copy of the public domain SHA-1 library code by David Ireland. |
38 | | */ |
39 | | |
40 | | #include "tsk_base_i.h" |
41 | | |
42 | | |
43 | | /* The SHS block size and message digest sizes, in bytes */ |
44 | | |
45 | 0 | #define SHS_DATASIZE 64 |
46 | 0 | #define SHS_DIGESTSIZE 20 |
47 | | |
48 | | |
49 | | /* The SHS f()-functions. The f1 and f3 functions can be optimized to |
50 | | save one boolean operation each - thanks to Rich Schroeppel, |
51 | | rcs@cs.arizona.edu for discovering this */ |
52 | | |
53 | | /*#define f1(x,y,z) ( ( x & y ) | ( ~x & z ) ) // Rounds 0-19 */ |
54 | 0 | #define f1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) /* Rounds 0-19 */ |
55 | 0 | #define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ |
56 | | /*#define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) // Rounds 40-59 */ |
57 | 0 | #define f3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) /* Rounds 40-59 */ |
58 | 0 | #define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ |
59 | | |
60 | | /* The SHS Mysterious Constants */ |
61 | | |
62 | | #define K1 0x5A827999UL /* Rounds 0-19 */ |
63 | | #define K2 0x6ED9EBA1UL /* Rounds 20-39 */ |
64 | | #define K3 0x8F1BBCDCUL /* Rounds 40-59 */ |
65 | | #define K4 0xCA62C1D6UL /* Rounds 60-79 */ |
66 | | |
67 | | /* SHS initial values */ |
68 | | |
69 | 0 | #define h0init 0x67452301UL |
70 | 0 | #define h1init 0xEFCDAB89UL |
71 | 0 | #define h2init 0x98BADCFEUL |
72 | 0 | #define h3init 0x10325476UL |
73 | 0 | #define h4init 0xC3D2E1F0UL |
74 | | |
75 | | /* Note that it may be necessary to add parentheses to these macros if they |
76 | | are to be called with expressions as arguments */ |
77 | | /* 32-bit rotate left - kludged with shifts */ |
78 | | |
79 | 0 | #define ROTL(n,X) ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) ) |
80 | | |
81 | | /* The initial expanding function. The hash function is defined over an |
82 | | 80-UINT2 expanded input array W, where the first 16 are copies of the input |
83 | | data, and the remaining 64 are defined by |
84 | | |
85 | | W[ i ] = W[ i - 16 ] ^ W[ i - 14 ] ^ W[ i - 8 ] ^ W[ i - 3 ] |
86 | | |
87 | | This implementation generates these values on the fly in a circular |
88 | | buffer - thanks to Colin Plumb, colin@nyx10.cs.du.edu for this |
89 | | optimization. |
90 | | |
91 | | The updated SHS changes the expanding function by adding a rotate of 1 |
92 | | bit. Thanks to Jim Gillogly, jim@rand.org, and an anonymous contributor |
93 | | for this information */ |
94 | | |
95 | | #define expand(W,i) ( W[ i & 15 ] = ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \ |
96 | | W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ) ) ) |
97 | | |
98 | | |
99 | | /* The prototype SHS sub-round. The fundamental sub-round is: |
100 | | |
101 | | a' = e + ROTL( 5, a ) + f( b, c, d ) + k + data; |
102 | | b' = a; |
103 | | c' = ROTL( 30, b ); |
104 | | d' = c; |
105 | | e' = d; |
106 | | |
107 | | but this is implemented by unrolling the loop 5 times and renaming the |
108 | | variables ( e, a, b, c, d ) = ( a', b', c', d', e' ) each iteration. |
109 | | This code is then replicated 20 times for each of the 4 functions, using |
110 | | the next 20 values from the W[] array each time */ |
111 | | |
112 | | #define subRound(a, b, c, d, e, f, k, data) \ |
113 | 0 | ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) ) |
114 | | |
115 | | |
116 | | |
117 | | /* endian.c */ |
118 | | static void |
119 | | endianTest(int *endian_ness) |
120 | 0 | { |
121 | 0 | if ((*(unsigned short *) ("#S") >> 8) == '#') { |
122 | | /* printf("Big endian = no change\n"); */ |
123 | 0 | *endian_ness = !(0); |
124 | 0 | } |
125 | 0 | else { |
126 | | /* printf("Little endian = swap\n"); */ |
127 | 0 | *endian_ness = 0; |
128 | 0 | } |
129 | 0 | } |
130 | | |
131 | | /** |
132 | | * \ingroup baselib |
133 | | * Initialize a SHA-1 context so that data can be added to it. |
134 | | * @param shsInfo Pointer to context structure to initialize |
135 | | */ |
136 | | void |
137 | | TSK_SHA_Init(TSK_SHA_CTX * shsInfo) |
138 | 0 | { |
139 | 0 | endianTest(&shsInfo->Endianness); |
140 | | /* Set the h-vars to their initial values */ |
141 | 0 | shsInfo->digest[0] = h0init; |
142 | 0 | shsInfo->digest[1] = h1init; |
143 | 0 | shsInfo->digest[2] = h2init; |
144 | 0 | shsInfo->digest[3] = h3init; |
145 | 0 | shsInfo->digest[4] = h4init; |
146 | | |
147 | | /* Initialise bit count */ |
148 | 0 | shsInfo->countLo = shsInfo->countHi = 0; |
149 | 0 | } |
150 | | |
151 | | |
152 | | /* Perform the SHS transformation. Note that this code, like MD5, seems to |
153 | | break some optimizing compilers due to the complexity of the expressions |
154 | | and the size of the basic block. It may be necessary to split it into |
155 | | sections, e.g. based on the four subrounds |
156 | | |
157 | | Note that this corrupts the shsInfo->data area */ |
158 | | |
159 | | static void |
160 | | SHSTransform(UINT4 *digest, UINT4 *data) |
161 | 0 | { |
162 | 0 | UINT4 A, B, C, D, E; /* Local vars */ |
163 | 0 | UINT4 eData[16]; /* Expanded data */ |
164 | | |
165 | | /* Set up first buffer and local data buffer */ |
166 | 0 | A = digest[0]; |
167 | 0 | B = digest[1]; |
168 | 0 | C = digest[2]; |
169 | 0 | D = digest[3]; |
170 | 0 | E = digest[4]; |
171 | 0 | memcpy((POINTER) eData, (POINTER) data, SHS_DATASIZE); |
172 | | |
173 | | /* Heavy mangling, in 4 sub-rounds of 20 iterations each. */ |
174 | 0 | subRound(A, B, C, D, E, f1, K1, eData[0]); |
175 | 0 | subRound(E, A, B, C, D, f1, K1, eData[1]); |
176 | 0 | subRound(D, E, A, B, C, f1, K1, eData[2]); |
177 | 0 | subRound(C, D, E, A, B, f1, K1, eData[3]); |
178 | 0 | subRound(B, C, D, E, A, f1, K1, eData[4]); |
179 | 0 | subRound(A, B, C, D, E, f1, K1, eData[5]); |
180 | 0 | subRound(E, A, B, C, D, f1, K1, eData[6]); |
181 | 0 | subRound(D, E, A, B, C, f1, K1, eData[7]); |
182 | 0 | subRound(C, D, E, A, B, f1, K1, eData[8]); |
183 | 0 | subRound(B, C, D, E, A, f1, K1, eData[9]); |
184 | 0 | subRound(A, B, C, D, E, f1, K1, eData[10]); |
185 | 0 | subRound(E, A, B, C, D, f1, K1, eData[11]); |
186 | 0 | subRound(D, E, A, B, C, f1, K1, eData[12]); |
187 | 0 | subRound(C, D, E, A, B, f1, K1, eData[13]); |
188 | 0 | subRound(B, C, D, E, A, f1, K1, eData[14]); |
189 | 0 | subRound(A, B, C, D, E, f1, K1, eData[15]); |
190 | 0 | subRound(E, A, B, C, D, f1, K1, expand(eData, 16)); |
191 | 0 | subRound(D, E, A, B, C, f1, K1, expand(eData, 17)); |
192 | 0 | subRound(C, D, E, A, B, f1, K1, expand(eData, 18)); |
193 | 0 | subRound(B, C, D, E, A, f1, K1, expand(eData, 19)); |
194 | |
|
195 | 0 | subRound(A, B, C, D, E, f2, K2, expand(eData, 20)); |
196 | 0 | subRound(E, A, B, C, D, f2, K2, expand(eData, 21)); |
197 | 0 | subRound(D, E, A, B, C, f2, K2, expand(eData, 22)); |
198 | 0 | subRound(C, D, E, A, B, f2, K2, expand(eData, 23)); |
199 | 0 | subRound(B, C, D, E, A, f2, K2, expand(eData, 24)); |
200 | 0 | subRound(A, B, C, D, E, f2, K2, expand(eData, 25)); |
201 | 0 | subRound(E, A, B, C, D, f2, K2, expand(eData, 26)); |
202 | 0 | subRound(D, E, A, B, C, f2, K2, expand(eData, 27)); |
203 | 0 | subRound(C, D, E, A, B, f2, K2, expand(eData, 28)); |
204 | 0 | subRound(B, C, D, E, A, f2, K2, expand(eData, 29)); |
205 | 0 | subRound(A, B, C, D, E, f2, K2, expand(eData, 30)); |
206 | 0 | subRound(E, A, B, C, D, f2, K2, expand(eData, 31)); |
207 | 0 | subRound(D, E, A, B, C, f2, K2, expand(eData, 32)); |
208 | 0 | subRound(C, D, E, A, B, f2, K2, expand(eData, 33)); |
209 | 0 | subRound(B, C, D, E, A, f2, K2, expand(eData, 34)); |
210 | 0 | subRound(A, B, C, D, E, f2, K2, expand(eData, 35)); |
211 | 0 | subRound(E, A, B, C, D, f2, K2, expand(eData, 36)); |
212 | 0 | subRound(D, E, A, B, C, f2, K2, expand(eData, 37)); |
213 | 0 | subRound(C, D, E, A, B, f2, K2, expand(eData, 38)); |
214 | 0 | subRound(B, C, D, E, A, f2, K2, expand(eData, 39)); |
215 | |
|
216 | 0 | subRound(A, B, C, D, E, f3, K3, expand(eData, 40)); |
217 | 0 | subRound(E, A, B, C, D, f3, K3, expand(eData, 41)); |
218 | 0 | subRound(D, E, A, B, C, f3, K3, expand(eData, 42)); |
219 | 0 | subRound(C, D, E, A, B, f3, K3, expand(eData, 43)); |
220 | 0 | subRound(B, C, D, E, A, f3, K3, expand(eData, 44)); |
221 | 0 | subRound(A, B, C, D, E, f3, K3, expand(eData, 45)); |
222 | 0 | subRound(E, A, B, C, D, f3, K3, expand(eData, 46)); |
223 | 0 | subRound(D, E, A, B, C, f3, K3, expand(eData, 47)); |
224 | 0 | subRound(C, D, E, A, B, f3, K3, expand(eData, 48)); |
225 | 0 | subRound(B, C, D, E, A, f3, K3, expand(eData, 49)); |
226 | 0 | subRound(A, B, C, D, E, f3, K3, expand(eData, 50)); |
227 | 0 | subRound(E, A, B, C, D, f3, K3, expand(eData, 51)); |
228 | 0 | subRound(D, E, A, B, C, f3, K3, expand(eData, 52)); |
229 | 0 | subRound(C, D, E, A, B, f3, K3, expand(eData, 53)); |
230 | 0 | subRound(B, C, D, E, A, f3, K3, expand(eData, 54)); |
231 | 0 | subRound(A, B, C, D, E, f3, K3, expand(eData, 55)); |
232 | 0 | subRound(E, A, B, C, D, f3, K3, expand(eData, 56)); |
233 | 0 | subRound(D, E, A, B, C, f3, K3, expand(eData, 57)); |
234 | 0 | subRound(C, D, E, A, B, f3, K3, expand(eData, 58)); |
235 | 0 | subRound(B, C, D, E, A, f3, K3, expand(eData, 59)); |
236 | |
|
237 | 0 | subRound(A, B, C, D, E, f4, K4, expand(eData, 60)); |
238 | 0 | subRound(E, A, B, C, D, f4, K4, expand(eData, 61)); |
239 | 0 | subRound(D, E, A, B, C, f4, K4, expand(eData, 62)); |
240 | 0 | subRound(C, D, E, A, B, f4, K4, expand(eData, 63)); |
241 | 0 | subRound(B, C, D, E, A, f4, K4, expand(eData, 64)); |
242 | 0 | subRound(A, B, C, D, E, f4, K4, expand(eData, 65)); |
243 | 0 | subRound(E, A, B, C, D, f4, K4, expand(eData, 66)); |
244 | 0 | subRound(D, E, A, B, C, f4, K4, expand(eData, 67)); |
245 | 0 | subRound(C, D, E, A, B, f4, K4, expand(eData, 68)); |
246 | 0 | subRound(B, C, D, E, A, f4, K4, expand(eData, 69)); |
247 | 0 | subRound(A, B, C, D, E, f4, K4, expand(eData, 70)); |
248 | 0 | subRound(E, A, B, C, D, f4, K4, expand(eData, 71)); |
249 | 0 | subRound(D, E, A, B, C, f4, K4, expand(eData, 72)); |
250 | 0 | subRound(C, D, E, A, B, f4, K4, expand(eData, 73)); |
251 | 0 | subRound(B, C, D, E, A, f4, K4, expand(eData, 74)); |
252 | 0 | subRound(A, B, C, D, E, f4, K4, expand(eData, 75)); |
253 | 0 | subRound(E, A, B, C, D, f4, K4, expand(eData, 76)); |
254 | 0 | subRound(D, E, A, B, C, f4, K4, expand(eData, 77)); |
255 | 0 | subRound(C, D, E, A, B, f4, K4, expand(eData, 78)); |
256 | 0 | subRound(B, C, D, E, A, f4, K4, expand(eData, 79)); |
257 | | |
258 | | /* Build message digest */ |
259 | 0 | digest[0] += A; |
260 | 0 | digest[1] += B; |
261 | 0 | digest[2] += C; |
262 | 0 | digest[3] += D; |
263 | 0 | digest[4] += E; |
264 | 0 | } |
265 | | |
266 | | /* When run on a little-endian CPU we need to perform byte reversal on an |
267 | | array of long words. */ |
268 | | |
269 | | static void |
270 | | longReverse(UINT4 * buffer, int byteCount, int Endianness) |
271 | 0 | { |
272 | 0 | UINT4 value; |
273 | |
|
274 | 0 | if (Endianness == TRUE) |
275 | 0 | return; |
276 | 0 | byteCount /= sizeof(UINT4); |
277 | 0 | while (byteCount--) { |
278 | 0 | value = *buffer; |
279 | 0 | value = ((value & 0xFF00FF00UL) >> 8) | |
280 | 0 | ((value & 0x00FF00FFUL) << 8); |
281 | 0 | *buffer++ = (value << 16) | (value >> 16); |
282 | 0 | } |
283 | 0 | } |
284 | | |
285 | | /** |
286 | | * \ingroup baselib |
287 | | * Add data to an initialized SHA-1 context. |
288 | | * @param shsInfo Context to add data to |
289 | | * @param buffer Data to process |
290 | | * @param count Number of bytes in buffer |
291 | | */ |
292 | | void |
293 | | TSK_SHA_Update(TSK_SHA_CTX * shsInfo, const BYTE * buffer, unsigned int count) |
294 | 0 | { |
295 | 0 | UINT4 tmp; |
296 | 0 | unsigned int dataCount; |
297 | | |
298 | | /* Update bitcount */ |
299 | 0 | tmp = shsInfo->countLo; |
300 | 0 | if ((shsInfo->countLo = tmp + ((UINT4) count << 3)) < tmp) |
301 | 0 | shsInfo->countHi++; /* Carry from low to high */ |
302 | 0 | shsInfo->countHi += count >> 29; |
303 | | |
304 | | /* Get count of bytes already in data */ |
305 | 0 | dataCount = (int) (tmp >> 3) & 0x3F; |
306 | | |
307 | | /* Handle any leading odd-sized chunks */ |
308 | 0 | if (dataCount) { |
309 | 0 | BYTE *p = (BYTE *) shsInfo->data + dataCount; |
310 | |
|
311 | 0 | dataCount = SHS_DATASIZE - dataCount; |
312 | 0 | if (count < dataCount) { |
313 | 0 | memcpy(p, buffer, count); |
314 | 0 | return; |
315 | 0 | } |
316 | 0 | memcpy(p, buffer, dataCount); |
317 | 0 | longReverse(shsInfo->data, SHS_DATASIZE, shsInfo->Endianness); |
318 | 0 | SHSTransform(shsInfo->digest, shsInfo->data); |
319 | 0 | buffer += dataCount; |
320 | 0 | count -= dataCount; |
321 | 0 | } |
322 | | |
323 | | /* Process data in SHS_DATASIZE chunks */ |
324 | 0 | while (count >= SHS_DATASIZE) { |
325 | 0 | memcpy((POINTER) shsInfo->data, (POINTER) buffer, SHS_DATASIZE); |
326 | 0 | longReverse(shsInfo->data, SHS_DATASIZE, shsInfo->Endianness); |
327 | 0 | SHSTransform(shsInfo->digest, shsInfo->data); |
328 | 0 | buffer += SHS_DATASIZE; |
329 | 0 | count -= SHS_DATASIZE; |
330 | 0 | } |
331 | | |
332 | | /* Handle any remaining bytes of data. */ |
333 | 0 | memcpy((POINTER) shsInfo->data, (POINTER) buffer, count); |
334 | 0 | } |
335 | | |
336 | | static void |
337 | | SHAtoByte(BYTE output[SHS_DIGESTSIZE], UINT4 * input) |
338 | 0 | { /* Output SHA digest in byte array */ |
339 | 0 | unsigned int i, j; |
340 | |
|
341 | 0 | for (i = 0, j = 0; j < SHS_DIGESTSIZE; i++, j += 4) { |
342 | 0 | output[j + 3] = (BYTE) (input[i] & 0xff); |
343 | 0 | output[j + 2] = (BYTE) ((input[i] >> 8) & 0xff); |
344 | 0 | output[j + 1] = (BYTE) ((input[i] >> 16) & 0xff); |
345 | 0 | output[j] = (BYTE) ((input[i] >> 24) & 0xff); |
346 | 0 | } |
347 | 0 | } |
348 | | |
349 | | /** |
350 | | * \ingroup baselib |
351 | | * Calculate the hash of the data added to the context. |
352 | | * @param shsInfo Context that has data added to it. |
353 | | * @param output Buffer to store hash value |
354 | | */ |
355 | | void |
356 | | TSK_SHA_Final(TSK_SHA_CTX * shsInfo, BYTE* output) |
357 | 0 | { |
358 | 0 | int count; |
359 | 0 | BYTE *dataPtr; |
360 | | |
361 | | /* Compute number of bytes mod 64 */ |
362 | 0 | count = (int) shsInfo->countLo; |
363 | 0 | count = (count >> 3) & 0x3F; |
364 | | |
365 | | /* Set the first char of padding to 0x80. This is safe since there is |
366 | | always at least one byte free */ |
367 | 0 | dataPtr = (BYTE *) shsInfo->data + count; |
368 | 0 | *dataPtr++ = 0x80; |
369 | | |
370 | | /* Bytes of padding needed to make 64 bytes */ |
371 | 0 | count = SHS_DATASIZE - 1 - count; |
372 | | |
373 | | /* Pad out to 56 mod 64 */ |
374 | 0 | if (count < 8) { |
375 | | /* Two lots of padding: Pad the first block to 64 bytes */ |
376 | 0 | memset(dataPtr, 0, count); |
377 | 0 | longReverse(shsInfo->data, SHS_DATASIZE, shsInfo->Endianness); |
378 | 0 | SHSTransform(shsInfo->digest, shsInfo->data); |
379 | | |
380 | | /* Now fill the next block with 56 bytes */ |
381 | 0 | memset((POINTER) shsInfo->data, 0, SHS_DATASIZE - 8); |
382 | 0 | } |
383 | 0 | else |
384 | | /* Pad block to 56 bytes */ |
385 | 0 | memset(dataPtr, 0, count - 8); |
386 | | |
387 | | /* Append length in bits and transform */ |
388 | 0 | shsInfo->data[14] = shsInfo->countHi; |
389 | 0 | shsInfo->data[15] = shsInfo->countLo; |
390 | |
|
391 | 0 | longReverse(shsInfo->data, SHS_DATASIZE - 8, shsInfo->Endianness); |
392 | 0 | SHSTransform(shsInfo->digest, shsInfo->data); |
393 | | |
394 | | /* Output to an array of bytes */ |
395 | 0 | SHAtoByte(output, shsInfo->digest); |
396 | | |
397 | | /* Zeroise sensitive stuff */ |
398 | 0 | memset((POINTER) shsInfo, 0, sizeof(shsInfo)); |
399 | 0 | } |