1 /*
2  *	binkleyforce -- unix FTN mailer project
3  *
4  *	Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
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  *	$Id: u_md5.c,v 1.1.1.1 2004/09/09 09:52:39 kstepanenkov Exp $
12  */
13 
14 #include "includes.h"
15 #include "confread.h"
16 #include "logger.h"
17 #include "util.h"
18 
19 /* Data structure for MD5 (Message-Digest) computation */
20 typedef struct {
21 	int chunks;                   /* Number of 64 byte chunks */
22 	unsigned int buf[4];
23 } s_md5;
24 
25 /* F, G, H and I are basic MD5 functions */
26 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
27 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
28 #define H(x, y, z) ((x) ^ (y) ^ (z))
29 #define I(x, y, z) ((y) ^ ((x) | (~z)))
30 
31 /* ROTATE_LEFT rotates x left n bits */
32 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
33 
34 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
35 /* Rotation is separate from addition to prevent recomputation */
36 #define FF(a, b, c, d, x, s, ac) \
37   {(a) += F ((b), (c), (d)) + (x) + (unsigned int)(ac); \
38    (a) = ROTATE_LEFT ((a), (s)); \
39    (a) += (b); \
40   }
41 #define GG(a, b, c, d, x, s, ac) \
42   {(a) += G ((b), (c), (d)) + (x) + (unsigned int)(ac); \
43    (a) = ROTATE_LEFT ((a), (s)); \
44    (a) += (b); \
45   }
46 #define HH(a, b, c, d, x, s, ac) \
47   {(a) += H ((b), (c), (d)) + (x) + (unsigned int)(ac); \
48    (a) = ROTATE_LEFT ((a), (s)); \
49    (a) += (b); \
50   }
51 #define II(a, b, c, d, x, s, ac) \
52   {(a) += I ((b), (c), (d)) + (x) + (unsigned int)(ac); \
53    (a) = ROTATE_LEFT ((a), (s)); \
54    (a) += (b); \
55   }
56 
57 #ifdef __STDC__
58 #define UL(x)	x##U
59 #else
60 #define UL(x)	x
61 #endif
62 
63 /*****************************************************************************
64  * Initialise MD5 structure
65  *
66  * Arguments:
67  * 	md        pointer to the MD5 structure
68  *
69  * Return value:
70  * 	None
71  */
md5_init(s_md5 * md)72 static void md5_init(s_md5 *md)
73 {
74 	md->chunks = 0;
75 
76 	md->buf[0] = (unsigned int)0x67452301;
77 	md->buf[1] = (unsigned int)0xefcdab89;
78 	md->buf[2] = (unsigned int)0x98badcfe;
79 	md->buf[3] = (unsigned int)0x10325476;
80 }
81 
82 /*****************************************************************************
83  * Process next data chunk
84  *
85  * Arguments:
86  * 	md        pointer to the MD5 structure
87  * 	buffer    pointer to the data chunk (must be 64 bytes)
88  *
89  * Return value:
90  * 	None
91  */
md5_update(s_md5 * md,const unsigned char * buffer)92 static void md5_update(s_md5 *md, const unsigned char *buffer)
93 {
94 	int i;
95 	unsigned int in[16];
96 	unsigned int a = md->buf[0];
97 	unsigned int b = md->buf[1];
98 	unsigned int c = md->buf[2];
99 	unsigned int d = md->buf[3];
100 
101 	++md->chunks;
102 
103 	/* Unpack buffer */
104 	for( i = 0; i < 16; i++ )
105 	{
106 		in[i] = ((unsigned int)(buffer[0])      )
107 		      | ((unsigned int)(buffer[1]) << 8 )
108 		      | ((unsigned int)(buffer[2]) << 16)
109 		      | ((unsigned int)(buffer[3]) << 24);
110 		buffer += 4;
111 	}
112 
113 	/* Round 1 */
114 #define S11 7
115 #define S12 12
116 #define S13 17
117 #define S14 22
118 	FF( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */
119 	FF( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */
120 	FF( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */
121 	FF( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */
122 	FF( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */
123 	FF( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */
124 	FF( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */
125 	FF( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */
126 	FF( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */
127 	FF( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */
128 	FF( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */
129 	FF( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */
130 	FF( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */
131 	FF( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */
132 	FF( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */
133 	FF( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */
134 
135 	/* Round 2 */
136 #define S21 5
137 #define S22 9
138 #define S23 14
139 #define S24 20
140 	GG( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */
141 	GG( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */
142 	GG( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */
143 	GG( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */
144 	GG( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */
145 	GG( d, a, b, c, in[10], S22, UL(  38016083)); /* 22 */
146 	GG( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */
147 	GG( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */
148 	GG( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */
149 	GG( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */
150 	GG( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */
151 	GG( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */
152 	GG( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */
153 	GG( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */
154 	GG( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */
155 	GG( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */
156 
157 	/* Round 3 */
158 #define S31 4
159 #define S32 11
160 #define S33 16
161 #define S34 23
162 	HH( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */
163 	HH( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */
164 	HH( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */
165 	HH( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */
166 	HH( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */
167 	HH( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */
168 	HH( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */
169 	HH( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */
170 	HH( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */
171 	HH( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */
172 	HH( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */
173 	HH( b, c, d, a, in[ 6], S34, UL(  76029189)); /* 44 */
174 	HH( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */
175 	HH( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */
176 	HH( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */
177 	HH( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */
178 
179 	/* Round 4 */
180 #define S41 6
181 #define S42 10
182 #define S43 15
183 #define S44 21
184 	II( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */
185 	II( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */
186 	II( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */
187 	II( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */
188 	II( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */
189 	II( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */
190 	II( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */
191 	II( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */
192 	II( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */
193 	II( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */
194 	II( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */
195 	II( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */
196 	II( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */
197 	II( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */
198 	II( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */
199 	II( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */
200 
201 	md->buf[0] += a;
202 	md->buf[1] += b;
203 	md->buf[2] += c;
204 	md->buf[3] += d;
205 }
206 
207 /*****************************************************************************
208  * Compute MD5 digest (RFC-1321)
209  *
210  * Arguments:
211  * 	md        pointer to the MD5 structure
212  * 	digest    pointer to the resulting digest buffer (must be 16 bytes)
213  * 	data      pointer to the source data
214  * 	length    source data length
215  *
216  * Return value:
217  * 	None
218  */
md5_compute(s_md5 * md,const unsigned char * data,size_t length,unsigned char * digest)219 static void md5_compute(s_md5 *md, const unsigned char *data, size_t length,
220                         unsigned char *digest)
221 {
222 	unsigned char buffer[64];
223 	int i;
224 
225 	while( length >= 64 )
226 	{
227 		md5_update(md, data);
228 		data += 64;
229 		length -= 64;
230 	}
231 
232 	memcpy(buffer, data, length);
233 	buffer[length] = 0x80;
234 	memset(buffer + length + 1, '\0', 63 - length);
235 
236 	if( length > 55 )
237 	{
238 		md5_update(md, buffer);
239 		memset(buffer, '\0', 64);
240 		--md->chunks;
241 	}
242 
243 	length += (md->chunks * 64);
244 	length <<= 3;
245 
246 	buffer[56] = (unsigned char)((length      ) & 0xff);
247 	buffer[57] = (unsigned char)((length >> 8 ) & 0xff);
248 	buffer[58] = (unsigned char)((length >> 16) & 0xff);
249 	buffer[59] = (unsigned char)((length >> 24) & 0xff);
250 
251 	md5_update(md, buffer);
252 
253 	for( i = 0; i < 4; i++ )
254 	{
255 		unsigned int x = md->buf[i];
256 		*digest++ = (unsigned char)((x      ) & 0xff);
257 		*digest++ = (unsigned char)((x >> 8 ) & 0xff);
258 		*digest++ = (unsigned char)((x >> 16) & 0xff);
259 		*digest++ = (unsigned char)((x >> 24) & 0xff);
260 	}
261 }
262 
md5_get(const unsigned char * data,size_t length,unsigned char * digest)263 void md5_get(const unsigned char *data, size_t length, unsigned char *digest)
264 {
265 	s_md5 md;
266 
267 	md5_init(&md);
268 	md5_compute(&md, data, length, digest);
269 }
270 
271 /*****************************************************************************
272  * Compute CRAM-MD5 digest (RFC-2195). It is produced by calculating
273  *
274  *   MD5((secret XOR opad), MD5((secret XOR ipad), challengedata))
275  *
276  * where MD5 is chosen hash function, ipad and opad are 36 hex and 5C hex
277  * and secret is null-padded to a length of 64 bytes. If the secret is
278  * longer than 64 bytes, the hash-function digest of the secret is used as
279  * an input
280  *
281  * Arguments:
282  * 	secret    pointer to the null-terminated secret string (e.g. password)
283  * 	challenge pointer to the challenge data
284  * 	challenge_length length of the challenge data
285  * 	digest    pointer to the resulting digest buffer (must be 16 bytes)
286  *
287  * Return value:
288  * 	None
289  */
md5_cram_get(const unsigned char * secret,const unsigned char * challenge,int challenge_length,unsigned char * digest)290 void md5_cram_get(const unsigned char *secret, const unsigned char *challenge,
291                   int challenge_length, unsigned char *digest)
292 {
293 	int i;
294 	unsigned char secret_md5[16];
295 	int secret_length = strlen(secret);
296 	unsigned char osecret[64];
297 	unsigned char isecret[64];
298 	s_md5 md;
299 
300 	/*
301 	 * If the secret length is longer 64 bytes
302 	 * use MD5 digest of the secret as input
303 	 */
304 	if( secret_length > 64 )
305 	{
306 		md5_get(secret, secret_length, secret_md5);
307 		secret = secret_md5;
308 		secret_length = 16;
309 	}
310 
311 	memcpy(osecret, secret, secret_length);
312 	memcpy(isecret, secret, secret_length);
313 	memset(osecret + secret_length, '\0', 64 - secret_length);
314 	memset(isecret + secret_length, '\0', 64 - secret_length);
315 
316 	for( i = 0; i < 64; i++ )
317 	{
318 		osecret[i] ^= 0x5c;
319 		isecret[i] ^= 0x36;
320 	}
321 
322 	/*
323 	 * Compute HASH((secret XOR ipad), challenge)
324 	 */
325 	md5_init(&md);
326 	md5_update(&md, isecret);
327 	md5_compute(&md, challenge, challenge_length, secret_md5);
328 
329 	/*
330 	 * Compute HASH((secret XOR opad), secret_md5)
331 	 */
332 	md5_init(&md);
333 	md5_update(&md, osecret);
334 	md5_compute(&md, secret_md5, 16, digest);
335 }
336 
337