Imported Upstream version 7.53.1
[platform/upstream/curl.git] / lib / md4.c
1 /*
2  * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
3  * MD4 Message-Digest Algorithm (RFC 1320).
4  *
5  * Homepage:
6  http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
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.  In case
13  * this attempt to disclaim copyright and place the software in the public
14  * domain is deemed null and void, then the software is Copyright (c) 2001
15  * Alexander Peslyak and it is hereby released to the general public under the
16  * 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 #include "curl_setup.h"
39
40 /* NSS and OS/400 crypto library do not provide the MD4 hash algorithm, so
41  * that we have a local implementation of it */
42 #if defined(USE_NSS) || defined(USE_OS400CRYPTO)
43
44 #include "curl_md4.h"
45 #include "warnless.h"
46
47 #ifndef HAVE_OPENSSL
48
49 #include <string.h>
50
51 /* Any 32-bit or wider unsigned integer data type will do */
52 typedef unsigned int MD4_u32plus;
53
54 typedef struct {
55   MD4_u32plus lo, hi;
56   MD4_u32plus a, b, c, d;
57   unsigned char buffer[64];
58   MD4_u32plus block[16];
59 } MD4_CTX;
60
61 static void MD4_Init(MD4_CTX *ctx);
62 static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size);
63 static void MD4_Final(unsigned char *result, MD4_CTX *ctx);
64
65 /*
66  * The basic MD4 functions.
67  *
68  * F and G are optimized compared to their RFC 1320 definitions, with the
69  * optimization for F borrowed from Colin Plumb's MD5 implementation.
70  */
71 #define F(x, y, z)                      ((z) ^ ((x) & ((y) ^ (z))))
72 #define G(x, y, z)                      (((x) & ((y) | (z))) | ((y) & (z)))
73 #define H(x, y, z)                      ((x) ^ (y) ^ (z))
74
75 /*
76  * The MD4 transformation for all three rounds.
77  */
78 #define STEP(f, a, b, c, d, x, s) \
79         (a) += f((b), (c), (d)) + (x); \
80         (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s))));
81
82 /*
83  * SET reads 4 input bytes in little-endian byte order and stores them
84  * in a properly aligned word in host byte order.
85  *
86  * The check for little-endian architectures that tolerate unaligned
87  * memory accesses is just an optimization.  Nothing will break if it
88  * doesn't work.
89  */
90 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
91 #define SET(n) \
92         (*(MD4_u32plus *)&ptr[(n) * 4])
93 #define GET(n) \
94         SET(n)
95 #else
96 #define SET(n) \
97         (ctx->block[(n)] = \
98         (MD4_u32plus)ptr[(n) * 4] | \
99         ((MD4_u32plus)ptr[(n) * 4 + 1] << 8) | \
100         ((MD4_u32plus)ptr[(n) * 4 + 2] << 16) | \
101         ((MD4_u32plus)ptr[(n) * 4 + 3] << 24))
102 #define GET(n) \
103         (ctx->block[(n)])
104 #endif
105
106 /*
107  * This processes one or more 64-byte data blocks, but does NOT update
108  * the bit counters.  There are no alignment requirements.
109  */
110 static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
111 {
112   const unsigned char *ptr;
113   MD4_u32plus a, b, c, d;
114   MD4_u32plus saved_a, saved_b, saved_c, saved_d;
115
116   ptr = (const unsigned char *)data;
117
118   a = ctx->a;
119   b = ctx->b;
120   c = ctx->c;
121   d = ctx->d;
122
123   do {
124     saved_a = a;
125     saved_b = b;
126     saved_c = c;
127     saved_d = d;
128
129 /* Round 1 */
130     STEP(F, a, b, c, d, SET(0), 3)
131       STEP(F, d, a, b, c, SET(1), 7)
132       STEP(F, c, d, a, b, SET(2), 11)
133       STEP(F, b, c, d, a, SET(3), 19)
134       STEP(F, a, b, c, d, SET(4), 3)
135       STEP(F, d, a, b, c, SET(5), 7)
136       STEP(F, c, d, a, b, SET(6), 11)
137       STEP(F, b, c, d, a, SET(7), 19)
138       STEP(F, a, b, c, d, SET(8), 3)
139       STEP(F, d, a, b, c, SET(9), 7)
140       STEP(F, c, d, a, b, SET(10), 11)
141       STEP(F, b, c, d, a, SET(11), 19)
142       STEP(F, a, b, c, d, SET(12), 3)
143       STEP(F, d, a, b, c, SET(13), 7)
144       STEP(F, c, d, a, b, SET(14), 11)
145       STEP(F, b, c, d, a, SET(15), 19)
146
147 /* Round 2 */
148       STEP(G, a, b, c, d, GET(0) + 0x5a827999, 3)
149       STEP(G, d, a, b, c, GET(4) + 0x5a827999, 5)
150       STEP(G, c, d, a, b, GET(8) + 0x5a827999, 9)
151       STEP(G, b, c, d, a, GET(12) + 0x5a827999, 13)
152       STEP(G, a, b, c, d, GET(1) + 0x5a827999, 3)
153       STEP(G, d, a, b, c, GET(5) + 0x5a827999, 5)
154       STEP(G, c, d, a, b, GET(9) + 0x5a827999, 9)
155       STEP(G, b, c, d, a, GET(13) + 0x5a827999, 13)
156       STEP(G, a, b, c, d, GET(2) + 0x5a827999, 3)
157       STEP(G, d, a, b, c, GET(6) + 0x5a827999, 5)
158       STEP(G, c, d, a, b, GET(10) + 0x5a827999, 9)
159       STEP(G, b, c, d, a, GET(14) + 0x5a827999, 13)
160       STEP(G, a, b, c, d, GET(3) + 0x5a827999, 3)
161       STEP(G, d, a, b, c, GET(7) + 0x5a827999, 5)
162       STEP(G, c, d, a, b, GET(11) + 0x5a827999, 9)
163       STEP(G, b, c, d, a, GET(15) + 0x5a827999, 13)
164
165 /* Round 3 */
166       STEP(H, a, b, c, d, GET(0) + 0x6ed9eba1, 3)
167       STEP(H, d, a, b, c, GET(8) + 0x6ed9eba1, 9)
168       STEP(H, c, d, a, b, GET(4) + 0x6ed9eba1, 11)
169       STEP(H, b, c, d, a, GET(12) + 0x6ed9eba1, 15)
170       STEP(H, a, b, c, d, GET(2) + 0x6ed9eba1, 3)
171       STEP(H, d, a, b, c, GET(10) + 0x6ed9eba1, 9)
172       STEP(H, c, d, a, b, GET(6) + 0x6ed9eba1, 11)
173       STEP(H, b, c, d, a, GET(14) + 0x6ed9eba1, 15)
174       STEP(H, a, b, c, d, GET(1) + 0x6ed9eba1, 3)
175       STEP(H, d, a, b, c, GET(9) + 0x6ed9eba1, 9)
176       STEP(H, c, d, a, b, GET(5) + 0x6ed9eba1, 11)
177       STEP(H, b, c, d, a, GET(13) + 0x6ed9eba1, 15)
178       STEP(H, a, b, c, d, GET(3) + 0x6ed9eba1, 3)
179       STEP(H, d, a, b, c, GET(11) + 0x6ed9eba1, 9)
180       STEP(H, c, d, a, b, GET(7) + 0x6ed9eba1, 11)
181       STEP(H, b, c, d, a, GET(15) + 0x6ed9eba1, 15)
182
183       a += saved_a;
184     b += saved_b;
185     c += saved_c;
186     d += saved_d;
187
188     ptr += 64;
189   } while(size -= 64);
190
191   ctx->a = a;
192   ctx->b = b;
193   ctx->c = c;
194   ctx->d = d;
195
196   return ptr;
197 }
198
199 static void MD4_Init(MD4_CTX *ctx)
200 {
201   ctx->a = 0x67452301;
202   ctx->b = 0xefcdab89;
203   ctx->c = 0x98badcfe;
204   ctx->d = 0x10325476;
205
206   ctx->lo = 0;
207   ctx->hi = 0;
208 }
209
210 static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
211 {
212   MD4_u32plus saved_lo;
213   unsigned long used, available;
214
215   saved_lo = ctx->lo;
216   ctx->lo = (saved_lo + size) & 0x1fffffff;
217   if(ctx->lo < saved_lo)
218     ctx->hi++;
219   ctx->hi += (MD4_u32plus)size >> 29;
220
221   used = saved_lo & 0x3f;
222
223   if(used) {
224     available = 64 - used;
225
226     if(size < available) {
227       memcpy(&ctx->buffer[used], data, size);
228       return;
229     }
230
231     memcpy(&ctx->buffer[used], data, available);
232     data = (const unsigned char *)data + available;
233     size -= available;
234     body(ctx, ctx->buffer, 64);
235   }
236
237   if(size >= 64) {
238     data = body(ctx, data, size & ~(unsigned long)0x3f);
239     size &= 0x3f;
240   }
241
242   memcpy(ctx->buffer, data, size);
243 }
244
245 static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
246 {
247   unsigned long used, available;
248
249   used = ctx->lo & 0x3f;
250
251   ctx->buffer[used++] = 0x80;
252
253   available = 64 - used;
254
255   if(available < 8) {
256     memset(&ctx->buffer[used], 0, available);
257     body(ctx, ctx->buffer, 64);
258     used = 0;
259     available = 64;
260   }
261
262   memset(&ctx->buffer[used], 0, available - 8);
263
264   ctx->lo <<= 3;
265   ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff);
266   ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff);
267   ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff);
268   ctx->buffer[59] = curlx_ultouc((ctx->lo >> 24)&0xff);
269   ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff);
270   ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff);
271   ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff);
272   ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24);
273
274   body(ctx, ctx->buffer, 64);
275
276   result[0] = curlx_ultouc((ctx->a)&0xff);
277   result[1] = curlx_ultouc((ctx->a >> 8)&0xff);
278   result[2] = curlx_ultouc((ctx->a >> 16)&0xff);
279   result[3] = curlx_ultouc(ctx->a >> 24);
280   result[4] = curlx_ultouc((ctx->b)&0xff);
281   result[5] = curlx_ultouc((ctx->b >> 8)&0xff);
282   result[6] = curlx_ultouc((ctx->b >> 16)&0xff);
283   result[7] = curlx_ultouc(ctx->b >> 24);
284   result[8] = curlx_ultouc((ctx->c)&0xff);
285   result[9] = curlx_ultouc((ctx->c >> 8)&0xff);
286   result[10] = curlx_ultouc((ctx->c >> 16)&0xff);
287   result[11] = curlx_ultouc(ctx->c >> 24);
288   result[12] = curlx_ultouc((ctx->d)&0xff);
289   result[13] = curlx_ultouc((ctx->d >> 8)&0xff);
290   result[14] = curlx_ultouc((ctx->d >> 16)&0xff);
291   result[15] = curlx_ultouc(ctx->d >> 24);
292
293   memset(ctx, 0, sizeof(*ctx));
294 }
295
296 #endif
297
298 void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len)
299 {
300   MD4_CTX ctx;
301   MD4_Init(&ctx);
302   MD4_Update(&ctx, input, curlx_uztoui(len));
303   MD4_Final(output, &ctx);
304 }
305 #endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) */