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 07/2002 60 By Ralph Giles <giles (at) ghostscript.com> 61 Still 100% public domain 62 modified for use with stdint types, autoconf 63 code cleanup, removed attribution comments 64 switched SHA1Final() argument order for consistency 65 use SHA1_ prefix for public api 66 move public api to sha1.h 67 */ 68 69 /* 70 Test Vectors (from FIPS PUB 180-1) 71 "abc" 72 A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D 73 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 74 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 75 A million repetitions of "a" 76 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F 77 */ 78 79 #include <stdio.h> 80 #include <string.h> 81 #include <stdlib.h> 82 83 #include "sha1.h" 84 85 #if defined(_MSC_VER) 86 #pragma warning(disable : 4267) 87 #pragma warning(disable : 4996) 88 #pragma warning(disable : 4100) 89 #endif 90 91 void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]); 92 93 #define rol ROTL32 94 95 /* blk0() and blk() perform the initial expand. */ 96 /* I got the idea of expanding during the round function from SSLeay */ 97 /* FIXME: can we do this in an endian-proof way? */ 98 99 #ifdef WORDS_BIGENDIAN 100 #define blk0(i) block->l[i] 101 #else 102 #define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) | (rol(block->l[i],8)&0x00FF00FF)) 103 #endif 104 #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] ^ block->l[(i+2)&15]^block->l[i&15],1)) 105 106 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ 107 #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); 108 #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); 109 #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); 110 #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); 111 #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); 112 113 114 /* Hash a single 512-bit block. This is the core of the algorithm. */ 115 void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]) 116 { 117 uint32_t a, b, c, d, e; 118 typedef union { 119 uint8_t c[64]; 120 uint32_t l[16]; 121 } CHAR64LONG16; 122 CHAR64LONG16* block; 123 124 block = (CHAR64LONG16*)buffer; 125 126 /* Copy context->state[] to working vars */ 127 a = state[0]; 128 b = state[1]; 129 c = state[2]; 130 d = state[3]; 131 e = state[4]; 132 133 /* 4 rounds of 20 operations each. Loop unrolled. */ 134 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); 135 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); 136 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); 137 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); 138 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); 139 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); 140 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); 141 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); 142 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); 143 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); 144 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); 145 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); 146 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); 147 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); 148 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); 149 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); 150 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); 151 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); 152 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); 153 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); 154 155 /* Add the working vars back into context.state[] */ 156 state[0] += a; 157 state[1] += b; 158 state[2] += c; 159 state[3] += d; 160 state[4] += e; 161 162 /* Wipe variables */ 163 a = b = c = d = e = 0; 164 } 165 166 167 /* SHA1Init - Initialize new context */ 168 void SHA1_Init(SHA1_CTX* context) 169 { 170 /* SHA1 initialization constants */ 171 context->state[0] = 0x67452301; 172 context->state[1] = 0xEFCDAB89; 173 context->state[2] = 0x98BADCFE; 174 context->state[3] = 0x10325476; 175 context->state[4] = 0xC3D2E1F0; 176 context->count[0] = 0; 177 context->count[1] = 0; 178 } 179 180 181 /* Run your data through this. */ 182 void SHA1_Update(SHA1_CTX* context, const uint8_t* data, const size_t len) 183 { 184 size_t i, j; 185 186 j = (context->count[0] >> 3) & 63; 187 if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; 188 189 context->count[1] += (len >> 29); 190 191 if ((j + len) > 63) 192 { 193 memcpy(&context->buffer[j], data, (i = 64-j)); 194 SHA1_Transform(context->state, context->buffer); 195 196 for ( ; i + 63 < len; i += 64) 197 { 198 SHA1_Transform(context->state, data + i); 199 } 200 201 j = 0; 202 } 203 else i = 0; 204 memcpy(&context->buffer[j], &data[i], len - i); 205 } 206 207 208 /* Add padding and return the message digest. */ 209 void SHA1_Final(SHA1_CTX* context, uint8_t digest[SHA1_DIGEST_SIZE]) 210 { 211 uint32_t i; 212 uint8_t finalcount[8]; 213 214 for (i = 0; i < 8; i++) { 215 finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] 216 >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ 217 } 218 SHA1_Update(context, (uint8_t *)"\200", 1); 219 while ((context->count[0] & 504) != 448) { 220 SHA1_Update(context, (uint8_t *)"\0", 1); 221 } 222 SHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */ 223 for (i = 0; i < SHA1_DIGEST_SIZE; i++) { 224 digest[i] = (uint8_t) 225 ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); 226 } 227 228 /* Wipe variables */ 229 i = 0; 230 memset(context->buffer, 0, 64); 231 memset(context->state, 0, 20); 232 memset(context->count, 0, 8); 233 memset(finalcount, 0, 8); /* SWR */ 234 } 235 236 //----------------------------------------------------------------------------- 237 238 void sha1_32a ( const void * key, int len, uint32_t seed, void * out ) 239 { 240 SHA1_CTX context; 241 242 uint8_t digest[20]; 243 244 SHA1_Init(&context); 245 SHA1_Update(&context, (uint8_t*)key, len); 246 SHA1_Final(&context, digest); 247 248 memcpy(out,&digest[0],4); 249 } 250 251 //----------------------------------------------------------------------------- 252 // self test 253 254 //#define TEST 255 256 #ifdef TEST 257 258 static char *test_data[] = { 259 "abc", 260 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 261 "A million repetitions of 'a'"}; 262 static char *test_results[] = { 263 "A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D", 264 "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1", 265 "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F"}; 266 267 268 void digest_to_hex(const uint8_t digest[SHA1_DIGEST_SIZE], char *output) 269 { 270 int i,j; 271 char *c = output; 272 273 for (i = 0; i < SHA1_DIGEST_SIZE/4; i++) { 274 for (j = 0; j < 4; j++) { 275 sprintf(c,"%02X", digest[i*4+j]); 276 c += 2; 277 } 278 sprintf(c, " "); 279 c += 1; 280 } 281 *(c - 1) = '\0'; 282 } 283 284 int main(int argc, char** argv) 285 { 286 int k; 287 SHA1_CTX context; 288 uint8_t digest[20]; 289 char output[80]; 290 291 fprintf(stdout, "verifying SHA-1 implementation... "); 292 293 for (k = 0; k < 2; k++){ 294 SHA1_Init(&context); 295 SHA1_Update(&context, (uint8_t*)test_data[k], strlen(test_data[k])); 296 SHA1_Final(&context, digest); 297 digest_to_hex(digest, output); 298 299 if (strcmp(output, test_results[k])) { 300 fprintf(stdout, "FAIL\n"); 301 fprintf(stderr,"* hash of \"%s\" incorrect:\n", test_data[k]); 302 fprintf(stderr,"\t%s returned\n", output); 303 fprintf(stderr,"\t%s is correct\n", test_results[k]); 304 return (1); 305 } 306 } 307 /* million 'a' vector we feed separately */ 308 SHA1_Init(&context); 309 for (k = 0; k < 1000000; k++) 310 SHA1_Update(&context, (uint8_t*)"a", 1); 311 SHA1_Final(&context, digest); 312 digest_to_hex(digest, output); 313 if (strcmp(output, test_results[2])) { 314 fprintf(stdout, "FAIL\n"); 315 fprintf(stderr,"* hash of \"%s\" incorrect:\n", test_data[2]); 316 fprintf(stderr,"\t%s returned\n", output); 317 fprintf(stderr,"\t%s is correct\n", test_results[2]); 318 return (1); 319 } 320 321 /* success */ 322 fprintf(stdout, "ok\n"); 323 return(0); 324 } 325 #endif /* TEST */ 326