chiark / gitweb /
Makefiles: Use Final.sd.mk to implementing RECHECK_RM
[secnet.git] / sha1.c
1 /*
2 SHA-1 in C
3 By Steve Reid <sreid@sea-to-sky.net>
4 100% Public Domain
5
6 Note: parts of this file have been removed or modified to work in secnet.
7 Instead of using this file in new projects, I suggest you use the
8 unmodified version. SDE.
9
10 -----------------
11 Modified 7/98 
12 By James H. Brown <jbrown@burgoyne.com>
13 Still 100% Public Domain
14
15 Corrected a problem which generated improper hash values on 16 bit machines
16 Routine SHA1Update changed from
17         void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
18 len)
19 to
20         void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
21 long len)
22
23 The 'len' parameter was declared an int which works fine on 32 bit machines.
24 However, on 16 bit machines an int is too small for the shifts being done
25 against
26 it.  This caused the hash function to generate incorrect values if len was
27 greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
28
29 Since the file IO in main() reads 16K at a time, any file 8K or larger would
30 be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
31 "a"s).
32
33 I also changed the declaration of variables i & j in SHA1Update to 
34 unsigned long from unsigned int for the same reason.
35
36 These changes should make no difference to any 32 bit implementations since
37 an
38 int and a long are the same size in those environments.
39
40 --
41 I also corrected a few compiler warnings generated by Borland C.
42 1. Added #include <process.h> for exit() prototype
43 2. Removed unused variable 'j' in SHA1Final
44 3. Changed exit(0) to return(0) at end of main.
45
46 ALL changes I made can be located by searching for comments containing 'JHB'
47 -----------------
48 Modified 8/98
49 By Steve Reid <sreid@sea-to-sky.net>
50 Still 100% public domain
51
52 1- Removed #include <process.h> and used return() instead of exit()
53 2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
54 3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
55
56 -----------------
57 Modified 4/01
58 By Saul Kravitz <Saul.Kravitz@celera.com>
59 Still 100% PD
60 Modified to run on Compaq Alpha hardware.  
61
62
63 */
64
65 /*
66 Test Vectors (from FIPS PUB 180-1)
67 "abc"
68   A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
69 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
70   84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
71 A million repetitions of "a"
72   34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
73 */
74
75 /* #define SHA1HANDSOFF  */
76
77 #include "secnet.h"
78 #include <stdio.h>
79 #include <string.h>
80
81 #define SHA1HANDSOFF
82
83 #if 0
84 #ifndef  i386   /* For ALPHA  (SAK) */
85 #define LITTLE_ENDIAN 
86 typedef          long int int64;
87 typedef unsigned long int uint64;
88 typedef          int int32;
89 typedef unsigned int uint32;
90 #else  /*i386*/
91 #define LITTLE_ENDIAN 
92 typedef          long long int int64;
93 typedef unsigned long long int uint64;
94 typedef          long int int32;
95 typedef unsigned long int uint32;
96 #endif /*i386*/
97 #endif /* 0 */
98
99 /* Get types and defines from the secnet configuration */
100 /* typedef int64_t int64; */
101 typedef uint64_t uint64;
102 /* typedef int32_t int32; */
103 typedef uint32_t uint32;
104
105 /* #include <process.h> */      /* prototype for exit() - JHB */
106 /* Using return() instead of exit() - SWR */
107
108 typedef struct {
109     uint32 state[5];
110     uint32 count[2];
111     unsigned char buffer[64];
112 } SHA1_CTX;
113
114 void SHA1Transform(uint32 state[5], unsigned char const buffer[64]);
115 void SHA1Init(SHA1_CTX* context);
116 void SHA1Update(SHA1_CTX* context, unsigned char const * data, uint32 len);
117 /* JHB */
118 void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
119
120 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
121
122 /* blk0() and blk() perform the initial expand. */
123 /* I got the idea of expanding during the round function from SSLeay */
124 #ifndef WORDS_BIGENDIAN
125 #define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
126     |(rol(block->l[i],8)&0x00FF00FF))
127 #else
128 #define blk0(i) block->l[i]
129 #endif
130 #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
131     ^block->l[(i+2)&15]^block->l[i&15],1))
132
133 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
134 #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
135 #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
136 #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
137 #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
138 #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
139
140
141 #ifdef VERBOSE  /* SAK */
142 void SHAPrintContext(SHA1_CTX *context, char *msg){
143   printf("%s (%d,%d) %x %x %x %x %x\n",
144          msg,
145          context->count[0], context->count[1], 
146          context->state[0],
147          context->state[1],
148          context->state[2],
149          context->state[3],
150          context->state[4]);
151 }
152 #endif
153
154 /* Hash a single 512-bit block. This is the core of the algorithm. */
155
156 void SHA1Transform(uint32 state[5], unsigned char const buffer[64])
157 {
158 uint32 a, b, c, d, e;
159 typedef union {
160     unsigned char c[64];
161     uint32 l[16];
162 } CHAR64LONG16;
163 CHAR64LONG16* block;
164 #ifdef SHA1HANDSOFF
165 static unsigned char workspace[64];
166     block = (CHAR64LONG16*)workspace;
167     memcpy(block, buffer, 64);
168 #else
169     block = (CHAR64LONG16*)buffer;
170 #endif
171     /* Copy context->state[] to working vars */
172     a = state[0];
173     b = state[1];
174     c = state[2];
175     d = state[3];
176     e = state[4];
177     /* 4 rounds of 20 operations each. Loop unrolled. */
178     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);
179     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);
180     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);
181     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);
182     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);
183     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);
184     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);
185     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);
186     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);
187     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);
188     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);
189     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);
190     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);
191     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);
192     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);
193     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);
194     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);
195     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);
196     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);
197     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);
198     /* Add the working vars back into context.state[] */
199     state[0] += a;
200     state[1] += b;
201     state[2] += c;
202     state[3] += d;
203     state[4] += e;
204     /* Wipe variables */
205     a = b = c = d = e = 0;
206 }
207
208
209 /* SHA1Init - Initialize new context */
210
211 void SHA1Init(SHA1_CTX* context)
212 {
213     /* SHA1 initialization constants */
214     context->state[0] = 0x67452301;
215     context->state[1] = 0xEFCDAB89;
216     context->state[2] = 0x98BADCFE;
217     context->state[3] = 0x10325476;
218     context->state[4] = 0xC3D2E1F0;
219     context->count[0] = context->count[1] = 0;
220 }
221
222
223 /* Run your data through this. */
224
225 void SHA1Update(SHA1_CTX* context, unsigned char const* data, uint32 len)       /*
226 JHB */
227 {
228 uint32 i, j;    /* JHB */
229
230 #ifdef VERBOSE
231     SHAPrintContext(context, "before");
232 #endif
233     j = (context->count[0] >> 3) & 63;
234     if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
235     context->count[1] += (len >> 29);
236     if ((j + len) > 63) {
237         memcpy(&context->buffer[j], data, (i = 64-j));
238         SHA1Transform(context->state, context->buffer);
239         for ( ; i + 63 < len; i += 64) {
240             SHA1Transform(context->state, &data[i]);
241         }
242         j = 0;
243     }
244     else i = 0;
245     memcpy(&context->buffer[j], &data[i], len - i);
246 #ifdef VERBOSE
247     SHAPrintContext(context, "after ");
248 #endif
249 }
250
251
252 /* Add padding and return the message digest. */
253
254 void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
255 {
256 uint32 i;       /* JHB */
257 unsigned char finalcount[8];
258
259     for (i = 0; i < 8; i++) {
260         finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
261          >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
262     }
263     SHA1Update(context, (unsigned char *)"\200", 1);
264     while ((context->count[0] & 504) != 448) {
265         SHA1Update(context, (unsigned char *)"\0", 1);
266     }
267     SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform()
268 */
269     for (i = 0; i < 20; i++) {
270         digest[i] = (unsigned char)
271          ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
272     }
273     /* Wipe variables */
274     i = 0;      /* JHB */
275     memset(context->buffer, 0, 64);
276     memset(context->state, 0, 20);
277     memset(context->count, 0, 8);
278     memset(finalcount, 0, 8);   /* SWR */
279 #ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite it's own static vars */
280     SHA1Transform(context->state, context->buffer);
281 #endif
282 }
283   
284 /*************************************************************/
285
286 /* Everything below here is the interface to secnet */
287 static void *sha1_init(void)
288 {
289     SHA1_CTX *ctx;
290
291     ctx=safe_malloc(sizeof(*ctx),"sha1_init");
292     SHA1Init(ctx);
293
294     return ctx;
295 }
296
297 static void sha1_update(void *sst, const void *buf, int32_t len)
298 {
299     SHA1_CTX *ctx=sst;
300
301     SHA1Update(ctx,buf,len);
302 }
303
304 static void sha1_final(void *sst, uint8_t *digest)
305 {
306     SHA1_CTX *ctx=sst;
307
308     SHA1Final(digest,ctx);
309     free(ctx);
310 }
311
312 struct sha1 {
313     closure_t cl;
314     struct hash_if ops;
315 };
316
317 void sha1_module(dict_t *dict)
318 {
319     struct sha1 *st;
320     void *ctx;
321     cstring_t testinput="abcdbcdecdefdefgefghfghigh"
322         "ijhijkijkljklmklmnlmnomnopnopq";
323     uint8_t expected[20]=
324     { 0x84,0x98,0x3e,0x44,
325       0x1c,0x3b,0xd2,0x6e,
326       0xba,0xae,0x4a,0xa1,
327       0xf9,0x51,0x29,0xe5,
328       0xe5,0x46,0x70,0xf1};
329     uint8_t digest[20];
330     int i;
331
332     st=safe_malloc(sizeof(*st),"sha1_module");
333     st->cl.description="sha1";
334     st->cl.type=CL_HASH;
335     st->cl.apply=NULL;
336     st->cl.interface=&st->ops;
337     st->ops.len=20;
338     st->ops.init=sha1_init;
339     st->ops.update=sha1_update;
340     st->ops.final=sha1_final;
341
342     dict_add(dict,"sha1",new_closure(&st->cl));
343
344     ctx=sha1_init();
345     sha1_update(ctx,testinput,strlen(testinput));
346     sha1_final(ctx,digest);
347     for (i=0; i<20; i++) {
348         if (digest[i]!=expected[i]) {
349             fatal("sha1 module failed self-test");
350         }
351     }
352 }