1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1996-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * *
19 ***********************************************************************/
20 #pragma prototyped
21
22 /*
23 * md5
24 */
25
26 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
27 rights reserved.
28
29 License to copy and use this software is granted provided that it
30 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
31 Method" in all material mentioning or referencing this software
32 or this function.
33
34 License is also granted to make and use derivative works provided
35 that such works are identified as "derived from the RSA Data
36 Security, Inc. MD5 Message-Digest Method" in all material
37 mentioning or referencing the derived work.
38
39 RSA Data Security, Inc. makes no representations concerning either
40 the merchantability of this software or the suitability of this
41 software for any particular purpose. It is provided "as is"
42 without express or implied warranty of any kind.
43
44 These notices must be retained in any copies of any part of this
45 documentation and/or software.
46 */
47
48 #define md5_description \
49 "The RSA Data Security, Inc. MD5 Message-Digest Method, 1991-2, \
50 used with permission. The block count is not printed."
51 #define md5_options "[+(version)?md5 (RSA Data Security, Inc. MD5 Message-Digest, 1991-2) 1996-02-29]"
52 #define md5_match "md5|MD5"
53 #define md5_scale 0
54
55 typedef uint32_t UINT4;
56
57 typedef struct Md5_s
58 {
59 _SUM_PUBLIC_
60 _SUM_PRIVATE_
61 UINT4 state[4]; /* state (ABCD) */
62 UINT4 count[2]; /* # bits handled mod 2^64 (lsb)*/
63 unsigned char buffer[64]; /* input buffer */
64 unsigned char digest[16]; /* final digest */
65 unsigned char digest_sum[16]; /* sum of all digests */
66 } Md5_t;
67
68 static const unsigned char md5_pad[] =
69 {
70 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
78 };
79
80 /*
81 * encode input into output
82 * len must be a multiple of 4
83 */
84
85 static void
md5_encode(register unsigned char * output,register UINT4 * input,unsigned int len)86 md5_encode(register unsigned char* output, register UINT4* input, unsigned int len)
87 {
88 register unsigned int i;
89 register unsigned int j;
90
91 for (i = j = 0; j < len; i++, j += 4)
92 {
93 output[j] = (unsigned char)(input[i] & 0xff);
94 output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
95 output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
96 output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
97 }
98 }
99
100 /*
101 * decode input into output
102 * len must be a multiple of 4
103 */
104
105 static void
md5_decode(register UINT4 * output,register unsigned char * input,unsigned int len)106 md5_decode(register UINT4* output, register unsigned char* input, unsigned int len)
107 {
108 unsigned int i;
109 unsigned int j;
110
111 for (i = j = 0; j < len; i++, j += 4)
112 output[i] = ((UINT4)input[j]) |
113 (((UINT4)input[j+1]) << 8) |
114 (((UINT4)input[j+2]) << 16) |
115 (((UINT4)input[j+3]) << 24);
116 }
117
118 static int
md5_init(Sum_t * p)119 md5_init(Sum_t* p)
120 {
121 register Md5_t* context = (Md5_t*)p;
122
123 context->count[0] = context->count[1] = 0;
124 context->state[0] = 0x67452301;
125 context->state[1] = 0xefcdab89;
126 context->state[2] = 0x98badcfe;
127 context->state[3] = 0x10325476;
128 return 0;
129 }
130
131 static Sum_t*
md5_open(const Method_t * method,const char * name)132 md5_open(const Method_t* method, const char* name)
133 {
134 Md5_t* p;
135
136 if (p = newof(0, Md5_t, 1, 0))
137 {
138 p->method = (Method_t*)method;
139 p->name = name;
140 md5_init((Sum_t*)p);
141 }
142 return (Sum_t*)p;
143 }
144
145 /*
146 * basic MD5 step -- transforms buf based on in
147 */
148
149 #define S11 7
150 #define S12 12
151 #define S13 17
152 #define S14 22
153 #define S21 5
154 #define S22 9
155 #define S23 14
156 #define S24 20
157 #define S31 4
158 #define S32 11
159 #define S33 16
160 #define S34 23
161 #define S41 6
162 #define S42 10
163 #define S43 15
164 #define S44 21
165
166 /* F, G, H and I are basic MD5 functions */
167 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
168 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
169 #define H(x, y, z) ((x) ^ (y) ^ (z))
170 #define I(x, y, z) ((y) ^ ((x) | (~z)))
171
172 /* ROTATE_LEFT rotates x left n bits */
173 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
174
175 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
176 /* Rotation is separate from addition to prevent recomputation */
177 #define FF(a, b, c, d, x, s, ac) { \
178 (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
179 (a) = ROTATE_LEFT ((a), (s)); \
180 (a) += (b); \
181 }
182 #define GG(a, b, c, d, x, s, ac) { \
183 (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
184 (a) = ROTATE_LEFT ((a), (s)); \
185 (a) += (b); \
186 }
187 #define HH(a, b, c, d, x, s, ac) { \
188 (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
189 (a) = ROTATE_LEFT ((a), (s)); \
190 (a) += (b); \
191 }
192 #define II(a, b, c, d, x, s, ac) { \
193 (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
194 (a) = ROTATE_LEFT ((a), (s)); \
195 (a) += (b); \
196 }
197
198 static void
md5_transform(UINT4 state[4],unsigned char block[64])199 md5_transform(UINT4 state[4], unsigned char block[64])
200 {
201 UINT4 a = state[0];
202 UINT4 b = state[1];
203 UINT4 c = state[2];
204 UINT4 d = state[3];
205 UINT4 x[16];
206
207 md5_decode(x, block, 64);
208
209 /* round 1 */
210 FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
211 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
212 FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
213 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
214 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
215 FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
216 FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
217 FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
218 FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
219 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
220 FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
221 FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
222 FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
223 FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
224 FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
225 FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
226
227 /* round 2 */
228 GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
229 GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
230 GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
231 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
232 GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
233 GG (d, a, b, c, x[10], S22, 0x02441453); /* 22 */
234 GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
235 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
236 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
237 GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
238 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
239 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
240 GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
241 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
242 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
243 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
244
245 /* round 3 */
246 HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
247 HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
248 HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
249 HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
250 HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
251 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
252 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
253 HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
254 HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
255 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
256 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
257 HH (b, c, d, a, x[ 6], S34, 0x04881d05); /* 44 */
258 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
259 HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
260 HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
261 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
262
263 /* round 4 */
264 II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
265 II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
266 II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
267 II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
268 II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
269 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
270 II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
271 II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
272 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
273 II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
274 II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
275 II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
276 II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
277 II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
278 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
279 II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
280
281 state[0] += a;
282 state[1] += b;
283 state[2] += c;
284 state[3] += d;
285 }
286
287 static int
md5_block(Sum_t * p,const void * s,size_t inputLen)288 md5_block(Sum_t* p, const void* s, size_t inputLen)
289 {
290 register Md5_t* context = (Md5_t*)p;
291 unsigned char* input = (unsigned char*)s;
292 unsigned int i;
293 unsigned int index;
294 unsigned int partLen;
295
296 /* compute number of bytes mod 64 */
297 index = (unsigned int)((context->count[0] >> 3) & 0x3f);
298
299 /* update number of bits */
300 if ((context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3))
301 context->count[1]++;
302 context->count[1] += ((UINT4)inputLen >> 29);
303 partLen = 64 - index;
304
305 /* transform as many times as possible */
306 if (inputLen >= partLen)
307 {
308 memcpy(&context->buffer[index], input, partLen);
309 md5_transform(context->state, context->buffer);
310 for (i = partLen; i + 63 < inputLen; i += 64)
311 md5_transform(context->state, &input[i]);
312 index = 0;
313 }
314 else
315 i = 0;
316
317 /* buffer remaining input */
318 memcpy(&context->buffer[index], &input[i], inputLen - i);
319
320 return 0;
321 }
322
323 static int
md5_done(Sum_t * p)324 md5_done(Sum_t* p)
325 {
326 register Md5_t* context = (Md5_t*)p;
327 unsigned char bits[8];
328 unsigned int index;
329 unsigned int padLen;
330
331 /* save number of bits */
332 md5_encode(bits, context->count, sizeof(bits));
333
334 /* pad out to 56 mod 64 */
335 index = (unsigned int)((context->count[0] >> 3) & 0x3f);
336 padLen = (index < 56) ? (56 - index) : (120 - index);
337 md5_block(p, md5_pad, padLen);
338
339 /* append length (before padding) */
340 md5_block(p, bits, sizeof(bits));
341
342 /* store state in digest */
343 md5_encode(context->digest, context->state, sizeof(context->digest));
344
345 /* accumulate the digests */
346 for (index = 0; index < elementsof(context->digest); index++)
347 context->digest_sum[index] ^= context->digest[index];
348
349 return 0;
350 }
351
352 static int
md5_print(Sum_t * p,Sfio_t * sp,register int flags,size_t scale)353 md5_print(Sum_t* p, Sfio_t* sp, register int flags, size_t scale)
354 {
355 register Md5_t* x = (Md5_t*)p;
356 register unsigned char* d;
357 register int n;
358
359 d = (flags & SUM_TOTAL) ? x->digest_sum : x->digest;
360 for (n = 0; n < elementsof(x->digest); n++)
361 sfprintf(sp, "%02x", d[n]);
362 return 0;
363 }
364
365 static int
md5_data(Sum_t * p,Sumdata_t * data)366 md5_data(Sum_t* p, Sumdata_t* data)
367 {
368 register Md5_t* x = (Md5_t*)p;
369
370 data->size = elementsof(x->digest);
371 data->num = 0;
372 data->buf = x->digest;
373 return 0;
374 }
375