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