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
13Abstract:
14
15 SHA-1 implementation
16
17Revision 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
47typedef const DWORD DWORDC;
48#define ROTATE32L(x,n) _rotl(x,n)
49#define SHAVE32(x) (DWORD)(x)
50
51static 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
198void 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
226void 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
315void 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
365SHA1Hash::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
378void 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.
394BYTE *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