1/*
2 * $Id$
3 */
4
5#include "db_config.h"
6
7#include "db_int.h"
8#include "dbinc/hmac.h"
9
10/*
11SHA-1 in C
12By Steve Reid <sreid@sea-to-sky.net>
13100% Public Domain
14
15-----------------
16Modified 7/98
17By James H. Brown <jbrown@burgoyne.com>
18Still 100% Public Domain
19
20Corrected a problem which generated improper hash values on 16 bit machines
21Routine SHA1Update changed from
22	void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
23len)
24to
25	void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
26long len)
27
28The 'len' parameter was declared an int which works fine on 32 bit machines.
29However, on 16 bit machines an int is too small for the shifts being done
30against
31it.  This caused the hash function to generate incorrect values if len was
32greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
33
34Since the file IO in main() reads 16K at a time, any file 8K or larger would
35be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
36"a"s).
37
38I also changed the declaration of variables i & j in SHA1Update to
39unsigned long from unsigned int for the same reason.
40
41These changes should make no difference to any 32 bit implementations since
42an
43int and a long are the same size in those environments.
44
45--
46I also corrected a few compiler warnings generated by Borland C.
471. Added #include <process.h> for exit() prototype
482. Removed unused variable 'j' in SHA1Final
493. Changed exit(0) to return (0) at end of main.
50
51ALL changes I made can be located by searching for comments containing 'JHB'
52-----------------
53Modified 8/98
54By Steve Reid <sreid@sea-to-sky.net>
55Still 100% public domain
56
571- Removed #include <process.h> and used return () instead of exit()
582- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
593- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
60
61-----------------
62Modified 4/01
63By Saul Kravitz <Saul.Kravitz@celera.com>
64Still 100% PD
65Modified to run on Compaq Alpha hardware.
66
67*/
68
69/*
70Test Vectors (from FIPS PUB 180-1)
71"abc"
72  A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
73"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
74  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
75A million repetitions of "a"
76  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
77*/
78
79#define	SHA1HANDSOFF
80
81/* #include <process.h> */	/* prototype for exit() - JHB */
82/* Using return () instead of exit() - SWR */
83
84#define	rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
85
86/* blk0() and blk() perform the initial expand. */
87/* I got the idea of expanding during the round function from SSLeay */
88#define	blk0(i) is_bigendian ? block->l[i] : \
89    (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
90    |(rol(block->l[i],8)&0x00FF00FF))
91#define	blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
92    ^block->l[(i+2)&15]^block->l[i&15],1))
93
94/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
95#define	R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5); \
96    w=rol(w,30);
97#define	R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5); \
98    w=rol(w,30);
99#define	R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
100#define	R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5); \
101    w=rol(w,30);
102#define	R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
103
104#ifdef VERBOSE  /* SAK */
105static void __db_SHAPrintContext __P((SHA1_CTX *, char *));
106static void
107__db_SHAPrintContext(context, msg)
108	SHA1_CTX *context;
109	char *msg;
110{
111  printf("%s (%d,%d) %x %x %x %x %x\n",
112	 msg,
113	 context->count[0], context->count[1],
114	 context->state[0],
115	 context->state[1],
116	 context->state[2],
117	 context->state[3],
118	 context->state[4]);
119}
120#endif
121
122/* Hash a single 512-bit block. This is the core of the algorithm. */
123
124/*
125 * __db_SHA1Transform --
126 *
127 * PUBLIC: void __db_SHA1Transform __P((u_int32_t *, unsigned char *));
128 */
129void
130__db_SHA1Transform(state, buffer)
131	u_int32_t *state;
132	unsigned char *buffer;
133{
134u_int32_t a, b, c, d, e;
135typedef union {
136    unsigned char c[64];
137    u_int32_t l[16];
138} CHAR64LONG16;
139CHAR64LONG16* block;
140    int is_bigendian;
141#ifdef SHA1HANDSOFF
142    unsigned char workspace[64];
143
144    block = (CHAR64LONG16*)workspace;
145    memcpy(block, buffer, 64);
146#else
147    block = (CHAR64LONG16*)buffer;
148#endif
149    is_bigendian = __db_isbigendian();
150
151    /* Copy context->state[] to working vars */
152    a = state[0];
153    b = state[1];
154    c = state[2];
155    d = state[3];
156    e = state[4];
157    /* 4 rounds of 20 operations each. Loop unrolled. */
158    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);
159    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);
160    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);
161    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);
162    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);
163    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);
164    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);
165    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);
166    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);
167    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);
168    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);
169    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);
170    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);
171    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);
172    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);
173    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);
174    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);
175    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);
176    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);
177    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);
178    /* Add the working vars back into context.state[] */
179    state[0] += a;
180    state[1] += b;
181    state[2] += c;
182    state[3] += d;
183    state[4] += e;
184    /* Wipe variables */
185    a = b = c = d = e = 0;
186}
187
188/* SHA1Init - Initialize new context */
189
190/*
191 * __db_SHA1Init --
192 *      Initialize new context
193 *
194 * PUBLIC: void __db_SHA1Init __P((SHA1_CTX *));
195 */
196void
197__db_SHA1Init(context)
198	SHA1_CTX *context;
199{
200    /* SHA1 initialization constants */
201    context->state[0] = 0x67452301;
202    context->state[1] = 0xEFCDAB89;
203    context->state[2] = 0x98BADCFE;
204    context->state[3] = 0x10325476;
205    context->state[4] = 0xC3D2E1F0;
206    context->count[0] = context->count[1] = 0;
207}
208
209/* Run your data through this. */
210
211/*
212 * __db_SHA1Update --
213 *      Run your data through this.
214 *
215 * PUBLIC: void __db_SHA1Update __P((SHA1_CTX *, unsigned char *,
216 * PUBLIC:     size_t));
217 */
218void
219__db_SHA1Update(context, data, len)
220	SHA1_CTX *context;
221	unsigned char *data;
222	size_t len;
223{
224u_int32_t i, j;	/* JHB */
225
226#ifdef VERBOSE
227    __db_SHAPrintContext(context, "before");
228#endif
229    j = (context->count[0] >> 3) & 63;
230    if ((context->count[0] += (u_int32_t)len << 3) < (len << 3))
231	    context->count[1]++;
232    context->count[1] += (u_int32_t)(len >> 29);
233    if ((j + len) > 63) {
234	memcpy(&context->buffer[j], data, (i = 64-j));
235	__db_SHA1Transform(context->state, context->buffer);
236	for ( ; i + 63 < len; i += 64) {
237	    __db_SHA1Transform(context->state, &data[i]);
238	}
239	j = 0;
240    }
241    else i = 0;
242    memcpy(&context->buffer[j], &data[i], len - i);
243#ifdef VERBOSE
244    __db_SHAPrintContext(context, "after ");
245#endif
246}
247
248/* Add padding and return the message digest. */
249
250/*
251 * __db_SHA1Final --
252 *      Add padding and return the message digest.
253 *
254 * PUBLIC: void __db_SHA1Final __P((unsigned char *, SHA1_CTX *));
255 */
256void
257__db_SHA1Final(digest, context)
258	unsigned char *digest;
259	SHA1_CTX *context;
260{
261u_int32_t i;	/* JHB */
262unsigned char finalcount[8];
263
264    for (i = 0; i < 8; i++) {
265	finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
266	 >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
267    }
268    __db_SHA1Update(context, (unsigned char *)"\200", 1);
269    while ((context->count[0] & 504) != 448) {
270	__db_SHA1Update(context, (unsigned char *)"\0", 1);
271    }
272    __db_SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform()
273*/
274    for (i = 0; i < 20; i++) {
275	digest[i] = (unsigned char)
276	 ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
277    }
278    /* Wipe variables */
279    i = 0;	/* JHB */
280    memset(context->buffer, 0, 64);
281    memset(context->state, 0, 20);
282    memset(context->count, 0, 8);
283    memset(finalcount, 0, 8);	/* SWR */
284#ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite it's own static vars */
285    __db_SHA1Transform(context->state, context->buffer);
286#endif
287}
288
289/*************************************************************/
290