Changeset 407 for trunk/thune/support/sha1.c
- Timestamp:
- 06/08/07 23:06:09 (18 months ago)
- Files:
-
- 1 modified
-
trunk/thune/support/sha1.c (modified) (15 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/thune/support/sha1.c
r299 r407 1 1 /* 2 2 SHA-1 in C 3 By Steve Reid <s teve@edmweb.com>3 By Steve Reid <sreid@sea-to-sky.net> 4 4 100% Public Domain 5 5 6 ----------------- 7 Modified 7/98 8 By James H. Brown <jbrown@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@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@edmweb.com to sreid@sea-to-sky.net 51 52 ----------------- 53 Modified 4/01 54 By Saul Kravitz <Saul.Kravitz@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@artofcode.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 /* 6 70 Test Vectors (from FIPS PUB 180-1) 7 71 "abc" … … 13 77 */ 14 78 15 /* #define LITTLE_ENDIAN* This should be #define'd if true. */79 /* #define __BIG_ENDIAN__ * This should be #define'd if true. */ 16 80 /* #define SHA1HANDSOFF * Copies data before messing with it. */ 17 81 18 #include <stdio.h> 82 19 83 #include <string.h> 84 #include <stdint.h> 85 20 86 21 87 typedef struct { 22 u nsigned longstate[5];23 u nsigned longcount[2];24 u nsigned charbuffer[64];88 uint32_t state[5]; 89 uint32_t count[2]; 90 uint8_t buffer[64]; 25 91 } SHA1_CTX; 26 92 27 void SHA1Transform(unsigned long state[5], unsigned char buffer[64]); 28 void SHA1Init(SHA1_CTX* context); 29 void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len); 30 void SHA1Final(unsigned char digest[20], SHA1_CTX* context); 93 94 #define SHA1_DIGEST_SIZE 20 31 95 32 96 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) … … 34 98 /* blk0() and blk() perform the initial expand. */ 35 99 /* I got the idea of expanding during the round function from SSLeay */ 36 #ifdef LITTLE_ENDIAN 100 /* FIXME: can we do this in an endian-proof way? */ 101 #ifdef __BIG_ENDIAN__ 102 #define blk0(i) block->l[i] 103 #else 37 104 #define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ 38 105 |(rol(block->l[i],8)&0x00FF00FF)) 39 #else40 #define blk0(i) block->l[i]41 106 #endif 42 107 #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ … … 52 117 53 118 /* Hash a single 512-bit block. This is the core of the algorithm. */ 54 55 void SHA1Transform(unsigned long state[5], unsigned char buffer[64]) 56 { 57 unsigned long a, b, c, d, e; 58 typedef union { 59 unsigned char c[64];60 unsigned long l[16];61 } CHAR64LONG16;62 CHAR64LONG16* block; 119 void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]) 120 { 121 uint32_t a, b, c, d, e; 122 typedef union { 123 uint8_t c[64]; 124 uint32_t l[16]; 125 } CHAR64LONG16; 126 CHAR64LONG16* block; 127 63 128 #ifdef SHA1HANDSOFF 64 static unsigned charworkspace[64];129 static uint8_t workspace[64]; 65 130 block = (CHAR64LONG16*)workspace; 66 131 memcpy(block, buffer, 64); … … 68 133 block = (CHAR64LONG16*)buffer; 69 134 #endif 135 70 136 /* Copy context->state[] to working vars */ 71 137 a = state[0]; … … 74 140 d = state[3]; 75 141 e = state[4]; 142 76 143 /* 4 rounds of 20 operations each. Loop unrolled. */ 77 144 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); … … 95 162 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); 96 163 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); 164 97 165 /* Add the working vars back into context.state[] */ 98 166 state[0] += a; … … 101 169 state[3] += d; 102 170 state[4] += e; 171 103 172 /* Wipe variables */ 104 173 a = b = c = d = e = 0; … … 107 176 108 177 /* SHA1Init - Initialize new context */ 109 110 void SHA1Init(SHA1_CTX* context) 178 void SHA1_Init(SHA1_CTX* context) 111 179 { 112 180 /* SHA1 initialization constants */ … … 121 189 122 190 /* Run your data through this. */ 123 124 void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len) 125 { 126 unsigned int i, j; 191 void SHA1_Update(SHA1_CTX* context, const uint8_t* data, const size_t len) 192 { 193 size_t i, j; 127 194 128 195 j = (context->count[0] >> 3) & 63; … … 131 198 if ((j + len) > 63) { 132 199 memcpy(&context->buffer[j], data, (i = 64-j)); 133 SHA1 Transform(context->state, context->buffer);200 SHA1_Transform(context->state, context->buffer); 134 201 for ( ; i + 63 < len; i += 64) { 135 SHA1 Transform(context->state, &data[i]);202 SHA1_Transform(context->state, data + i); 136 203 } 137 204 j = 0; … … 143 210 144 211 /* Add padding and return the message digest. */ 145 146 void SHA1Final(unsigned char digest[20], SHA1_CTX* context) 147 { 148 unsigned long i, j; 149 unsigned char finalcount[8]; 212 void SHA1_Final(SHA1_CTX* context, uint8_t digest[SHA1_DIGEST_SIZE]) 213 { 214 uint32_t i; 215 uint8_t finalcount[8]; 150 216 151 217 for (i = 0; i < 8; i++) { … … 153 219 >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ 154 220 } 155 SHA1 Update(context, (unsigned char*)"\200", 1);221 SHA1_Update(context, (uint8_t *)"\200", 1); 156 222 while ((context->count[0] & 504) != 448) { 157 SHA1 Update(context, (unsigned char*)"\0", 1);158 } 159 SHA1 Update(context, finalcount, 8); /* Should cause a SHA1Transform() */160 for (i = 0; i < 20; i++) {161 digest[i] = (u nsigned char)223 SHA1_Update(context, (uint8_t *)"\0", 1); 224 } 225 SHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */ 226 for (i = 0; i < SHA1_DIGEST_SIZE; i++) { 227 digest[i] = (uint8_t) 162 228 ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); 163 229 } 230 164 231 /* Wipe variables */ 165 i = j =0;232 i = 0; 166 233 memset(context->buffer, 0, 64); 167 234 memset(context->state, 0, 20); 168 235 memset(context->count, 0, 8); 169 memset( &finalcount, 0, 8);170 #ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ 171 SHA1Transform(context->state, context->buffer); 172 #endif 173 } 174 175 236 memset(finalcount, 0, 8); /* SWR */ 237 238 #ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */ 239 SHA1_Transform(context->state, context->buffer); 240 #endif 241 } 242 176 243 /*************************************************************/ 177 244 178 179 245 #ifdef UNIT_TEST 246 #include <stdio.h> 247 180 248 int main(int argc, char** argv) 181 249 { 182 250 int i, j; 183 251 SHA1_CTX context; 184 unsigned char digest[ 20], buffer[16384];252 unsigned char digest[SHA1_DIGEST_SIZE], buffer[16384]; 185 253 FILE* file; 186 254 187 255 if (argc > 2) { 188 puts("Public domain SHA-1 implementation - by Steve Reid <steve@edmweb.com>"); 256 puts("Public domain SHA-1 implementation - by Steve Reid <sreid@sea-to-sky.net>"); 257 puts("Modified for 16 bit environments 7/98 - by James H. Brown <jbrown@burgoyne.com>"); /* JHB */ 189 258 puts("Produces the SHA-1 hash of a file, or stdin if no file is specified."); 190 exit(0);259 return(0); 191 260 } 192 261 if (argc < 2) { … … 196 265 if (!(file = fopen(argv[1], "rb"))) { 197 266 fputs("Unable to open file.", stderr); 198 exit(-1);267 return(-1); 199 268 } 200 269 } 201 SHA1 Init(&context);270 SHA1_Init(&context); 202 271 while (!feof(file)) { /* note: what if ferror(file) */ 203 272 i = fread(buffer, 1, 16384, file); 204 SHA1 Update(&context, buffer, i);205 } 206 SHA1 Final(digest, &context);273 SHA1_Update(&context, buffer, i); 274 } 275 SHA1_Final(&context, digest); 207 276 fclose(file); 208 for (i = 0; i < 5; i++) {277 for (i = 0; i < SHA1_DIGEST_SIZE/4; i++) { 209 278 for (j = 0; j < 4; j++) { 210 279 printf("%02X", digest[i*4+j]); … … 213 282 } 214 283 putchar('\n'); 215 exit(0);216 } 217 #endif 284 return(0); /* JHB */ 285 } 286 #endif
