]>
Commit | Line | Data |
---|---|---|
1c0d5243 AS |
1 | /* |
2 | * RFC 1321 compliant MD5 implementation | |
3 | * | |
4 | * Copyright (C) 2001-2003 Christophe Devine | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program; if not, write to the Free Software | |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 | */ | |
20 | ||
21 | #include <string.h> | |
22 | ||
23 | #include "common.h" | |
24 | #include "md5.h" | |
25 | ||
26 | #define OLDPASSFUNC | |
27 | #ifdef OLDPASSFUNC | |
28 | /* ----------------------------------------------------- */ | |
29 | /* DELETE THIS SOME DAY - OLD STUFF HERE */ | |
30 | /* ----------------------------------------------------- */ | |
31 | ||
d76ed9a9 AS |
32 | /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm */ |
33 | ||
34 | /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All | |
35 | rights reserved. | |
36 | ||
37 | License to copy and use this software is granted provided that it | |
38 | is identified as the "RSA Data Security, Inc. MD5 Message-Digest | |
39 | Algorithm" in all material mentioning or referencing this software | |
40 | or this function. | |
41 | ||
42 | License is also granted to make and use derivative works provided | |
43 | that such works are identified as "derived from the RSA Data | |
44 | Security, Inc. MD5 Message-Digest Algorithm" in all material | |
45 | mentioning or referencing the derived work. | |
46 | ||
47 | RSA Data Security, Inc. makes no representations concerning either | |
48 | the merchantability of this software or the suitability of this | |
49 | software for any particular purpose. It is provided "as is" | |
50 | without express or implied warranty of any kind. | |
51 | ||
52 | These notices must be retained in any copies of any part of this | |
53 | documentation and/or software. | |
54 | */ | |
55 | ||
d76ed9a9 AS |
56 | /* Constants for MD5Transform routine. |
57 | */ | |
58 | #define S11 7 | |
59 | #define S12 12 | |
60 | #define S13 17 | |
61 | #define S14 22 | |
62 | #define S21 5 | |
63 | #define S22 9 | |
64 | #define S23 14 | |
65 | #define S24 20 | |
66 | #define S31 4 | |
67 | #define S32 11 | |
68 | #define S33 16 | |
69 | #define S34 23 | |
70 | #define S41 6 | |
71 | #define S42 10 | |
72 | #define S43 15 | |
73 | #define S44 21 | |
74 | ||
75 | static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); | |
76 | static void Encode PROTO_LIST | |
77 | ((unsigned char *, UINT4 *, unsigned int)); | |
78 | static void Decode PROTO_LIST | |
79 | ((UINT4 *, unsigned char *, unsigned int)); | |
80 | ||
81 | static unsigned char PADDING[64] = { | |
82 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
83 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
84 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
85 | }; | |
86 | ||
87 | /* F, G, H and I are basic MD5 functions. | |
88 | */ | |
89 | #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) | |
90 | #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) | |
91 | #define H(x, y, z) ((x) ^ (y) ^ (z)) | |
92 | #define I(x, y, z) ((y) ^ ((x) | (~z))) | |
93 | ||
94 | /* ROTATE_LEFT rotates x left n bits. */ | |
95 | #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) | |
96 | ||
97 | /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. | |
98 | Rotation is separate from addition to prevent recomputation. | |
99 | */ | |
100 | #define FF(a, b, c, d, x, s, ac) { \ | |
101 | (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ | |
102 | (a) = ROTATE_LEFT ((a), (s)); \ | |
103 | (a) += (b); \ | |
104 | } | |
105 | #define GG(a, b, c, d, x, s, ac) { \ | |
106 | (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ | |
107 | (a) = ROTATE_LEFT ((a), (s)); \ | |
108 | (a) += (b); \ | |
109 | } | |
110 | #define HH(a, b, c, d, x, s, ac) { \ | |
111 | (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ | |
112 | (a) = ROTATE_LEFT ((a), (s)); \ | |
113 | (a) += (b); \ | |
114 | } | |
115 | #define II(a, b, c, d, x, s, ac) { \ | |
116 | (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ | |
117 | (a) = ROTATE_LEFT ((a), (s)); \ | |
118 | (a) += (b); \ | |
119 | } | |
120 | ||
121 | /* MD5 initialization. Begins an MD5 operation, writing a new context. */ | |
122 | void MD5Init (context) | |
123 | MD5_CTX *context; /* context */ | |
124 | { | |
125 | context->count[0] = context->count[1] = 0; | |
126 | /* Load magic initialization constants. */ | |
127 | context->state[0] = 0x67452301; | |
128 | context->state[1] = 0xefcdab89; | |
129 | context->state[2] = 0x98badcfe; | |
130 | context->state[3] = 0x10325476; | |
131 | } | |
132 | ||
133 | /* MD5 block update operation. Continues an MD5 message-digest | |
134 | operation, processing another message block, and updating the | |
135 | context. | |
136 | */ | |
137 | void MD5Update (context, input, inputLen) | |
138 | MD5_CTX *context; /* context */ | |
139 | unsigned char *input; /* input block */ | |
140 | unsigned int inputLen; /* length of input block */ | |
141 | { | |
142 | unsigned int i, index, partLen; | |
143 | ||
144 | /* Compute number of bytes mod 64 */ | |
145 | index = (unsigned int)((context->count[0] >> 3) & 0x3F); | |
146 | ||
147 | /* Update number of bits */ | |
148 | if ((context->count[0] += ((UINT4)inputLen << 3)) | |
149 | < ((UINT4)inputLen << 3)) | |
150 | context->count[1]++; | |
151 | context->count[1] += ((UINT4)inputLen >> 29); | |
152 | ||
153 | partLen = 64 - index; | |
154 | ||
155 | /* Transform as many times as possible. */ | |
156 | if (inputLen >= partLen) { | |
157 | memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen); | |
158 | MD5Transform (context->state, context->buffer); | |
159 | ||
160 | for (i = partLen; i + 63 < inputLen; i += 64) | |
161 | MD5Transform (context->state, &input[i]); | |
162 | ||
163 | index = 0; | |
164 | } | |
165 | else | |
166 | i = 0; | |
167 | ||
168 | /* Buffer remaining input */ | |
169 | memcpy((POINTER)&context->buffer[index], (POINTER)&input[i], | |
170 | inputLen-i); | |
171 | } | |
172 | ||
173 | /* MD5 finalization. Ends an MD5 message-digest operation, writing the | |
174 | the message digest and zeroizing the context. | |
175 | */ | |
176 | void MD5Final (digest, context) | |
177 | unsigned char digest[16]; /* message digest */ | |
178 | MD5_CTX *context; /* context */ | |
179 | { | |
180 | unsigned char bits[8]; | |
181 | unsigned int index, padLen; | |
182 | ||
183 | /* Save number of bits */ | |
184 | Encode (bits, context->count, 8); | |
185 | ||
186 | /* Pad out to 56 mod 64. */ | |
187 | index = (unsigned int)((context->count[0] >> 3) & 0x3f); | |
188 | padLen = (index < 56) ? (56 - index) : (120 - index); | |
189 | MD5Update (context, PADDING, padLen); | |
190 | ||
191 | /* Append length (before padding) */ | |
192 | MD5Update (context, bits, 8); | |
193 | ||
194 | /* Store state in digest */ | |
195 | Encode (digest, context->state, 16); | |
196 | ||
197 | /* Zeroize sensitive information. */ | |
198 | memset ((POINTER)context, 0, sizeof (*context)); | |
199 | } | |
200 | ||
201 | /* MD5 basic transformation. Transforms state based on block. */ | |
202 | static void MD5Transform (state, block) | |
203 | UINT4 state[4]; | |
204 | unsigned char block[64]; | |
205 | { | |
206 | UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; | |
207 | ||
208 | Decode (x, block, 64); | |
209 | ||
210 | /* Round 1 */ | |
211 | FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ | |
212 | FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ | |
213 | FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ | |
214 | FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ | |
215 | FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ | |
216 | FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ | |
217 | FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ | |
218 | FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ | |
219 | FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ | |
220 | FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ | |
221 | FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ | |
222 | FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ | |
223 | FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ | |
224 | FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ | |
225 | FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ | |
226 | FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ | |
227 | ||
228 | /* Round 2 */ | |
229 | GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ | |
230 | GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ | |
231 | GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ | |
232 | GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ | |
233 | GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ | |
234 | GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ | |
235 | GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ | |
236 | GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ | |
237 | GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ | |
238 | GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ | |
239 | GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ | |
240 | GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ | |
241 | GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ | |
242 | GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ | |
243 | GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ | |
244 | GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ | |
245 | ||
246 | /* Round 3 */ | |
247 | HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ | |
248 | HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ | |
249 | HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ | |
250 | HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ | |
251 | HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ | |
252 | HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ | |
253 | HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ | |
254 | HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ | |
255 | HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ | |
256 | HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ | |
257 | HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ | |
258 | HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ | |
259 | HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ | |
260 | HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ | |
261 | HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ | |
262 | HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ | |
263 | ||
264 | /* Round 4 */ | |
265 | II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ | |
266 | II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ | |
267 | II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ | |
268 | II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ | |
269 | II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ | |
270 | II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ | |
271 | II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ | |
272 | II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ | |
273 | II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ | |
274 | II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ | |
275 | II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ | |
276 | II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ | |
277 | II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ | |
278 | II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ | |
279 | II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ | |
280 | II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ | |
281 | ||
282 | state[0] += a; | |
283 | state[1] += b; | |
284 | state[2] += c; | |
285 | state[3] += d; | |
286 | ||
287 | /* Zeroize sensitive information. */ | |
288 | memset ((POINTER)x, 0, sizeof (x)); | |
289 | } | |
290 | ||
291 | /* Encodes input (UINT4) into output (unsigned char). Assumes len is | |
292 | a multiple of 4. | |
293 | */ | |
294 | static void Encode (output, input, len) | |
295 | unsigned char *output; | |
296 | UINT4 *input; | |
297 | unsigned int len; | |
298 | { | |
299 | unsigned int i, j; | |
300 | ||
301 | for (i = 0, j = 0; j < len; i++, j += 4) { | |
302 | output[j] = (unsigned char)(input[i] & 0xff); | |
303 | output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); | |
304 | output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); | |
305 | output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); | |
306 | } | |
307 | } | |
308 | ||
309 | /* Decodes input (unsigned char) into output (UINT4). Assumes len is | |
310 | a multiple of 4. | |
311 | */ | |
312 | static void Decode (output, input, len) | |
313 | UINT4 *output; | |
314 | unsigned char *input; | |
315 | unsigned int len; | |
316 | { | |
317 | unsigned int i, j; | |
318 | ||
319 | for (i = 0, j = 0; j < len; i++, j += 4) | |
320 | output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | | |
321 | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); | |
322 | } | |
323 | ||
324 | static const char * | |
325 | cryptpass_real(const char *pass, char *buffer, int seed) | |
326 | { | |
327 | static const char hex_digits[] = "0123456789ABCDEF"; | |
328 | MD5_CTX ctx; | |
329 | unsigned int len, i, j; | |
330 | unsigned char temp[64], buff[16]; | |
331 | ||
332 | /* first: generate seed */ | |
333 | if (seed) { | |
334 | for (i=j=0; j<4; j++) { | |
335 | temp[i++] = hex_digits[(seed >> (28 - 8*j)) & 15]; | |
336 | temp[i++] = hex_digits[(seed >> (24 - 8*j)) & 15]; | |
337 | } | |
338 | /* fill temp buffer with password, 1 and then 0's */ | |
339 | j = strlen(pass); | |
340 | if ((sizeof(temp) - i) < j) j = sizeof(temp) - i; | |
341 | memcpy(temp+i, pass, j); | |
342 | i += j; | |
343 | if (i < sizeof(temp)) temp[i++] = '1'; | |
344 | while (i < sizeof(temp)) temp[i++] = '0'; | |
345 | } else { | |
346 | i = 0; | |
347 | /* next: duplicate password to fill temp buffer */ | |
348 | len = strlen(pass); | |
349 | for (j=0; i<sizeof(temp); i++) { | |
350 | temp[i] = pass[j]; | |
351 | if (++j == len) j = 0; | |
352 | } | |
353 | } | |
354 | /* next: compute MD5 digest of repeated password */ | |
355 | MD5Init(&ctx); | |
356 | MD5Update(&ctx, temp, sizeof(temp)); | |
357 | MD5Final(buff, &ctx); | |
358 | /* finally: write digest to output buffer */ | |
359 | if (seed) { | |
360 | buffer[0] = '$'; | |
361 | for (i=0,j=1; i<4; i++) { | |
362 | buffer[j++] = hex_digits[(seed >> (28 - 8*i)) & 15]; | |
363 | buffer[j++] = hex_digits[(seed >> (24 - 8*i)) & 15]; | |
364 | } | |
365 | } else { | |
366 | j = 0; | |
367 | } | |
368 | for (i=0; i<sizeof(buff); i++) { | |
369 | buffer[j++] = hex_digits[buff[i] >> 4]; | |
370 | buffer[j++] = hex_digits[buff[i] & 15]; | |
371 | } | |
372 | buffer[j] = 0; | |
373 | return buffer; | |
374 | } | |
375 | ||
1c0d5243 AS |
376 | /* ----------------------------------------------------- */ |
377 | /* DELETE ABOVE SOME DAY -- OLD STUFF */ | |
378 | /* ----------------------------------------------------- */ | |
379 | ||
380 | #endif | |
381 | ||
382 | #define GET_UINT32(n,b,i) \ | |
383 | { \ | |
384 | (n) = ( (uint32) (b)[(i) ] ) \ | |
385 | | ( (uint32) (b)[(i) + 1] << 8 ) \ | |
386 | | ( (uint32) (b)[(i) + 2] << 16 ) \ | |
387 | | ( (uint32) (b)[(i) + 3] << 24 ); \ | |
388 | } | |
389 | ||
390 | #define PUT_UINT32(n,b,i) \ | |
391 | { \ | |
392 | (b)[(i) ] = (uint8) ( (n) ); \ | |
393 | (b)[(i) + 1] = (uint8) ( (n) >> 8 ); \ | |
394 | (b)[(i) + 2] = (uint8) ( (n) >> 16 ); \ | |
395 | (b)[(i) + 3] = (uint8) ( (n) >> 24 ); \ | |
396 | } | |
397 | ||
398 | void md5_starts( md5_context *ctx ) | |
399 | { | |
400 | ctx->total[0] = 0; | |
401 | ctx->total[1] = 0; | |
402 | ||
403 | ctx->state[0] = 0x67452301; | |
404 | ctx->state[1] = 0xEFCDAB89; | |
405 | ctx->state[2] = 0x98BADCFE; | |
406 | ctx->state[3] = 0x10325476; | |
407 | } | |
408 | ||
409 | void md5_process( md5_context *ctx, uint8 data[64] ) | |
410 | { | |
411 | uint32 X[16], A, B, C, D; | |
412 | ||
413 | GET_UINT32( X[0], data, 0 ); | |
414 | GET_UINT32( X[1], data, 4 ); | |
415 | GET_UINT32( X[2], data, 8 ); | |
416 | GET_UINT32( X[3], data, 12 ); | |
417 | GET_UINT32( X[4], data, 16 ); | |
418 | GET_UINT32( X[5], data, 20 ); | |
419 | GET_UINT32( X[6], data, 24 ); | |
420 | GET_UINT32( X[7], data, 28 ); | |
421 | GET_UINT32( X[8], data, 32 ); | |
422 | GET_UINT32( X[9], data, 36 ); | |
423 | GET_UINT32( X[10], data, 40 ); | |
424 | GET_UINT32( X[11], data, 44 ); | |
425 | GET_UINT32( X[12], data, 48 ); | |
426 | GET_UINT32( X[13], data, 52 ); | |
427 | GET_UINT32( X[14], data, 56 ); | |
428 | GET_UINT32( X[15], data, 60 ); | |
429 | ||
430 | #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) | |
431 | ||
432 | #define P(a,b,c,d,k,s,t) \ | |
433 | { \ | |
434 | a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ | |
435 | } | |
436 | ||
437 | A = ctx->state[0]; | |
438 | B = ctx->state[1]; | |
439 | C = ctx->state[2]; | |
440 | D = ctx->state[3]; | |
441 | ||
34938510 | 442 | #undef F |
1c0d5243 AS |
443 | #define F(x,y,z) (z ^ (x & (y ^ z))) |
444 | ||
445 | P( A, B, C, D, 0, 7, 0xD76AA478 ); | |
446 | P( D, A, B, C, 1, 12, 0xE8C7B756 ); | |
447 | P( C, D, A, B, 2, 17, 0x242070DB ); | |
448 | P( B, C, D, A, 3, 22, 0xC1BDCEEE ); | |
449 | P( A, B, C, D, 4, 7, 0xF57C0FAF ); | |
450 | P( D, A, B, C, 5, 12, 0x4787C62A ); | |
451 | P( C, D, A, B, 6, 17, 0xA8304613 ); | |
452 | P( B, C, D, A, 7, 22, 0xFD469501 ); | |
453 | P( A, B, C, D, 8, 7, 0x698098D8 ); | |
454 | P( D, A, B, C, 9, 12, 0x8B44F7AF ); | |
455 | P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); | |
456 | P( B, C, D, A, 11, 22, 0x895CD7BE ); | |
457 | P( A, B, C, D, 12, 7, 0x6B901122 ); | |
458 | P( D, A, B, C, 13, 12, 0xFD987193 ); | |
459 | P( C, D, A, B, 14, 17, 0xA679438E ); | |
460 | P( B, C, D, A, 15, 22, 0x49B40821 ); | |
461 | ||
462 | #undef F | |
463 | ||
464 | #define F(x,y,z) (y ^ (z & (x ^ y))) | |
465 | ||
466 | P( A, B, C, D, 1, 5, 0xF61E2562 ); | |
467 | P( D, A, B, C, 6, 9, 0xC040B340 ); | |
468 | P( C, D, A, B, 11, 14, 0x265E5A51 ); | |
469 | P( B, C, D, A, 0, 20, 0xE9B6C7AA ); | |
470 | P( A, B, C, D, 5, 5, 0xD62F105D ); | |
471 | P( D, A, B, C, 10, 9, 0x02441453 ); | |
472 | P( C, D, A, B, 15, 14, 0xD8A1E681 ); | |
473 | P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); | |
474 | P( A, B, C, D, 9, 5, 0x21E1CDE6 ); | |
475 | P( D, A, B, C, 14, 9, 0xC33707D6 ); | |
476 | P( C, D, A, B, 3, 14, 0xF4D50D87 ); | |
477 | P( B, C, D, A, 8, 20, 0x455A14ED ); | |
478 | P( A, B, C, D, 13, 5, 0xA9E3E905 ); | |
479 | P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); | |
480 | P( C, D, A, B, 7, 14, 0x676F02D9 ); | |
481 | P( B, C, D, A, 12, 20, 0x8D2A4C8A ); | |
482 | ||
483 | #undef F | |
484 | ||
485 | #define F(x,y,z) (x ^ y ^ z) | |
486 | ||
487 | P( A, B, C, D, 5, 4, 0xFFFA3942 ); | |
488 | P( D, A, B, C, 8, 11, 0x8771F681 ); | |
489 | P( C, D, A, B, 11, 16, 0x6D9D6122 ); | |
490 | P( B, C, D, A, 14, 23, 0xFDE5380C ); | |
491 | P( A, B, C, D, 1, 4, 0xA4BEEA44 ); | |
492 | P( D, A, B, C, 4, 11, 0x4BDECFA9 ); | |
493 | P( C, D, A, B, 7, 16, 0xF6BB4B60 ); | |
494 | P( B, C, D, A, 10, 23, 0xBEBFBC70 ); | |
495 | P( A, B, C, D, 13, 4, 0x289B7EC6 ); | |
496 | P( D, A, B, C, 0, 11, 0xEAA127FA ); | |
497 | P( C, D, A, B, 3, 16, 0xD4EF3085 ); | |
498 | P( B, C, D, A, 6, 23, 0x04881D05 ); | |
499 | P( A, B, C, D, 9, 4, 0xD9D4D039 ); | |
500 | P( D, A, B, C, 12, 11, 0xE6DB99E5 ); | |
501 | P( C, D, A, B, 15, 16, 0x1FA27CF8 ); | |
502 | P( B, C, D, A, 2, 23, 0xC4AC5665 ); | |
503 | ||
504 | #undef F | |
505 | ||
506 | #define F(x,y,z) (y ^ (x | ~z)) | |
507 | ||
508 | P( A, B, C, D, 0, 6, 0xF4292244 ); | |
509 | P( D, A, B, C, 7, 10, 0x432AFF97 ); | |
510 | P( C, D, A, B, 14, 15, 0xAB9423A7 ); | |
511 | P( B, C, D, A, 5, 21, 0xFC93A039 ); | |
512 | P( A, B, C, D, 12, 6, 0x655B59C3 ); | |
513 | P( D, A, B, C, 3, 10, 0x8F0CCC92 ); | |
514 | P( C, D, A, B, 10, 15, 0xFFEFF47D ); | |
515 | P( B, C, D, A, 1, 21, 0x85845DD1 ); | |
516 | P( A, B, C, D, 8, 6, 0x6FA87E4F ); | |
517 | P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); | |
518 | P( C, D, A, B, 6, 15, 0xA3014314 ); | |
519 | P( B, C, D, A, 13, 21, 0x4E0811A1 ); | |
520 | P( A, B, C, D, 4, 6, 0xF7537E82 ); | |
521 | P( D, A, B, C, 11, 10, 0xBD3AF235 ); | |
522 | P( C, D, A, B, 2, 15, 0x2AD7D2BB ); | |
523 | P( B, C, D, A, 9, 21, 0xEB86D391 ); | |
524 | ||
525 | #undef F | |
526 | ||
527 | ctx->state[0] += A; | |
528 | ctx->state[1] += B; | |
529 | ctx->state[2] += C; | |
530 | ctx->state[3] += D; | |
531 | } | |
532 | ||
533 | void md5_update( md5_context *ctx, uint8 *input, uint32 length ) | |
534 | { | |
535 | uint32 left, fill; | |
536 | ||
537 | if( ! length ) return; | |
538 | ||
539 | left = ctx->total[0] & 0x3F; | |
540 | fill = 64 - left; | |
541 | ||
542 | ctx->total[0] += length; | |
543 | ctx->total[0] &= 0xFFFFFFFF; | |
544 | ||
545 | if( ctx->total[0] < length ) | |
546 | ctx->total[1]++; | |
547 | ||
548 | if( left && length >= fill ) | |
549 | { | |
550 | memcpy( (void *) (ctx->buffer + left), | |
551 | (void *) input, fill ); | |
552 | md5_process( ctx, ctx->buffer ); | |
553 | length -= fill; | |
554 | input += fill; | |
555 | left = 0; | |
556 | } | |
557 | ||
558 | while( length >= 64 ) | |
559 | { | |
560 | md5_process( ctx, input ); | |
561 | length -= 64; | |
562 | input += 64; | |
563 | } | |
564 | ||
565 | if( length ) | |
566 | { | |
567 | memcpy( (void *) (ctx->buffer + left), | |
568 | (void *) input, length ); | |
569 | } | |
570 | } | |
571 | ||
572 | static uint8 md5_padding[64] = | |
573 | { | |
574 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
575 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
576 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
577 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
578 | }; | |
579 | ||
580 | void md5_finish( md5_context *ctx, uint8 digest[16] ) | |
581 | { | |
582 | uint32 last, padn; | |
583 | uint32 high, low; | |
584 | uint8 msglen[8]; | |
585 | ||
586 | high = ( ctx->total[0] >> 29 ) | |
587 | | ( ctx->total[1] << 3 ); | |
588 | low = ( ctx->total[0] << 3 ); | |
589 | ||
590 | PUT_UINT32( low, msglen, 0 ); | |
591 | PUT_UINT32( high, msglen, 4 ); | |
592 | ||
593 | last = ctx->total[0] & 0x3F; | |
594 | padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); | |
595 | ||
596 | md5_update( ctx, md5_padding, padn ); | |
597 | md5_update( ctx, msglen, 8 ); | |
598 | ||
599 | PUT_UINT32( ctx->state[0], digest, 0 ); | |
600 | PUT_UINT32( ctx->state[1], digest, 4 ); | |
601 | PUT_UINT32( ctx->state[2], digest, 8 ); | |
602 | PUT_UINT32( ctx->state[3], digest, 12 ); | |
603 | } | |
604 | ||
605 | #define TEST | |
606 | #ifdef TEST | |
607 | ||
608 | #include <stdlib.h> | |
609 | #include <stdio.h> | |
610 | ||
611 | /* | |
612 | * those are the standard RFC 1321 test vectors | |
613 | */ | |
614 | ||
ceafd592 | 615 | char* md5(const char* pass, char* output) |
1c0d5243 AS |
616 | { |
617 | md5_context ctx; | |
618 | int j; | |
619 | unsigned char md5sum[16]; | |
620 | ||
621 | md5_starts( &ctx ); | |
622 | md5_update( &ctx, (uint8 *) pass, strlen(pass)); | |
623 | md5_finish( &ctx, md5sum ); | |
624 | for(j = 0; j<16; j++) | |
625 | { | |
626 | sprintf(output + j * 2, "%02x", md5sum[j]); | |
627 | } | |
628 | printf("The hash of %s is %s\n\n", pass, output); | |
ceafd592 | 629 | return 0; |
1c0d5243 AS |
630 | } |
631 | ||
d76ed9a9 AS |
632 | const char * |
633 | cryptpass(const char *pass, char *buffer) | |
634 | { | |
1c0d5243 | 635 | return md5(pass, buffer); |
d76ed9a9 AS |
636 | } |
637 | ||
638 | int | |
639 | checkpass(const char *pass, const char *crypt) | |
640 | { | |
641 | char new_crypt[MD5_CRYPT_LENGTH], hseed[9]; | |
642 | int seed; | |
643 | ||
644 | if (crypt[0] == '$') { | |
645 | /* new-style crypt, use "seed" after '$' */ | |
646 | strncpy(hseed, crypt+1, 8); | |
647 | hseed[8] = 0; | |
648 | seed = strtoul(hseed, NULL, 16); | |
1c0d5243 | 649 | cryptpass_real(pass, new_crypt, seed); |
d76ed9a9 | 650 | } else { |
1c0d5243 AS |
651 | /* new "old-style" md5 crypt compatable with php, md5sum etc */ |
652 | md5(pass, new_crypt); | |
d76ed9a9 | 653 | } |
d76ed9a9 AS |
654 | return !strcmp(crypt, new_crypt); |
655 | } | |
1c0d5243 AS |
656 | |
657 | ||
658 | ||
659 | #endif |