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 
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 
20 static SHA1_WORD K[80] = { K20(K0), K20(K1), K20(K2), K20(K3) };
21 
sha1_context_init(struct SHA1_CONTEXT * c)22 void 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 
sha1_context_hash(struct SHA1_CONTEXT * c,const unsigned char blk[SHA1_BLOCK_SIZE])35 void sha1_context_hash(struct SHA1_CONTEXT *c,
36 		const unsigned char blk[SHA1_BLOCK_SIZE])
37 {
38 SHA1_WORD	A,B,C,D,E;
39 SHA1_WORD	TEMP;
40 SHA1_WORD	W[80];
41 unsigned	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 
sha1_context_hashstream(struct SHA1_CONTEXT * c,const void * p,unsigned l)92 void sha1_context_hashstream(struct SHA1_CONTEXT *c, const void *p, unsigned l)
93 {
94 const unsigned char *cp=(const unsigned char *)p;
95 unsigned 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 
sha1_context_endstream(struct SHA1_CONTEXT * c,unsigned long l)122 void sha1_context_endstream(struct SHA1_CONTEXT *c, unsigned long l)
123 {
124 	unsigned char buf[8];
125 	static const unsigned char zero[SHA1_BLOCK_SIZE-8];
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 
sha1_context_digest(struct SHA1_CONTEXT * c,SHA1_DIGEST d)151 void sha1_context_digest(struct SHA1_CONTEXT *c, SHA1_DIGEST d)
152 {
153 unsigned char *dp=d + SHA1_DIGEST_SIZE;
154 unsigned 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 
sha1_context_restore(struct SHA1_CONTEXT * c,const SHA1_DIGEST d)167 void sha1_context_restore(struct SHA1_CONTEXT *c, const SHA1_DIGEST d)
168 {
169 const unsigned char *dp=d;
170 unsigned 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 
sha1_digest(const void * msg,unsigned len,SHA1_DIGEST d)184 void sha1_digest(const void *msg, unsigned len, SHA1_DIGEST d)
185 {
186 struct 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 }
193