Clean up gcc compiler warnings
[dyninst.git] / common / src / sha1.C
1 /*
2 SHA-1 in C
3 By Steve Reid <sreid@sea-to-sky.net>
4 100% Public Domain
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 */
60
61 /*
62 Test Vectors (from FIPS PUB 180-1)
63 "abc"
64   A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
65 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
66   84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
67 A million repetitions of "a"
68   34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
69 */
70
71 /* #define SHA1HANDSOFF  */
72
73
74 #include <stdio.h>
75 #include <string.h>
76
77 #if defined(HAVE_INTTYPES_H)
78 #include <inttypes.h>
79
80 #else
81 #if defined(HAVE_STDINT_H)
82 #include <stdint.h>
83
84 #else
85 typedef          long long int int64_t;
86 typedef unsigned long long int uint64_t;
87 typedef          int int32_t;
88 typedef unsigned int uint32_t;
89
90 #endif
91 #endif
92
93 #include "common/h/sha1.h"
94 /* #include <process.h> */      /* prototype for exit() - JHB */
95 /* Using return() instead of exit() - SWR */
96
97 typedef struct {
98     uint32_t state[5];
99     uint32_t count[2];
100     unsigned char buffer[64];
101 } SHA1_CTX;
102
103 void SHA1Transform(uint32_t state[5], unsigned char buffer[64]);
104 void SHA1Init(SHA1_CTX* context);
105 void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len);  /*JHB */
106 void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
107
108 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
109
110 /* blk0() and blk() perform the initial expand. */
111 /* I got the idea of expanding during the round function from SSLeay */
112 #if defined(WORDS_BIGENDIAN)
113 #define blk0(i) block->l[i]
114 #else
115 #define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
116     |(rol(block->l[i],8)&0x00FF00FF))
117 #endif
118 #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
119     ^block->l[(i+2)&15]^block->l[i&15],1))
120
121 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
122 #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
123 #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
124 #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
125 #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
126 #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
127
128
129 #ifdef VERBOSE  /* SAK */
130 void SHAPrintContext(SHA1_CTX *context, char *msg){
131   printf("%s (%d,%d) %x %x %x %x %x\n",
132          msg,
133          context->count[0], context->count[1], 
134          context->state[0],
135          context->state[1],
136          context->state[2],
137          context->state[3],
138          context->state[4]);
139 }
140 #endif
141
142 /* Hash a single 512-bit block. This is the core of the algorithm. */
143
144 void SHA1Transform(uint32_t state[5], unsigned char buffer[64])
145 {
146 uint32_t a, b, c, d, e;
147 typedef union {
148     unsigned char c[64];
149     uint32_t l[16];
150 } CHAR64LONG16;
151 CHAR64LONG16* block;
152 #ifdef SHA1HANDSOFF
153 static unsigned char workspace[64];
154     block = (CHAR64LONG16*)workspace;
155     memcpy(block, buffer, 64);
156 #else
157     block = (CHAR64LONG16*)(void*)buffer;
158 #endif
159     /* Copy context->state[] to working vars */
160     a = state[0];
161     b = state[1];
162     c = state[2];
163     d = state[3];
164     e = state[4];
165     /* 4 rounds of 20 operations each. Loop unrolled. */
166     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);
167     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);
168     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);
169     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);
170     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);
171     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);
172     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);
173     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);
174     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);
175     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);
176     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);
177     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);
178     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);
179     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);
180     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);
181     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);
182     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);
183     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);
184     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);
185     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);
186     /* Add the working vars back into context.state[] */
187     state[0] += a;
188     state[1] += b;
189     state[2] += c;
190     state[3] += d;
191     state[4] += e;
192     /* Wipe variables */
193     a = b = c = d = e = 0;
194 }
195
196
197 /* SHA1Init - Initialize new context */
198
199 void SHA1Init(SHA1_CTX* context)
200 {
201     /* SHA1 initialization constants */
202     context->state[0] = 0x67452301;
203     context->state[1] = 0xEFCDAB89;
204     context->state[2] = 0x98BADCFE;
205     context->state[3] = 0x10325476;
206     context->state[4] = 0xC3D2E1F0;
207     context->count[0] = context->count[1] = 0;
208 }
209
210
211 /* Run your data through this. */
212
213 void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len)   /*JHB */
214 {
215 uint32_t i, j;  /* JHB */
216
217 #ifdef VERBOSE
218     SHAPrintContext(context, "before");
219 #endif
220     j = (context->count[0] >> 3) & 63;
221     if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
222     context->count[1] += (len >> 29);
223     if ((j + len) > 63) {
224         memcpy(&context->buffer[j], data, (i = 64-j));
225         SHA1Transform(context->state, context->buffer);
226         for ( ; i + 63 < len; i += 64) {
227             SHA1Transform(context->state, &data[i]);
228         }
229         j = 0;
230     }
231     else i = 0;
232     memcpy(&context->buffer[j], &data[i], len - i);
233 #ifdef VERBOSE
234     SHAPrintContext(context, "after ");
235 #endif
236 }
237
238
239 /* Add padding and return the message digest. */
240
241 void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
242 {
243 uint32_t i;     /* JHB */
244 unsigned char finalcount[8];
245
246     for (i = 0; i < 8; i++) {
247         finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
248          >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
249     }
250     SHA1Update(context, (unsigned char *)const_cast< char *>("\200"), 1);
251     while ((context->count[0] & 504) != 448) {
252         SHA1Update(context, (unsigned char *)const_cast<char *>("\0"), 1);
253     }
254     SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
255     for (i = 0; i < 20; i++) {
256         digest[i] = (unsigned char)
257          ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
258     }
259     /* Wipe variables */
260     i = 0;      /* JHB */
261     memset(context->buffer, 0, 64);
262     memset(context->state, 0, 20);
263     memset(context->count, 0, 8);
264     memset(finalcount, 0, 8);   /* SWR */
265 #ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite it's own static vars */
266     SHA1Transform(context->state, context->buffer);
267 #endif
268 }
269   
270 /*************************************************************/
271
272 char *sha1_file(const char *filename, char *result_ptr)
273 {
274     static char result[SHA1_STRING_LEN] = {0};
275
276     SHA1_CTX ctx;
277     unsigned char buf[16384];
278
279     if (result_ptr == NULL)
280         result_ptr = result;
281
282     FILE *fd = fopen(filename, "r");
283     if (!fd) return NULL;
284
285     SHA1Init(&ctx);
286     while (!feof(fd)) {
287         unsigned long len = fread((char *)buf, sizeof(char), sizeof(buf), fd);
288         if (ferror(fd)) {
289             fclose(fd);
290             return NULL;
291         }
292         SHA1Update(&ctx, buf, len);
293     }
294     SHA1Final(buf, &ctx);
295
296     fclose(fd);
297
298     for (unsigned int i = 0; i < SHA1_DIGEST_LEN; ++i)
299         sprintf(&result_ptr[i*2], "%02x", buf[i]);
300
301     return result_ptr;
302 }