Imported upstream version 0.59.3
[hcoop/debian/courier-authlib.git] / sha1 / sha1.c
1 /*
2 ** Copyright 2001 Double Precision, Inc.
3 ** See COPYING for distribution information.
4 */
5
6 #define SHA1_INTERNAL
7 #include "sha1.h"
8
9 #include <string.h>
10 #include <stdlib.h>
11
12 static const char rcsid[]="$Id: sha1.c,v 1.2 2001/11/01 08:43:43 mrsam Exp $";
13
14 #define K0 0x5A827999
15 #define K1 0x6ED9EBA1
16 #define K2 0x8F1BBCDC
17 #define K3 0XCA62C1D6
18
19 #define K20(x) x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x
20
21 static SHA1_WORD K[80] = { K20(K0), K20(K1), K20(K2), K20(K3) };
22
23 void sha1_context_init(struct SHA1_CONTEXT *c)
24 {
25 if (sizeof(SHA1_WORD) != 4)
26 abort();
27
28 c->H[0] = 0x67452301;
29 c->H[1] = 0xEFCDAB89;
30 c->H[2] = 0x98BADCFE;
31 c->H[3] = 0x10325476;
32 c->H[4] = 0xC3D2E1F0;
33 c->blk_ptr=0;
34 }
35
36 void sha1_context_hash(struct SHA1_CONTEXT *c,
37 const unsigned char blk[SHA1_BLOCK_SIZE])
38 {
39 SHA1_WORD A,B,C,D,E;
40 SHA1_WORD TEMP;
41 SHA1_WORD W[80];
42 unsigned i, t;
43
44 #define f(t,B,C,D) ( \
45 (t) < 20 ? ( (B) & (C) ) | ( (~(B)) & (D) ) : \
46 (t) >= 40 && (t) < 60 ? ( (B) & (C) ) | ( (B) & (D) ) | ( (C) & (D) ):\
47 (B) ^ (C) ^ (D) )
48
49 #define S(a,b) ( ((SHA1_WORD)(a) << (b)) | ((SHA1_WORD)(a) >> (32 - (b))))
50
51 for (i=t=0; t<16; t++)
52 {
53 W[t]= blk[i]; i++;
54 W[t] = (W[t] << 8) | blk[i]; i++;
55 W[t] = (W[t] << 8) | blk[i]; i++;
56 W[t] = (W[t] << 8) | blk[i]; i++;
57 }
58
59 for (t=16; t<80; t++)
60 {
61 TEMP= W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
62 W[t]= S(TEMP, 1);
63 }
64
65 A=c->H[0];
66 B=c->H[1];
67 C=c->H[2];
68 D=c->H[3];
69 E=c->H[4];
70
71 for (t=0; t<80; t++)
72 {
73 TEMP = S(A,5);
74 TEMP += f(t, B, C, D);
75 TEMP += E;
76 TEMP += W[t];
77 TEMP += K[t];
78
79 E=D;
80 D=C;
81 C= S(B, 30);
82 B=A;
83 A=TEMP;
84 }
85
86 c->H[0] += A;
87 c->H[1] += B;
88 c->H[2] += C;
89 c->H[3] += D;
90 c->H[4] += E;
91 }
92
93 void sha1_context_hashstream(struct SHA1_CONTEXT *c, const void *p, unsigned l)
94 {
95 const unsigned char *cp=(const unsigned char *)p;
96 unsigned ll;
97
98 while (l)
99 {
100 if (c->blk_ptr == 0 && l >= SHA1_BLOCK_SIZE)
101 {
102 sha1_context_hash(c, cp);
103 cp += SHA1_BLOCK_SIZE;
104 l -= SHA1_BLOCK_SIZE;
105 continue;
106 }
107
108 ll=l;
109 if (ll > SHA1_BLOCK_SIZE - c->blk_ptr)
110 ll=SHA1_BLOCK_SIZE - c->blk_ptr;
111 memcpy(c->blk + c->blk_ptr, cp, ll);
112 c->blk_ptr += ll;
113 cp += ll;
114 l -= ll;
115 if (c->blk_ptr >= SHA1_BLOCK_SIZE)
116 {
117 sha1_context_hash(c, c->blk);
118 c->blk_ptr=0;
119 }
120 }
121 }
122
123 void sha1_context_endstream(struct SHA1_CONTEXT *c, unsigned long l)
124 {
125 unsigned char buf[8];
126 static unsigned char zero[SHA1_BLOCK_SIZE-8];
127
128 buf[0]=0x80;
129 sha1_context_hashstream(c, &buf, 1);
130 while (c->blk_ptr != SHA1_BLOCK_SIZE-8)
131 {
132 if (c->blk_ptr > SHA1_BLOCK_SIZE-8)
133 {
134 sha1_context_hashstream(c, zero,
135 SHA1_BLOCK_SIZE - c->blk_ptr);
136 continue;
137 }
138 sha1_context_hashstream(c, zero,
139 SHA1_BLOCK_SIZE-8-c->blk_ptr);
140 }
141
142 l *= 8;
143 buf[7] = l;
144 buf[6] = (l >>= 8);
145 buf[5] = (l >>= 8);
146 buf[4] = (l >> 8);
147 buf[3]=buf[2]=buf[1]=buf[0]=0;
148
149 sha1_context_hashstream(c, buf, 8);
150 }
151
152 void sha1_context_digest(struct SHA1_CONTEXT *c, SHA1_DIGEST d)
153 {
154 unsigned char *dp=d + SHA1_DIGEST_SIZE;
155 unsigned i;
156
157 for ( i=5; i; )
158 {
159 SHA1_WORD w=c->H[--i];
160
161 *--dp=w; w >>= 8;
162 *--dp=w; w >>= 8;
163 *--dp=w; w >>= 8;
164 *--dp=w;
165 }
166 }
167
168 void sha1_context_restore(struct SHA1_CONTEXT *c, const SHA1_DIGEST d)
169 {
170 const unsigned char *dp=d;
171 unsigned i;
172
173 for (i=0; i<5; i++)
174 {
175 SHA1_WORD w= *dp++;
176
177 w=(w << 8) | *dp++;
178 w=(w << 8) | *dp++;
179 w=(w << 8) | *dp++;
180 c->H[i]=w;
181 }
182 c->blk_ptr=0;
183 }
184
185 void sha1_digest(const void *msg, unsigned len, SHA1_DIGEST d)
186 {
187 struct SHA1_CONTEXT c;
188
189 sha1_context_init( &c );
190 sha1_context_hashstream(&c, msg, len);
191 sha1_context_endstream(&c, len);
192 sha1_context_digest( &c, d );
193 }