XRootD
XrdCksCalcmd5.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d C k s C a l c m d 5 . c c */
4 /* */
5 /* (c) 2011 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* All Rights Reserved */
7 /* Produced by Andrew Hanushevsky for Stanford University under contract */
8 /* DE-AC02-76-SFO0515 with the Department of Energy */
9 /* */
10 /* This file is part of the XRootD software suite. */
11 /* */
12 /* XRootD is free software: you can redistribute it and/or modify it under */
13 /* the terms of the GNU Lesser General Public License as published by the */
14 /* Free Software Foundation, either version 3 of the License, or (at your */
15 /* option) any later version. */
16 /* */
17 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20 /* License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25 /* */
26 /* The copyright holder's institutional names and contributor's names may not */
27 /* be used to endorse or promote products derived from this software without */
28 /* specific prior written permission of the institution or contributor. */
29 /******************************************************************************/
30 
31 #include <cstring>
32 
33 #include "XrdCks/XrdCksCalcmd5.hh"
34 #include "XrdSys/XrdSysPlatform.hh"
35 
36 /*
37  * This code implements the MD5 message-digest algorithm.
38  * The algorithm is due to Ron Rivest. This code was
39  * written by Colin Plumb in 1993, no copyright is claimed.
40  * This code is in the public domain; do with it what you wish.
41  *
42  * Equivalent code is available from RSA Data Security, Inc.
43  * This code has been tested against that, and is equivalent,
44  * except that you don't need to include two pages of legalese
45  * with every copy.
46  *
47  * To compute the message digest of a chunk of bytes, declare an
48  * MD5Context structure, pass it to MD5Init, call MD5Update as
49  * needed on buffers full of bytes, and then call MD5Final, which
50  * will fill a supplied 16-byte array with the digest.
51  */
52 
53 /******************************************************************************/
54 /* B y t e R e v e r s e */
55 /******************************************************************************/
56 
57 #ifndef Xrd_Big_Endian
58 void XrdCksCalcmd5::byteReverse(unsigned char *buf, unsigned longs) {} /* Nothing */
59 #else
60 #ifndef ASM_MD5
61 void XrdCksCalcmd5::byteReverse(unsigned char *buf, unsigned longs)
62 {
63  unsigned int t;
64  do {t = (unsigned int) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
65  ((unsigned) buf[1] << 8 | buf[0]);
66  *(unsigned int *) buf = t;
67  buf += 4;
68  } while (--longs);
69 }
70 #endif
71 #endif
72 
73 /******************************************************************************/
74 /* I n i t */
75 /******************************************************************************/
76 
77 /******************************************************************************/
78 /* M D 5 I n i t */
79 /******************************************************************************/
80 
81 /* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
82  initialization constants.
83 */
85 {
86  myContext.buf[0] = 0x67452301;
87  myContext.buf[1] = 0xefcdab89;
88  myContext.buf[2] = 0x98badcfe;
89  myContext.buf[3] = 0x10325476;
90 
91  myContext.bits[0] = 0;
92  myContext.bits[1] = 0;
93 }
94 
95 /******************************************************************************/
96 /* M D 5 U p d a t e */
97 /******************************************************************************/
98 
99 /* Update context to reflect the concatenation of another buffer full of bytes.
100 */
101 void XrdCksCalcmd5::MD5Update(unsigned char const *buf, unsigned int len)
102 {
103  unsigned int t;
104 
105 // Update bitcount
106 //
107  t = myContext.bits[0];
108  if ((myContext.bits[0] = t + ((unsigned int) len << 3)) < t)
109 
110 // Carry from low to high
111 //
112  myContext.bits[1]++;
113  myContext.bits[1] += len >> 29;
114 
115 // Bytes already in shsInfo->data
116 //
117  t = (t >> 3) & 0x3f;
118 
119 // Handle any leading odd-sized chunks
120 //
121  if (t) {unsigned char *p = (unsigned char *) myContext.in + t;
122  t = 64 - t;
123  if (len < t) {memcpy(p, buf, len); return;}
124  memcpy(p, buf, t);
125  byteReverse(myContext.in, 16);
126  MD5Transform(myContext.buf, (unsigned int *) myContext.in);
127  buf += t;
128  len -= t;
129  }
130 
131 // Process data in 64-byte chunks
132 //
133  while(len >= 64)
134  {memcpy(myContext.in, buf, 64);
135  byteReverse(myContext.in, 16);
136  MD5Transform(myContext.buf, (unsigned int *) myContext.in);
137  buf += 64;
138  len -= 64;
139  }
140 
141 // Handle any remaining bytes of data.
142 
143  memcpy(myContext.in, buf, len);
144 }
145 
146 /******************************************************************************/
147 /* F i n a l */
148 /******************************************************************************/
149 
150 /* Final wrapup - pad to 64-byte boundary with the bit pattern
151  1 0* (64-bit count of bits processed, MSB-first)
152 */
154 {
155  unsigned count;
156  unsigned char *p;
157 
158 // Compute number of bytes mod 64
159 //
160  count = (myContext.bits[0] >> 3) & 0x3F;
161 
162 // Set the first char of padding to 0x80. This is safe since there is
163 // always at least one byte free.
164 //
165  p = myContext.in + count;
166  *p++ = 0x80;
167 
168 // Bytes of padding needed to make 64 bytes
169 //
170  count = 64 - 1 - count;
171 
172 // Pad out to 56 mod 64
173 //
174  if (count < 8) // Two lots of padding: Pad the first block to 64 bytes
175  {memset(p, 0, count);
176  byteReverse(myContext.in, 16);
177  MD5Transform(myContext.buf, (unsigned int *) myContext.in);
178  memset(myContext.in, 0, 56); // Now fill the next block with 56 bytes
179  } else memset(p, 0, count - 8); // Else pad block to 56 bytes
180 
181  byteReverse(myContext.in, 14);
182 
183 // Append length in bits and transform (original code in comments)
184 //
185 // ((unsigned int *) myContext.in)[14] = myContext.bits[0];
186 // ((unsigned int *) myContext.in)[15] = myContext.bits[1];
187  myContext.i64[7] = myContext.b64;
188 
189  MD5Transform(myContext.buf, (unsigned int *) myContext.in);
190  byteReverse((unsigned char *) myContext.buf, 4);
191 
192 // Copy to a separate buffer and return ASCII value if so wanted
193 //
194  memcpy(myDigest, myContext.buf, 16);
195  return (char *)myDigest;
196 }
197 
198 /******************************************************************************/
199 /* M D 5 T r a n s f o r m */
200 /******************************************************************************/
201 
202 #ifndef ASM_MD5
203 
204 /* The four core functions - F1 is optimized somewhat */
205 
206 // #define F1(x, y, z) (x & y | ~x & z)
207 //
208 #define F1(x, y, z) (z ^ (x & (y ^ z)))
209 #define F2(x, y, z) F1(z, x, y)
210 #define F3(x, y, z) (x ^ y ^ z)
211 #define F4(x, y, z) (y ^ (x | ~z))
212 
213 // This is the central step in the MD5 algorithm.
214 //
215 #define MD5STEP(f, w, x, y, z, data, s) \
216  ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
217 
218 /* The core of the MD5 algorithm, this alters an existing MD5 hash to
219  reflect the addition of 16 longwords of new data. MD5Update blocks
220  the data and converts bytes into longwords for this routine.
221 */
222 void XrdCksCalcmd5::MD5Transform(unsigned int buf[4], unsigned int const in[16])
223 {
224  unsigned int a, b, c, d;
225 
226  a = buf[0];
227  b = buf[1];
228  c = buf[2];
229  d = buf[3];
230 
231  MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
232  MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
233  MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
234  MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
235  MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
236  MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
237  MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
238  MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
239  MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
240  MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
241  MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
242  MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
243  MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
244  MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
245  MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
246  MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
247 
248  MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
249  MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
250  MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
251  MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
252  MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
253  MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
254  MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
255  MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
256  MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
257  MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
258  MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
259  MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
260  MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
261  MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
262  MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
263  MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
264 
265  MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
266  MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
267  MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
268  MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
269  MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
270  MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
271  MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
272  MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
273  MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
274  MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
275  MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
276  MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
277  MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
278  MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
279  MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
280  MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
281 
282  MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
283  MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
284  MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
285  MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
286  MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
287  MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
288  MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
289  MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
290  MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
291  MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
292  MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
293  MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
294  MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
295  MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
296  MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
297  MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
298 
299  buf[0] += a;
300  buf[1] += b;
301  buf[2] += c;
302  buf[3] += d;
303 }
304 #endif
#define MD5STEP(f, w, x, y, z, data, s)
#define F1(x, y, z)
#define F4(x, y, z)
#define F3(x, y, z)
#define F2(x, y, z)
if(Avsz)