ATLAS Offline Software
MD5.cxx
Go to the documentation of this file.
1 
9 /*
10  * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
11  * MD5 Message-Digest Algorithm (RFC 1321).
12  *
13  * Homepage:
14  * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
15  *
16  * Author:
17  * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
18  *
19  * This software was written by Alexander Peslyak in 2001. No copyright is
20  * claimed, and the software is hereby placed in the public domain.
21  * In case this attempt to disclaim copyright and place the software in the
22  * public domain is deemed null and void, then the software is
23  * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
24  * general public under the following terms:
25  *
26  * Redistribution and use in source and binary forms, with or without
27  * modification, are permitted.
28  *
29  * There's ABSOLUTELY NO WARRANTY, express or implied.
30  *
31  * (This is a heavily cut-down "BSD license".)
32  *
33  * This differs from Colin Plumb's older public domain implementation in that
34  * no exactly 32-bit integer data type is required (any 32-bit or wider
35  * unsigned integer data type will do), there's no compile-time endianness
36  * configuration, and the function prototypes match OpenSSL's. No code from
37  * Colin Plumb's implementation has been reused; this comment merely compares
38  * the properties of the two independent implementations.
39  *
40  * The primary goals of this implementation are portability and ease of use.
41  * It is meant to be fast, but not as fast as possible. Some known
42  * optimizations are not included to reduce source code size and avoid
43  * compile-time configuration.
44  */
45 
46 //#ifndef HAVE_OPENSSL
47 
48 #include <string.h>
49 
50 #include "CxxUtils/MD5.h"
51 
52 // C++ wrapper functions.
53 
54 
55 // cppcheck-suppress uninitMemberVar; false positive
56 MD5::MD5 (const unsigned char* buffer, unsigned long len)
57 {
58  init();
59  update (buffer, len);
60  digest (m_digest);
61 }
62 
63 
64 // cppcheck-suppress uninitMemberVar; false positive
65 MD5::MD5 (const char* buffer, size_t len)
66 {
67  init();
68  update (buffer, len);
69  digest (m_digest);
70 }
71 
72 
73 // cppcheck-suppress uninitMemberVar; false positive
74 MD5::MD5 (const std::string& s)
75 {
76  init();
77  update (s.c_str(), s.size());
78  digest (m_digest);
79 }
80 
81 
82 void MD5::raw_digest (unsigned char* s) const
83 {
84  memcpy (s, m_digest, 16);
85 }
86 
87 
88 void MD5::uuid_digest (uuid_t& uuid) const
89 {
90  memcpy (&uuid, m_digest, 16);
91 }
92 
93 
94 std::string MD5::hex_digest() const
95 {
96  char s[33];
97  for (int i = 0; i < 16; i++) {
98  snprintf (s+i*2, 3, "%02x", m_digest[i]);
99  }
100  s[32] = '\0';
101  return s;
102 }
103 
104 
105 /*
106  * The basic MD5 functions.
107  *
108  * F and G are optimized compared to their RFC 1321 definitions for
109  * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
110  * implementation.
111  */
112 #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
113 #define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
114 #define H(x, y, z) (((x) ^ (y)) ^ (z))
115 #define H2(x, y, z) ((x) ^ ((y) ^ (z)))
116 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
117 
118 /*
119  * The MD5 transformation for all four rounds.
120  */
121 #define STEP(f, a, b, c, d, x, t, s) \
122  (a) += f((b), (c), (d)) + (x) + (t); \
123  (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
124  (a) += (b);
125 
126 /*
127  * SET reads 4 input bytes in little-endian byte order and stores them in a
128  * properly aligned word in host byte order.
129  *
130  * The check for little-endian architectures that tolerate unaligned memory
131  * accesses is just an optimization. Nothing will break if it fails to detect
132  * a suitable architecture.
133  *
134  * Unfortunately, this optimization may be a C strict aliasing rules violation
135  * if the caller's data buffer has effective type that cannot be aliased by
136  * MD5_u32plus. In practice, this problem may occur if these MD5 routines are
137  * inlined into a calling function, or with future and dangerously advanced
138  * link-time optimizations. For the time being, keeping these MD5 routines in
139  * their own translation unit avoids the problem.
140  */
141 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
142 #define SET(n) \
143  (*(MD5_u32plus *)&ptr[(n) * 4])
144 #define GET(n) \
145  SET(n)
146 #else
147 #define SET(n) \
148  (ctx->block[(n)] = \
149  (MD5_u32plus)ptr[(n) * 4] | \
150  ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
151  ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
152  ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
153 #define GET(n) \
154  (ctx->block[(n)])
155 #endif
156 
157 /*
158  * This processes one or more 64-byte data blocks, but does NOT update the bit
159  * counters. There are no alignment requirements.
160  */
161 const void* MD5::body (const void *data, size_t size)
162 {
163  const unsigned char *ptr;
164  MD5_u32plus a, b, c, d;
165  MD5_u32plus saved_a, saved_b, saved_c, saved_d;
166  Context* ctx = &m_ctx;
167 
168  ptr = (const unsigned char *)data;
169 
170  a = ctx->a;
171  b = ctx->b;
172  c = ctx->c;
173  d = ctx->d;
174 
175  do {
176  saved_a = a;
177  saved_b = b;
178  saved_c = c;
179  saved_d = d;
180 
181 /* Round 1 */
182  STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
183  STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
184  STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
185  STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
186  STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
187  STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
188  STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
189  STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
190  STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
191  STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
192  STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
193  STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
194  STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
195  STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
196  STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
197  STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
198 
199 /* Round 2 */
200  STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
201  STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
202  STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
203  STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
204  STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
205  STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
206  STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
207  STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
208  STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
209  STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
210  STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
211  STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
212  STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
213  STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
214  STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
215  STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
216 
217 /* Round 3 */
218  STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
219  STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
220  STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
221  STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
222  STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
223  STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
224  STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
225  STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
226  STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
227  STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
228  STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
229  STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
230  STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
231  STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
232  STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
233  STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
234 
235 /* Round 4 */
236  STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
237  STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
238  STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
239  STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
240  STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
241  STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
242  STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
243  STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
244  STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
245  STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
246  STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
247  STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
248  STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
249  STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
250  STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
251  STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
252 
253  a += saved_a;
254  b += saved_b;
255  c += saved_c;
256  d += saved_d;
257 
258  ptr += 64;
259  } while (size -= 64);
260 
261  ctx->a = a;
262  ctx->b = b;
263  ctx->c = c;
264  ctx->d = d;
265 
266  return ptr;
267 }
268 
269 void MD5::init()
270 {
271  Context* ctx = &m_ctx;
272  ctx->a = 0x67452301;
273  ctx->b = 0xefcdab89;
274  ctx->c = 0x98badcfe;
275  ctx->d = 0x10325476;
276 
277  ctx->lo = 0;
278  ctx->hi = 0;
279 }
280 
281 void MD5::update (const void *data, size_t size)
282 {
283  MD5_u32plus saved_lo;
284  unsigned long used, available;
285  Context* ctx = &m_ctx;
286 
287  saved_lo = ctx->lo;
288  if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
289  ctx->hi++;
290  ctx->hi += size >> 29;
291 
292  used = saved_lo & 0x3f;
293 
294  if (used) {
295  available = 64 - used;
296 
297  if (size < available) {
298  memcpy(&ctx->buffer[used], data, size);
299  return;
300  }
301 
302  memcpy(&ctx->buffer[used], data, available);
303  data = (const unsigned char *)data + available;
304  size -= available;
305  body(ctx->buffer, 64);
306  }
307 
308  if (size >= 64) {
309  data = body(data, size & ~(unsigned long)0x3f);
310  size &= 0x3f;
311  }
312 
313  memcpy(ctx->buffer, data, size);
314 }
315 
316 #define OUT(dst, src) \
317  (dst)[0] = (unsigned char)(src); \
318  (dst)[1] = (unsigned char)((src) >> 8); \
319  (dst)[2] = (unsigned char)((src) >> 16); \
320  (dst)[3] = (unsigned char)((src) >> 24);
321 
322 void MD5::digest (unsigned char *result)
323 {
324  unsigned long used, available;
325  Context* ctx = &m_ctx;
326 
327  used = ctx->lo & 0x3f;
328 
329  ctx->buffer[used++] = 0x80;
330 
331  available = 64 - used;
332 
333  if (available < 8) {
334  memset(&ctx->buffer[used], 0, available);
335  body(ctx->buffer, 64);
336  used = 0;
337  available = 64;
338  }
339 
340  memset(&ctx->buffer[used], 0, available - 8);
341 
342  ctx->lo <<= 3;
343  // cppcheck-suppress objectIndex
344  OUT(&ctx->buffer[56], ctx->lo)
345  // cppcheck-suppress objectIndex
346  OUT(&ctx->buffer[60], ctx->hi)
347 
348  body(ctx->buffer, 64);
349 
350  OUT(&result[0], ctx->a)
351  OUT(&result[4], ctx->b)
352  OUT(&result[8], ctx->c)
353  OUT(&result[12], ctx->d)
354 
355  memset(ctx, 0, sizeof(*ctx));
356 }
357 
358 //#endif
used
MD5::Context::c
MD5_u32plus c
Definition: MD5.h:33
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
get_generator_info.result
result
Definition: get_generator_info.py:21
MD5::Context::lo
MD5_u32plus lo
Definition: MD5.h:32
MD5::Context::d
MD5_u32plus d
Definition: MD5.h:33
MD5::hex_digest
std::string hex_digest() const
Definition: MD5.cxx:94
MD5::Context::b
MD5_u32plus b
Definition: MD5.h:33
hist_file_dump.d
d
Definition: hist_file_dump.py:137
MD5::body
const void * body(const void *data, size_t size)
Definition: MD5.cxx:161
MD5::MD5_u32plus
uint32_t MD5_u32plus
Definition: MD5.h:30
MD5::Context::hi
MD5_u32plus hi
Definition: MD5.h:32
dbg::ptr
void * ptr(T *p)
Definition: SGImplSvc.cxx:74
MD5::raw_digest
void raw_digest(unsigned char *s) const
Definition: MD5.cxx:82
H2
#define H2(x, y, z)
Definition: MD5.cxx:115
MD5.h
solar's public-domain MD5, wrapped for C++.
OUT
#define OUT(dst, src)
Definition: MD5.cxx:316
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
H
#define H(x, y, z)
Definition: MD5.cxx:114
createCoolChannelIdFile.buffer
buffer
Definition: createCoolChannelIdFile.py:12
MD5::init
void init()
Definition: MD5.cxx:269
MD5::MD5
MD5(const unsigned char *buffer, unsigned long len)
Definition: MD5.cxx:56
lumiFormat.i
int i
Definition: lumiFormat.py:85
G
#define G(x, y, z)
Definition: MD5.cxx:113
GET
#define GET(n)
Definition: MD5.cxx:153
MD5::Context
Definition: MD5.h:31
MD5::update
void update(const void *data, size_t size)
Definition: MD5.cxx:281
MD5::Context::a
MD5_u32plus a
Definition: MD5.h:33
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
MD5::uuid_digest
void uuid_digest(uuid_t &uuid) const
Definition: MD5.cxx:88
a
TList * a
Definition: liststreamerinfos.cxx:10
MD5::m_ctx
Context m_ctx
Definition: MD5.h:38
F
#define F(x, y, z)
Definition: MD5.cxx:112
MD5::digest
void digest(unsigned char *result)
Definition: MD5.cxx:322
MD5::Context::buffer
unsigned char buffer[64]
Definition: MD5.h:34
I
#define I(x, y, z)
Definition: MD5.cxx:116
MD5::m_digest
unsigned char m_digest[16]
Definition: MD5.h:39
python.compressB64.c
def c
Definition: compressB64.py:93
STEP
#define STEP(f, a, b, c, d, x, t, s)
Definition: MD5.cxx:121
SET
#define SET(n)
Definition: MD5.cxx:147