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