]> git.xonotic.org Git - xonotic/netradiant.git/blob - libs/md5lib/md4.c
compiles again on win32, trashed mhash
[xonotic/netradiant.git] / libs / md5lib / md4.c
1 /*
2  * MD4 (RFC-1320) message digest.
3  * Modified from MD5 code by Andrey Panin <pazke@donpac.ru>
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 <stdlib.h>
19 #include <string.h>
20
21 #ifdef _WIN32
22         #include "../stdint.msvc.h"\r
23 #endif\r
24
25 #include "md4lib.h"
26
27 /*
28  * The basic MD4 functions.
29  */
30 #define F(x, y, z)      ((z) ^ ((x) & ((y) ^ (z))))
31 #define G(x, y, z)      (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
32 #define H(x, y, z)      ((x) ^ (y) ^ (z))
33
34 /*
35  * The MD4 transformation for all four rounds.
36  */
37 #define STEP(f, a, b, c, d, x, s) \
38         (a) += f((b), (c), (d)) + (x);   \
39         (a) = ((a) << (s)) | ((a) >> (32 - (s)))
40
41
42 /*
43  * SET reads 4 input bytes in little-endian byte order and stores them
44  * in a properly aligned word in host byte order.
45  *
46  * The check for little-endian architectures which tolerate unaligned
47  * memory accesses is just an optimization.  Nothing will break if it
48  * doesn't work.
49  */
50 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
51 #define SET(n) \
52         (*(const uint_fast32_t *)&ptr[(n) * 4])
53 #define GET(n) \
54         SET(n)
55 #else
56 #define SET(n) \
57         (ctx->block[(n)] = \
58         (uint_fast32_t)ptr[(n) * 4] | \
59         ((uint_fast32_t)ptr[(n) * 4 + 1] << 8) | \
60         ((uint_fast32_t)ptr[(n) * 4 + 2] << 16) | \
61         ((uint_fast32_t)ptr[(n) * 4 + 3] << 24))
62 #define GET(n) \
63         (ctx->block[(n)])
64 #endif
65
66 /*
67  * This processes one or more 64-byte data blocks, but does NOT update
68  * the bit counters.  There're no alignment requirements.
69  */
70 static const void *body(struct md4_context *ctx, const void *data, size_t size)
71 {
72         const unsigned char *ptr;
73         uint32_t a, b, c, d;
74         uint32_t saved_a, saved_b, saved_c, saved_d;
75
76         ptr = data;
77
78         a = ctx->a;
79         b = ctx->b;
80         c = ctx->c;
81         d = ctx->d;
82
83         do {
84                 saved_a = a;
85                 saved_b = b;
86                 saved_c = c;
87                 saved_d = d;
88
89 /* Round 1 */
90                 STEP(F, a, b, c, d, SET( 0),  3);
91                 STEP(F, d, a, b, c, SET( 1),  7);
92                 STEP(F, c, d, a, b, SET( 2), 11);
93                 STEP(F, b, c, d, a, SET( 3), 19);
94
95                 STEP(F, a, b, c, d, SET( 4),  3);
96                 STEP(F, d, a, b, c, SET( 5),  7);
97                 STEP(F, c, d, a, b, SET( 6), 11);
98                 STEP(F, b, c, d, a, SET( 7), 19);
99
100                 STEP(F, a, b, c, d, SET( 8),  3);
101                 STEP(F, d, a, b, c, SET( 9),  7);
102                 STEP(F, c, d, a, b, SET(10), 11);
103                 STEP(F, b, c, d, a, SET(11), 19);
104
105                 STEP(F, a, b, c, d, SET(12),  3);
106                 STEP(F, d, a, b, c, SET(13),  7);
107                 STEP(F, c, d, a, b, SET(14), 11);
108                 STEP(F, b, c, d, a, SET(15), 19);
109 /* Round 2 */
110                 STEP(G, a, b, c, d, GET( 0) + 0x5A827999,  3);
111                 STEP(G, d, a, b, c, GET( 4) + 0x5A827999,  5);
112                 STEP(G, c, d, a, b, GET( 8) + 0x5A827999,  9);
113                 STEP(G, b, c, d, a, GET(12) + 0x5A827999, 13);
114
115                 STEP(G, a, b, c, d, GET( 1) + 0x5A827999,  3);
116                 STEP(G, d, a, b, c, GET( 5) + 0x5A827999,  5);
117                 STEP(G, c, d, a, b, GET( 9) + 0x5A827999,  9);
118                 STEP(G, b, c, d, a, GET(13) + 0x5A827999, 13);
119
120                 STEP(G, a, b, c, d, GET( 2) + 0x5A827999,  3);
121                 STEP(G, d, a, b, c, GET( 6) + 0x5A827999,  5);
122                 STEP(G, c, d, a, b, GET(10) + 0x5A827999,  9);
123                 STEP(G, b, c, d, a, GET(14) + 0x5A827999, 13);
124
125                 STEP(G, a, b, c, d, GET( 3) + 0x5A827999,  3);
126                 STEP(G, d, a, b, c, GET( 7) + 0x5A827999,  5);
127                 STEP(G, c, d, a, b, GET(11) + 0x5A827999,  9);
128                 STEP(G, b, c, d, a, GET(15) + 0x5A827999, 13);
129 /* Round 3 */
130                 STEP(H, a, b, c, d, GET( 0) + 0x6ED9EBA1,  3);
131                 STEP(H, d, a, b, c, GET( 8) + 0x6ED9EBA1,  9);
132                 STEP(H, c, d, a, b, GET( 4) + 0x6ED9EBA1, 11);
133                 STEP(H, b, c, d, a, GET(12) + 0x6ED9EBA1, 15);
134
135                 STEP(H, a, b, c, d, GET( 2) + 0x6ED9EBA1,  3);
136                 STEP(H, d, a, b, c, GET(10) + 0x6ED9EBA1,  9);
137                 STEP(H, c, d, a, b, GET( 6) + 0x6ED9EBA1, 11);
138                 STEP(H, b, c, d, a, GET(14) + 0x6ED9EBA1, 15);
139
140                 STEP(H, a, b, c, d, GET( 1) + 0x6ED9EBA1,  3);
141                 STEP(H, d, a, b, c, GET( 9) + 0x6ED9EBA1,  9);
142                 STEP(H, c, d, a, b, GET( 5) + 0x6ED9EBA1, 11);
143                 STEP(H, b, c, d, a, GET(13) + 0x6ED9EBA1, 15);
144
145                 STEP(H, a, b, c, d, GET( 3) + 0x6ED9EBA1,  3);
146                 STEP(H, d, a, b, c, GET(11) + 0x6ED9EBA1,  9);
147                 STEP(H, c, d, a, b, GET( 7) + 0x6ED9EBA1, 11);
148                 STEP(H, b, c, d, a, GET(15) + 0x6ED9EBA1, 15);
149
150                 a += saved_a;
151                 b += saved_b;
152                 c += saved_c;
153                 d += saved_d;
154
155                 ptr += 64;
156         } while (size -= 64);
157
158         ctx->a = a;
159         ctx->b = b;
160         ctx->c = c;
161         ctx->d = d;
162
163         return ptr;
164 }
165
166 void md4_init(struct md4_context *ctx)
167 {
168         ctx->a = 0x67452301;
169         ctx->b = 0xefcdab89;
170         ctx->c = 0x98badcfe;
171         ctx->d = 0x10325476;
172
173         ctx->lo = 0;
174         ctx->hi = 0;
175 }
176
177 void md4_update(struct md4_context *ctx, const void *data, size_t size)
178 {
179         /* @UNSAFE */
180         uint_fast32_t saved_lo;
181         unsigned long used, free;
182
183         saved_lo = ctx->lo;
184         if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
185                 ctx->hi++;
186         ctx->hi += size >> 29;
187
188         used = saved_lo & 0x3f;
189
190         if (used) {
191                 free = 64 - used;
192
193                 if (size < free) {
194                         memcpy(&ctx->buffer[used], data, size);
195                         return;
196                 }
197
198                 memcpy(&ctx->buffer[used], data, free);
199                 data = (const unsigned char *) data + free;
200                 size -= free;
201                 body(ctx, ctx->buffer, 64);
202         }
203
204         if (size >= 64) {
205                 data = body(ctx, data, size & ~(unsigned long)0x3f);
206                 size &= 0x3f;
207         }
208
209         memcpy(ctx->buffer, data, size);
210 }
211
212 void md4_final(struct md4_context *ctx, unsigned char result[MD4_RESULTLEN])
213 {
214         /* @UNSAFE */
215         unsigned long used, free;
216
217         used = ctx->lo & 0x3f;
218
219         ctx->buffer[used++] = 0x80;
220
221         free = 64 - used;
222
223         if (free < 8) {
224                 memset(&ctx->buffer[used], 0, free);
225                 body(ctx, ctx->buffer, 64);
226                 used = 0;
227                 free = 64;
228         }
229
230         memset(&ctx->buffer[used], 0, free - 8);
231
232         ctx->lo <<= 3;
233         ctx->buffer[56] = ctx->lo;
234         ctx->buffer[57] = ctx->lo >> 8;
235         ctx->buffer[58] = ctx->lo >> 16;
236         ctx->buffer[59] = ctx->lo >> 24;
237         ctx->buffer[60] = ctx->hi;
238         ctx->buffer[61] = ctx->hi >> 8;
239         ctx->buffer[62] = ctx->hi >> 16;
240         ctx->buffer[63] = ctx->hi >> 24;
241
242         body(ctx, ctx->buffer, 64);
243
244         result[0] = ctx->a;
245         result[1] = ctx->a >> 8;
246         result[2] = ctx->a >> 16;
247         result[3] = ctx->a >> 24;
248         result[4] = ctx->b;
249         result[5] = ctx->b >> 8;
250         result[6] = ctx->b >> 16;
251         result[7] = ctx->b >> 24;
252         result[8] = ctx->c;
253         result[9] = ctx->c >> 8;
254         result[10] = ctx->c >> 16;
255         result[11] = ctx->c >> 24;
256         result[12] = ctx->d;
257         result[13] = ctx->d >> 8;
258         result[14] = ctx->d >> 16;
259         result[15] = ctx->d >> 24;
260
261         memset(ctx, 0, sizeof(*ctx));
262 }
263
264 void md4_get_digest(const void *data, size_t size,
265                     unsigned char result[MD4_RESULTLEN])
266 {
267         struct md4_context ctx;
268
269         md4_init(&ctx);
270         md4_update(&ctx, data, size);
271         md4_final(&ctx, result);
272 }
273
274 static void hash_method_init_md4(void *context)
275 {
276         md4_init(context);
277 }
278 static void hash_method_loop_md4(void *context, const void *data, size_t size)
279 {
280         md4_update(context, data, size);
281 }
282
283 static void hash_method_result_md4(void *context, unsigned char *result_r)
284 {
285         md4_final(context, result_r);
286 }
287
288 const struct hash_method hash_method_md4 = {
289         "md4",
290         sizeof(struct md4_context),
291         MD4_RESULTLEN,
292
293         hash_method_init_md4,
294         hash_method_loop_md4,
295         hash_method_result_md4
296 };