root/pehunter/md5.c

Revision 1134, 7.9 kB (checked in by till, 2 years ago)

pehunter initial insert

Line 
1 /*
2  * md5.c
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  *
18  * Copyright (C) 2007 Tillmann Werner <tillmann.werner@gmx.de>
19  */
20
21 #include <string.h>
22 #include <sys/types.h>
23 #include <stdio.h>
24
25 #include "md5.h"
26
27 /*
28  * The basic MD5 functions.
29  *
30  * F is optimized compared to its RFC 1321 definition just like in Colin
31  * Plumb's implementation.
32  */
33 #define F(x, y, z)                      ((z) ^ ((x) & ((y) ^ (z))))
34 #define G(x, y, z)                      ((y) ^ ((z) & ((x) ^ (y))))
35 #define H(x, y, z)                      ((x) ^ (y) ^ (z))
36 #define I(x, y, z)                      ((y) ^ ((x) | ~(z)))
37
38 /*
39  * The MD5 transformation for all four rounds.
40  */
41 #define STEP(f, a, b, c, d, x, t, s) \
42         (a) += f((b), (c), (d)) + (x) + (t); \
43         (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
44         (a) += (b);
45
46 /*
47  * SET reads 4 input bytes in little-endian byte order and stores them
48  * in a properly aligned word in host byte order.
49  *
50  * The check for little-endian architectures which tolerate unaligned
51  * memory accesses is just an optimization.  Nothing will break if it
52  * doesn't work.
53  */
54 #if defined(__i386__) || defined(__vax__)
55 #define SET(n) \
56         (*(MD5_u32plus *)&ptr[(n) * 4])
57 #define GET(n) \
58         SET(n)
59 #else
60 #define SET(n) \
61         (ctx->block[(n)] = \
62         (MD5_u32plus)ptr[(n) * 4] | \
63         ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
64         ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
65         ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
66 #define GET(n) \
67         (ctx->block[(n)])
68 #endif
69
70 /*
71  * This processes one or more 64-byte data blocks, but does NOT update
72  * the bit counters.  There're no alignment requirements.
73  */
74 static void *body(MD5_CTX *ctx, void *data, unsigned long size)
75 {
76         unsigned char *ptr;
77         MD5_u32plus a, b, c, d;
78         MD5_u32plus saved_a, saved_b, saved_c, saved_d;
79
80         ptr = data;
81
82         a = ctx->a;
83         b = ctx->b;
84         c = ctx->c;
85         d = ctx->d;
86
87         do {
88                 saved_a = a;
89                 saved_b = b;
90                 saved_c = c;
91                 saved_d = d;
92
93 /* Round 1 */
94                 STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
95                 STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
96                 STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
97                 STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
98                 STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
99                 STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
100                 STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
101                 STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
102                 STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
103                 STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
104                 STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
105                 STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
106                 STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
107                 STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
108                 STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
109                 STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
110
111 /* Round 2 */
112                 STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
113                 STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
114                 STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
115                 STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
116                 STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
117                 STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
118                 STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
119                 STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
120                 STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
121                 STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
122                 STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
123                 STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
124                 STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
125                 STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
126                 STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
127                 STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
128
129 /* Round 3 */
130                 STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
131                 STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
132                 STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
133                 STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
134                 STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
135                 STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
136                 STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
137                 STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
138                 STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
139                 STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
140                 STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
141                 STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
142                 STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
143                 STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
144                 STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
145                 STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
146
147 /* Round 4 */
148                 STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
149                 STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
150                 STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
151                 STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
152                 STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
153                 STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
154                 STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
155                 STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
156                 STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
157                 STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
158                 STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
159                 STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
160                 STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
161                 STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
162                 STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
163                 STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
164
165                 a += saved_a;
166                 b += saved_b;
167                 c += saved_c;
168                 d += saved_d;
169
170                 ptr += 64;
171         } while (size -= 64);
172
173         ctx->a = a;
174         ctx->b = b;
175         ctx->c = c;
176         ctx->d = d;
177
178         return ptr;
179 }
180
181 void MD5_Init(MD5_CTX *ctx)
182 {
183         ctx->a = 0x67452301;
184         ctx->b = 0xefcdab89;
185         ctx->c = 0x98badcfe;
186         ctx->d = 0x10325476;
187
188         ctx->lo = 0;
189         ctx->hi = 0;
190 }
191
192 void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size)
193 {
194         MD5_u32plus saved_lo;
195         unsigned long used, free;
196
197         saved_lo = ctx->lo;
198         if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
199                 ctx->hi++;
200         ctx->hi += size >> 29;
201
202         used = saved_lo & 0x3f;
203
204         if (used) {
205                 free = 64 - used;
206
207                 if (size < free) {
208                         memcpy(&ctx->buffer[used], data, size);
209                         return;
210                 }
211
212                 memcpy(&ctx->buffer[used], data, free);
213                 data = (unsigned char *)data + free;
214                 size -= free;
215                 body(ctx, ctx->buffer, 64);
216         }
217
218         if (size >= 64) {
219                 data = body(ctx, data, size & ~(unsigned long)0x3f);
220                 size &= 0x3f;
221         }
222
223         memcpy(ctx->buffer, data, size);
224 }
225
226 void MD5_Final(unsigned char *result, MD5_CTX *ctx)
227 {
228         unsigned long used, free;
229
230         used = ctx->lo & 0x3f;
231
232         ctx->buffer[used++] = 0x80;
233
234         free = 64 - used;
235
236         if (free < 8) {
237                 memset(&ctx->buffer[used], 0, free);
238                 body(ctx, ctx->buffer, 64);
239                 used = 0;
240                 free = 64;
241         }
242
243         memset(&ctx->buffer[used], 0, free - 8);
244
245         ctx->lo <<= 3;
246         ctx->buffer[56] = ctx->lo;
247         ctx->buffer[57] = ctx->lo >> 8;
248         ctx->buffer[58] = ctx->lo >> 16;
249         ctx->buffer[59] = ctx->lo >> 24;
250         ctx->buffer[60] = ctx->hi;
251         ctx->buffer[61] = ctx->hi >> 8;
252         ctx->buffer[62] = ctx->hi >> 16;
253         ctx->buffer[63] = ctx->hi >> 24;
254
255         body(ctx, ctx->buffer, 64);
256
257         result[0] = ctx->a;
258         result[1] = ctx->a >> 8;
259         result[2] = ctx->a >> 16;
260         result[3] = ctx->a >> 24;
261         result[4] = ctx->b;
262         result[5] = ctx->b >> 8;
263         result[6] = ctx->b >> 16;
264         result[7] = ctx->b >> 24;
265         result[8] = ctx->c;
266         result[9] = ctx->c >> 8;
267         result[10] = ctx->c >> 16;
268         result[11] = ctx->c >> 24;
269         result[12] = ctx->d;
270         result[13] = ctx->d >> 8;
271         result[14] = ctx->d >> 16;
272         result[15] = ctx->d >> 24;
273
274         memset(ctx, 0, sizeof(*ctx));
275 }
276
277 char *mem_md5sum(u_char *mempos, u_int32_t size)
278 {
279         unsigned char digest[16];
280         MD5_CTX ctx;
281         char *md5sum, *ptr;
282         int i, bytes;
283
284         MD5_Init(&ctx);
285
286         /* calculate md5 checksum */
287         while (size > 0) {
288                 bytes = (size < 8192) ? size : 8192;
289                 MD5_Update(&ctx, mempos, bytes);
290                 mempos += bytes;
291                 size -= bytes;
292         }
293
294         MD5_Final(digest, &ctx);
295
296         /* allocate memory for md5sum string */
297         if(!(md5sum = (char *) calloc(32 + 1, 1))) return(NULL);
298
299         ptr = md5sum;
300         for(i = 0; i < 16; i++) {
301                 snprintf(ptr, 4, "%02x", digest[i]);
302                 ptr += 2;
303         }
304
305         return(md5sum);
306 }
Note: See TracBrowser for help on using the browser.