1 /////////////////////////////////////////////////////////////////////////
2 // MD5.cpp
3 // Implementation file for MD5 class
4 //
5 // This C++ Class implementation of the original RSA Data Security, Inc.
6 // MD5 Message-Digest Algorithm is copyright (c) 2002, Gary McNickle.
7 // All rights reserved.  This software is a derivative of the "RSA Data
8 //  Security, Inc. MD5 Message-Digest Algorithm"
9 //
10 // You may use this software free of any charge, but without any
11 // warranty or implied warranty, provided that you follow the terms
12 // of the original RSA copyright, listed below.
13 //
14 // Original RSA Data Security, Inc. Copyright notice
15 /////////////////////////////////////////////////////////////////////////
16 //
17 // Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
18 // rights reserved.
19 //
20 // License to copy and use this software is granted provided that it
21 // is identified as the "RSA Data Security, Inc. MD5 Message-Digest
22 // Algorithm" in all material mentioning or referencing this software
23 // or this function.
24 // License is also granted to make and use derivative works provided
25 // that such works are identified as "derived from the RSA Data
26 // Security, Inc. MD5 Message-Digest Algorithm" in all material
27 // mentioning or referencing the derived work.
28 // RSA Data Security, Inc. makes no representations concerning either
29 // the merchantability of this software or the suitability of this
30 // software for any particular purpose. It is provided "as is"
31 // without express or implied warranty of any kind.
32 // These notices must be retained in any copies of any part of this
33 // documentation and/or software.
34 /////////////////////////////////////////////////////////////////////////
35 
36 /*------------------------------------------------------------------------------
37 * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team
38 *
39 * Distributable under the terms of either the Apache License (Version 2.0) or
40 * the GNU Lesser General Public License, as specified in the COPYING file.
41 ------------------------------------------------------------------------------*/
42 
43 #include "CLucene/_ApiHeader.h"
44 #include "_MD5Digester.h"
45 CL_NS_DEF(util)
46 
47 static unsigned char PADDING[64] =
48 {
49   0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
51   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
52 };
53 
54 #define S11 7
55 #define S12 12
56 #define S13 17
57 #define S14 22
58 #define S21 5
59 #define S22 9
60 #define S23 14
61 #define S24 20
62 #define S31 4
63 #define S32 11
64 #define S33 16
65 #define S34 23
66 #define S41 6
67 #define S42 10
68 #define S43 15
69 #define S44 21
70 
71 
72 // PrintMD5: Converts a completed md5 digest into a char* string.
PrintMD5(uint8_t md5Digest[16])73 char* PrintMD5(uint8_t md5Digest[16])
74 {
75 	const char toHex[] = "0123456789abcdef";
76 	char chBuffer[16 * 2 + 1];
77 	int nCount;
78 
79 	for (nCount = 0; nCount < 16; nCount++)
80 	{
81 		chBuffer[nCount * 2] = toHex[(md5Digest[nCount] & 0xf0) >> 4];
82 		chBuffer[nCount * 2 + 1] = toHex[md5Digest[nCount] & 0x0f];
83 	}
84 	chBuffer[nCount * 2] = '\0';
85 
86 	return STRDUP_AtoA(chBuffer);
87 }
88 
89 // MD5String: Performs the MD5 algorithm on a char* string, returning
90 // the results as a char*.
MD5String(char * szString)91 char* MD5String(char* szString)
92 {
93 	int nLen = strlen(szString);
94 	md5 alg;
95 
96 	alg.Update((unsigned char*)szString, (unsigned int)nLen);
97 	alg.Finalize();
98 
99 	return PrintMD5(alg.Digest());
100 
101 }
102 
103 // MD5File: Performs the MD5 algorithm on a file (binar or text),
104 // returning the results as a char*.  Returns NULL if it fails.
MD5File(char * szFilename)105 char* MD5File(char* szFilename)
106 {
107 	FILE* file;
108 	md5 alg;
109 	int nLen;
110 	unsigned char chBuffer[1024];
111 
112 	try
113 	{
114 		memset(chBuffer, 0, 1024);
115 
116 		if ((file = fopen (szFilename, "rb")) != NULL)
117 		{
118 			while ((nLen = fread (chBuffer, 1, 1024, file)))
119 				alg.Update(chBuffer, nLen);
120 
121 			alg.Finalize();
122 
123 			fclose (file);
124 
125 			return PrintMD5(alg.Digest());
126 		}
127 	}
128 	catch(...) //todo: only catch IO Err???
129 	{
130 
131 	}
132 
133 	return NULL; // failed
134 }
135 
136 
137 // md5::Init
138 // Initializes a new context.
Init()139 void md5::Init()
140 {
141 	memset(m_Count, 0, 2 * sizeof(uint32_t));
142 
143 	m_State[0] = 0x67452301;
144 	m_State[1] = 0xefcdab89;
145 	m_State[2] = 0x98badcfe;
146 	m_State[3] = 0x10325476;
147 }
148 
149 // md5::Update
150 // MD5 block update operation. Continues an MD5 message-digest
151 // operation, processing another message block, and updating the
152 // context.
Update(uint8_t * chInput,uint32_t nInputLen)153 void md5::Update(uint8_t* chInput, uint32_t nInputLen)
154 {
155 	uint32_t i, index, partLen;
156 
157 	// Compute number of bytes mod 64
158 	index = (unsigned int)((m_Count[0] >> 3) & 0x3F);
159 
160 	// Update number of bits
161 	if ((m_Count[0] += (nInputLen << 3)) < (nInputLen << 3))
162 		m_Count[1]++;
163 
164 	m_Count[1] += (nInputLen >> 29);
165 
166 	partLen = 64 - index;
167 
168 	// Transform as many times as possible.
169 	if (nInputLen >= partLen)
170 	{
171 		memcpy( &m_Buffer[index], chInput, partLen );
172 		Transform(m_Buffer);
173 
174 		for (i = partLen; i + 63 < nInputLen; i += 64)
175 			Transform(&chInput[i]);
176 
177 		index = 0;
178 	}
179 	else
180 		i = 0;
181 
182   // Buffer remaining input
183   memcpy( &m_Buffer[index], &chInput[i], nInputLen-i );
184 }
185 
186 // md5::Finalize
187 // MD5 finalization. Ends an MD5 message-digest operation, writing
188 // the message digest and zeroizing the context.
Finalize()189 void md5::Finalize()
190 {
191 	uint8_t bits[8];
192 	uint32_t index, padLen;
193 
194 	// Save number of bits
195 	Encode (bits, m_Count, 8);
196 
197 	// Pad out to 56 mod 64
198 	index = (unsigned int)((m_Count[0] >> 3) & 0x3f);
199 	padLen = (index < 56) ? (56 - index) : (120 - index);
200 	Update(PADDING, padLen);
201 
202 	// Append length (before padding)
203 	Update (bits, 8);
204 
205 	// Store state in digest
206 	Encode (m_Digest, m_State, 16);
207 
208 	memset(m_Count, 0, 2 * sizeof(uint32_t));
209 	memset(m_State, 0, 4 * sizeof(uint32_t));
210 	memset(m_Buffer,0, 64 * sizeof(uint8_t));
211 }
212 
213 // md5::Transform
214 // MD5 basic transformation. Transforms state based on block.
Transform(uint8_t * block)215 void md5::Transform (uint8_t* block)
216 {
217   uint32_t a = m_State[0], b = m_State[1], c = m_State[2], d = m_State[3], x[16];
218 
219   Decode (x, block, 64);
220 
221   // Round 1
222   FF (a, b, c, d, x[ 0], S11, 0xd76aa478);
223   FF (d, a, b, c, x[ 1], S12, 0xe8c7b756);
224   FF (c, d, a, b, x[ 2], S13, 0x242070db);
225   FF (b, c, d, a, x[ 3], S14, 0xc1bdceee);
226   FF (a, b, c, d, x[ 4], S11, 0xf57c0faf);
227   FF (d, a, b, c, x[ 5], S12, 0x4787c62a);
228   FF (c, d, a, b, x[ 6], S13, 0xa8304613);
229   FF (b, c, d, a, x[ 7], S14, 0xfd469501);
230   FF (a, b, c, d, x[ 8], S11, 0x698098d8);
231   FF (d, a, b, c, x[ 9], S12, 0x8b44f7af);
232   FF (c, d, a, b, x[10], S13, 0xffff5bb1);
233   FF (b, c, d, a, x[11], S14, 0x895cd7be);
234   FF (a, b, c, d, x[12], S11, 0x6b901122);
235   FF (d, a, b, c, x[13], S12, 0xfd987193);
236   FF (c, d, a, b, x[14], S13, 0xa679438e);
237   FF (b, c, d, a, x[15], S14, 0x49b40821);
238 
239  // Round 2
240   GG (a, b, c, d, x[ 1], S21, 0xf61e2562);
241   GG (d, a, b, c, x[ 6], S22, 0xc040b340);
242   GG (c, d, a, b, x[11], S23, 0x265e5a51);
243   GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa);
244   GG (a, b, c, d, x[ 5], S21, 0xd62f105d);
245   GG (d, a, b, c, x[10], S22,  0x2441453);
246   GG (c, d, a, b, x[15], S23, 0xd8a1e681);
247   GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8);
248   GG (a, b, c, d, x[ 9], S21, 0x21e1cde6);
249   GG (d, a, b, c, x[14], S22, 0xc33707d6);
250   GG (c, d, a, b, x[ 3], S23, 0xf4d50d87);
251   GG (b, c, d, a, x[ 8], S24, 0x455a14ed);
252   GG (a, b, c, d, x[13], S21, 0xa9e3e905);
253   GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8);
254   GG (c, d, a, b, x[ 7], S23, 0x676f02d9);
255   GG (b, c, d, a, x[12], S24, 0x8d2a4c8a);
256 
257   // Round 3
258   HH (a, b, c, d, x[ 5], S31, 0xfffa3942);
259   HH (d, a, b, c, x[ 8], S32, 0x8771f681);
260   HH (c, d, a, b, x[11], S33, 0x6d9d6122);
261   HH (b, c, d, a, x[14], S34, 0xfde5380c);
262   HH (a, b, c, d, x[ 1], S31, 0xa4beea44);
263   HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9);
264   HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60);
265   HH (b, c, d, a, x[10], S34, 0xbebfbc70);
266   HH (a, b, c, d, x[13], S31, 0x289b7ec6);
267   HH (d, a, b, c, x[ 0], S32, 0xeaa127fa);
268   HH (c, d, a, b, x[ 3], S33, 0xd4ef3085);
269   HH (b, c, d, a, x[ 6], S34,  0x4881d05);
270   HH (a, b, c, d, x[ 9], S31, 0xd9d4d039);
271   HH (d, a, b, c, x[12], S32, 0xe6db99e5);
272   HH (c, d, a, b, x[15], S33, 0x1fa27cf8);
273   HH (b, c, d, a, x[ 2], S34, 0xc4ac5665);
274 
275   // Round 4
276   II (a, b, c, d, x[ 0], S41, 0xf4292244);
277   II (d, a, b, c, x[ 7], S42, 0x432aff97);
278   II (c, d, a, b, x[14], S43, 0xab9423a7);
279   II (b, c, d, a, x[ 5], S44, 0xfc93a039);
280   II (a, b, c, d, x[12], S41, 0x655b59c3);
281   II (d, a, b, c, x[ 3], S42, 0x8f0ccc92);
282   II (c, d, a, b, x[10], S43, 0xffeff47d);
283   II (b, c, d, a, x[ 1], S44, 0x85845dd1);
284   II (a, b, c, d, x[ 8], S41, 0x6fa87e4f);
285   II (d, a, b, c, x[15], S42, 0xfe2ce6e0);
286   II (c, d, a, b, x[ 6], S43, 0xa3014314);
287   II (b, c, d, a, x[13], S44, 0x4e0811a1);
288   II (a, b, c, d, x[ 4], S41, 0xf7537e82);
289   II (d, a, b, c, x[11], S42, 0xbd3af235);
290   II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb);
291   II (b, c, d, a, x[ 9], S44, 0xeb86d391);
292 
293   m_State[0] += a;
294   m_State[1] += b;
295   m_State[2] += c;
296   m_State[3] += d;
297 
298   memset(x, 0, sizeof(x));
299 }
300 
301 // md5::Encode
302 // Encodes input (uint32_t) into output (uint8_t). Assumes nLength is
303 // a multiple of 4.
Encode(uint8_t * dest,uint32_t * src,uint32_t nLength)304 void md5::Encode(uint8_t* dest, uint32_t* src, uint32_t nLength)
305 {
306 	uint32_t i, j;
307 
308 	CND_PRECONDITION(nLength % 4 == 0,"nLength % 4 != 0")
309 
310 	for (i = 0, j = 0; j < nLength; i++, j += 4)
311 	{
312 		dest[j] = (uint8_t)(src[i] & 0xff);
313 		dest[j+1] = (uint8_t)((src[i] >> 8) & 0xff);
314 		dest[j+2] = (uint8_t)((src[i] >> 16) & 0xff);
315 		dest[j+3] = (uint8_t)((src[i] >> 24) & 0xff);
316 	}
317 }
318 
319 // md5::Decode
320 // Decodes input (uint8_t) into output (uint32_t). Assumes nLength is
321 // a multiple of 4.
Decode(uint32_t * dest,uint8_t * src,uint32_t nLength)322 void md5::Decode(uint32_t* dest, uint8_t* src, uint32_t nLength)
323 {
324 	uint32_t i, j;
325 
326 	CND_PRECONDITION(nLength % 4 == 0, "nLength % 4 != 0");
327 
328 	for (i = 0, j = 0; j < nLength; i++, j += 4)
329 	{
330 		dest[i] = ((uint32_t)src[j]) | (((uint32_t)src[j+1])<<8) |
331 			      (((uint32_t)src[j+2])<<16) | (((uint32_t)src[j+3])<<24);
332 	}
333 }
334 
335 CL_NS_END
336