1 /* 2 SHA-1 in C 3 By Steve Reid <sreid (at) sea-to-sky.net> 4 100% Public Domain 5 6 ----------------- 7 Modified 7/98 8 By James H. Brown <jbrown (at) burgoyne.com> 9 Still 100% Public Domain 10 11 Corrected a problem which generated improper hash values on 16 bit machines 12 Routine SHA1Update changed from 13 void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int 14 len) 15 to 16 void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned 17 long len) 18 19 The 'len' parameter was declared an int which works fine on 32 bit machines. 20 However, on 16 bit machines an int is too small for the shifts being done 21 against 22 it. This caused the hash function to generate incorrect values if len was 23 greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). 24 25 Since the file IO in main() reads 16K at a time, any file 8K or larger would 26 be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million 27 "a"s). 28 29 I also changed the declaration of variables i & j in SHA1Update to 30 unsigned long from unsigned int for the same reason. 31 32 These changes should make no difference to any 32 bit implementations since 33 an 34 int and a long are the same size in those environments. 35 36 -- 37 I also corrected a few compiler warnings generated by Borland C. 38 1. Added #include <process.h> for exit() prototype 39 2. Removed unused variable 'j' in SHA1Final 40 3. Changed exit(0) to return(0) at end of main. 41 42 ALL changes I made can be located by searching for comments containing 'JHB' 43 ----------------- 44 Modified 8/98 45 By Steve Reid <sreid (at) sea-to-sky.net> 46 Still 100% public domain 47 48 1- Removed #include <process.h> and used return() instead of exit() 49 2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) 50 3- Changed email address from steve (at) edmweb.com to sreid (at) sea-to-sky.net 51 52 ----------------- 53 Modified 4/01 54 By Saul Kravitz <Saul.Kravitz (at) celera.com> 55 Still 100% PD 56 Modified to run on Compaq Alpha hardware. 57 58 ----------------- 59 Modified 2/03 60 By H. Peter Anvin <hpa (at) zytor.com> 61 Still 100% PD 62 Modified to run on any hardware with <inttypes.h> and <netinet/in.h> 63 Changed the driver program 64 65 */ 66 67 /* 68 Test Vectors (from FIPS PUB 180-1) 69 "abc" 70 A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D 71 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 72 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 73 A million repetitions of "a" 74 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F 75 */ 76 77 /* #define SHA1HANDSOFF */ 78 79 #include <stdio.h> 80 #include <string.h> 81 #include <inttypes.h> 82 #include <netinet/in.h> /* For htonl/ntohl/htons/ntohs */ 83 84 #include "sha1.h" 85 86 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) 87 88 /* blk0() and blk() perform the initial expand. */ 89 /* I got the idea of expanding during the round function from SSLeay */ 90 #define blk0(i) (block->l[i] = ntohl(block->l[i])) 91 #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ 92 ^block->l[(i+2)&15]^block->l[i&15],1)) 93 94 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ 95 #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); 96 #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); 97 #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); 98 #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); 99 #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); 100 101 #ifdef VERBOSE /* SAK */ 102 void SHAPrintContext(SHA1_CTX * context, char *msg) 103 { 104 printf("%s (%d,%d) %x %x %x %x %x\n", 105 msg, 106 context->count[0], context->count[1], 107 context->state[0], 108 context->state[1], 109 context->state[2], context->state[3], context->state[4]); 110 } 111 #endif 112 113 /* Hash a single 512-bit block. This is the core of the algorithm. */ 114 115 void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]) 116 { 117 uint32_t a, b, c, d, e; 118 typedef union { 119 unsigned char c[64]; 120 uint32_t l[16]; 121 } CHAR64LONG16; 122 CHAR64LONG16 *block; 123 #ifdef SHA1HANDSOFF 124 static unsigned char workspace[64]; 125 block = (CHAR64LONG16 *) workspace; 126 memcpy(block, buffer, 64); 127 #else 128 block = (CHAR64LONG16 *) buffer; 129 #endif 130 /* Copy context->state[] to working vars */ 131 a = state[0]; 132 b = state[1]; 133 c = state[2]; 134 d = state[3]; 135 e = state[4]; 136 /* 4 rounds of 20 operations each. Loop unrolled. */ 137 R0(a, b, c, d, e, 0); 138 R0(e, a, b, c, d, 1); 139 R0(d, e, a, b, c, 2); 140 R0(c, d, e, a, b, 3); 141 R0(b, c, d, e, a, 4); 142 R0(a, b, c, d, e, 5); 143 R0(e, a, b, c, d, 6); 144 R0(d, e, a, b, c, 7); 145 R0(c, d, e, a, b, 8); 146 R0(b, c, d, e, a, 9); 147 R0(a, b, c, d, e, 10); 148 R0(e, a, b, c, d, 11); 149 R0(d, e, a, b, c, 12); 150 R0(c, d, e, a, b, 13); 151 R0(b, c, d, e, a, 14); 152 R0(a, b, c, d, e, 15); 153 R1(e, a, b, c, d, 16); 154 R1(d, e, a, b, c, 17); 155 R1(c, d, e, a, b, 18); 156 R1(b, c, d, e, a, 19); 157 R2(a, b, c, d, e, 20); 158 R2(e, a, b, c, d, 21); 159 R2(d, e, a, b, c, 22); 160 R2(c, d, e, a, b, 23); 161 R2(b, c, d, e, a, 24); 162 R2(a, b, c, d, e, 25); 163 R2(e, a, b, c, d, 26); 164 R2(d, e, a, b, c, 27); 165 R2(c, d, e, a, b, 28); 166 R2(b, c, d, e, a, 29); 167 R2(a, b, c, d, e, 30); 168 R2(e, a, b, c, d, 31); 169 R2(d, e, a, b, c, 32); 170 R2(c, d, e, a, b, 33); 171 R2(b, c, d, e, a, 34); 172 R2(a, b, c, d, e, 35); 173 R2(e, a, b, c, d, 36); 174 R2(d, e, a, b, c, 37); 175 R2(c, d, e, a, b, 38); 176 R2(b, c, d, e, a, 39); 177 R3(a, b, c, d, e, 40); 178 R3(e, a, b, c, d, 41); 179 R3(d, e, a, b, c, 42); 180 R3(c, d, e, a, b, 43); 181 R3(b, c, d, e, a, 44); 182 R3(a, b, c, d, e, 45); 183 R3(e, a, b, c, d, 46); 184 R3(d, e, a, b, c, 47); 185 R3(c, d, e, a, b, 48); 186 R3(b, c, d, e, a, 49); 187 R3(a, b, c, d, e, 50); 188 R3(e, a, b, c, d, 51); 189 R3(d, e, a, b, c, 52); 190 R3(c, d, e, a, b, 53); 191 R3(b, c, d, e, a, 54); 192 R3(a, b, c, d, e, 55); 193 R3(e, a, b, c, d, 56); 194 R3(d, e, a, b, c, 57); 195 R3(c, d, e, a, b, 58); 196 R3(b, c, d, e, a, 59); 197 R4(a, b, c, d, e, 60); 198 R4(e, a, b, c, d, 61); 199 R4(d, e, a, b, c, 62); 200 R4(c, d, e, a, b, 63); 201 R4(b, c, d, e, a, 64); 202 R4(a, b, c, d, e, 65); 203 R4(e, a, b, c, d, 66); 204 R4(d, e, a, b, c, 67); 205 R4(c, d, e, a, b, 68); 206 R4(b, c, d, e, a, 69); 207 R4(a, b, c, d, e, 70); 208 R4(e, a, b, c, d, 71); 209 R4(d, e, a, b, c, 72); 210 R4(c, d, e, a, b, 73); 211 R4(b, c, d, e, a, 74); 212 R4(a, b, c, d, e, 75); 213 R4(e, a, b, c, d, 76); 214 R4(d, e, a, b, c, 77); 215 R4(c, d, e, a, b, 78); 216 R4(b, c, d, e, a, 79); 217 /* Add the working vars back into context.state[] */ 218 state[0] += a; 219 state[1] += b; 220 state[2] += c; 221 state[3] += d; 222 state[4] += e; 223 /* Wipe variables */ 224 a = b = c = d = e = 0; 225 } 226 227 /* SHA1Init - Initialize new context */ 228 229 void SHA1Init(SHA1_CTX * context) 230 { 231 /* SHA1 initialization constants */ 232 context->state[0] = 0x67452301; 233 context->state[1] = 0xEFCDAB89; 234 context->state[2] = 0x98BADCFE; 235 context->state[3] = 0x10325476; 236 context->state[4] = 0xC3D2E1F0; 237 context->count[0] = context->count[1] = 0; 238 } 239 240 /* Run your data through this. */ 241 242 void SHA1Update(SHA1_CTX * context, const unsigned char *data, uint32_t len) 243 { /* 244 JHB */ 245 uint32_t i, j; /* JHB */ 246 247 #ifdef VERBOSE 248 SHAPrintContext(context, "before"); 249 #endif 250 j = (context->count[0] >> 3) & 63; 251 if ((context->count[0] += len << 3) < (len << 3)) 252 context->count[1]++; 253 context->count[1] += (len >> 29); 254 if ((j + len) > 63) { 255 memcpy(&context->buffer[j], data, (i = 64 - j)); 256 SHA1Transform(context->state, context->buffer); 257 for (; i + 63 < len; i += 64) { 258 SHA1Transform(context->state, &data[i]); 259 } 260 j = 0; 261 } else 262 i = 0; 263 memcpy(&context->buffer[j], &data[i], len - i); 264 #ifdef VERBOSE 265 SHAPrintContext(context, "after "); 266 #endif 267 } 268 269 /* Add padding and return the message digest. */ 270 271 void SHA1Final(unsigned char digest[20], SHA1_CTX * context) 272 { 273 uint32_t i; /* JHB */ 274 unsigned char finalcount[8]; 275 276 for (i = 0; i < 8; i++) { 277 finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] 278 >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ 279 } 280 SHA1Update(context, (unsigned char *)"\200", 1); 281 while ((context->count[0] & 504) != 448) { 282 SHA1Update(context, (unsigned char *)"\0", 1); 283 } 284 SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() 285 */ 286 for (i = 0; i < 20; i++) { 287 digest[i] = (unsigned char) 288 ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); 289 } 290 /* Wipe variables */ 291 i = 0; /* JHB */ 292 memset(context->buffer, 0, 64); 293 memset(context->state, 0, 20); 294 memset(context->count, 0, 8); 295 memset(finalcount, 0, 8); /* SWR */ 296 #ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ 297 SHA1Transform(context->state, context->buffer); 298 #endif 299 } 300 301 /*************************************************************/ 302 303 /* This is not quite the MIME base64 algorithm: it uses _ instead of /, 304 and instead of padding the output with = characters we just make the 305 output shorter. */ 306 char *mybase64(uint8_t digest[20]) 307 { 308 static const char charz[] = 309 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_"; 310 uint8_t input[21]; 311 static char output[28]; 312 int i, j; 313 uint8_t *p; 314 char *q; 315 uint32_t bv; 316 317 memcpy(input, digest, 20); 318 input[20] = 0; /* Pad to multiple of 3 bytes */ 319 320 p = input; 321 q = output; 322 for (i = 0; i < 7; i++) { 323 bv = (p[0] << 16) | (p[1] << 8) | p[2]; 324 p += 3; 325 for (j = 0; j < 4; j++) { 326 *q++ = charz[(bv >> 18) & 0x3f]; 327 bv <<= 6; 328 } 329 } 330 *--q = '\0'; /* The last character is not significant */ 331 return output; 332 } 333 334 #ifdef FOR_TESTING_ONLY 335 336 int main(int argc, char **argv) 337 { 338 int i; 339 SHA1_CTX context; 340 uint8_t digest[20], buffer[16384]; 341 FILE *file; 342 343 if (argc < 2) { 344 file = stdin; 345 } else { 346 if (!(file = fopen(argv[1], "rb"))) { 347 fputs("Unable to open file.", stderr); 348 return (-1); 349 } 350 } 351 SHA1Init(&context); 352 while (!feof(file)) { /* note: what if ferror(file) */ 353 i = fread(buffer, 1, 16384, file); 354 SHA1Update(&context, buffer, i); 355 } 356 SHA1Final(digest, &context); 357 fclose(file); 358 359 puts(mybase64(digest)); 360 361 return 0; 362 } 363 364 #endif 365