1 /*
2    Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org>
3    Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org>
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU Lesser General Public License (LGPL)
7    version 2 as published by the Free Software Foundation.
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 Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 
18    RFC 1321 "MD5 Message-Digest Algorithm" Copyright (C) 1991-1992.             // krazy:exclude=copyright
19    RSA Data Security, Inc. Created 1991. All rights reserved.
20 
21    The KMD5 class is based on a C++ implementation of
22    "RSA Data Security, Inc. MD5 Message-Digest Algorithm" by
23    Mordechai T. Abzug,  Copyright (c) 1995.  This implementation                // krazy:exclude=copyright
24    passes the test-suite as defined in RFC 1321.
25 
26    The encoding and decoding utilities in KCodecs with the exception of
27    quoted-printable are based on the java implementation in HTTPClient
28    package by Ronald Tschalär Copyright (C) 1996-1999.                          // krazy:exclude=copyright
29 
30    The quoted-printable codec as described in RFC 2045, section 6.7. is by
31    Rik Hemsley (C) 2001.
32 */
33 
34 #include "kmd5.h"
35 
36 #include <stdio.h>
37 #include <string.h>
38 #include <stdlib.h>
39 
40 #include <QDebug>
41 #include <QIODevice>
42 #include <QTextCodec>
43 
44 #define KMD5_S11 7
45 #define KMD5_S12 12
46 #define KMD5_S13 17
47 #define KMD5_S14 22
48 #define KMD5_S21 5
49 #define KMD5_S22 9
50 #define KMD5_S23 14
51 #define KMD5_S24 20
52 #define KMD5_S31 4
53 #define KMD5_S32 11
54 #define KMD5_S33 16
55 #define KMD5_S34 23
56 #define KMD5_S41 6
57 #define KMD5_S42 10
58 #define KMD5_S43 15
59 #define KMD5_S44 21
60 
KMD5()61 KMD5::KMD5()
62 {
63     init();
64 }
65 
KMD5(const char * in,int len)66 KMD5::KMD5(const char *in, int len)
67 {
68     init();
69     update(in, len);
70 }
71 
KMD5(const QByteArray & in)72 KMD5::KMD5(const QByteArray &in)
73 {
74     init();
75     update(in);
76 }
77 
~KMD5()78 KMD5::~KMD5()
79 {
80 }
81 
update(const QByteArray & in)82 void KMD5::update(const QByteArray &in)
83 {
84     update(in.data(), int(in.size()));
85 }
86 
update(const char * in,int len)87 void KMD5::update(const char *in, int len)
88 {
89     update(reinterpret_cast<const unsigned char *>(in), len);
90 }
91 
update(const unsigned char * in,int len)92 void KMD5::update(const unsigned char *in, int len)
93 {
94     if (len < 0) {
95         len = qstrlen(reinterpret_cast<const char *>(in));
96     }
97 
98     if (!len) {
99         return;
100     }
101 
102     if (m_finalized) {
103         qWarning() << "KMD5::update called after state was finalized!";
104         return;
105     }
106 
107     quint32 in_index;
108     quint32 buffer_index;
109     quint32 buffer_space;
110     quint32 in_length = static_cast<quint32>(len);
111 
112     buffer_index = static_cast<quint32>((m_count[0] >> 3) & 0x3F);
113 
114     if ((m_count[0] += (in_length << 3)) < (in_length << 3)) {
115         m_count[1]++;
116     }
117 
118     m_count[1] += (in_length >> 29);
119     buffer_space = 64 - buffer_index;
120 
121     if (in_length >= buffer_space) {
122         memcpy(m_buffer + buffer_index, in, buffer_space);
123         transform(m_buffer);
124 
125         for (in_index = buffer_space; in_index + 63 < in_length;
126                 in_index += 64) {
127             transform(reinterpret_cast<const unsigned char *>(in + in_index));
128         }
129 
130         buffer_index = 0;
131     } else {
132         in_index = 0;
133     }
134 
135     memcpy(m_buffer + buffer_index, in + in_index, in_length - in_index);
136 }
137 
update(QIODevice & file)138 bool KMD5::update(QIODevice &file)
139 {
140     char buffer[1024];
141     int len;
142 
143     while ((len = file.read(buffer, sizeof(buffer))) > 0) {
144         update(buffer, len);
145     }
146 
147     return file.atEnd();
148 }
149 
finalize()150 void KMD5::finalize()
151 {
152     if (m_finalized) {
153         return;
154     }
155 
156     quint8 bits[8];
157     quint32 index, padLen;
158     static const unsigned char PADDING[64] = {
159         0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
160         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
161         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
162         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
163     };
164 
165     encode(bits, m_count, 8);
166     //memcpy( bits, m_count, 8 );
167 
168     // Pad out to 56 mod 64.
169     index = static_cast<quint32>((m_count[0] >> 3) & 0x3f);
170     padLen = (index < 56) ? (56 - index) : (120 - index);
171     update(reinterpret_cast<const char *>(PADDING), padLen);
172 
173     // Append length (before padding)
174     update(reinterpret_cast<const char *>(bits), 8);
175 
176     // Store state in digest
177     encode(m_digest, m_state, 16);
178     //memcpy( m_digest, m_state, 16 );
179 
180     // Fill sensitive information with zero's
181     memset((void *)m_buffer, 0, sizeof(*m_buffer));
182 
183     m_finalized = true;
184 }
185 
verify(const KMD5::Digest & digest)186 bool KMD5::verify(const KMD5::Digest &digest)
187 {
188     finalize();
189     return (0 == memcmp(rawDigest(), digest, sizeof(KMD5::Digest)));
190 }
191 
verify(const QByteArray & hexdigest)192 bool KMD5::verify(const QByteArray &hexdigest)
193 {
194     finalize();
195     return (0 == strcmp(hexDigest().data(), hexdigest.data()));
196 }
197 
rawDigest()198 const KMD5::Digest &KMD5::rawDigest()
199 {
200     finalize();
201     return m_digest;
202 }
203 
rawDigest(KMD5::Digest & bin)204 void KMD5::rawDigest(KMD5::Digest &bin)
205 {
206     finalize();
207     memcpy(bin, m_digest, 16);
208 }
209 
hexDigest()210 QByteArray KMD5::hexDigest()
211 {
212     QByteArray s(32, 0);
213 
214     finalize();
215     sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
216             m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
217             m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
218             m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
219 
220     return s;
221 }
222 
hexDigest(QByteArray & s)223 void KMD5::hexDigest(QByteArray &s)
224 {
225     finalize();
226     s.resize(32);
227     sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
228             m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
229             m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
230             m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
231 }
232 
base64Digest()233 QByteArray KMD5::base64Digest()
234 {
235     finalize();
236     return QByteArray::fromRawData(reinterpret_cast<const char *>(m_digest), 16).toBase64();
237 }
238 
init()239 void KMD5::init()
240 {
241     d = nullptr;
242     reset();
243 }
244 
reset()245 void KMD5::reset()
246 {
247     m_finalized = false;
248 
249     m_count[0] = 0;
250     m_count[1] = 0;
251 
252     m_state[0] = 0x67452301;
253     m_state[1] = 0xefcdab89;
254     m_state[2] = 0x98badcfe;
255     m_state[3] = 0x10325476;
256 
257     memset(m_buffer, 0, sizeof(*m_buffer));
258     memset(m_digest, 0, sizeof(*m_digest));
259 }
260 
transform(const unsigned char block[64])261 void KMD5::transform(const unsigned char block[64])
262 {
263 
264     quint32 a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3], x[16];
265 
266     decode(x, block, 64);
267     //memcpy( x, block, 64 );
268 
269     Q_ASSERT(!m_finalized);  // not just a user error, since the method is private
270 
271     /* Round 1 */
272     FF(a, b, c, d, x[ 0], KMD5_S11, 0xd76aa478);  /* 1 */
273     FF(d, a, b, c, x[ 1], KMD5_S12, 0xe8c7b756);  /* 2 */
274     FF(c, d, a, b, x[ 2], KMD5_S13, 0x242070db);  /* 3 */
275     FF(b, c, d, a, x[ 3], KMD5_S14, 0xc1bdceee);  /* 4 */
276     FF(a, b, c, d, x[ 4], KMD5_S11, 0xf57c0faf);  /* 5 */
277     FF(d, a, b, c, x[ 5], KMD5_S12, 0x4787c62a);  /* 6 */
278     FF(c, d, a, b, x[ 6], KMD5_S13, 0xa8304613);  /* 7 */
279     FF(b, c, d, a, x[ 7], KMD5_S14, 0xfd469501);  /* 8 */
280     FF(a, b, c, d, x[ 8], KMD5_S11, 0x698098d8);  /* 9 */
281     FF(d, a, b, c, x[ 9], KMD5_S12, 0x8b44f7af);  /* 10 */
282     FF(c, d, a, b, x[10], KMD5_S13, 0xffff5bb1);  /* 11 */
283     FF(b, c, d, a, x[11], KMD5_S14, 0x895cd7be);  /* 12 */
284     FF(a, b, c, d, x[12], KMD5_S11, 0x6b901122);  /* 13 */
285     FF(d, a, b, c, x[13], KMD5_S12, 0xfd987193);  /* 14 */
286     FF(c, d, a, b, x[14], KMD5_S13, 0xa679438e);  /* 15 */
287     FF(b, c, d, a, x[15], KMD5_S14, 0x49b40821);  /* 16 */
288 
289     /* Round 2 */
290     GG(a, b, c, d, x[ 1], KMD5_S21, 0xf61e2562);  /* 17 */
291     GG(d, a, b, c, x[ 6], KMD5_S22, 0xc040b340);  /* 18 */
292     GG(c, d, a, b, x[11], KMD5_S23, 0x265e5a51);  /* 19 */
293     GG(b, c, d, a, x[ 0], KMD5_S24, 0xe9b6c7aa);  /* 20 */
294     GG(a, b, c, d, x[ 5], KMD5_S21, 0xd62f105d);  /* 21 */
295     GG(d, a, b, c, x[10], KMD5_S22,  0x2441453);  /* 22 */
296     GG(c, d, a, b, x[15], KMD5_S23, 0xd8a1e681);  /* 23 */
297     GG(b, c, d, a, x[ 4], KMD5_S24, 0xe7d3fbc8);  /* 24 */
298     GG(a, b, c, d, x[ 9], KMD5_S21, 0x21e1cde6);  /* 25 */
299     GG(d, a, b, c, x[14], KMD5_S22, 0xc33707d6);  /* 26 */
300     GG(c, d, a, b, x[ 3], KMD5_S23, 0xf4d50d87);  /* 27 */
301     GG(b, c, d, a, x[ 8], KMD5_S24, 0x455a14ed);  /* 28 */
302     GG(a, b, c, d, x[13], KMD5_S21, 0xa9e3e905);  /* 29 */
303     GG(d, a, b, c, x[ 2], KMD5_S22, 0xfcefa3f8);  /* 30 */
304     GG(c, d, a, b, x[ 7], KMD5_S23, 0x676f02d9);  /* 31 */
305     GG(b, c, d, a, x[12], KMD5_S24, 0x8d2a4c8a);  /* 32 */
306 
307     /* Round 3 */
308     HH(a, b, c, d, x[ 5], KMD5_S31, 0xfffa3942);  /* 33 */
309     HH(d, a, b, c, x[ 8], KMD5_S32, 0x8771f681);  /* 34 */
310     HH(c, d, a, b, x[11], KMD5_S33, 0x6d9d6122);  /* 35 */
311     HH(b, c, d, a, x[14], KMD5_S34, 0xfde5380c);  /* 36 */
312     HH(a, b, c, d, x[ 1], KMD5_S31, 0xa4beea44);  /* 37 */
313     HH(d, a, b, c, x[ 4], KMD5_S32, 0x4bdecfa9);  /* 38 */
314     HH(c, d, a, b, x[ 7], KMD5_S33, 0xf6bb4b60);  /* 39 */
315     HH(b, c, d, a, x[10], KMD5_S34, 0xbebfbc70);  /* 40 */
316     HH(a, b, c, d, x[13], KMD5_S31, 0x289b7ec6);  /* 41 */
317     HH(d, a, b, c, x[ 0], KMD5_S32, 0xeaa127fa);  /* 42 */
318     HH(c, d, a, b, x[ 3], KMD5_S33, 0xd4ef3085);  /* 43 */
319     HH(b, c, d, a, x[ 6], KMD5_S34,  0x4881d05);  /* 44 */
320     HH(a, b, c, d, x[ 9], KMD5_S31, 0xd9d4d039);  /* 45 */
321     HH(d, a, b, c, x[12], KMD5_S32, 0xe6db99e5);  /* 46 */
322     HH(c, d, a, b, x[15], KMD5_S33, 0x1fa27cf8);  /* 47 */
323     HH(b, c, d, a, x[ 2], KMD5_S34, 0xc4ac5665);  /* 48 */
324 
325     /* Round 4 */
326     II(a, b, c, d, x[ 0], KMD5_S41, 0xf4292244);  /* 49 */
327     II(d, a, b, c, x[ 7], KMD5_S42, 0x432aff97);  /* 50 */
328     II(c, d, a, b, x[14], KMD5_S43, 0xab9423a7);  /* 51 */
329     II(b, c, d, a, x[ 5], KMD5_S44, 0xfc93a039);  /* 52 */
330     II(a, b, c, d, x[12], KMD5_S41, 0x655b59c3);  /* 53 */
331     II(d, a, b, c, x[ 3], KMD5_S42, 0x8f0ccc92);  /* 54 */
332     II(c, d, a, b, x[10], KMD5_S43, 0xffeff47d);  /* 55 */
333     II(b, c, d, a, x[ 1], KMD5_S44, 0x85845dd1);  /* 56 */
334     II(a, b, c, d, x[ 8], KMD5_S41, 0x6fa87e4f);  /* 57 */
335     II(d, a, b, c, x[15], KMD5_S42, 0xfe2ce6e0);  /* 58 */
336     II(c, d, a, b, x[ 6], KMD5_S43, 0xa3014314);  /* 59 */
337     II(b, c, d, a, x[13], KMD5_S44, 0x4e0811a1);  /* 60 */
338     II(a, b, c, d, x[ 4], KMD5_S41, 0xf7537e82);  /* 61 */
339     II(d, a, b, c, x[11], KMD5_S42, 0xbd3af235);  /* 62 */
340     II(c, d, a, b, x[ 2], KMD5_S43, 0x2ad7d2bb);  /* 63 */
341     II(b, c, d, a, x[ 9], KMD5_S44, 0xeb86d391);  /* 64 */
342 
343     m_state[0] += a;
344     m_state[1] += b;
345     m_state[2] += c;
346     m_state[3] += d;
347 
348     memset(static_cast<void *>(x), 0, sizeof(x));
349 }
350 
rotate_left(quint32 x,quint32 n)351 inline quint32 KMD5::rotate_left(quint32 x, quint32 n)
352 {
353     return (x << n) | (x >> (32 - n));
354 }
355 
F(quint32 x,quint32 y,quint32 z)356 inline quint32 KMD5::F(quint32 x, quint32 y, quint32 z)
357 {
358     return (x & y) | (~x & z);
359 }
360 
G(quint32 x,quint32 y,quint32 z)361 inline quint32 KMD5::G(quint32 x, quint32 y, quint32 z)
362 {
363     return (x & z) | (y & ~z);
364 }
365 
H(quint32 x,quint32 y,quint32 z)366 inline quint32 KMD5::H(quint32 x, quint32 y, quint32 z)
367 {
368     return x ^ y ^ z;
369 }
370 
I(quint32 x,quint32 y,quint32 z)371 inline quint32 KMD5::I(quint32 x, quint32 y, quint32 z)
372 {
373     return y ^ (x | ~z);
374 }
375 
FF(quint32 & a,quint32 b,quint32 c,quint32 d,quint32 x,quint32 s,quint32 ac)376 void KMD5::FF(quint32 &a, quint32 b, quint32 c, quint32 d,
377               quint32 x, quint32  s, quint32 ac)
378 {
379     a += F(b, c, d) + x + ac;
380     a = rotate_left(a, s) + b;
381 }
382 
GG(quint32 & a,quint32 b,quint32 c,quint32 d,quint32 x,quint32 s,quint32 ac)383 void KMD5::GG(quint32 &a, quint32 b, quint32 c, quint32 d,
384               quint32 x, quint32 s, quint32 ac)
385 {
386     a += G(b, c, d) + x + ac;
387     a = rotate_left(a, s) + b;
388 }
389 
HH(quint32 & a,quint32 b,quint32 c,quint32 d,quint32 x,quint32 s,quint32 ac)390 void KMD5::HH(quint32 &a, quint32 b, quint32 c, quint32 d,
391               quint32 x, quint32 s, quint32 ac)
392 {
393     a += H(b, c, d) + x + ac;
394     a = rotate_left(a, s) + b;
395 }
396 
II(quint32 & a,quint32 b,quint32 c,quint32 d,quint32 x,quint32 s,quint32 ac)397 void KMD5::II(quint32 &a, quint32 b, quint32 c, quint32 d,
398               quint32 x, quint32 s, quint32 ac)
399 {
400     a += I(b, c, d) + x + ac;
401     a = rotate_left(a, s) + b;
402 }
403 
encode(unsigned char * output,quint32 * in,quint32 len)404 void KMD5::encode(unsigned char *output, quint32 *in, quint32 len)
405 {
406 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
407     memcpy(output, in, len);
408 #else
409     quint32 i, j;
410     for (i = 0, j = 0; j < len; i++, j += 4) {
411         output[j]   = static_cast<quint8>((in[i] & 0xff));
412         output[j + 1] = static_cast<quint8>(((in[i] >> 8) & 0xff));
413         output[j + 2] = static_cast<quint8>(((in[i] >> 16) & 0xff));
414         output[j + 3] = static_cast<quint8>(((in[i] >> 24) & 0xff));
415     }
416 #endif
417 }
418 
419 // Decodes in (quint8) into output (quint32). Assumes len is a
420 // multiple of 4.
decode(quint32 * output,const unsigned char * in,quint32 len)421 void KMD5::decode(quint32 *output, const unsigned char *in, quint32 len)
422 {
423 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
424     memcpy(output, in, len);
425 
426 #else
427     quint32 i, j;
428     for (i = 0, j = 0; j < len; i++, j += 4)
429         output[i] = static_cast<quint32>(in[j]) |
430                     (static_cast<quint32>(in[j + 1]) << 8)  |
431                     (static_cast<quint32>(in[j + 2]) << 16) |
432                     (static_cast<quint32>(in[j + 3]) << 24);
433 #endif
434 }
435 
436 /**************************************************************/
437