3 By Steve Reid <sreid@sea-to-sky.net>
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.
12 By James H. Brown <jbrown@burgoyne.com>
13 Still 100% Public Domain
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
20 void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
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
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().
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
33 I also changed the declaration of variables i & j in SHA1Update to
34 unsigned long from unsigned int for the same reason.
36 These changes should make no difference to any 32 bit implementations since
38 int and a long are the same size in those environments.
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.
46 ALL changes I made can be located by searching for comments containing 'JHB'
49 By Steve Reid <sreid@sea-to-sky.net>
50 Still 100% public domain
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
58 By Saul Kravitz <Saul.Kravitz@celera.com>
60 Modified to run on Compaq Alpha hardware.
66 Test Vectors (from FIPS PUB 180-1)
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
75 /* #define SHA1HANDSOFF */
84 #ifndef i386 /* For ALPHA (SAK) */
86 typedef long int int64;
87 typedef unsigned long int uint64;
89 typedef unsigned int uint32;
92 typedef long long int int64;
93 typedef unsigned long long int uint64;
94 typedef long int int32;
95 typedef unsigned long int uint32;
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;
105 /* #include <process.h> */ /* prototype for exit() - JHB */
106 /* Using return() instead of exit() - SWR */
111 unsigned char buffer[64];
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);
118 void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
120 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
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))
128 #define blk0(i) block->l[i]
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))
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);
141 #ifdef VERBOSE /* SAK */
142 void SHAPrintContext(SHA1_CTX *context, char *msg){
143 printf("%s (%d,%d) %x %x %x %x %x\n",
145 context->count[0], context->count[1],
154 /* Hash a single 512-bit block. This is the core of the algorithm. */
156 void SHA1Transform(uint32 state[5], unsigned char const buffer[64])
158 uint32 a, b, c, d, e;
165 static unsigned char workspace[64];
166 block = (CHAR64LONG16*)workspace;
167 memcpy(block, buffer, 64);
169 block = (CHAR64LONG16*)buffer;
171 /* Copy context->state[] to working vars */
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[] */
205 a = b = c = d = e = 0;
209 /* SHA1Init - Initialize new context */
211 void SHA1Init(SHA1_CTX* context)
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;
223 /* Run your data through this. */
225 void SHA1Update(SHA1_CTX* context, unsigned char const* data, uint32 len) /*
228 uint32 i, j; /* JHB */
231 SHAPrintContext(context, "before");
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]);
245 memcpy(&context->buffer[j], &data[i], len - i);
247 SHAPrintContext(context, "after ");
252 /* Add padding and return the message digest. */
254 void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
257 unsigned char finalcount[8];
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 */
263 SHA1Update(context, (unsigned char *)"\200", 1);
264 while ((context->count[0] & 504) != 448) {
265 SHA1Update(context, (unsigned char *)"\0", 1);
267 SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform()
269 for (i = 0; i < 20; i++) {
270 digest[i] = (unsigned char)
271 ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
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);
284 /*************************************************************/
286 /* Everything below here is the interface to secnet */
287 static void *sha1_init(void)
291 ctx=safe_malloc(sizeof(*ctx),"sha1_init");
297 static void sha1_update(void *sst, uint8_t const *buf, uint32_t len)
301 SHA1Update(ctx,buf,len);
304 static void sha1_final(void *sst, uint8_t *digest)
308 SHA1Final(digest,ctx);
317 void sha1_module(dict_t *dict)
321 cstring_t testinput="abcdbcdecdefdefgefghfghigh"
322 "ijhijkijkljklmklmnlmnomnopnopq";
323 uint8_t expected[20]=
324 { 0x84,0x98,0x3e,0x44,
328 0xe5,0x46,0x70,0xf1};
332 st=safe_malloc(sizeof(*st),"sha1_module");
333 st->cl.description="sha1";
336 st->cl.interface=&st->ops;
338 st->ops.init=sha1_init;
339 st->ops.update=sha1_update;
340 st->ops.final=sha1_final;
342 dict_add(dict,"sha1",new_closure(&st->cl));
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");