1) Cmake support for PPC64LE builds
[dyninst.git] / common / src / sha1.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30 /*
31 SHA-1 in C
32 By Steve Reid <sreid@sea-to-sky.net>
33 100% Public Domain
34
35 -----------------
36 Modified 7/98 
37 By James H. Brown <jbrown@burgoyne.com>
38 Still 100% Public Domain
39
40 Corrected a problem which generated improper hash values on 16 bit machines
41 Routine SHA1Update changed from
42         void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
43 len)
44 to
45         void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
46 long len)
47
48 The 'len' parameter was declared an int which works fine on 32 bit machines.
49 However, on 16 bit machines an int is too small for the shifts being done
50 against
51 it.  This caused the hash function to generate incorrect values if len was
52 greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
53
54 Since the file IO in main() reads 16K at a time, any file 8K or larger would
55 be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
56 "a"s).
57
58 I also changed the declaration of variables i & j in SHA1Update to 
59 unsigned long from unsigned int for the same reason.
60
61 These changes should make no difference to any 32 bit implementations since
62 an
63 int and a long are the same size in those environments.
64
65 --
66 I also corrected a few compiler warnings generated by Borland C.
67 1. Added #include <process.h> for exit() prototype
68 2. Removed unused variable 'j' in SHA1Final
69 3. Changed exit(0) to return(0) at end of main.
70
71 ALL changes I made can be located by searching for comments containing 'JHB'
72 -----------------
73 Modified 8/98
74 By Steve Reid <sreid@sea-to-sky.net>
75 Still 100% public domain
76
77 1- Removed #include <process.h> and used return() instead of exit()
78 2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
79 3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
80
81 -----------------
82 Modified 4/01
83 By Saul Kravitz <Saul.Kravitz@celera.com>
84 Still 100% PD
85 Modified to run on Compaq Alpha hardware.  
86
87
88 */
89
90 /*
91 Test Vectors (from FIPS PUB 180-1)
92 "abc"
93   A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
94 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
95   84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
96 A million repetitions of "a"
97   34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
98 */
99
100 /* #define SHA1HANDSOFF  */
101
102
103 #include <stdio.h>
104 #include <string.h>
105
106 #include "common/src/Types.h"
107 #include "common/src/sha1.h"
108 /* #include <process.h> */      /* prototype for exit() - JHB */
109 /* Using return() instead of exit() - SWR */
110
111 typedef struct {
112     uint32_t state[5];
113     uint32_t count[2];
114     unsigned char buffer[64];
115 } SHA1_CTX;
116
117 void SHA1Transform(uint32_t state[5], unsigned char buffer[64]);
118 void SHA1Init(SHA1_CTX* context);
119 void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len);  /*JHB */
120 void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
121
122 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
123
124 /* blk0() and blk() perform the initial expand. */
125 /* I got the idea of expanding during the round function from SSLeay */
126 /* TODOMJM - Need to determine is this is used by proccontrol, symtab, and/or stackwalk */
127 #if defined(arch_power) //Big Endian
128 #define blk0(i) block->l[i]
129 #else
130 #define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
131     |(rol(block->l[i],8)&0x00FF00FF))
132 #endif
133 #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
134     ^block->l[(i+2)&15]^block->l[i&15],1))
135
136 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
137 #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
138 #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
139 #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
140 #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
141 #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
142
143
144 #ifdef VERBOSE  /* SAK */
145 void SHAPrintContext(SHA1_CTX *context, char *msg){
146   printf("%s (%d,%d) %x %x %x %x %x\n",
147          msg,
148          context->count[0], context->count[1], 
149          context->state[0],
150          context->state[1],
151          context->state[2],
152          context->state[3],
153          context->state[4]);
154 }
155 #endif
156
157 /* Hash a single 512-bit block. This is the core of the algorithm. */
158
159 void SHA1Transform(uint32_t state[5], unsigned char buffer[64])
160 {
161 uint32_t a, b, c, d, e;
162 typedef union {
163     unsigned char c[64];
164     uint32_t l[16];
165 } CHAR64LONG16;
166 CHAR64LONG16* block;
167 #ifdef SHA1HANDSOFF
168 static unsigned char workspace[64];
169     block = (CHAR64LONG16*)workspace;
170     memcpy(block, buffer, 64);
171 #else
172     block = (CHAR64LONG16*)(void*)buffer;
173 #endif
174     /* Copy context->state[] to working vars */
175     a = state[0];
176     b = state[1];
177     c = state[2];
178     d = state[3];
179     e = state[4];
180     /* 4 rounds of 20 operations each. Loop unrolled. */
181     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);
182     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);
183     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);
184     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);
185     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);
186     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);
187     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);
188     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);
189     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);
190     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);
191     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);
192     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);
193     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);
194     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);
195     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);
196     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);
197     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);
198     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);
199     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);
200     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);
201     /* Add the working vars back into context.state[] */
202     state[0] += a;
203     state[1] += b;
204     state[2] += c;
205     state[3] += d;
206     state[4] += e;
207     /* Wipe variables */
208     a = b = c = d = e = 0;
209 }
210
211
212 /* SHA1Init - Initialize new context */
213
214 void SHA1Init(SHA1_CTX* context)
215 {
216     /* SHA1 initialization constants */
217     context->state[0] = 0x67452301;
218     context->state[1] = 0xEFCDAB89;
219     context->state[2] = 0x98BADCFE;
220     context->state[3] = 0x10325476;
221     context->state[4] = 0xC3D2E1F0;
222     context->count[0] = context->count[1] = 0;
223 }
224
225
226 /* Run your data through this. */
227
228 void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len)   /*JHB */
229 {
230 uint32_t i, j;  /* JHB */
231
232 #ifdef VERBOSE
233     SHAPrintContext(context, "before");
234 #endif
235     j = (context->count[0] >> 3) & 63;
236     if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
237     context->count[1] += (len >> 29);
238     if ((j + len) > 63) {
239         memcpy(&context->buffer[j], data, (i = 64-j));
240         SHA1Transform(context->state, context->buffer);
241         for ( ; i + 63 < len; i += 64) {
242             SHA1Transform(context->state, &data[i]);
243         }
244         j = 0;
245     }
246     else i = 0;
247     memcpy(&context->buffer[j], &data[i], len - i);
248 #ifdef VERBOSE
249     SHAPrintContext(context, "after ");
250 #endif
251 }
252
253
254 /* Add padding and return the message digest. */
255
256 void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
257 {
258 uint32_t i;     /* JHB */
259 unsigned char finalcount[8];
260
261     for (i = 0; i < 8; i++) {
262         finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
263          >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
264     }
265     SHA1Update(context, (unsigned char *)const_cast< char *>("\200"), 1);
266     while ((context->count[0] & 504) != 448) {
267         SHA1Update(context, (unsigned char *)const_cast<char *>("\0"), 1);
268     }
269     SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
270     for (i = 0; i < 20; i++) {
271         digest[i] = (unsigned char)
272          ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
273     }
274     /* Wipe variables */
275     i = 0;      /* JHB */
276     memset(context->buffer, 0, 64);
277     memset(context->state, 0, 20);
278     memset(context->count, 0, 8);
279     memset(finalcount, 0, 8);   /* SWR */
280 #ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite it's own static vars */
281     SHA1Transform(context->state, context->buffer);
282 #endif
283 }
284   
285 /*************************************************************/
286
287 char *sha1_file(const char *filename, char *result_ptr)
288 {
289     static char result[SHA1_STRING_LEN] = {0};
290
291     SHA1_CTX ctx;
292     unsigned char buf[16384];
293
294     if (result_ptr == NULL)
295         result_ptr = result;
296
297     FILE *fd = fopen(filename, "r");
298     if (!fd) return NULL;
299
300     SHA1Init(&ctx);
301     while (!feof(fd)) {
302         unsigned long len = fread((char *)buf, sizeof(char), sizeof(buf), fd);
303         if (ferror(fd)) {
304             fclose(fd);
305             return NULL;
306         }
307         SHA1Update(&ctx, buf, len);
308     }
309     SHA1Final(buf, &ctx);
310
311     fclose(fd);
312
313     for (unsigned int i = 0; i < SHA1_DIGEST_LEN; ++i)
314         sprintf(&result_ptr[i*2], "%02x", buf[i]);
315
316     return result_ptr;
317 }