| 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 | |