| 1 | // [License] | 
|---|
| 2 | // 100% free public domain implementation of the SHA-1 algorithm | 
|---|
| 3 | // by Dominik Reichl <dominik.reichl@t-online.de> | 
|---|
| 4 | // [License] | 
|---|
| 5 | /* | 
|---|
| 6 | Version 1.5 - 2005-01-01 | 
|---|
| 7 | - 64-bit compiler compatibility added | 
|---|
| 8 | - Made variable wiping optional (define SHA1_WIPE_VARIABLES) | 
|---|
| 9 | - Removed unnecessary variable initializations | 
|---|
| 10 | - ROL32 improvement for the Microsoft compiler (using _rotl) | 
|---|
| 11 |  | 
|---|
| 12 | ======== Test Vectors (from FIPS PUB 180-1) ======== | 
|---|
| 13 |  | 
|---|
| 14 | SHA1("abc") = | 
|---|
| 15 | A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D | 
|---|
| 16 |  | 
|---|
| 17 | SHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = | 
|---|
| 18 | 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 | 
|---|
| 19 |  | 
|---|
| 20 | SHA1(A million repetitions of "a") = | 
|---|
| 21 | 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F | 
|---|
| 22 | */ | 
|---|
| 23 |  | 
|---|
| 24 |  | 
|---|
| 25 | /** | 
|---|
| 26 | * @file SHA1.cc | 
|---|
| 27 | */ | 
|---|
| 28 |  | 
|---|
| 29 | #include "sha1.h" | 
|---|
| 30 |  | 
|---|
| 31 | #ifdef SHA1_UTILITY_FUNCTIONS | 
|---|
| 32 | #define SHA1_MAX_FILE_BUFFER 8000 | 
|---|
| 33 | #endif | 
|---|
| 34 |  | 
|---|
| 35 | // Rotate x bits to the left | 
|---|
| 36 | #ifndef ROL32 | 
|---|
| 37 | #ifdef _MSC_VER | 
|---|
| 38 | #define ROL32(_val32, _nBits) _rotl(_val32, _nBits) | 
|---|
| 39 | #else | 
|---|
| 40 | #define ROL32(_val32, _nBits) (((_val32)<<(_nBits))|((_val32)>>(32-(_nBits)))) | 
|---|
| 41 | #endif | 
|---|
| 42 | #endif | 
|---|
| 43 |  | 
|---|
| 44 | #ifdef SHA1_LITTLE_ENDIAN | 
|---|
| 45 | #define SHABLK0(i) (m_block->l[i] = \ | 
|---|
| 46 | (ROL32(m_block->l[i],24) & 0xFF00FF00) | (ROL32(m_block->l[i],8) & 0x00FF00FF)) | 
|---|
| 47 | #else | 
|---|
| 48 | #define SHABLK0(i) (m_block->l[i]) | 
|---|
| 49 | #endif | 
|---|
| 50 |  | 
|---|
| 51 | #define SHABLK(i) (m_block->l[i&15] = ROL32(m_block->l[(i+13)&15] ^ m_block->l[(i+8)&15] \ | 
|---|
| 52 | ^ m_block->l[(i+2)&15] ^ m_block->l[i&15],1)) | 
|---|
| 53 |  | 
|---|
| 54 | // SHA-1 rounds | 
|---|
| 55 | #define _R0(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK0(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); } | 
|---|
| 56 | #define _R1(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); } | 
|---|
| 57 | #define _R2(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0x6ED9EBA1+ROL32(v,5); w=ROL32(w,30); } | 
|---|
| 58 | #define _R3(v,w,x,y,z,i) { z+=(((w|x)&y)|(w&x))+SHABLK(i)+0x8F1BBCDC+ROL32(v,5); w=ROL32(w,30); } | 
|---|
| 59 | #define _R4(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0xCA62C1D6+ROL32(v,5); w=ROL32(w,30); } | 
|---|
| 60 |  | 
|---|
| 61 | CSHA1::CSHA1() | 
|---|
| 62 | { | 
|---|
| 63 | m_block = (SHA1_WORKSPACE_BLOCK *)m_workspace; | 
|---|
| 64 |  | 
|---|
| 65 | Reset(); | 
|---|
| 66 | } | 
|---|
| 67 |  | 
|---|
| 68 | CSHA1::~CSHA1() | 
|---|
| 69 | { | 
|---|
| 70 | Reset(); | 
|---|
| 71 | } | 
|---|
| 72 |  | 
|---|
| 73 | void CSHA1::Reset() | 
|---|
| 74 | { | 
|---|
| 75 | // SHA1 initialization constants | 
|---|
| 76 | m_state[0] = 0x67452301; | 
|---|
| 77 | m_state[1] = 0xEFCDAB89; | 
|---|
| 78 | m_state[2] = 0x98BADCFE; | 
|---|
| 79 | m_state[3] = 0x10325476; | 
|---|
| 80 | m_state[4] = 0xC3D2E1F0; | 
|---|
| 81 |  | 
|---|
| 82 | m_count[0] = 0; | 
|---|
| 83 | m_count[1] = 0; | 
|---|
| 84 | } | 
|---|
| 85 |  | 
|---|
| 86 | void CSHA1::Transform(UINT_32 *state, UINT_8 *buffer) | 
|---|
| 87 | { | 
|---|
| 88 | // Copy state[] to working vars | 
|---|
| 89 | UINT_32 a = state[0], b = state[1], c = state[2], d = state[3], e = state[4]; | 
|---|
| 90 |  | 
|---|
| 91 | memcpy(m_block, buffer, 64); | 
|---|
| 92 |  | 
|---|
| 93 | // 4 rounds of 20 operations each. Loop unrolled. | 
|---|
| 94 | _R0(a,b,c,d,e, 0); | 
|---|
| 95 | _R0(e,a,b,c,d, 1); | 
|---|
| 96 | _R0(d,e,a,b,c, 2); | 
|---|
| 97 | _R0(c,d,e,a,b, 3); | 
|---|
| 98 | _R0(b,c,d,e,a, 4); | 
|---|
| 99 | _R0(a,b,c,d,e, 5); | 
|---|
| 100 | _R0(e,a,b,c,d, 6); | 
|---|
| 101 | _R0(d,e,a,b,c, 7); | 
|---|
| 102 | _R0(c,d,e,a,b, 8); | 
|---|
| 103 | _R0(b,c,d,e,a, 9); | 
|---|
| 104 | _R0(a,b,c,d,e,10); | 
|---|
| 105 | _R0(e,a,b,c,d,11); | 
|---|
| 106 | _R0(d,e,a,b,c,12); | 
|---|
| 107 | _R0(c,d,e,a,b,13); | 
|---|
| 108 | _R0(b,c,d,e,a,14); | 
|---|
| 109 | _R0(a,b,c,d,e,15); | 
|---|
| 110 | _R1(e,a,b,c,d,16); | 
|---|
| 111 | _R1(d,e,a,b,c,17); | 
|---|
| 112 | _R1(c,d,e,a,b,18); | 
|---|
| 113 | _R1(b,c,d,e,a,19); | 
|---|
| 114 | _R2(a,b,c,d,e,20); | 
|---|
| 115 | _R2(e,a,b,c,d,21); | 
|---|
| 116 | _R2(d,e,a,b,c,22); | 
|---|
| 117 | _R2(c,d,e,a,b,23); | 
|---|
| 118 | _R2(b,c,d,e,a,24); | 
|---|
| 119 | _R2(a,b,c,d,e,25); | 
|---|
| 120 | _R2(e,a,b,c,d,26); | 
|---|
| 121 | _R2(d,e,a,b,c,27); | 
|---|
| 122 | _R2(c,d,e,a,b,28); | 
|---|
| 123 | _R2(b,c,d,e,a,29); | 
|---|
| 124 | _R2(a,b,c,d,e,30); | 
|---|
| 125 | _R2(e,a,b,c,d,31); | 
|---|
| 126 | _R2(d,e,a,b,c,32); | 
|---|
| 127 | _R2(c,d,e,a,b,33); | 
|---|
| 128 | _R2(b,c,d,e,a,34); | 
|---|
| 129 | _R2(a,b,c,d,e,35); | 
|---|
| 130 | _R2(e,a,b,c,d,36); | 
|---|
| 131 | _R2(d,e,a,b,c,37); | 
|---|
| 132 | _R2(c,d,e,a,b,38); | 
|---|
| 133 | _R2(b,c,d,e,a,39); | 
|---|
| 134 | _R3(a,b,c,d,e,40); | 
|---|
| 135 | _R3(e,a,b,c,d,41); | 
|---|
| 136 | _R3(d,e,a,b,c,42); | 
|---|
| 137 | _R3(c,d,e,a,b,43); | 
|---|
| 138 | _R3(b,c,d,e,a,44); | 
|---|
| 139 | _R3(a,b,c,d,e,45); | 
|---|
| 140 | _R3(e,a,b,c,d,46); | 
|---|
| 141 | _R3(d,e,a,b,c,47); | 
|---|
| 142 | _R3(c,d,e,a,b,48); | 
|---|
| 143 | _R3(b,c,d,e,a,49); | 
|---|
| 144 | _R3(a,b,c,d,e,50); | 
|---|
| 145 | _R3(e,a,b,c,d,51); | 
|---|
| 146 | _R3(d,e,a,b,c,52); | 
|---|
| 147 | _R3(c,d,e,a,b,53); | 
|---|
| 148 | _R3(b,c,d,e,a,54); | 
|---|
| 149 | _R3(a,b,c,d,e,55); | 
|---|
| 150 | _R3(e,a,b,c,d,56); | 
|---|
| 151 | _R3(d,e,a,b,c,57); | 
|---|
| 152 | _R3(c,d,e,a,b,58); | 
|---|
| 153 | _R3(b,c,d,e,a,59); | 
|---|
| 154 | _R4(a,b,c,d,e,60); | 
|---|
| 155 | _R4(e,a,b,c,d,61); | 
|---|
| 156 | _R4(d,e,a,b,c,62); | 
|---|
| 157 | _R4(c,d,e,a,b,63); | 
|---|
| 158 | _R4(b,c,d,e,a,64); | 
|---|
| 159 | _R4(a,b,c,d,e,65); | 
|---|
| 160 | _R4(e,a,b,c,d,66); | 
|---|
| 161 | _R4(d,e,a,b,c,67); | 
|---|
| 162 | _R4(c,d,e,a,b,68); | 
|---|
| 163 | _R4(b,c,d,e,a,69); | 
|---|
| 164 | _R4(a,b,c,d,e,70); | 
|---|
| 165 | _R4(e,a,b,c,d,71); | 
|---|
| 166 | _R4(d,e,a,b,c,72); | 
|---|
| 167 | _R4(c,d,e,a,b,73); | 
|---|
| 168 | _R4(b,c,d,e,a,74); | 
|---|
| 169 | _R4(a,b,c,d,e,75); | 
|---|
| 170 | _R4(e,a,b,c,d,76); | 
|---|
| 171 | _R4(d,e,a,b,c,77); | 
|---|
| 172 | _R4(c,d,e,a,b,78); | 
|---|
| 173 | _R4(b,c,d,e,a,79); | 
|---|
| 174 |  | 
|---|
| 175 | // Add the working vars back into state | 
|---|
| 176 | state[0] += a; | 
|---|
| 177 | state[1] += b; | 
|---|
| 178 | state[2] += c; | 
|---|
| 179 | state[3] += d; | 
|---|
| 180 | state[4] += e; | 
|---|
| 181 |  | 
|---|
| 182 | // Wipe variables | 
|---|
| 183 | #ifdef SHA1_WIPE_VARIABLES | 
|---|
| 184 |  | 
|---|
| 185 | a = b = c = d = e = 0; | 
|---|
| 186 | #endif | 
|---|
| 187 | } | 
|---|
| 188 |  | 
|---|
| 189 | // Use this function to hash in binary data and strings | 
|---|
| 190 | void CSHA1::Update(UINT_8 *data, UINT_32 len) | 
|---|
| 191 | { | 
|---|
| 192 | UINT_32 i, j; | 
|---|
| 193 |  | 
|---|
| 194 | j = (m_count[0] >> 3) & 63; | 
|---|
| 195 |  | 
|---|
| 196 | if((m_count[0] += len << 3) < (len << 3)) | 
|---|
| 197 | m_count[1]++; | 
|---|
| 198 |  | 
|---|
| 199 | m_count[1] += (len >> 29); | 
|---|
| 200 |  | 
|---|
| 201 | if((j + len) > 63) { | 
|---|
| 202 | i = 64 - j; | 
|---|
| 203 | memcpy(&m_buffer[j], data, i); | 
|---|
| 204 | Transform(m_state, m_buffer); | 
|---|
| 205 |  | 
|---|
| 206 | for( ; i + 63 < len; i += 64) | 
|---|
| 207 | Transform(m_state, &data[i]); | 
|---|
| 208 |  | 
|---|
| 209 | j = 0; | 
|---|
| 210 | } else | 
|---|
| 211 | i = 0; | 
|---|
| 212 |  | 
|---|
| 213 | memcpy(&m_buffer[j], &data[i], len - i); | 
|---|
| 214 | } | 
|---|
| 215 |  | 
|---|
| 216 | #ifdef SHA1_UTILITY_FUNCTIONS | 
|---|
| 217 | // Hash in file contents | 
|---|
| 218 | bool CSHA1::HashFile(char *szFileName) | 
|---|
| 219 | { | 
|---|
| 220 | unsigned long ulFileSize, ulRest, ulBlocks; | 
|---|
| 221 | unsigned long i; | 
|---|
| 222 | UINT_8 uData[SHA1_MAX_FILE_BUFFER]; | 
|---|
| 223 | FILE *fIn; | 
|---|
| 224 |  | 
|---|
| 225 | if(szFileName == NULL) | 
|---|
| 226 | return false; | 
|---|
| 227 |  | 
|---|
| 228 | fIn = fopen(szFileName, "rb"); | 
|---|
| 229 | if(fIn == NULL) | 
|---|
| 230 | return false; | 
|---|
| 231 |  | 
|---|
| 232 | fseek(fIn, 0, SEEK_END); | 
|---|
| 233 | ulFileSize = (unsigned long)ftell(fIn); | 
|---|
| 234 | fseek(fIn, 0, SEEK_SET); | 
|---|
| 235 |  | 
|---|
| 236 | if(ulFileSize != 0) { | 
|---|
| 237 | ulBlocks = ulFileSize / SHA1_MAX_FILE_BUFFER; | 
|---|
| 238 | ulRest = ulFileSize % SHA1_MAX_FILE_BUFFER; | 
|---|
| 239 | } else { | 
|---|
| 240 | ulBlocks = 0; | 
|---|
| 241 | ulRest = 0; | 
|---|
| 242 | } | 
|---|
| 243 |  | 
|---|
| 244 | bool ret = true; | 
|---|
| 245 | size_t rets = -1; | 
|---|
| 246 |  | 
|---|
| 247 | for(i = 0; i < ulBlocks; i++) { | 
|---|
| 248 | rets = fread(uData, 1, SHA1_MAX_FILE_BUFFER, fIn); | 
|---|
| 249 | ret &= (rets > 0 ); | 
|---|
| 250 | Update((UINT_8 *)uData, SHA1_MAX_FILE_BUFFER); | 
|---|
| 251 | } | 
|---|
| 252 |  | 
|---|
| 253 | if(ulRest != 0) { | 
|---|
| 254 | rets = fread(uData, 1, ulRest, fIn); | 
|---|
| 255 | ret &= (rets > 0 ); | 
|---|
| 256 | Update((UINT_8 *)uData, ulRest); | 
|---|
| 257 | } | 
|---|
| 258 |  | 
|---|
| 259 | fclose(fIn); | 
|---|
| 260 | fIn = NULL; | 
|---|
| 261 | return ret; | 
|---|
| 262 | } | 
|---|
| 263 | #endif | 
|---|
| 264 |  | 
|---|
| 265 | void CSHA1::Final() | 
|---|
| 266 | { | 
|---|
| 267 | UINT_32 i; | 
|---|
| 268 | UINT_8 finalcount[8]; | 
|---|
| 269 |  | 
|---|
| 270 | for(i = 0; i < 8; i++) | 
|---|
| 271 | finalcount[i] = (UINT_8)((m_count[((i >= 4) ? 0 : 1)] | 
|---|
| 272 | >> ((3 - (i & 3)) * 8) ) & 255); // Endian independent | 
|---|
| 273 |  | 
|---|
| 274 | Update((UINT_8 *)"\200", 1); | 
|---|
| 275 |  | 
|---|
| 276 | while ((m_count[0] & 504) != 448) | 
|---|
| 277 | Update((UINT_8 *)"\0", 1); | 
|---|
| 278 |  | 
|---|
| 279 | Update(finalcount, 8); // Cause a SHA1Transform() | 
|---|
| 280 |  | 
|---|
| 281 | for(i = 0; i < 20; i++) { | 
|---|
| 282 | m_digest[i] = (UINT_8)((m_state[i >> 2] >> ((3 - (i & 3)) * 8) ) & 255); | 
|---|
| 283 | } | 
|---|
| 284 |  | 
|---|
| 285 | // Wipe variables for security reasons | 
|---|
| 286 | #ifdef SHA1_WIPE_VARIABLES | 
|---|
| 287 | i = 0; | 
|---|
| 288 | memset(m_buffer, 0, 64); | 
|---|
| 289 | memset(m_state, 0, 20); | 
|---|
| 290 | memset(m_count, 0, 8); | 
|---|
| 291 | memset(finalcount, 0, 8); | 
|---|
| 292 | Transform(m_state, m_buffer); | 
|---|
| 293 | #endif | 
|---|
| 294 | } | 
|---|
| 295 |  | 
|---|
| 296 | #ifdef SHA1_UTILITY_FUNCTIONS | 
|---|
| 297 | // Get the final hash as a pre-formatted string | 
|---|
| 298 | void CSHA1::ReportHash(char *szReport, unsigned char uReportType) | 
|---|
| 299 | { | 
|---|
| 300 | unsigned char i; | 
|---|
| 301 | char szTemp[16]; | 
|---|
| 302 |  | 
|---|
| 303 | if(szReport == NULL) | 
|---|
| 304 | return; | 
|---|
| 305 |  | 
|---|
| 306 | if(uReportType == REPORT_HEX) { | 
|---|
| 307 | //sprintf(szTemp, "%02x", m_digest[0]); | 
|---|
| 308 | //strcat(szReport, szTemp); | 
|---|
| 309 |  | 
|---|
| 310 | for(i = 0; i < 20; i++) { | 
|---|
| 311 | sprintf(szTemp, "%02x", m_digest[i]); | 
|---|
| 312 | strcat(szReport, szTemp); | 
|---|
| 313 | } | 
|---|
| 314 | } else if(uReportType == REPORT_DIGIT) { | 
|---|
| 315 | sprintf(szTemp, "%u", m_digest[0]); | 
|---|
| 316 | strcat(szReport, szTemp); | 
|---|
| 317 |  | 
|---|
| 318 | for(i = 1; i < 20; i++) { | 
|---|
| 319 | sprintf(szTemp, " %u", m_digest[i]); | 
|---|
| 320 | strcat(szReport, szTemp); | 
|---|
| 321 | } | 
|---|
| 322 | } else | 
|---|
| 323 | strcpy(szReport, "Error: Unknown report type!"); | 
|---|
| 324 | } | 
|---|
| 325 | #endif | 
|---|
| 326 |  | 
|---|
| 327 | // Get the raw message digest | 
|---|
| 328 | void CSHA1::GetHash(UINT_8 *puDest) | 
|---|
| 329 | { | 
|---|
| 330 | memcpy(puDest, m_digest, 20); | 
|---|
| 331 | } | 
|---|