1 /* Copyright (C) 2014 InfiniDB, Inc.
2 
3    This program is free software; you can redistribute it and/or
4    modify it under the terms of the GNU General Public License
5    as published by the Free Software Foundation; version 2 of
6    the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16    MA 02110-1301, USA. */
17 
18 /****************************************************************************
19 * $Id: func_md5.cpp 3923 2013-06-19 21:43:06Z bwilkinson $
20 *
21 *
22 ****************************************************************************/
23 #include <assert.h>
24 #include <memory.h>
25 #include <stdio.h>
26 #include <string.h>
27 
28 
29 #include <cstdlib>
30 #include <string>
31 #include <unistd.h>
32 #include <limits.h>
33 using namespace std;
34 
35 #include "functor_str.h"
36 #include "functioncolumn.h"
37 using namespace execplan;
38 
39 #include "rowgroup.h"
40 using namespace rowgroup;
41 
42 namespace
43 {
44 /////////////////////////////////////////////////////////////////////////
45 // MD5.cpp
46 // Implementation file for MD5 class
47 //
48 // This C++ Class implementation of the original RSA Data Security, Inc.
49 // MD5 Message-Digest Algorithm is copyright (c) 2002, Gary McNickle.
50 // All rights reserved.  This software is a derivative of the "RSA Data
51 //  Security, Inc. MD5 Message-Digest Algorithm"
52 //
53 // You may use this software free of any charge, but without any
54 // warranty or implied warranty, provided that you follow the terms
55 // of the original RSA copyright, listed below.
56 //
57 // Original RSA Data Security, Inc. Copyright notice
58 /////////////////////////////////////////////////////////////////////////
59 //
60 // Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
61 // rights reserved.
62 //
63 // License to copy and use this software is granted provided that it
64 // is identified as the "RSA Data Security, Inc. MD5 Message-Digest
65 // Algorithm" in all material mentioning or referencing this software
66 // or this function.
67 // License is also granted to make and use derivative works provided
68 // that such works are identified as "derived from the RSA Data
69 // Security, Inc. MD5 Message-Digest Algorithm" in all material
70 // mentioning or referencing the derived work.
71 // RSA Data Security, Inc. makes no representations concerning either
72 // the merchantability of this software or the suitability of this
73 // software for any particular purpose. It is provided "as is"
74 // without express or implied warranty of any kind.
75 // These notices must be retained in any copies of any part of this
76 // documentation and/or software.
77 /////////////////////////////////////////////////////////////////////////
78 
79 typedef unsigned       int uint4;
80 typedef unsigned short int uint2;
81 typedef unsigned      char uchar;
82 
83 char* PrintMD5(uchar md5Digest[16]);
84 char* MD5String(const char* szString);
85 //char* MD5File(char* szFilename);
86 
87 class md5
88 {
89 // Methods
90 public:
md5()91     md5()
92     {
93         Init();
94     }
95     void	Init();
96     void	Update(uchar* chInput, uint4 nInputLen);
97     void	Finalize();
Digest()98     uchar*	Digest()
99     {
100         return m_Digest;
101     }
102 
103 private:
104 
105     void	Transform(uchar* block);
106     void	Encode(uchar* dest, uint4* src, uint4 nLength);
107     void	Decode(uint4* dest, uchar* src, uint4 nLength);
108 
109 
rotate_left(uint4 x,uint4 n)110     inline	uint4	rotate_left(uint4 x, uint4 n)
111     {
112         return ((x << n) | (x >> (32 - n)));
113     }
114 
F(uint4 x,uint4 y,uint4 z)115     inline	uint4	F(uint4 x, uint4 y, uint4 z)
116     {
117         return ((x & y) | (~x & z));
118     }
119 
G(uint4 x,uint4 y,uint4 z)120     inline  uint4	G(uint4 x, uint4 y, uint4 z)
121     {
122         return ((x & z) | (y & ~z));
123     }
124 
H(uint4 x,uint4 y,uint4 z)125     inline  uint4	H(uint4 x, uint4 y, uint4 z)
126     {
127         return (x ^ y ^ z);
128     }
129 
I(uint4 x,uint4 y,uint4 z)130     inline  uint4	I(uint4 x, uint4 y, uint4 z)
131     {
132         return (y ^ (x | ~z));
133     }
134 
FF(uint4 & a,uint4 b,uint4 c,uint4 d,uint4 x,uint4 s,uint4 ac)135     inline	void	FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
136     {
137         a += F(b, c, d) + x + ac;
138         a = rotate_left(a, s);
139         a += b;
140     }
141 
GG(uint4 & a,uint4 b,uint4 c,uint4 d,uint4 x,uint4 s,uint4 ac)142     inline	void	GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
143     {
144         a += G(b, c, d) + x + ac;
145         a = rotate_left(a, s);
146         a += b;
147     }
148 
HH(uint4 & a,uint4 b,uint4 c,uint4 d,uint4 x,uint4 s,uint4 ac)149     inline	void	HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
150     {
151         a += H(b, c, d) + x + ac;
152         a = rotate_left(a, s);
153         a += b;
154     }
155 
II(uint4 & a,uint4 b,uint4 c,uint4 d,uint4 x,uint4 s,uint4 ac)156     inline	void	II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac)
157     {
158         a += I(b, c, d) + x + ac;
159         a = rotate_left(a, s);
160         a += b;
161     }
162 
163 // Data
164 private:
165     uint4		m_State[4];
166     uint4		m_Count[2];
167     uchar		m_Buffer[64];
168     uchar		m_Digest[16];
169     uchar		m_Finalized;
170 
171 };
172 
173 /////////////////////////////////////////////////////////////////////////
174 // MD5.cpp
175 // Implementation file for MD5 class
176 //
177 // This C++ Class implementation of the original RSA Data Security, Inc.
178 // MD5 Message-Digest Algorithm is copyright (c) 2002, Gary McNickle.
179 // All rights reserved.  This software is a derivative of the "RSA Data
180 //  Security, Inc. MD5 Message-Digest Algorithm"
181 //
182 // You may use this software free of any charge, but without any
183 // warranty or implied warranty, provided that you follow the terms
184 // of the original RSA copyright, listed below.
185 //
186 // Original RSA Data Security, Inc. Copyright notice
187 /////////////////////////////////////////////////////////////////////////
188 //
189 // Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
190 // rights reserved.
191 //
192 // License to copy and use this software is granted provided that it
193 // is identified as the "RSA Data Security, Inc. MD5 Message-Digest
194 // Algorithm" in all material mentioning or referencing this software
195 // or this function.
196 // License is also granted to make and use derivative works provided
197 // that such works are identified as "derived from the RSA Data
198 // Security, Inc. MD5 Message-Digest Algorithm" in all material
199 // mentioning or referencing the derived work.
200 // RSA Data Security, Inc. makes no representations concerning either
201 // the merchantability of this software or the suitability of this
202 // software for any particular purpose. It is provided "as is"
203 // without express or implied warranty of any kind.
204 // These notices must be retained in any copies of any part of this
205 // documentation and/or software.
206 /////////////////////////////////////////////////////////////////////////
207 
208 static unsigned char PADDING[64] =
209 {
210     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
211     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
212     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
213 };
214 
215 #define S11 7
216 #define S12 12
217 #define S13 17
218 #define S14 22
219 #define S21 5
220 #define S22 9
221 #define S23 14
222 #define S24 20
223 #define S31 4
224 #define S32 11
225 #define S33 16
226 #define S34 23
227 #define S41 6
228 #define S42 10
229 #define S43 15
230 #define S44 21
231 
232 
233 // PrintMD5: Converts a completed md5 digest into a char* string.
PrintMD5(uchar md5Digest[16])234 char* PrintMD5(uchar md5Digest[16])
235 {
236     char chBuffer[256];
237     char chEach[10];
238     int nCount;
239     size_t chEachSize = 0;
240 
241     memset(chBuffer, 0, 256);
242     memset(chEach, 0, 10);
243 
244     for (nCount = 0; nCount < 16; nCount++)
245     {
246         sprintf(chEach, "%02x", md5Digest[nCount]);
247         chEachSize = sizeof(chEach);
248         strncat(chBuffer, chEach, chEachSize);
249     }
250 
251     return strdup(chBuffer);
252 }
253 
254 // MD5String: Performs the MD5 algorithm on a char* string, returning
255 // the results as a char*.
MD5String(const char * szString)256 char* MD5String(const char* szString)
257 {
258     int nLen = strlen(szString);
259     md5 alg;
260 
261     alg.Update((unsigned char*)szString, (unsigned int)nLen);
262     alg.Finalize();
263 
264     return PrintMD5(alg.Digest());
265 
266 }
267 
268 // this fcn isn't used, so commenting it
269 #if 0
270 // MD5File: Performs the MD5 algorithm on a file (binary or text),
271 // returning the results as a char*.  Returns NULL if it fails.
272 char* MD5File(char* szFilename)
273 {
274     FILE* file;
275     md5 alg;
276     int nLen;
277     unsigned char chBuffer[1024];
278 
279     try
280     {
281         memset(chBuffer, 0, 1024);
282 
283         if ((file = fopen (szFilename, "rb")) != NULL)
284         {
285             while ((nLen = fread (chBuffer, 1, 1024, file)))
286                 alg.Update(chBuffer, nLen);
287 
288             alg.Finalize();
289 
290             fclose (file);
291 
292             return PrintMD5(alg.Digest());
293         }
294     }
295     catch (...)
296     {
297 
298     }
299 
300     return NULL; // failed
301 }
302 #endif
303 
304 // md5::Init
305 // Initializes a new context.
Init()306 void md5::Init()
307 {
308     memset(m_Count, 0, 2 * sizeof(uint4));
309 
310     m_State[0] = 0x67452301;
311     m_State[1] = 0xefcdab89;
312     m_State[2] = 0x98badcfe;
313     m_State[3] = 0x10325476;
314 }
315 
316 // md5::Update
317 // MD5 block update operation. Continues an MD5 message-digest
318 // operation, processing another message block, and updating the
319 // context.
Update(uchar * chInput,uint4 nInputLen)320 void md5::Update(uchar* chInput, uint4 nInputLen)
321 {
322     uint4 i, index, partLen;
323 
324     // Compute number of bytes mod 64
325     index = (unsigned int)((m_Count[0] >> 3) & 0x3F);
326 
327     // Update number of bits
328     if ((m_Count[0] += (nInputLen << 3)) < (nInputLen << 3))
329         m_Count[1]++;
330 
331     m_Count[1] += (nInputLen >> 29);
332 
333     partLen = 64 - index;
334 
335     // Transform as many times as possible.
336     if (nInputLen >= partLen)
337     {
338         memcpy( &m_Buffer[index], chInput, partLen );
339         Transform(m_Buffer);
340 
341         for (i = partLen; i + 63 < nInputLen; i += 64)
342             Transform(&chInput[i]);
343 
344         index = 0;
345     }
346     else
347         i = 0;
348 
349     // Buffer remaining input
350     memcpy( &m_Buffer[index], &chInput[i], nInputLen - i );
351 }
352 
353 // md5::Finalize
354 // MD5 finalization. Ends an MD5 message-digest operation, writing
355 // the message digest and zeroizing the context.
Finalize()356 void md5::Finalize()
357 {
358     uchar bits[8];
359     uint4 index, padLen;
360 
361     // Save number of bits
362     Encode (bits, m_Count, 8);
363 
364     // Pad out to 56 mod 64
365     index = (unsigned int)((m_Count[0] >> 3) & 0x3f);
366     padLen = (index < 56) ? (56 - index) : (120 - index);
367     Update(PADDING, padLen);
368 
369     // Append length (before padding)
370     Update (bits, 8);
371 
372     // Store state in digest
373     Encode (m_Digest, m_State, 16);
374 
375     memset(m_Count, 0, 2 * sizeof(uint4));
376     memset(m_State, 0, 4 * sizeof(uint4));
377     memset(m_Buffer, 0, 64 * sizeof(uchar));
378 }
379 
380 // md5::Transform
381 // MD5 basic transformation. Transforms state based on block.
Transform(uchar * block)382 void md5::Transform (uchar* block)
383 {
384     uint4 a = m_State[0], b = m_State[1], c = m_State[2], d = m_State[3], x[16];
385 
386     Decode (x, block, 64);
387 
388     // Round 1
389     FF (a, b, c, d, x[ 0], S11, 0xd76aa478);
390     FF (d, a, b, c, x[ 1], S12, 0xe8c7b756);
391     FF (c, d, a, b, x[ 2], S13, 0x242070db);
392     FF (b, c, d, a, x[ 3], S14, 0xc1bdceee);
393     FF (a, b, c, d, x[ 4], S11, 0xf57c0faf);
394     FF (d, a, b, c, x[ 5], S12, 0x4787c62a);
395     FF (c, d, a, b, x[ 6], S13, 0xa8304613);
396     FF (b, c, d, a, x[ 7], S14, 0xfd469501);
397     FF (a, b, c, d, x[ 8], S11, 0x698098d8);
398     FF (d, a, b, c, x[ 9], S12, 0x8b44f7af);
399     FF (c, d, a, b, x[10], S13, 0xffff5bb1);
400     FF (b, c, d, a, x[11], S14, 0x895cd7be);
401     FF (a, b, c, d, x[12], S11, 0x6b901122);
402     FF (d, a, b, c, x[13], S12, 0xfd987193);
403     FF (c, d, a, b, x[14], S13, 0xa679438e);
404     FF (b, c, d, a, x[15], S14, 0x49b40821);
405 
406 // Round 2
407     GG (a, b, c, d, x[ 1], S21, 0xf61e2562);
408     GG (d, a, b, c, x[ 6], S22, 0xc040b340);
409     GG (c, d, a, b, x[11], S23, 0x265e5a51);
410     GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa);
411     GG (a, b, c, d, x[ 5], S21, 0xd62f105d);
412     GG (d, a, b, c, x[10], S22,  0x2441453);
413     GG (c, d, a, b, x[15], S23, 0xd8a1e681);
414     GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8);
415     GG (a, b, c, d, x[ 9], S21, 0x21e1cde6);
416     GG (d, a, b, c, x[14], S22, 0xc33707d6);
417     GG (c, d, a, b, x[ 3], S23, 0xf4d50d87);
418     GG (b, c, d, a, x[ 8], S24, 0x455a14ed);
419     GG (a, b, c, d, x[13], S21, 0xa9e3e905);
420     GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8);
421     GG (c, d, a, b, x[ 7], S23, 0x676f02d9);
422     GG (b, c, d, a, x[12], S24, 0x8d2a4c8a);
423 
424     // Round 3
425     HH (a, b, c, d, x[ 5], S31, 0xfffa3942);
426     HH (d, a, b, c, x[ 8], S32, 0x8771f681);
427     HH (c, d, a, b, x[11], S33, 0x6d9d6122);
428     HH (b, c, d, a, x[14], S34, 0xfde5380c);
429     HH (a, b, c, d, x[ 1], S31, 0xa4beea44);
430     HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9);
431     HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60);
432     HH (b, c, d, a, x[10], S34, 0xbebfbc70);
433     HH (a, b, c, d, x[13], S31, 0x289b7ec6);
434     HH (d, a, b, c, x[ 0], S32, 0xeaa127fa);
435     HH (c, d, a, b, x[ 3], S33, 0xd4ef3085);
436     HH (b, c, d, a, x[ 6], S34,  0x4881d05);
437     HH (a, b, c, d, x[ 9], S31, 0xd9d4d039);
438     HH (d, a, b, c, x[12], S32, 0xe6db99e5);
439     HH (c, d, a, b, x[15], S33, 0x1fa27cf8);
440     HH (b, c, d, a, x[ 2], S34, 0xc4ac5665);
441 
442     // Round 4
443     II (a, b, c, d, x[ 0], S41, 0xf4292244);
444     II (d, a, b, c, x[ 7], S42, 0x432aff97);
445     II (c, d, a, b, x[14], S43, 0xab9423a7);
446     II (b, c, d, a, x[ 5], S44, 0xfc93a039);
447     II (a, b, c, d, x[12], S41, 0x655b59c3);
448     II (d, a, b, c, x[ 3], S42, 0x8f0ccc92);
449     II (c, d, a, b, x[10], S43, 0xffeff47d);
450     II (b, c, d, a, x[ 1], S44, 0x85845dd1);
451     II (a, b, c, d, x[ 8], S41, 0x6fa87e4f);
452     II (d, a, b, c, x[15], S42, 0xfe2ce6e0);
453     II (c, d, a, b, x[ 6], S43, 0xa3014314);
454     II (b, c, d, a, x[13], S44, 0x4e0811a1);
455     II (a, b, c, d, x[ 4], S41, 0xf7537e82);
456     II (d, a, b, c, x[11], S42, 0xbd3af235);
457     II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb);
458     II (b, c, d, a, x[ 9], S44, 0xeb86d391);
459 
460     m_State[0] += a;
461     m_State[1] += b;
462     m_State[2] += c;
463     m_State[3] += d;
464 
465     memset(x, 0, sizeof(x));
466 }
467 
468 // md5::Encode
469 // Encodes input (uint4) into output (uchar). Assumes nLength is
470 // a multiple of 4.
Encode(uchar * dest,uint4 * src,uint4 nLength)471 void md5::Encode(uchar* dest, uint4* src, uint4 nLength)
472 {
473     uint4 i, j;
474 
475     idbassert(nLength % 4 == 0);
476 
477     for (i = 0, j = 0; j < nLength; i++, j += 4)
478     {
479         dest[j] = (uchar)(src[i] & 0xff);
480         dest[j + 1] = (uchar)((src[i] >> 8) & 0xff);
481         dest[j + 2] = (uchar)((src[i] >> 16) & 0xff);
482         dest[j + 3] = (uchar)((src[i] >> 24) & 0xff);
483     }
484 }
485 
486 // md5::Decode
487 // Decodes input (uchar) into output (uint4). Assumes nLength is
488 // a multiple of 4.
Decode(uint4 * dest,uchar * src,uint4 nLength)489 void md5::Decode(uint4* dest, uchar* src, uint4 nLength)
490 {
491     uint4 i, j;
492 
493     idbassert(nLength % 4 == 0);
494 
495     for (i = 0, j = 0; j < nLength; i++, j += 4)
496     {
497         dest[i] = ((uint4)src[j]) | (((uint4)src[j + 1]) << 8) |
498                   (((uint4)src[j + 2]) << 16) | (((uint4)src[j + 3]) << 24);
499     }
500 }
501 
502 }
503 
504 
505 namespace funcexp
506 {
operationType(FunctionParm & fp,CalpontSystemCatalog::ColType & resultType)507 CalpontSystemCatalog::ColType Func_md5::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType)
508 {
509     // operation type is not used by this functor
510     return fp[0]->data()->resultType();
511 }
512 
513 
getStrVal(rowgroup::Row & row,FunctionParm & parm,bool & isNull,CalpontSystemCatalog::ColType & op_ct)514 string Func_md5::getStrVal(rowgroup::Row& row,
515                            FunctionParm& parm,
516                            bool& isNull,
517                            CalpontSystemCatalog::ColType& op_ct)
518 {
519     const string& arg = parm[0]->data()->getStrVal(row, isNull);
520     return MD5String(arg.c_str());
521 
522     //return str;
523 }
524 
525 
526 } // namespace funcexp
527 
528 
529 // vim:ts=4 sw=4:
530