tsha1.c - libeech - bittorrent library
(HTM) git clone git://z3bra.org/libeech.git
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
tsha1.c (8538B)
---
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
2 *
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
5 *
6 * The library is free for all purposes without any express
7 * guarantee it works.
8 */
9
10 #include <stddef.h>
11 #include <stdint.h>
12
13 #include "sha1.h"
14
15 #define F0(x,y,z) (z ^ (x & (y ^ z)))
16 #define F1(x,y,z) (x ^ y ^ z)
17 #define F2(x,y,z) ((x & y) | (z & (x | y)))
18 #define F3(x,y,z) (x ^ y ^ z)
19
20 #define ROL(x,n) ( (((x)<<(n))&(UINT32_MAX))|(((x)>>(sizeof(x)*8-(n)))&(UINT32_MAX)) )
21
22 #define MAX(x, y) ( ((x)>(y))?(x):(y) )
23 #define MIN(x, y) ( ((x)<(y))?(x):(y) )
24
25 #define STORE32L(x, y) \
26 do { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
27 (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
28
29 #define LOAD32L(x, y) \
30 do { x = ((uint32_t)((y)[3] & 255)<<24) | \
31 ((uint32_t)((y)[2] & 255)<<16) | \
32 ((uint32_t)((y)[1] & 255)<<8) | \
33 ((uint32_t)((y)[0] & 255)); } while(0)
34
35 #define STORE64L(x, y) \
36 do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
37 (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
38 (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
39 (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0)
40
41 #define LOAD64L(x, y) \
42 do { x = (((uint64_t)((y)[7] & 255))<<56)|(((uint64_t)((y)[6] & 255))<<48)| \
43 (((uint64_t)((y)[5] & 255))<<40)|(((uint64_t)((y)[4] & 255))<<32)| \
44 (((uint64_t)((y)[3] & 255))<<24)|(((uint64_t)((y)[2] & 255))<<16)| \
45 (((uint64_t)((y)[1] & 255))<<8)|(((uint64_t)((y)[0] & 255))); } while(0)
46
47 #define STORE32H(x, y) \
48 do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
49 (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0)
50
51 #define LOAD32H(x, y) \
52 do { x = ((uint32_t)((y)[0] & 255)<<24) | \
53 ((uint32_t)((y)[1] & 255)<<16) | \
54 ((uint32_t)((y)[2] & 255)<<8) | \
55 ((uint32_t)((y)[3] & 255)); } while(0)
56
57 #define STORE64H(x, y) \
58 do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
59 (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
60 (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
61 (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0)
62
63 #define LOAD64H(x, y) \
64 do { x = (((uint64_t)((y)[0] & 255))<<56)|(((uint64_t)((y)[1] & 255))<<48) | \
65 (((uint64_t)((y)[2] & 255))<<40)|(((uint64_t)((y)[3] & 255))<<32) | \
66 (((uint64_t)((y)[4] & 255))<<24)|(((uint64_t)((y)[5] & 255))<<16) | \
67 (((uint64_t)((y)[6] & 255))<<8)|(((uint64_t)((y)[7] & 255))); } while(0)
68
69 static int sha1_compress(sha1_context *md, unsigned char *buf)
70 {
71 uint32_t a,b,c,d,e,W[80],i;
72
73 /* copy the state into 512-bits into W[0..15] */
74 for (i = 0; i < 16; i++) {
75 LOAD32H(W[i], buf + (4*i));
76 }
77
78 /* copy state */
79 a = md->state[0];
80 b = md->state[1];
81 c = md->state[2];
82 d = md->state[3];
83 e = md->state[4];
84
85 /* expand it */
86 for (i = 16; i < 80; i++) {
87 W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
88 }
89
90 /* compress */
91 /* round one */
92 #define FF0(a,b,c,d,e,i) e = (ROL(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROL(b, 30);
93 #define FF1(a,b,c,d,e,i) e = (ROL(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROL(b, 30);
94 #define FF2(a,b,c,d,e,i) e = (ROL(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROL(b, 30);
95 #define FF3(a,b,c,d,e,i) e = (ROL(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROL(b, 30);
96
97 for (i = 0; i < 20; ) {
98 FF0(a,b,c,d,e,i++);
99 FF0(e,a,b,c,d,i++);
100 FF0(d,e,a,b,c,i++);
101 FF0(c,d,e,a,b,i++);
102 FF0(b,c,d,e,a,i++);
103 }
104
105 /* round two */
106 for (; i < 40; ) {
107 FF1(a,b,c,d,e,i++);
108 FF1(e,a,b,c,d,i++);
109 FF1(d,e,a,b,c,i++);
110 FF1(c,d,e,a,b,i++);
111 FF1(b,c,d,e,a,i++);
112 }
113
114 /* round three */
115 for (; i < 60; ) {
116 FF2(a,b,c,d,e,i++);
117 FF2(e,a,b,c,d,i++);
118 FF2(d,e,a,b,c,i++);
119 FF2(c,d,e,a,b,i++);
120 FF2(b,c,d,e,a,i++);
121 }
122
123 /* round four */
124 for (; i < 80; ) {
125 FF3(a,b,c,d,e,i++);
126 FF3(e,a,b,c,d,i++);
127 FF3(d,e,a,b,c,i++);
128 FF3(c,d,e,a,b,i++);
129 FF3(b,c,d,e,a,i++);
130 }
131
132 #undef FF0
133 #undef FF1
134 #undef FF2
135 #undef FF3
136
137 /* store */
138 md->state[0] = md->state[0] + a;
139 md->state[1] = md->state[1] + b;
140 md->state[2] = md->state[2] + c;
141 md->state[3] = md->state[3] + d;
142 md->state[4] = md->state[4] + e;
143
144 return 0;
145 }
146
147 /**
148 Initialize the hash state
149 @param md The hash state you wish to initialize
150 @return 0 if successful
151 */
152 int sha1_init(sha1_context * md)
153 {
154 if (md == NULL) return 1;
155 md->state[0] = 0x67452301UL;
156 md->state[1] = 0xefcdab89UL;
157 md->state[2] = 0x98badcfeUL;
158 md->state[3] = 0x10325476UL;
159 md->state[4] = 0xc3d2e1f0UL;
160 md->curlen = 0;
161 md->length = 0;
162 return 0;
163 }
164
165 /**
166 Process a block of memory though the hash
167 @param md The hash state
168 @param in The data to hash
169 @param inlen The length of the data (octets)
170 @return 0 if successful
171 */
172 int sha1_process (sha1_context * md, const unsigned char *in, unsigned long inlen)
173 {
174 size_t n;
175 size_t i;
176 int err;
177 if (md == NULL) return 1;
178 if (in == NULL) return 1;
179 if (md->curlen > sizeof(md->buf)) {
180 return 1;
181 }
182 if ((md->length + inlen) < md->length) {
183 return 1;
184 }
185 while (inlen > 0) {
186 if (md->curlen == 0 && inlen >= 64) {
187 if ((err = sha1_compress (md, (unsigned char *)in)) != 0) {
188 return err;
189 }
190 md->length += 64 * 8;
191 in += 64;
192 inlen -= 64;
193 } else {
194 n = MIN(inlen, (64 - md->curlen));
195 for (i = 0; i < n; i++) {
196 md->buf[md->curlen + i] = in[i];
197 }
198 md->curlen += n;
199 in += n;
200 inlen -= n;
201 if (md->curlen == 64) {
202 if ((err = sha1_compress (md, md->buf)) != 0) {
203 return err;
204 }
205 md->length += 8*64;
206 md->curlen = 0;
207 }
208 }
209 }
210 return 0;
211 }
212
213 /**
214 Terminate the hash to get the digest
215 @param md The hash state
216 @param out [out] The destination of the hash (20 bytes)
217 @return 0 if successful
218 */
219 int sha1_done(sha1_context * md, unsigned char *out)
220 {
221 int i;
222
223 if (md == NULL) return 1;
224 if (out == NULL) return 1;
225
226 if (md->curlen >= sizeof(md->buf)) {
227 return 1;
228 }
229
230 /* increase the length of the message */
231 md->length += md->curlen * 8;
232
233 /* append the '1' bit */
234 md->buf[md->curlen++] = (unsigned char)0x80;
235
236 /* if the length is currently above 56 bytes we append zeros
237 * then compress. Then we can fall back to padding zeros and length
238 * encoding like normal.
239 */
240 if (md->curlen > 56) {
241 while (md->curlen < 64) {
242 md->buf[md->curlen++] = (unsigned char)0;
243 }
244 sha1_compress(md, md->buf);
245 md->curlen = 0;
246 }
247
248 /* pad upto 56 bytes of zeroes */
249 while (md->curlen < 56) {
250 md->buf[md->curlen++] = (unsigned char)0;
251 }
252
253 /* store length */
254 STORE64H(md->length, md->buf+56);
255 sha1_compress(md, md->buf);
256
257 /* copy output */
258 for (i = 0; i < 5; i++) {
259 STORE32H(md->state[i], out+(4*i));
260 }
261 return 0;
262 }
263
264 int sha1(const char *msg, size_t len, char *hash)
265 {
266 sha1_context ctx;
267 int ret;
268 if ((ret = sha1_init(&ctx))) return ret;
269 if ((ret = sha1_process(&ctx, (const unsigned char *)msg, len))) return ret;
270 if ((ret = sha1_done(&ctx, (unsigned char *)hash))) return ret;
271 return 0;
272 }