XRootD
Loading...
Searching...
No Matches
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
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
58void XrdCksCalcmd5::byteReverse(unsigned char *buf, unsigned longs) {} /* Nothing */
59#else
60#ifndef ASM_MD5
61void 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*/
101void 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*/
222void 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)