source: project/release/4/md5/trunk/md5-ssl.c @ 23314

Last change on this file since 23314 was 23314, checked in by kon, 8 years ago

Revert bitlen apnd. Keep register clear & symbolic digest length.

File size: 8.4 KB
Line 
1/*
2 * This is an OpenSSL-compatible implementation of the RSA Data Security,
3 * Inc. MD5 Message-Digest Algorithm.
4 *
5 * Written by Solar Designer <solar@openwall.com> in 2001, and placed in
6 * the public domain.  There's absolutely no warranty.
7 *
8 * This differs from Colin Plumb's older public domain implementation in
9 * that no 32-bit integer data type is required, there's no compile-time
10 * endianness configuration, and the function prototypes match OpenSSL's.
11 * The primary goals are portability and ease of use.
12 *
13 * This implementation is meant to be fast, but not as fast as possible.
14 * Some known optimizations are not included to reduce source code size
15 * and avoid compile-time configuration.
16 */
17
18#include <string.h> /* for memcpy() */
19 
20/* Any 32-bit or wider unsigned integer data type will do */
21typedef unsigned int MD5_u32plus;
22
23struct MD5Context {
24        MD5_u32plus lo, hi;
25        MD5_u32plus a, b, c, d;
26        unsigned char buffer[64];
27        MD5_u32plus block[16];
28};
29 
30#define MD5_DIGEST_SIZE 16
31
32/*
33 * The basic MD5 functions.
34 *
35 * F is optimized compared to its RFC 1321 definition just like in Colin
36 * Plumb's implementation.
37 */
38#define F(x, y, z)              ((z) ^ ((x) & ((y) ^ (z))))
39#define G(x, y, z)              ((y) ^ ((z) & ((x) ^ (y))))
40#define H(x, y, z)              ((x) ^ (y) ^ (z))
41#define I(x, y, z)              ((y) ^ ((x) | ~(z)))
42
43/*
44 * The MD5 transformation for all four rounds.
45 */
46#define STEP(f, a, b, c, d, x, t, s) \
47    (a) += f((b), (c), (d)) + (x) + (t); \
48    (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
49    (a) += (b);
50
51/*
52 * SET reads 4 input bytes in little-endian byte order and stores them
53 * in a properly aligned word in host byte order.
54 *
55 * The check for little-endian architectures which tolerate unaligned
56 * memory accesses is just an optimization.  Nothing will break if it
57 * doesn't work.
58 */
59#if defined(__i386__) || defined(__vax__)
60#define SET(n) \
61    (*(MD5_u32plus *)&ptr[(n) * 4])
62#define GET(n) \
63    SET(n)
64#else
65#define SET(n) \
66    (ctx->block[(n)] = \
67        (MD5_u32plus)ptr[(n) * 4] | \
68        ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
69        ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
70        ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
71#define GET(n) \
72    (ctx->block[(n)])
73#endif
74
75/*
76 * This processes one or more 64-byte data blocks, but does NOT update
77 * the bit counters.  There're no alignment requirements.
78 */
79static void *body(struct MD5Context *ctx, void *data, unsigned long size)
80{
81    unsigned char *ptr;
82    MD5_u32plus a, b, c, d;
83    MD5_u32plus saved_a, saved_b, saved_c, saved_d;
84
85    ptr = data;
86
87    a = ctx->a;
88    b = ctx->b;
89    c = ctx->c;
90    d = ctx->d;
91
92    do {
93        saved_a = a;
94        saved_b = b;
95        saved_c = c;
96        saved_d = d;
97
98/* Round 1 */
99        STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
100        STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
101        STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
102        STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
103        STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
104        STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
105        STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
106        STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
107        STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
108        STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
109        STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
110        STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
111        STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
112        STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
113        STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
114        STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
115
116/* Round 2 */
117        STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
118        STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
119        STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
120        STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
121        STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
122        STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
123        STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
124        STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
125        STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
126        STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
127        STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
128        STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
129        STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
130        STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
131        STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
132        STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
133
134/* Round 3 */
135        STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
136        STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
137        STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
138        STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
139        STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
140        STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
141        STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
142        STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
143        STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
144        STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
145        STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
146        STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
147        STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
148        STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
149        STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
150        STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
151
152/* Round 4 */
153        STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
154        STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
155        STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
156        STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
157        STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
158        STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
159        STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
160        STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
161        STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
162        STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
163        STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
164        STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
165        STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
166        STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
167        STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
168        STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
169
170        a += saved_a;
171        b += saved_b;
172        c += saved_c;
173        d += saved_d;
174
175        ptr += 64;
176    } while (size -= 64);
177
178    ctx->a = a;
179    ctx->b = b;
180    ctx->c = c;
181    ctx->d = d;
182
183    return ptr;
184}
185
186static void MD5Init(struct MD5Context *ctx)
187{
188    ctx->a = 0x67452301;
189    ctx->b = 0xefcdab89;
190    ctx->c = 0x98badcfe;
191    ctx->d = 0x10325476;
192
193    ctx->lo = 0;
194    ctx->hi = 0;
195}
196
197static void MD5Update(struct MD5Context *ctx, void *data, unsigned long size)
198{
199    MD5_u32plus saved_lo;
200    unsigned long used, free;
201
202    saved_lo = ctx->lo;
203    if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
204        ctx->hi++;
205    ctx->hi += size >> 29;
206
207    used = saved_lo & 0x3f;
208
209    if (used) {
210        free = 64 - used;
211
212        if (size < free) {
213            memcpy(&ctx->buffer[used], data, size);
214            return;
215        }
216
217        memcpy(&ctx->buffer[used], data, free);
218        data = (unsigned char *)data + free;
219        size -= free;
220        body(ctx, ctx->buffer, 64);
221    }
222
223    if (size >= 64) {
224        data = body(ctx, data, size & ~(unsigned long)0x3f);
225        size &= 0x3f;
226    }
227
228    memcpy(ctx->buffer, data, size);
229}
230
231static void MD5Final(struct MD5Context *ctx, unsigned char result[MD5_DIGEST_SIZE])
232{
233    unsigned long used, free;
234
235    used = ctx->lo & 0x3f;
236
237    ctx->buffer[used++] = 0x80;
238
239    free = 64 - used;
240
241    if (free < 8) {
242        memset(&ctx->buffer[used], 0, free);
243        body(ctx, ctx->buffer, 64);
244        used = 0;
245        free = 64;
246    }
247
248    memset(&ctx->buffer[used], 0, free - 8);
249
250    ctx->lo <<= 3;
251    ctx->buffer[56] = ctx->lo;
252    ctx->buffer[57] = ctx->lo >> 8;
253    ctx->buffer[58] = ctx->lo >> 16;
254    ctx->buffer[59] = ctx->lo >> 24;
255    ctx->buffer[60] = ctx->hi;
256    ctx->buffer[61] = ctx->hi >> 8;
257    ctx->buffer[62] = ctx->hi >> 16;
258    ctx->buffer[63] = ctx->hi >> 24;
259
260    body(ctx, ctx->buffer, 64);
261
262    result[0] = ctx->a;
263    result[1] = ctx->a >> 8;
264    result[2] = ctx->a >> 16;
265    result[3] = ctx->a >> 24;
266    result[4] = ctx->b;
267    result[5] = ctx->b >> 8;
268    result[6] = ctx->b >> 16;
269    result[7] = ctx->b >> 24;
270    result[8] = ctx->c;
271    result[9] = ctx->c >> 8;
272    result[10] = ctx->c >> 16;
273    result[11] = ctx->c >> 24;
274    result[12] = ctx->d;
275    result[13] = ctx->d >> 8;
276    result[14] = ctx->d >> 16;
277    result[15] = ctx->d >> 24;
278
279    memset(ctx, 0, sizeof(*ctx));   /* In case it's sensitive */
280}
Note: See TracBrowser for help on using the repository browser.