blob: 842bf7846070d85fcec92d9a2ad39465a9acee38 [file] [log] [blame]
David Reiss18bf22d2007-08-28 20:49:17 +00001/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
2 *
3 * This file has been modified for use in Thrift.
4 */
5
6/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
7 rights reserved.
8
9 License to copy and use this software is granted provided that it
10 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
11 Algorithm" in all material mentioning or referencing this software
12 or this function.
13
14 License is also granted to make and use derivative works provided
15 that such works are identified as "derived from the RSA Data
16 Security, Inc. MD5 Message-Digest Algorithm" in all material
17 mentioning or referencing the derived work.
18
19 RSA Data Security, Inc. makes no representations concerning either
20 the merchantability of this software or the suitability of this
21 software for any particular purpose. It is provided "as is"
22 without express or implied warranty of any kind.
23
24 These notices must be retained in any copies of any part of this
25 documentation and/or software.
26 */
27
28#include "md5.h"
29
30/* GLOBAL.H - RSAREF types and constants
31 */
32
33/* POINTER defines a generic pointer type */
34typedef unsigned char *POINTER;
35
36/* UINT2 defines a two byte word */
37typedef uint16_t UINT2;
38
39/* UINT4 defines a four byte word */
40typedef uint32_t UINT4;
41
42#define PROTO_LIST(list) list
43
44/* END GLOBAL.H
45 */
46
47
48/* Constants for MD5Transform routine.
49 */
50#define S11 7
51#define S12 12
52#define S13 17
53#define S14 22
54#define S21 5
55#define S22 9
56#define S23 14
57#define S24 20
58#define S31 4
59#define S32 11
60#define S33 16
61#define S34 23
62#define S41 6
63#define S42 10
64#define S43 15
65#define S44 21
66
67static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
68static void Encode PROTO_LIST
69 ((unsigned char *, UINT4 *, unsigned int));
70static void Decode PROTO_LIST
71 ((UINT4 *, unsigned char *, unsigned int));
72static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
73static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
74
75static unsigned char PADDING[64] = {
76 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
77 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
78 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
79};
80
81/* F, G, H and I are basic MD5 functions.
82 */
83#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
84#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
85#define H(x, y, z) ((x) ^ (y) ^ (z))
86#define I(x, y, z) ((y) ^ ((x) | (~z)))
87
88/* ROTATE_LEFT rotates x left n bits.
89 */
90#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
91
92/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
93 Rotation is separate from addition to prevent recomputation.
94 */
95#define FF(a, b, c, d, x, s, ac) { \
96 (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
97 (a) = ROTATE_LEFT ((a), (s)); \
98 (a) += (b); \
99 }
100#define GG(a, b, c, d, x, s, ac) { \
101 (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
102 (a) = ROTATE_LEFT ((a), (s)); \
103 (a) += (b); \
104 }
105#define HH(a, b, c, d, x, s, ac) { \
106 (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
107 (a) = ROTATE_LEFT ((a), (s)); \
108 (a) += (b); \
109 }
110#define II(a, b, c, d, x, s, ac) { \
111 (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
112 (a) = ROTATE_LEFT ((a), (s)); \
113 (a) += (b); \
114 }
115
116/* MD5 initialization. Begins an MD5 operation, writing a new context.
117 */
118void MD5Init (context)
119MD5_CTX *context; /* context */
120{
121 context->count[0] = context->count[1] = 0;
122
123 /* Load magic initialization constants.
124 */
125 context->state[0] = 0x67452301;
126 context->state[1] = 0xefcdab89;
127 context->state[2] = 0x98badcfe;
128 context->state[3] = 0x10325476;
129}
130
131/* MD5 block update operation. Continues an MD5 message-digest
132 operation, processing another message block, and updating the
133 context.
134 */
135void MD5Update (context, input, inputLen)
136MD5_CTX *context; /* context */
137unsigned char *input; /* input block */
138unsigned int inputLen; /* length of input block */
139{
140 unsigned int i, index, partLen;
141
142 /* Compute number of bytes mod 64 */
143 index = (unsigned int)((context->count[0] >> 3) & 0x3F);
144
145 /* Update number of bits */
146 if ((context->count[0] += ((UINT4)inputLen << 3))
147 < ((UINT4)inputLen << 3))
148 context->count[1]++;
149 context->count[1] += ((UINT4)inputLen >> 29);
150
151 partLen = 64 - index;
152
153 /* Transform as many times as possible.
154 */
155 if (inputLen >= partLen) {
156 MD5_memcpy
157 ((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 MD5_memcpy
170 ((POINTER)&context->buffer[index], (POINTER)&input[i],
171 inputLen-i);
172}
173
174/* MD5 finalization. Ends an MD5 message-digest operation, writing the
175 the message digest and zeroizing the context.
176 */
177void MD5Final (digest, context)
178unsigned char digest[16]; /* message digest */
179MD5_CTX *context; /* context */
180{
181 unsigned char bits[8];
182 unsigned int index, padLen;
183
184 /* Save number of bits */
185 Encode (bits, context->count, 8);
186
187 /* Pad out to 56 mod 64.
188 */
189 index = (unsigned int)((context->count[0] >> 3) & 0x3f);
190 padLen = (index < 56) ? (56 - index) : (120 - index);
191 MD5Update (context, PADDING, padLen);
192
193 /* Append length (before padding) */
194 MD5Update (context, bits, 8);
195
196 /* Store state in digest */
197 Encode (digest, context->state, 16);
198
199 /* Zeroize sensitive information.
200 */
201 MD5_memset ((POINTER)context, 0, sizeof (*context));
202}
203
204/* MD5 basic transformation. Transforms state based on block.
205 */
206static void MD5Transform (state, block)
207UINT4 state[4];
208unsigned char block[64];
209{
210 UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
211
212 Decode (x, block, 64);
213
214 /* Round 1 */
215 FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
216 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
217 FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
218 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
219 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
220 FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
221 FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
222 FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
223 FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
224 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
225 FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
226 FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
227 FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
228 FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
229 FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
230 FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
231
232 /* Round 2 */
233 GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
234 GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
235 GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
236 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
237 GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
238 GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
239 GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
240 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
241 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
242 GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
243 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
244 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
245 GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
246 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
247 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
248 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
249
250 /* Round 3 */
251 HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
252 HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
253 HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
254 HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
255 HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
256 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
257 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
258 HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
259 HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
260 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
261 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
262 HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
263 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
264 HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
265 HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
266 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
267
268 /* Round 4 */
269 II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
270 II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
271 II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
272 II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
273 II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
274 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
275 II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
276 II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
277 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
278 II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
279 II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
280 II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
281 II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
282 II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
283 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
284 II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
285
286 state[0] += a;
287 state[1] += b;
288 state[2] += c;
289 state[3] += d;
290
291 /* Zeroize sensitive information.
292 */
293 MD5_memset ((POINTER)x, 0, sizeof (x));
294}
295
296/* Encodes input (UINT4) into output (unsigned char). Assumes len is
297 a multiple of 4.
298 */
299static void Encode (output, input, len)
300unsigned char *output;
301UINT4 *input;
302unsigned int len;
303{
304 unsigned int i, j;
305
306 for (i = 0, j = 0; j < len; i++, j += 4) {
307 output[j] = (unsigned char)(input[i] & 0xff);
308 output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
309 output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
310 output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
311 }
312}
313
314/* Decodes input (unsigned char) into output (UINT4). Assumes len is
315 a multiple of 4.
316 */
317static void Decode (output, input, len)
318UINT4 *output;
319unsigned char *input;
320unsigned int len;
321{
322 unsigned int i, j;
323
324 for (i = 0, j = 0; j < len; i++, j += 4)
325 output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
326 (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
327}
328
329/* Note: Replace "for loop" with standard memcpy if possible.
330 */
331static void MD5_memcpy (output, input, len)
332POINTER output;
333POINTER input;
334unsigned int len;
335{
336 unsigned int i;
337
338 for (i = 0; i < len; i++)
339 output[i] = input[i];
340}
341
342/* Note: Replace "for loop" with standard memset if possible.
343 */
344static void MD5_memset (output, value, len)
345POINTER output;
346int value;
347unsigned int len;
348{
349 unsigned int i;
350
351 for (i = 0; i < len; i++)
352 ((char *)output)[i] = (char)value;
353}
354