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