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