d9898ee8 |
1 | /* |
2 | ** Copyright 1998 - 2000 Double Precision, Inc. |
3 | ** See COPYING for distribution information. |
4 | */ |
5 | |
6 | #define MD5_INTERNAL |
7 | #include "md5.h" |
8 | #include <string.h> |
9 | #include <stdlib.h> |
10 | |
11 | static const char rcsid[]="$Id: md5.c,v 1.7 2000/07/30 01:08:09 mrsam Exp $"; |
12 | |
13 | #define MD5_BYTE unsigned char |
14 | |
15 | #define MD5_ROL(w,n) \ |
16 | ( (w) << (n) | ( (w) >> (32-(n)) ) ) |
17 | |
18 | static MD5_WORD T[64]={ |
19 | 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, |
20 | 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, |
21 | 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, |
22 | 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, |
23 | 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, |
24 | 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, |
25 | 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, |
26 | 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, |
27 | 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, |
28 | 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, |
29 | 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, |
30 | 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, |
31 | 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, |
32 | 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, |
33 | 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, |
34 | 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391}; |
35 | |
36 | void md5_context_init(struct MD5_CONTEXT *c) |
37 | { |
38 | if (sizeof(MD5_WORD) != 4) abort(); |
39 | |
40 | c->A=0x67452301; |
41 | c->B=0xefcdab89; |
42 | c->C=0x98badcfe; |
43 | c->D=0x10325476; |
44 | |
45 | c->blk_ptr=0; |
46 | } |
47 | |
48 | void md5_context_hash(struct MD5_CONTEXT *c, |
49 | const unsigned char blk[MD5_BLOCK_SIZE]) |
50 | { |
51 | MD5_WORD x[16]; |
52 | unsigned i, j; |
53 | MD5_WORD A, B, C, D; |
54 | MD5_WORD zz; |
55 | |
56 | for (i=j=0; i<16; i++) |
57 | { |
58 | MD5_WORD w=(MD5_WORD)blk[j++]; |
59 | |
60 | w |= (MD5_WORD)blk[j++] << 8; |
61 | w |= (MD5_WORD)blk[j++] << 16; |
62 | w |= (MD5_WORD)blk[j++] << 24; |
63 | x[i]= w; |
64 | } |
65 | |
66 | #define F(X,Y,Z) ( ((X) & (Y)) | ( (~(X)) & (Z))) |
67 | #define G(X,Y,Z) ( ((X) & (Z)) | ( (Y) & (~(Z)))) |
68 | #define H(X,Y,Z) ( (X) ^ (Y) ^ (Z) ) |
69 | #define I(X,Y,Z) ( (Y) ^ ( (X) | (~(Z)))) |
70 | |
71 | A=c->A; |
72 | B=c->B; |
73 | C=c->C; |
74 | D=c->D; |
75 | |
76 | #define ROUND1(a,b,c,d,k,s,i) \ |
77 | { zz=(a + F(b,c,d) + x[k] + T[i]); a=b+MD5_ROL(zz,s); } |
78 | |
79 | ROUND1(A,B,C,D,0,7,0); |
80 | ROUND1(D,A,B,C,1,12,1); |
81 | ROUND1(C,D,A,B,2,17,2); |
82 | ROUND1(B,C,D,A,3,22,3); |
83 | ROUND1(A,B,C,D,4,7,4); |
84 | ROUND1(D,A,B,C,5,12,5); |
85 | ROUND1(C,D,A,B,6,17,6); |
86 | ROUND1(B,C,D,A,7,22,7); |
87 | ROUND1(A,B,C,D,8,7,8); |
88 | ROUND1(D,A,B,C,9,12,9); |
89 | ROUND1(C,D,A,B,10,17,10); |
90 | ROUND1(B,C,D,A,11,22,11); |
91 | ROUND1(A,B,C,D,12,7,12); |
92 | ROUND1(D,A,B,C,13,12,13); |
93 | ROUND1(C,D,A,B,14,17,14); |
94 | ROUND1(B,C,D,A,15,22,15); |
95 | |
96 | #define ROUND2(a,b,c,d,k,s,i) \ |
97 | { zz=(a + G(b,c,d) + x[k] + T[i]); a = b + MD5_ROL(zz,s); } |
98 | |
99 | ROUND2(A,B,C,D,1,5,16); |
100 | ROUND2(D,A,B,C,6,9,17); |
101 | ROUND2(C,D,A,B,11,14,18); |
102 | ROUND2(B,C,D,A,0,20,19); |
103 | ROUND2(A,B,C,D,5,5,20); |
104 | ROUND2(D,A,B,C,10,9,21); |
105 | ROUND2(C,D,A,B,15,14,22); |
106 | ROUND2(B,C,D,A,4,20,23); |
107 | ROUND2(A,B,C,D,9,5,24); |
108 | ROUND2(D,A,B,C,14,9,25); |
109 | ROUND2(C,D,A,B,3,14,26); |
110 | ROUND2(B,C,D,A,8,20,27); |
111 | ROUND2(A,B,C,D,13,5,28); |
112 | ROUND2(D,A,B,C,2,9,29); |
113 | ROUND2(C,D,A,B,7,14,30); |
114 | ROUND2(B,C,D,A,12,20,31); |
115 | |
116 | #define ROUND3(a,b,c,d,k,s,i) \ |
117 | { zz=(a + H(b,c,d) + x[k] + T[i]); a = b + MD5_ROL(zz,s); } |
118 | |
119 | ROUND3(A,B,C,D,5,4,32); |
120 | ROUND3(D,A,B,C,8,11,33); |
121 | ROUND3(C,D,A,B,11,16,34); |
122 | ROUND3(B,C,D,A,14,23,35); |
123 | ROUND3(A,B,C,D,1,4,36); |
124 | ROUND3(D,A,B,C,4,11,37); |
125 | ROUND3(C,D,A,B,7,16,38); |
126 | ROUND3(B,C,D,A,10,23,39); |
127 | ROUND3(A,B,C,D,13,4,40); |
128 | ROUND3(D,A,B,C,0,11,41); |
129 | ROUND3(C,D,A,B,3,16,42); |
130 | ROUND3(B,C,D,A,6,23,43); |
131 | ROUND3(A,B,C,D,9,4,44); |
132 | ROUND3(D,A,B,C,12,11,45); |
133 | ROUND3(C,D,A,B,15,16,46); |
134 | ROUND3(B,C,D,A,2,23,47); |
135 | |
136 | #define ROUND4(a,b,c,d,k,s,i) \ |
137 | { zz=(a + I(b,c,d) + x[k] + T[i]); a = b + MD5_ROL(zz,s); } |
138 | |
139 | ROUND4(A,B,C,D,0,6,48); |
140 | ROUND4(D,A,B,C,7,10,49); |
141 | ROUND4(C,D,A,B,14,15,50); |
142 | ROUND4(B,C,D,A,5,21,51); |
143 | ROUND4(A,B,C,D,12,6,52); |
144 | ROUND4(D,A,B,C,3,10,53); |
145 | ROUND4(C,D,A,B,10,15,54); |
146 | ROUND4(B,C,D,A,1,21,55); |
147 | ROUND4(A,B,C,D,8,6,56); |
148 | ROUND4(D,A,B,C,15,10,57); |
149 | ROUND4(C,D,A,B,6,15,58); |
150 | ROUND4(B,C,D,A,13,21,59); |
151 | ROUND4(A,B,C,D,4,6,60); |
152 | ROUND4(D,A,B,C,11,10,61); |
153 | ROUND4(C,D,A,B,2,15,62); |
154 | ROUND4(B,C,D,A,9,21,63); |
155 | |
156 | c->A += A; |
157 | c->B += B; |
158 | c->C += C; |
159 | c->D += D; |
160 | } |
161 | |
162 | void md5_context_hashstream(struct MD5_CONTEXT *c, const void *p, unsigned l) |
163 | { |
164 | const unsigned char *cp=(const unsigned char *)p; |
165 | unsigned ll; |
166 | |
167 | while (l) |
168 | { |
169 | if (c->blk_ptr == 0 && l >= MD5_BLOCK_SIZE) |
170 | { |
171 | md5_context_hash(c, cp); |
172 | cp += MD5_BLOCK_SIZE; |
173 | l -= MD5_BLOCK_SIZE; |
174 | continue; |
175 | } |
176 | |
177 | ll=l; |
178 | if (ll > MD5_BLOCK_SIZE - c->blk_ptr) |
179 | ll=MD5_BLOCK_SIZE - c->blk_ptr; |
180 | memcpy(c->blk + c->blk_ptr, cp, ll); |
181 | c->blk_ptr += ll; |
182 | cp += ll; |
183 | l -= ll; |
184 | if (c->blk_ptr >= MD5_BLOCK_SIZE) |
185 | { |
186 | md5_context_hash(c, c->blk); |
187 | c->blk_ptr=0; |
188 | } |
189 | } |
190 | } |
191 | |
192 | void md5_context_endstream(struct MD5_CONTEXT *c, unsigned long ll) |
193 | { |
194 | unsigned char buf[8]; |
195 | |
196 | static unsigned char zero[MD5_BLOCK_SIZE-8]; |
197 | MD5_WORD l; |
198 | |
199 | buf[0]=0x80; |
200 | md5_context_hashstream(c, buf, 1); |
201 | while (c->blk_ptr != MD5_BLOCK_SIZE - 8) |
202 | { |
203 | if (c->blk_ptr > MD5_BLOCK_SIZE - 8) |
204 | { |
205 | md5_context_hashstream(c, zero, |
206 | MD5_BLOCK_SIZE - c->blk_ptr); |
207 | continue; |
208 | } |
209 | md5_context_hashstream(c, zero, |
210 | MD5_BLOCK_SIZE - 8 - c->blk_ptr); |
211 | } |
212 | |
213 | l= ll; |
214 | |
215 | l <<= 3; |
216 | |
217 | buf[0]=l; |
218 | l >>= 8; |
219 | buf[1]=l; |
220 | l >>= 8; |
221 | buf[2]=l; |
222 | l >>= 8; |
223 | buf[3]=l; |
224 | |
225 | l= ll; |
226 | l >>= 29; |
227 | buf[4]=l; |
228 | l >>= 8; |
229 | buf[5]=l; |
230 | l >>= 8; |
231 | buf[6]=l; |
232 | l >>= 8; |
233 | buf[7]=l; |
234 | |
235 | md5_context_hashstream(c, buf, 8); |
236 | } |
237 | |
238 | void md5_context_digest(struct MD5_CONTEXT *c, MD5_DIGEST d) |
239 | { |
240 | unsigned char *dp=d; |
241 | MD5_WORD w; |
242 | |
243 | #define PUT(c) (w=(c), *dp++ = w, w >>= 8, *dp++ = w, w >>= 8, *dp++ = w, w >>= 8, *dp++ = w) |
244 | |
245 | PUT(c->A); |
246 | PUT(c->B); |
247 | PUT(c->C); |
248 | PUT(c->D); |
249 | #undef PUT |
250 | } |
251 | |
252 | void md5_context_restore(struct MD5_CONTEXT *c, const MD5_DIGEST d) |
253 | { |
254 | const unsigned char *dp=(unsigned char *)d+MD5_DIGEST_SIZE; |
255 | MD5_WORD w; |
256 | |
257 | #define GET \ |
258 | w=*--dp; w=(w << 8) | *--dp; w=(w << 8) | *--dp; w=(w << 8) | *--dp; |
259 | |
260 | GET |
261 | c->D=w; |
262 | GET |
263 | c->C=w; |
264 | GET |
265 | c->B=w; |
266 | GET |
267 | c->A=w; |
268 | c->blk_ptr=0; |
269 | } |
270 | |
271 | void md5_digest(const void *msg, unsigned int len, MD5_DIGEST d) |
272 | { |
273 | struct MD5_CONTEXT c; |
274 | |
275 | md5_context_init(&c); |
276 | md5_context_hashstream(&c, msg, len); |
277 | md5_context_endstream(&c, len); |
278 | md5_context_digest(&c, d); |
279 | } |