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