Merge remote-tracking branch 'upstream/edge' into upstream-master
[clinton/Smoothieware.git] / src / libs / md5.cpp
1 /* MD5
2 converted to C++ class by Frank Thilo (thilo@unix-ag.org)
3 for bzflag (http://www.bzflag.org)
4
5 based on:
6
7 md5.h and md5.c
8 reference implemantion of RFC 1321
9
10 Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
11 rights reserved.
12
13 License to copy and use this software is granted provided that it
14 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
15 Algorithm" in all material mentioning or referencing this software
16 or this function.
17
18 License is also granted to make and use derivative works provided
19 that such works are identified as "derived from the RSA Data
20 Security, Inc. MD5 Message-Digest Algorithm" in all material
21 mentioning or referencing the derived work.
22
23 RSA Data Security, Inc. makes no representations concerning either
24 the merchantability of this software or the suitability of this
25 software for any particular purpose. It is provided "as is"
26 without express or implied warranty of any kind.
27
28 These notices must be retained in any copies of any part of this
29 documentation and/or software.
30
31 */
32
33 /* interface header */
34 #include "md5.h"
35
36 /* system implementation headers */
37 #include <string.h>
38 #include <stdio.h>
39
40 // Constants for MD5Transform routine.
41 #define S11 7
42 #define S12 12
43 #define S13 17
44 #define S14 22
45 #define S21 5
46 #define S22 9
47 #define S23 14
48 #define S24 20
49 #define S31 4
50 #define S32 11
51 #define S33 16
52 #define S34 23
53 #define S41 6
54 #define S42 10
55 #define S43 15
56 #define S44 21
57
58 ///////////////////////////////////////////////
59
60 // F, G, H and I are basic MD5 functions.
61 inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z)
62 {
63 return ((x & y) | (~x & z));
64 }
65
66 inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z)
67 {
68 return ((x & z) | (y&~z));
69 }
70
71 inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z)
72 {
73 return x ^ y ^ z;
74 }
75
76 inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z)
77 {
78 return y ^ (x | ~z);
79 }
80
81 // rotate_left rotates x left n bits.
82 inline MD5::uint4 MD5::rotate_left(uint4 x, int n)
83 {
84 return (x << n) | (x >> (32 - n));
85 }
86
87 // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
88 // Rotation is separate from addition to prevent recomputation.
89 inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
90 {
91 a = rotate_left(a + F(b, c, d) + x + ac, s) + b;
92 }
93
94 inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
95 {
96 a = rotate_left(a + G(b, c, d) + x + ac, s) + b;
97 }
98
99 inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
100 {
101 a = rotate_left(a + H(b, c, d) + x + ac, s) + b;
102 }
103
104 inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
105 {
106 a = rotate_left(a + I(b, c, d) + x + ac, s) + b;
107 }
108
109 //////////////////////////////////////////////
110
111 // default ctor, just initailize
112 MD5::MD5()
113 {
114 init();
115 }
116
117 //////////////////////////////////////////////
118
119 // nifty shortcut ctor, compute MD5 for string and finalize it right away
120 MD5::MD5(const std::string &text)
121 {
122 init();
123 update(text.c_str(), text.length());
124 finalize();
125 }
126
127 //////////////////////////////
128
129 void MD5::init()
130 {
131 finalized = false;
132
133 count[0] = 0;
134 count[1] = 0;
135
136 // load magic initialization constants.
137 state[0] = 0x67452301;
138 state[1] = 0xefcdab89;
139 state[2] = 0x98badcfe;
140 state[3] = 0x10325476;
141 }
142
143 //////////////////////////////
144
145 // decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4.
146 void MD5::decode(uint4 output[], const uint1 input[], size_type len)
147 {
148 for (unsigned int i = 0, j = 0; j < len; i++, j += 4)
149 output[i] = ((uint4)input[j]) | (((uint4)input[j + 1]) << 8) |
150 (((uint4)input[j + 2]) << 16) | (((uint4)input[j + 3]) << 24);
151 }
152
153 //////////////////////////////
154
155 // encodes input (uint4) into output (unsigned char). Assumes len is
156 // a multiple of 4.
157 void MD5::encode(uint1 output[], const uint4 input[], size_type len)
158 {
159 for (size_type i = 0, j = 0; j < len; i++, j += 4) {
160 output[j] = input[i] & 0xff;
161 output[j + 1] = (input[i] >> 8) & 0xff;
162 output[j + 2] = (input[i] >> 16) & 0xff;
163 output[j + 3] = (input[i] >> 24) & 0xff;
164 }
165 }
166
167 //////////////////////////////
168
169 // apply MD5 algo on a block
170 void MD5::transform(const uint1 block[blocksize])
171 {
172 uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
173 decode (x, block, blocksize);
174
175 /* Round 1 */
176 FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
177 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
178 FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
179 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
180 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
181 FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
182 FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
183 FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
184 FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
185 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
186 FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
187 FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
188 FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
189 FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
190 FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
191 FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
192
193 /* Round 2 */
194 GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
195 GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
196 GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
197 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
198 GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
199 GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
200 GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
201 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
202 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
203 GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
204 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
205 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
206 GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
207 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
208 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
209 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
210
211 /* Round 3 */
212 HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
213 HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
214 HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
215 HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
216 HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
217 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
218 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
219 HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
220 HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
221 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
222 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
223 HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
224 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
225 HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
226 HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
227 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
228
229 /* Round 4 */
230 II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
231 II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
232 II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
233 II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
234 II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
235 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
236 II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
237 II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
238 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
239 II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
240 II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
241 II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
242 II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
243 II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
244 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
245 II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
246
247 state[0] += a;
248 state[1] += b;
249 state[2] += c;
250 state[3] += d;
251
252 // Zeroize sensitive information.
253 memset(x, 0, sizeof x);
254 }
255
256 //////////////////////////////
257
258 // MD5 block update operation. Continues an MD5 message-digest
259 // operation, processing another message block
260 void MD5::update(const unsigned char input[], size_type length)
261 {
262 // compute number of bytes mod 64
263 size_type index = count[0] / 8 % blocksize;
264
265 // Update number of bits
266 if ((count[0] += (length << 3)) < (length << 3))
267 count[1]++;
268 count[1] += (length >> 29);
269
270 // number of bytes we need to fill in buffer
271 size_type firstpart = 64 - index;
272
273 size_type i;
274
275 // transform as many times as possible.
276 if (length >= firstpart) {
277 // fill buffer first, transform
278 memcpy(&buffer[index], input, firstpart);
279 transform(buffer);
280
281 // transform chunks of blocksize (64 bytes)
282 for (i = firstpart; i + blocksize <= length; i += blocksize)
283 transform(&input[i]);
284
285 index = 0;
286 } else
287 i = 0;
288
289 // buffer remaining input
290 memcpy(&buffer[index], &input[i], length - i);
291 }
292
293 //////////////////////////////
294
295 // for convenience provide a verson with signed char
296 void MD5::update(const char input[], size_type length)
297 {
298 update((const unsigned char *)input, length);
299 }
300
301 //////////////////////////////
302
303 // MD5 finalization. Ends an MD5 message-digest operation, writing the
304 // the message digest and zeroizing the context.
305 MD5 &MD5::finalize()
306 {
307 static unsigned char padding[64] = {
308 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
309 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
310 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
311 };
312
313 if (!finalized) {
314 // Save number of bits
315 unsigned char bits[8];
316 encode(bits, count, 8);
317
318 // pad out to 56 mod 64.
319 size_type index = count[0] / 8 % 64;
320 size_type padLen = (index < 56) ? (56 - index) : (120 - index);
321 update(padding, padLen);
322
323 // Append length (before padding)
324 update(bits, 8);
325
326 // Store state in digest
327 encode(digest, state, 16);
328
329 // Zeroize sensitive information.
330 memset(buffer, 0, sizeof buffer);
331 memset(count, 0, sizeof count);
332
333 finalized = true;
334 }
335
336 return *this;
337 }
338
339 //////////////////////////////
340
341 // return hex representation of digest as string
342 std::string MD5::hexdigest() const
343 {
344 if (!finalized)
345 return "";
346
347 char buf[33];
348 for (int i = 0; i < 16; i++)
349 sprintf(buf + i * 2, "%02x", digest[i]);
350 buf[32] = 0;
351
352 return std::string(buf);
353 }
354
355 // return the slected number of bytes from the digest
356 void MD5::bindigest(void *buf, int len) const
357 {
358 memcpy(buf, digest, len);
359 }
360
361 //////////////////////////////
362
363 // std::string md5(const std::string str)
364 // {
365 // MD5 md5 = MD5(str);
366
367 // return md5.hexdigest();
368 // }