blob: 44aaf15f44cd4e3f97f802255222b5bd59a3eaf4 [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001// Copyright (C) 1999-2005 Open Source Telecom Corporation.
2// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
3//
4// This program is free software; you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation; either version 2 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17//
18// As a special exception, you may use this file as part of a free software
19// library without restriction. Specifically, if other files instantiate
20// templates or use macros or inline functions from this file, or you compile
21// this file and link it with other files to produce an executable, this
22// file does not by itself cause the resulting executable to be covered by
23// the GNU General Public License. This exception does not however
24// invalidate any other reasons why the executable file might be covered by
25// the GNU General Public License.
26//
27// This exception applies only to the code released under the name GNU
28// Common C++. If you copy code from other releases into a copy of GNU
29// Common C++, as the General Public License permits, the exception does
30// not apply to the code that you add in this way. To avoid misleading
31// anyone as to the status of such modified files, you must delete
32// this exception notice from them.
33//
34// If you write modifications of your own for GNU Common C++, it is your choice
35// whether to permit this exception to apply to your modifications.
36// If you do not wish that, delete this exception notice.
37//
38
39#include <cc++/config.h>
40#include <cc++/exception.h>
41#include <cc++/thread.h>
42#include <cc++/export.h>
43#include <cc++/digest.h>
44#include <cstdio>
45
46#ifdef WIN32
47#include <io.h>
48#endif
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
67#ifdef CCXX_NAMESPACES
68namespace ost {
69using namespace std;
70#endif
71
72static inline unsigned long rotate_left(unsigned long x, unsigned long n)
73{
74 // is unsigned long > 32 bit mask
75#if ~0lu != 0xfffffffflu
76 return (x << n) | ((x & 0xffffffffu) >> (32-n));
77#else
78 return (x << n) | (x >> (32-n));
79#endif
80}
81
82static inline unsigned long F(unsigned long x, unsigned long y, unsigned long z)
83{
84 return (x & y) | (~x & z);
85}
86
87static inline unsigned long G(unsigned long x, unsigned long y, unsigned long z)
88{
89 return (x & z) | (y & ~z);
90}
91
92static inline unsigned long H(unsigned long x, unsigned long y, unsigned long z)
93{
94 return x ^ y ^ z;
95}
96
97inline unsigned long I(unsigned long x, unsigned long y, unsigned long z)
98{
99 return y ^ (x | ~z);
100}
101
102
103static void FF(unsigned long &a, unsigned long b, unsigned long c, unsigned long d, unsigned long x, unsigned long s, unsigned long ac)
104{
105 a += F(b, c, d) + x + ac;
106 a = rotate_left(a, s) + b;
107}
108
109static void GG(unsigned long &a, unsigned long b, unsigned long c, unsigned long d, unsigned long x, unsigned long s, unsigned long ac)
110{
111 a += G(b, c, d) + x + ac;
112 a = rotate_left(a, s) + b;
113}
114
115static void HH(unsigned long &a, unsigned long b, unsigned long c, unsigned long d, unsigned long x, unsigned long s, unsigned long ac)
116{
117 a += H(b, c, d) + x + ac;
118 a = rotate_left(a, s) + b;
119}
120
121static void II(unsigned long &a, unsigned long b, unsigned long c, unsigned long d, unsigned long x, unsigned long s, unsigned long ac)
122{
123 a += I(b, c, d) + x + ac;
124 a = rotate_left(a, s) + b;
125}
126
127MD5Digest::MD5Digest() :
128Digest()
129{
130 initDigest();
131 updated = true;
132}
133
134void MD5Digest::initDigest(void)
135{
136 count[0] = count[1] = 0;
137 state[0] = 0x67452301;
138 state[1] = 0xefcdab89;
139 state[2] = 0x98badcfe;
140 state[3] = 0x10325476;
141 bpos = 0;
142 updated = true; // CCY Added
143 setp((char*)buf,(char*)buf+64);
144}
145
146int MD5Digest::overflow(int c)
147{
148 updated = true;
149 bpos = (unsigned)((unsigned char*)pptr() - buf);
150 if(bpos >= 64)
151 update();
152 if (c != EOF)
153 buf[bpos++] = (unsigned char)c;
154 setp((char*)buf + bpos,(char*)buf + 64);
155
156 return c;
157}
158
159void MD5Digest::update(void)
160{
161 unsigned long x[16], a, b, c, d;
162 int i;
163
164 if(!bpos)
165 return;
166
167 while(bpos < 64)
168 buf[bpos++] = 0;
169 bpos = 0;
170
171 if((count[0] += 512) < 512)
172 ++count[1];
173
174 a = state[0];
175 b = state[1];
176 c = state[2];
177 d = state[3];
178
179 for(i = 0; i < 16; ++i)
180 x[i] = (unsigned long)(buf[i * 4]) |
181 (unsigned long)(buf[i * 4 + 1] << 8) |
182 (unsigned long)(buf[i * 4 + 2] << 16) |
183 (unsigned long)(buf[i * 4 + 3] << 24);
184
185 FF(a, b, c, d, x[ 0], S11, 0xd76aa478);
186 FF(d, a, b, c, x[ 1], S12, 0xe8c7b756);
187 FF(c, d, a, b, x[ 2], S13, 0x242070db);
188 FF(b, c, d, a, x[ 3], S14, 0xc1bdceee);
189 FF(a, b, c, d, x[ 4], S11, 0xf57c0faf);
190 FF(d, a, b, c, x[ 5], S12, 0x4787c62a);
191 FF(c, d, a, b, x[ 6], S13, 0xa8304613);
192 FF(b, c, d, a, x[ 7], S14, 0xfd469501);
193 FF(a, b, c, d, x[ 8], S11, 0x698098d8);
194 FF(d, a, b, c, x[ 9], S12, 0x8b44f7af);
195 FF(c, d, a, b, x[10], S13, 0xffff5bb1);
196 FF(b, c, d, a, x[11], S14, 0x895cd7be);
197 FF(a, b, c, d, x[12], S11, 0x6b901122);
198 FF(d, a, b, c, x[13], S12, 0xfd987193);
199 FF(c, d, a, b, x[14], S13, 0xa679438e);
200 FF(b, c, d, a, x[15], S14, 0x49b40821);
201
202 GG(a, b, c, d, x[ 1], S21, 0xf61e2562);
203 GG(d, a, b, c, x[ 6], S22, 0xc040b340);
204 GG(c, d, a, b, x[11], S23, 0x265e5a51);
205 GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa);
206 GG(a, b, c, d, x[ 5], S21, 0xd62f105d);
207 GG(d, a, b, c, x[10], S22, 0x2441453);
208 GG(c, d, a, b, x[15], S23, 0xd8a1e681);
209 GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8);
210 GG(a, b, c, d, x[ 9], S21, 0x21e1cde6);
211 GG(d, a, b, c, x[14], S22, 0xc33707d6);
212 GG(c, d, a, b, x[ 3], S23, 0xf4d50d87);
213 GG(b, c, d, a, x[ 8], S24, 0x455a14ed);
214 GG(a, b, c, d, x[13], S21, 0xa9e3e905);
215 GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8);
216 GG(c, d, a, b, x[ 7], S23, 0x676f02d9);
217 GG(b, c, d, a, x[12], S24, 0x8d2a4c8a);
218
219 HH(a, b, c, d, x[ 5], S31, 0xfffa3942);
220 HH(d, a, b, c, x[ 8], S32, 0x8771f681);
221 HH(c, d, a, b, x[11], S33, 0x6d9d6122);
222 HH(b, c, d, a, x[14], S34, 0xfde5380c);
223 HH(a, b, c, d, x[ 1], S31, 0xa4beea44);
224 HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9);
225 HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60);
226 HH(b, c, d, a, x[10], S34, 0xbebfbc70);
227 HH(a, b, c, d, x[13], S31, 0x289b7ec6);
228 HH(d, a, b, c, x[ 0], S32, 0xeaa127fa);
229 HH(c, d, a, b, x[ 3], S33, 0xd4ef3085);
230 HH(b, c, d, a, x[ 6], S34, 0x4881d05);
231 HH(a, b, c, d, x[ 9], S31, 0xd9d4d039);
232 HH(d, a, b, c, x[12], S32, 0xe6db99e5);
233 HH(c, d, a, b, x[15], S33, 0x1fa27cf8);
234 HH(b, c, d, a, x[ 2], S34, 0xc4ac5665);
235
236 II(a, b, c, d, x[ 0], S41, 0xf4292244);
237 II(d, a, b, c, x[ 7], S42, 0x432aff97);
238 II(c, d, a, b, x[14], S43, 0xab9423a7);
239 II(b, c, d, a, x[ 5], S44, 0xfc93a039);
240 II(a, b, c, d, x[12], S41, 0x655b59c3);
241 II(d, a, b, c, x[ 3], S42, 0x8f0ccc92);
242 II(c, d, a, b, x[10], S43, 0xffeff47d);
243 II(b, c, d, a, x[ 1], S44, 0x85845dd1);
244 II(a, b, c, d, x[ 8], S41, 0x6fa87e4f);
245 II(d, a, b, c, x[15], S42, 0xfe2ce6e0);
246 II(c, d, a, b, x[ 6], S43, 0xa3014314);
247 II(b, c, d, a, x[13], S44, 0x4e0811a1);
248 II(a, b, c, d, x[ 4], S41, 0xf7537e82);
249 II(d, a, b, c, x[11], S42, 0xbd3af235);
250 II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb);
251 II(b, c, d, a, x[ 9], S44, 0xeb86d391);
252
253 state[0] += a;
254 state[1] += b;
255 state[2] += c;
256 state[3] += d;
257 updated = true;
258}
259
260void MD5Digest::commit(void)
261{
262 unsigned char cbuf[8];
263 unsigned long i, len;
264
265 static unsigned char pad[64]={
266 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
267 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
268 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
269
270 bpos = (unsigned)((unsigned char*)pptr() - buf);
271 if(!updated && !bpos)
272 return;
273
274 count[0] += (unsigned long)(bpos << 3);
275 if(count[0] < (unsigned long)(bpos << 3))
276 ++count[1];
277
278 for(i = 0; i < 2; ++i) {
279 cbuf[i * 4] = (unsigned char)count[i] & 0xff;
280 cbuf[i * 4 + 1] = (unsigned char)((count[i] >> 8) & 0xff);
281 cbuf[i * 4 + 2] = (unsigned char)((count[i] >> 16) & 0xff);
282 cbuf[i * 4 + 3] = (unsigned char)((count[i] >> 24) & 0xff);
283 }
284
285 i = (unsigned) ((count[0] >> 3) & 0x3f);
286 len = (i < 56) ? (56 - i) : (120 - i);
287 if(len)
288 putDigest(pad, len);
289
290 putDigest(cbuf, 8);
291
292 for(i = 0; i < 4; ++i) {
293 md5[i * 4] = (unsigned char)state[i] & 0xff;
294 md5[i * 4 + 1] = (unsigned char)((state[i] >> 8) & 0xff);
295 md5[i * 4 + 2] = (unsigned char)((state[i] >> 16) & 0xff);
296 md5[i * 4 + 3] = (unsigned char)((state[i] >> 24) & 0xff);
297 }
298 initDigest();
299}
300
301unsigned MD5Digest::getDigest(unsigned char *buffer)
302{
303 commit();
304
305 memcpy(buffer, md5, 16);
306 return 16;
307}
308
309void MD5Digest::putDigest(const unsigned char *buffer, unsigned len)
310{
311 bpos = (unsigned)((unsigned char*)pptr()-buf);
312 if(bpos >= 64)
313 update();
314 while(len--) {
315 buf[bpos++] = *(buffer++);
316 if(bpos >= 64)
317 update();
318 }
319 setp((char*)buf+bpos,(char*)buf+64);
320}
321
322ostream &MD5Digest::strDigest(ostream &os)
323{
324 char dbuf[36];
325 int i;
326
327 commit();
328
329 for(i = 0; i < 16; ++i)
330 sprintf(dbuf + 2 * i, "%02x", md5[i]);
331 os << dbuf;
332 return os;
333}
334
335#ifdef CCXX_NAMESPACES
336}
337#endif
338