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.
7 // ===========================================================================
10 // ===========================================================================
22 File sha1.cpp <STRIP>Version 03 August 2000.</STRIP>
25 This implements the SHA-1 hash function.
26 For algorithmic background see (for example)
29 Alfred J. Menezes et al
30 Handbook of Applied Cryptography
31 The CRC Press Series on Discrete Mathematics
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).
47 typedef const DWORD DWORDC;
48 #define ROTATE32L(x,n) _rotl(x,n)
49 #define SHAVE32(x) (DWORD)(x)
51 static void SHA1_block(SHA1_CTX *ctx)
53 Update the SHA-1 hash from a fresh 64 bytes of data.
56 static DWORDC sha1_round1 = 0x5A827999u;
57 static DWORDC sha1_round2 = 0x6ED9EBA1u;
58 static DWORDC sha1_round3 = 0x8F1BBCDCu;
59 static DWORDC sha1_round4 = 0xCA62C1D6u;
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];
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).
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;
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);
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)
93 #define ROUND3(B, C, D) (((C & (B | D)) | (B & D)) + sha1_round3)
95 #define ROUND4(B, C, D) ((B ^ C ^ D) + sha1_round4)
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);
102 d += ROTATE32L(e, 5) + ROUND1(a, b, c) + msg80[i+1];
103 a = ROTATE32L(a, 30);
105 c += ROTATE32L(d, 5) + ROUND1(e, a, b) + msg80[i+2];
106 e = ROTATE32L(e, 30);
108 b += ROTATE32L(c, 5) + ROUND1(d, e, a) + msg80[i+3];
109 d = ROTATE32L(d, 30);
111 a += ROTATE32L(b, 5) + ROUND1(c, d, e) + msg80[i+4];
112 c = ROTATE32L(c, 30);
114 printf("i = %ld %08lx %08lx %08lx %08lx %08lx\n",
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);
124 d += ROTATE32L(e, 5) + ROUND2(a, b, c) + msg80[i+1];
125 a = ROTATE32L(a, 30);
127 c += ROTATE32L(d, 5) + ROUND2(e, a, b) + msg80[i+2];
128 e = ROTATE32L(e, 30);
130 b += ROTATE32L(c, 5) + ROUND2(d, e, a) + msg80[i+3];
131 d = ROTATE32L(d, 30);
133 a += ROTATE32L(b, 5) + ROUND2(c, d, e) + msg80[i+4];
134 c = ROTATE32L(c, 30);
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);
142 d += ROTATE32L(e, 5) + ROUND3(a, b, c) + msg80[i+1];
143 a = ROTATE32L(a, 30);
145 c += ROTATE32L(d, 5) + ROUND3(e, a, b) + msg80[i+2];
146 e = ROTATE32L(e, 30);
148 b += ROTATE32L(c, 5) + ROUND3(d, e, a) + msg80[i+3];
149 d = ROTATE32L(d, 30);
151 a += ROTATE32L(b, 5) + ROUND3(c, d, e) + msg80[i+4];
152 c = ROTATE32L(c, 30);
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);
160 d += ROTATE32L(e, 5) + ROUND4(a, b, c) + msg80[i+1];
161 a = ROTATE32L(a, 30);
163 c += ROTATE32L(d, 5) + ROUND4(e, a, b) + msg80[i+2];
164 e = ROTATE32L(e, 30);
166 b += ROTATE32L(c, 5) + ROUND4(d, e, a) + msg80[i+3];
167 d = ROTATE32L(d, 30);
169 a += ROTATE32L(b, 5) + ROUND4(c, d, e) + msg80[i+4];
170 c = ROTATE32L(c, 30);
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;
184 for (i = 0; i < 16; i++) {
185 printf("%8lx ", msg16[i]);
186 if ((i & 7) == 7) printf("\n");
188 printf("a, b, c, d, e = %08lx %08lx %08lx %08lx %08lx\n",
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]);
198 void SHA1Hash::SHA1Init(SHA1_CTX *ctx)
206 ctx->nbit_total[0] = ctx->nbit_total[1] = 0;
208 for (DWORD i = 0; i != 16; i++) {
209 ctx->awaiting_data[i] = 0;
213 Initialize hash variables.
217 ctx->partial_hash[0] = 0x67452301u;
218 ctx->partial_hash[1] = 0xefcdab89u;
219 ctx->partial_hash[2] = ~ctx->partial_hash[0];
220 ctx->partial_hash[3] = ~ctx->partial_hash[1];
221 ctx->partial_hash[4] = 0xc3d2e1f0u;
225 void SHA1Hash::SHA1Update(
226 SHA1_CTX * ctx, // IN/OUT
227 const BYTE * msg, // IN
230 Append data to a partially hashed SHA-1 message.
239 const BYTE *fresh_data = msg;
240 DWORD nbyte_left = nbyte;
241 DWORD nbit_occupied = ctx->nbit_total[0] & 511;
242 DWORD *awaiting_data;
243 DWORDC nbitnew_low = SHAVE32(8*nbyte);
246 _ASSERTE((nbit_occupied & 7) == 0); // Partial bytes not implemented
248 ctx->nbit_total[0] += nbitnew_low;
249 ctx->nbit_total[1] += (nbyte >> 29)
250 + (SHAVE32(ctx->nbit_total[0]) < nbitnew_low);
252 /* Advance to word boundary in waiting_data */
254 if ((nbit_occupied & 31) != 0) {
255 awaiting_data = ctx->awaiting_data + nbit_occupied/32;
257 while ((nbit_occupied & 31) != 0 && nbyte_left != 0) {
259 *awaiting_data |= (DWORD)*fresh_data++
260 << ((-(int)nbit_occupied) & 31);
261 nbyte_left--; // Start at most significant byte
263 } // if nbit_occupied
265 /* Transfer 4 bytes at a time */
268 DWORDC nword_occupied = nbit_occupied/32;
269 DWORD nwcopy = min(nbyte_left/4, 16 - nword_occupied);
270 _ASSERTE (nbit_occupied <= 512);
271 _ASSERTE ((nbit_occupied & 31) == 0 || nbyte_left == 0);
272 awaiting_data = ctx->awaiting_data + nword_occupied;
273 nbyte_left -= 4*nwcopy;
274 nbit_occupied += 32*nwcopy;
276 while (nwcopy != 0) {
277 DWORDC byte0 = (DWORD)fresh_data[0];
278 DWORDC byte1 = (DWORD)fresh_data[1];
279 DWORDC byte2 = (DWORD)fresh_data[2];
280 DWORDC byte3 = (DWORD)fresh_data[3];
281 *awaiting_data++ = byte3 | (byte2 << 8)
282 | (byte1 << 16) | (byte0 << 24);
288 if (nbit_occupied == 512) {
292 _ASSERTE(awaiting_data == ctx->awaiting_data);
294 } while (nbyte_left >= 4);
296 _ASSERTE (ctx->awaiting_data + nbit_occupied/32
299 while (nbyte_left != 0) {
300 DWORDC new_byte = (DWORD)*fresh_data++;
302 _ASSERTE((nbit_occupied & 31) <= 16);
304 *awaiting_data |= new_byte << ((-(int)nbit_occupied) & 31);
308 _ASSERTE (nbit_occupied == (ctx->nbit_total[0] & 511));
313 void SHA1Hash::SHA1Final(
314 SHA1_CTX * ctx, // IN/OUT
315 BYTE * digest) // OUT
326 DWORDC nbit0 = ctx->nbit_total[0];
327 DWORDC nbit1 = ctx->nbit_total[1];
328 DWORD nbit_occupied = nbit0 & 511;
331 _ASSERTE((nbit_occupied & 7) == 0);
333 ctx->awaiting_data[nbit_occupied/32]
334 |= (DWORD)0x80 << ((-8-nbit_occupied) & 31);
339 // Append zero bits until length (in bits) is 448 mod 512.
340 // Then append the length, in bits.
341 // Here we assume the buffer was zeroed earlier.
343 if (nbit_occupied > 448) { // If fewer than 64 bits left
347 ctx->awaiting_data[14] = nbit1;
348 ctx->awaiting_data[15] = nbit0;
351 /* Copy final digest to user-supplied byte array */
353 for (i = 0; i != 5; i++) {
354 DWORDC dwi = ctx->partial_hash[i];
355 digest[4*i + 0] = (BYTE)((dwi >> 24) & 255);
356 digest[4*i + 1] = (BYTE)((dwi >> 16) & 255);
357 digest[4*i + 2] = (BYTE)((dwi >> 8) & 255);
358 digest[4*i + 3] = (BYTE)(dwi & 255); // Big-endian
370 m_fFinalized = FALSE;
371 SHA1Init(&m_Context);
374 void SHA1Hash::AddData(BYTE *pbData, DWORD cbData)
385 SHA1Update(&m_Context, pbData, cbData);
388 // Retrieve a pointer to the final hash.
389 BYTE *SHA1Hash::GetHash()
400 SHA1Final(&m_Context, m_Value);