ATLAS Offline Software
Loading...
Searching...
No Matches
MD5.cxx
Go to the documentation of this file.
1
7
8
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
56MD5::MD5 (const unsigned char* buffer, unsigned long len)
57{
58 init();
59 update (buffer, len);
61}
62
63
64// cppcheck-suppress uninitMemberVar; false positive
65MD5::MD5 (const char* buffer, size_t len)
66{
67 init();
68 update (buffer, len);
70}
71
72
73// cppcheck-suppress uninitMemberVar; false positive
74MD5::MD5 (const std::string& s)
75{
76 init();
77 update (s.c_str(), s.size());
79}
80
81
82void MD5::raw_digest (unsigned char* s) const
83{
84 memcpy (s, m_digest, 16);
85}
86
87
88void MD5::uuid_digest (uuid_t& uuid) const
89{
90 memcpy (&uuid, m_digest, 16);
91}
92
93
94std::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 */
161const 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
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
281void 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
322void 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
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
static Double_t a
#define GET(n)
Definition MD5.cxx:153
#define STEP(f, a, b, c, d, x, t, s)
Definition MD5.cxx:121
#define SET(n)
Definition MD5.cxx:147
#define F(x, y, z)
Definition MD5.cxx:112
#define OUT(dst, src)
Definition MD5.cxx:316
#define I(x, y, z)
Definition MD5.cxx:116
#define G(x, y, z)
Definition MD5.cxx:113
#define H(x, y, z)
Definition MD5.cxx:114
#define H2(x, y, z)
Definition MD5.cxx:115
solar's public-domain MD5, wrapped for C++.
void digest(unsigned char *result)
Definition MD5.cxx:322
MD5(const unsigned char *buffer, unsigned long len)
Definition MD5.cxx:56
void uuid_digest(uuid_t &uuid) const
Definition MD5.cxx:88
const void * body(const void *data, size_t size)
Definition MD5.cxx:161
uint32_t MD5_u32plus
Definition MD5.h:30
void init()
Definition MD5.cxx:269
std::string hex_digest() const
Definition MD5.cxx:94
Context m_ctx
Definition MD5.h:38
void raw_digest(unsigned char *s) const
Definition MD5.cxx:82
void update(const void *data, size_t size)
Definition MD5.cxx:281
unsigned char m_digest[16]
Definition MD5.h:39
holding In fact this class is here in order to allow STL container for all features This class is sho...
MD5_u32plus hi
Definition MD5.h:32
unsigned char buffer[64]
Definition MD5.h:34
MD5_u32plus lo
Definition MD5.h:32
MD5_u32plus a
Definition MD5.h:33
MD5_u32plus c
Definition MD5.h:33
MD5_u32plus d
Definition MD5.h:33
MD5_u32plus b
Definition MD5.h:33