1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | // |
5 | // |
6 | // |
7 | // =========================================================================== |
8 | // File: sha1.cpp |
9 | // |
10 | // =========================================================================== |
11 | /*++ |
12 | |
13 | Abstract: |
14 | |
15 | SHA-1 implementation |
16 | |
17 | Revision History: |
18 | |
19 | --*/ |
20 | |
21 | /* |
22 | File sha1.cpp <STRIP>Version 03 August 2000.</STRIP> |
23 | |
24 | |
25 | This implements the SHA-1 hash function. |
26 | For algorithmic background see (for example) |
27 | |
28 | |
29 | Alfred J. Menezes et al |
30 | Handbook of Applied Cryptography |
31 | The CRC Press Series on Discrete Mathematics |
32 | and its Applications |
33 | CRC Press LLC, 1997 |
34 | ISBN 0-8495-8523-7 |
35 | QA76.9A25M643 |
36 | |
37 | Also see FIPS 180-1 - Secure Hash Standard, |
38 | 1993 May 11 and 1995 April 17, by the U.S. |
39 | National Institute of Standards and Technology (NIST). |
40 | |
41 | */ |
42 | |
43 | #include "common.h" |
44 | #include "sha1.h" |
45 | #include "contract.h" |
46 | |
47 | typedef const DWORD DWORDC; |
48 | #define ROTATE32L(x,n) _rotl(x,n) |
49 | #define SHAVE32(x) (DWORD)(x) |
50 | |
51 | static void SHA1_block(SHA1_CTX *ctx) |
52 | /* |
53 | Update the SHA-1 hash from a fresh 64 bytes of data. |
54 | */ |
55 | { |
56 | static DWORDC sha1_round1 = 0x5A827999u; |
57 | static DWORDC sha1_round2 = 0x6ED9EBA1u; |
58 | static DWORDC sha1_round3 = 0x8F1BBCDCu; |
59 | static DWORDC sha1_round4 = 0xCA62C1D6u; |
60 | |
61 | DWORD a = ctx->partial_hash[0], b = ctx->partial_hash[1]; |
62 | DWORD c = ctx->partial_hash[2], d = ctx->partial_hash[3]; |
63 | DWORD e = ctx->partial_hash[4]; |
64 | DWORD msg80[80]; |
65 | int i; |
66 | BOOL OK = TRUE; |
67 | |
68 | // OACR note: |
69 | // Loop conditions are using (i <= limit - increment) instead of (i < limit) to satisfy OACR. When the increment is greater |
70 | // than 1, OACR incorrectly thinks that the max value of 'i' is (limit - 1). |
71 | |
72 | for (i = 0; i < 16; i++) { // Copy to local array, zero original |
73 | // Extend length to 80 |
74 | DWORDC datval = ctx->awaiting_data[i]; |
75 | ctx->awaiting_data[i] = 0; |
76 | msg80[i] = datval; |
77 | } |
78 | |
79 | for (i = 16; i <= 80 - 2; i += 2) { |
80 | DWORDC temp1 = msg80[i-3] ^ msg80[i-8] |
81 | ^ msg80[i-14] ^ msg80[i-16]; |
82 | DWORDC temp2 = msg80[i-2] ^ msg80[i-7] |
83 | ^ msg80[i-13] ^ msg80[i-15]; |
84 | msg80[i ] = ROTATE32L(temp1, 1); |
85 | msg80[i+1] = ROTATE32L(temp2, 1); |
86 | } |
87 | |
88 | #define ROUND1(B, C, D) ((D ^ (B & (C ^ D))) + sha1_round1) |
89 | // Equivalent to (B & C) | (~B & D). |
90 | // (check cases B = 0 and B = 1) |
91 | #define ROUND2(B, C, D) ((B ^ C ^ D) + sha1_round2) |
92 | |
93 | #define ROUND3(B, C, D) ((C & (B | D) | (B & D)) + sha1_round3) |
94 | |
95 | #define ROUND4(B, C, D) ((B ^ C ^ D) + sha1_round4) |
96 | |
97 | // Round 1 |
98 | for (i = 0; i <= 20 - 5; i += 5) { |
99 | e += ROTATE32L(a, 5) + ROUND1(b, c, d) + msg80[i]; |
100 | b = ROTATE32L(b, 30); |
101 | |
102 | d += ROTATE32L(e, 5) + ROUND1(a, b, c) + msg80[i+1]; |
103 | a = ROTATE32L(a, 30); |
104 | |
105 | c += ROTATE32L(d, 5) + ROUND1(e, a, b) + msg80[i+2]; |
106 | e = ROTATE32L(e, 30); |
107 | |
108 | b += ROTATE32L(c, 5) + ROUND1(d, e, a) + msg80[i+3]; |
109 | d = ROTATE32L(d, 30); |
110 | |
111 | a += ROTATE32L(b, 5) + ROUND1(c, d, e) + msg80[i+4]; |
112 | c = ROTATE32L(c, 30); |
113 | #if 0 |
114 | printf("i = %ld %08lx %08lx %08lx %08lx %08lx\n" , |
115 | i, a, b, c, d, e); |
116 | #endif |
117 | } // for i |
118 | |
119 | // Round 2 |
120 | for (i = 20; i <= 40 - 5; i += 5) { |
121 | e += ROTATE32L(a, 5) + ROUND2(b, c, d) + msg80[i]; |
122 | b = ROTATE32L(b, 30); |
123 | |
124 | d += ROTATE32L(e, 5) + ROUND2(a, b, c) + msg80[i+1]; |
125 | a = ROTATE32L(a, 30); |
126 | |
127 | c += ROTATE32L(d, 5) + ROUND2(e, a, b) + msg80[i+2]; |
128 | e = ROTATE32L(e, 30); |
129 | |
130 | b += ROTATE32L(c, 5) + ROUND2(d, e, a) + msg80[i+3]; |
131 | d = ROTATE32L(d, 30); |
132 | |
133 | a += ROTATE32L(b, 5) + ROUND2(c, d, e) + msg80[i+4]; |
134 | c = ROTATE32L(c, 30); |
135 | } // for i |
136 | |
137 | // Round 3 |
138 | for (i = 40; i <= 60 - 5; i += 5) { |
139 | e += ROTATE32L(a, 5) + ROUND3(b, c, d) + msg80[i]; |
140 | b = ROTATE32L(b, 30); |
141 | |
142 | d += ROTATE32L(e, 5) + ROUND3(a, b, c) + msg80[i+1]; |
143 | a = ROTATE32L(a, 30); |
144 | |
145 | c += ROTATE32L(d, 5) + ROUND3(e, a, b) + msg80[i+2]; |
146 | e = ROTATE32L(e, 30); |
147 | |
148 | b += ROTATE32L(c, 5) + ROUND3(d, e, a) + msg80[i+3]; |
149 | d = ROTATE32L(d, 30); |
150 | |
151 | a += ROTATE32L(b, 5) + ROUND3(c, d, e) + msg80[i+4]; |
152 | c = ROTATE32L(c, 30); |
153 | } // for i |
154 | |
155 | // Round 4 |
156 | for (i = 60; i <= 80 - 5; i += 5) { |
157 | e += ROTATE32L(a, 5) + ROUND4(b, c, d) + msg80[i]; |
158 | b = ROTATE32L(b, 30); |
159 | |
160 | d += ROTATE32L(e, 5) + ROUND4(a, b, c) + msg80[i+1]; |
161 | a = ROTATE32L(a, 30); |
162 | |
163 | c += ROTATE32L(d, 5) + ROUND4(e, a, b) + msg80[i+2]; |
164 | e = ROTATE32L(e, 30); |
165 | |
166 | b += ROTATE32L(c, 5) + ROUND4(d, e, a) + msg80[i+3]; |
167 | d = ROTATE32L(d, 30); |
168 | |
169 | a += ROTATE32L(b, 5) + ROUND4(c, d, e) + msg80[i+4]; |
170 | c = ROTATE32L(c, 30); |
171 | } // for i |
172 | |
173 | #undef ROUND1 |
174 | #undef ROUND2 |
175 | #undef ROUND3 |
176 | #undef ROUND4 |
177 | |
178 | ctx->partial_hash[0] += a; |
179 | ctx->partial_hash[1] += b; |
180 | ctx->partial_hash[2] += c; |
181 | ctx->partial_hash[3] += d; |
182 | ctx->partial_hash[4] += e; |
183 | #if 0 |
184 | for (i = 0; i < 16; i++) { |
185 | printf("%8lx " , msg16[i]); |
186 | if ((i & 7) == 7) printf("\n" ); |
187 | } |
188 | printf("a, b, c, d, e = %08lx %08lx %08lx %08lx %08lx\n" , |
189 | a, b, c, d, e); |
190 | printf("Partial hash = %08lx %08lx %08lx %08lx %08lx\n" , |
191 | (long)ctx->partial_hash[0], (long)ctx->partial_hash[1], |
192 | (long)ctx->partial_hash[2], (long)ctx->partial_hash[3], |
193 | (long)ctx->partial_hash[4]); |
194 | #endif |
195 | } // end SHA1_block |
196 | |
197 | |
198 | void SHA1Hash::SHA1Init(SHA1_CTX *ctx) |
199 | { |
200 | CONTRACTL { |
201 | NOTHROW; |
202 | GC_NOTRIGGER; |
203 | MODE_ANY; |
204 | SO_TOLERANT; |
205 | } CONTRACTL_END; |
206 | |
207 | ctx->nbit_total[0] = ctx->nbit_total[1] = 0; |
208 | |
209 | for (DWORD i = 0; i != 16; i++) { |
210 | ctx->awaiting_data[i] = 0; |
211 | } |
212 | |
213 | /* |
214 | Initialize hash variables. |
215 | |
216 | */ |
217 | |
218 | ctx->partial_hash[0] = 0x67452301u; |
219 | ctx->partial_hash[1] = 0xefcdab89u; |
220 | ctx->partial_hash[2] = ~ctx->partial_hash[0]; |
221 | ctx->partial_hash[3] = ~ctx->partial_hash[1]; |
222 | ctx->partial_hash[4] = 0xc3d2e1f0u; |
223 | |
224 | } |
225 | |
226 | void SHA1Hash::SHA1Update( |
227 | SHA1_CTX * ctx, // IN/OUT |
228 | const BYTE * msg, // IN |
229 | DWORD nbyte) // IN |
230 | /* |
231 | Append data to a partially hashed SHA-1 message. |
232 | */ |
233 | { |
234 | CONTRACTL { |
235 | NOTHROW; |
236 | GC_NOTRIGGER; |
237 | MODE_ANY; |
238 | SO_TOLERANT; |
239 | } CONTRACTL_END; |
240 | |
241 | const BYTE *fresh_data = msg; |
242 | DWORD nbyte_left = nbyte; |
243 | DWORD nbit_occupied = ctx->nbit_total[0] & 511; |
244 | DWORD *awaiting_data; |
245 | DWORDC nbitnew_low = SHAVE32(8*nbyte); |
246 | |
247 | |
248 | _ASSERTE((nbit_occupied & 7) == 0); // Partial bytes not implemented |
249 | |
250 | ctx->nbit_total[0] += nbitnew_low; |
251 | ctx->nbit_total[1] += (nbyte >> 29) |
252 | + (SHAVE32(ctx->nbit_total[0]) < nbitnew_low); |
253 | |
254 | /* Advance to word boundary in waiting_data */ |
255 | |
256 | if ((nbit_occupied & 31) != 0) { |
257 | awaiting_data = ctx->awaiting_data + nbit_occupied/32; |
258 | |
259 | while ((nbit_occupied & 31) != 0 && nbyte_left != 0) { |
260 | nbit_occupied += 8; |
261 | *awaiting_data |= (DWORD)*fresh_data++ |
262 | << ((-(int)nbit_occupied) & 31); |
263 | nbyte_left--; // Start at most significant byte |
264 | } |
265 | } // if nbit_occupied |
266 | |
267 | /* Transfer 4 bytes at a time */ |
268 | |
269 | do { |
270 | DWORDC nword_occupied = nbit_occupied/32; |
271 | DWORD nwcopy = min(nbyte_left/4, 16 - nword_occupied); |
272 | _ASSERTE (nbit_occupied <= 512); |
273 | _ASSERTE ((nbit_occupied & 31) == 0 || nbyte_left == 0); |
274 | awaiting_data = ctx->awaiting_data + nword_occupied; |
275 | nbyte_left -= 4*nwcopy; |
276 | nbit_occupied += 32*nwcopy; |
277 | |
278 | while (nwcopy != 0) { |
279 | DWORDC byte0 = (DWORD)fresh_data[0]; |
280 | DWORDC byte1 = (DWORD)fresh_data[1]; |
281 | DWORDC byte2 = (DWORD)fresh_data[2]; |
282 | DWORDC byte3 = (DWORD)fresh_data[3]; |
283 | *awaiting_data++ = byte3 | (byte2 << 8) |
284 | | (byte1 << 16) | (byte0 << 24); |
285 | /* Big endian */ |
286 | fresh_data += 4; |
287 | nwcopy--; |
288 | } |
289 | |
290 | if (nbit_occupied == 512) { |
291 | SHA1_block(ctx); |
292 | nbit_occupied = 0; |
293 | awaiting_data -= 16; |
294 | _ASSERTE(awaiting_data == ctx->awaiting_data); |
295 | } |
296 | } while (nbyte_left >= 4); |
297 | |
298 | _ASSERTE (ctx->awaiting_data + nbit_occupied/32 |
299 | == awaiting_data); |
300 | |
301 | while (nbyte_left != 0) { |
302 | DWORDC new_byte = (DWORD)*fresh_data++; |
303 | |
304 | _ASSERTE((nbit_occupied & 31) <= 16); |
305 | nbit_occupied += 8; |
306 | *awaiting_data |= new_byte << ((-(int)nbit_occupied) & 31); |
307 | nbyte_left--; |
308 | } |
309 | |
310 | _ASSERTE (nbit_occupied == (ctx->nbit_total[0] & 511)); |
311 | } // end SHA1Update |
312 | |
313 | |
314 | |
315 | void SHA1Hash::SHA1Final( |
316 | SHA1_CTX * ctx, // IN/OUT |
317 | BYTE * digest) // OUT |
318 | /* |
319 | Finish a SHA-1 hash. |
320 | */ |
321 | { |
322 | CONTRACTL { |
323 | NOTHROW; |
324 | GC_NOTRIGGER; |
325 | MODE_ANY; |
326 | SO_TOLERANT; |
327 | } CONTRACTL_END; |
328 | |
329 | DWORDC nbit0 = ctx->nbit_total[0]; |
330 | DWORDC nbit1 = ctx->nbit_total[1]; |
331 | DWORD nbit_occupied = nbit0 & 511; |
332 | DWORD i; |
333 | |
334 | _ASSERTE((nbit_occupied & 7) == 0); |
335 | |
336 | ctx->awaiting_data[nbit_occupied/32] |
337 | |= (DWORD)0x80 << ((-8-nbit_occupied) & 31); |
338 | // Append a 1 bit |
339 | nbit_occupied += 8; |
340 | |
341 | |
342 | // Append zero bits until length (in bits) is 448 mod 512. |
343 | // Then append the length, in bits. |
344 | // Here we assume the buffer was zeroed earlier. |
345 | |
346 | if (nbit_occupied > 448) { // If fewer than 64 bits left |
347 | SHA1_block(ctx); |
348 | nbit_occupied = 0; |
349 | } |
350 | ctx->awaiting_data[14] = nbit1; |
351 | ctx->awaiting_data[15] = nbit0; |
352 | SHA1_block(ctx); |
353 | |
354 | /* Copy final digest to user-supplied byte array */ |
355 | |
356 | for (i = 0; i != 5; i++) { |
357 | DWORDC dwi = ctx->partial_hash[i]; |
358 | digest[4*i + 0] = (BYTE)((dwi >> 24) & 255); |
359 | digest[4*i + 1] = (BYTE)((dwi >> 16) & 255); |
360 | digest[4*i + 2] = (BYTE)((dwi >> 8) & 255); |
361 | digest[4*i + 3] = (BYTE)(dwi & 255); // Big-endian |
362 | } |
363 | } // end SHA1Final |
364 | |
365 | SHA1Hash::SHA1Hash() |
366 | { |
367 | CONTRACTL { |
368 | NOTHROW; |
369 | GC_NOTRIGGER; |
370 | MODE_ANY; |
371 | SO_TOLERANT; |
372 | } CONTRACTL_END; |
373 | |
374 | m_fFinalized = FALSE; |
375 | SHA1Init(&m_Context); |
376 | } |
377 | |
378 | void SHA1Hash::AddData(BYTE *pbData, DWORD cbData) |
379 | { |
380 | CONTRACTL { |
381 | NOTHROW; |
382 | GC_NOTRIGGER; |
383 | MODE_ANY; |
384 | SO_TOLERANT; |
385 | } CONTRACTL_END; |
386 | |
387 | if (m_fFinalized) |
388 | return; |
389 | |
390 | SHA1Update(&m_Context, pbData, cbData); |
391 | } |
392 | |
393 | // Retrieve a pointer to the final hash. |
394 | BYTE *SHA1Hash::GetHash() |
395 | { |
396 | CONTRACTL { |
397 | NOTHROW; |
398 | GC_NOTRIGGER; |
399 | MODE_ANY; |
400 | SO_TOLERANT; |
401 | } CONTRACTL_END; |
402 | |
403 | if (m_fFinalized) |
404 | return m_Value; |
405 | |
406 | SHA1Final(&m_Context, m_Value); |
407 | |
408 | m_fFinalized = TRUE; |
409 | |
410 | return m_Value; |
411 | } |
412 | |
413 | |