1/* 2SHA-1 in C 3By Steve Reid <sreid@sea-to-sky.net> 4100% Public Domain 5 6----------------- 7Modified 7/98 8By James H. Brown <jbrown@burgoyne.com> 9Still 100% Public Domain 10 11Corrected a problem which generated improper hash values on 16 bit machines 12Routine SHA1Update changed from 13 void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int 14len) 15to 16 void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned 17long len) 18 19The 'len' parameter was declared an int which works fine on 32 bit machines. 20However, on 16 bit machines an int is too small for the shifts being done 21against 22it. This caused the hash function to generate incorrect values if len was 23greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). 24 25Since the file IO in main() reads 16K at a time, any file 8K or larger would 26be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million 27"a"s). 28 29I also changed the declaration of variables i & j in SHA1Update to 30unsigned long from unsigned int for the same reason. 31 32These changes should make no difference to any 32 bit implementations since 33an 34int and a long are the same size in those environments. 35 36-- 37I also corrected a few compiler warnings generated by Borland C. 381. Added #include <process.h> for exit() prototype 392. Removed unused variable 'j' in SHA1Final 403. Changed exit(0) to return(0) at end of main. 41 42ALL changes I made can be located by searching for comments containing 'JHB' 43----------------- 44Modified 8/98 45By Steve Reid <sreid@sea-to-sky.net> 46Still 100% public domain 47 481- Removed #include <process.h> and used return() instead of exit() 492- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) 503- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net 51 52----------------- 53Modified 4/01 54By Saul Kravitz <Saul.Kravitz@celera.com> 55Still 100% PD 56Modified to run on Compaq Alpha hardware. 57 58----------------- 59Modified 07/2002 60By Ralph Giles <giles@ghostscript.com> 61Still 100% public domain 62modified for use with stdint types, autoconf 63code cleanup, removed attribution comments 64switched SHA1Final() argument order for consistency 65use SHA1_ prefix for public api 66move public api to sha1.h 67*/ 68 69/* 70Test Vectors (from FIPS PUB 180-1) 71"abc" 72 A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D 73"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 74 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 75A 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 91void 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. */ 115void 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 */ 168void 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. */ 182void 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. */ 209void 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 238void 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 258static char *test_data[] = { 259 "abc", 260 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 261 "A million repetitions of 'a'"}; 262static char *test_results[] = { 263 "A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D", 264 "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1", 265 "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F"}; 266 267 268void 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 284int 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