1/*-
2   Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved.
3
4   License to copy and use this software is granted provided that it
5   is identified as the "RSA Data Security, Inc. MD4 Message-Digest
6   Algorithm" in all material mentioning or referencing this software
7   or this function.
8
9   License is also granted to make and use derivative works provided
10   that such works are identified as "derived from the RSA Data
11   Security, Inc. MD4 Message-Digest Algorithm" in all material
12   mentioning or referencing the derived work.
13
14   RSA Data Security, Inc. makes no representations concerning either
15   the merchantability of this software or the suitability of this
16   software for any particular purpose. It is provided "as is"
17   without express or implied warranty of any kind.
18
19   These notices must be retained in any copies of any part of this
20   documentation and/or software.
21 */
22
23#include "setup.h"
24
25/* NSS crypto library does not provide the MD4 hash algorithm, so that we have
26 * a local implementation of it */
27#ifdef USE_NSS
28
29#include "curl_md4.h"
30#include <string.h>
31
32typedef unsigned int UINT4;
33
34typedef struct MD4Context {
35  UINT4 state[4];               /* state (ABCD) */
36  UINT4 count[2];               /* number of bits, modulo 2^64 (lsb first) */
37  unsigned char buffer[64];     /* input buffer */
38} MD4_CTX;
39
40/* Constants for MD4Transform routine.
41 */
42#define S11 3
43#define S12 7
44#define S13 11
45#define S14 19
46#define S21 3
47#define S22 5
48#define S23 9
49#define S24 13
50#define S31 3
51#define S32 9
52#define S33 11
53#define S34 15
54
55static void MD4Transform(UINT4 [4], const unsigned char [64]);
56static void Encode(unsigned char *, UINT4 *, unsigned int);
57static void Decode(UINT4 *, const unsigned char *, unsigned int);
58
59static unsigned char PADDING[64] = {
60  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
61  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
63};
64
65/* F, G and H are basic MD4 functions.
66 */
67#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
68#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
69#define H(x, y, z) ((x) ^ (y) ^ (z))
70
71/* ROTATE_LEFT rotates x left n bits.
72 */
73#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
74
75/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
76/* Rotation is separate from addition to prevent recomputation */
77#define FF(a, b, c, d, x, s) { \
78    (a) += F ((b), (c), (d)) + (x); \
79    (a) = ROTATE_LEFT ((a), (s)); \
80  }
81#define GG(a, b, c, d, x, s) { \
82    (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \
83    (a) = ROTATE_LEFT ((a), (s)); \
84  }
85#define HH(a, b, c, d, x, s) { \
86    (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \
87    (a) = ROTATE_LEFT ((a), (s)); \
88  }
89
90/* MD4 initialization. Begins an MD4 operation, writing a new context.
91 */
92static void MD4Init(MD4_CTX *context)
93{
94  context->count[0] = context->count[1] = 0;
95
96  /* Load magic initialization constants.
97   */
98  context->state[0] = 0x67452301;
99  context->state[1] = 0xefcdab89;
100  context->state[2] = 0x98badcfe;
101  context->state[3] = 0x10325476;
102}
103
104/* MD4 block update operation. Continues an MD4 message-digest
105     operation, processing another message block, and updating the
106     context.
107 */
108static void MD4Update(MD4_CTX *context, const unsigned char *input,
109                      unsigned int inputLen)
110{
111  unsigned int i, bufindex, partLen;
112
113  /* Compute number of bytes mod 64 */
114  bufindex = (unsigned int)((context->count[0] >> 3) & 0x3F);
115  /* Update number of bits */
116  if((context->count[0] += ((UINT4)inputLen << 3))
117     < ((UINT4)inputLen << 3))
118    context->count[1]++;
119  context->count[1] += ((UINT4)inputLen >> 29);
120
121  partLen = 64 - bufindex;
122  /* Transform as many times as possible.
123   */
124  if(inputLen >= partLen) {
125    memcpy(&context->buffer[bufindex], input, partLen);
126    MD4Transform (context->state, context->buffer);
127
128    for(i = partLen; i + 63 < inputLen; i += 64)
129      MD4Transform (context->state, &input[i]);
130
131    bufindex = 0;
132  }
133  else
134    i = 0;
135
136  /* Buffer remaining input */
137  memcpy(&context->buffer[bufindex], &input[i], inputLen-i);
138}
139
140/* MD4 padding. */
141static void MD4Pad(MD4_CTX *context)
142{
143  unsigned char bits[8];
144  unsigned int bufindex, padLen;
145
146  /* Save number of bits */
147  Encode (bits, context->count, 8);
148
149  /* Pad out to 56 mod 64.
150   */
151  bufindex = (unsigned int)((context->count[0] >> 3) & 0x3f);
152  padLen = (bufindex < 56) ? (56 - bufindex) : (120 - bufindex);
153  MD4Update (context, PADDING, padLen);
154
155  /* Append length (before padding) */
156  MD4Update (context, bits, 8);
157}
158
159/* MD4 finalization. Ends an MD4 message-digest operation, writing the
160     the message digest and zeroizing the context.
161 */
162static void MD4Final (unsigned char digest[16], MD4_CTX *context)
163{
164  /* Do padding */
165  MD4Pad (context);
166
167  /* Store state in digest */
168  Encode (digest, context->state, 16);
169
170  /* Zeroize sensitive information.
171   */
172  memset(context, 0, sizeof(*context));
173}
174
175/* MD4 basic transformation. Transforms state based on block.
176 */
177static void MD4Transform (UINT4 state[4], const unsigned char block[64])
178{
179  UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
180
181  Decode (x, block, 64);
182
183  /* Round 1 */
184  FF (a, b, c, d, x[ 0], S11); /* 1 */
185  FF (d, a, b, c, x[ 1], S12); /* 2 */
186  FF (c, d, a, b, x[ 2], S13); /* 3 */
187  FF (b, c, d, a, x[ 3], S14); /* 4 */
188  FF (a, b, c, d, x[ 4], S11); /* 5 */
189  FF (d, a, b, c, x[ 5], S12); /* 6 */
190  FF (c, d, a, b, x[ 6], S13); /* 7 */
191  FF (b, c, d, a, x[ 7], S14); /* 8 */
192  FF (a, b, c, d, x[ 8], S11); /* 9 */
193  FF (d, a, b, c, x[ 9], S12); /* 10 */
194  FF (c, d, a, b, x[10], S13); /* 11 */
195  FF (b, c, d, a, x[11], S14); /* 12 */
196  FF (a, b, c, d, x[12], S11); /* 13 */
197  FF (d, a, b, c, x[13], S12); /* 14 */
198  FF (c, d, a, b, x[14], S13); /* 15 */
199  FF (b, c, d, a, x[15], S14); /* 16 */
200
201  /* Round 2 */
202  GG (a, b, c, d, x[ 0], S21); /* 17 */
203  GG (d, a, b, c, x[ 4], S22); /* 18 */
204  GG (c, d, a, b, x[ 8], S23); /* 19 */
205  GG (b, c, d, a, x[12], S24); /* 20 */
206  GG (a, b, c, d, x[ 1], S21); /* 21 */
207  GG (d, a, b, c, x[ 5], S22); /* 22 */
208  GG (c, d, a, b, x[ 9], S23); /* 23 */
209  GG (b, c, d, a, x[13], S24); /* 24 */
210  GG (a, b, c, d, x[ 2], S21); /* 25 */
211  GG (d, a, b, c, x[ 6], S22); /* 26 */
212  GG (c, d, a, b, x[10], S23); /* 27 */
213  GG (b, c, d, a, x[14], S24); /* 28 */
214  GG (a, b, c, d, x[ 3], S21); /* 29 */
215  GG (d, a, b, c, x[ 7], S22); /* 30 */
216  GG (c, d, a, b, x[11], S23); /* 31 */
217  GG (b, c, d, a, x[15], S24); /* 32 */
218
219  /* Round 3 */
220  HH (a, b, c, d, x[ 0], S31); /* 33 */
221  HH (d, a, b, c, x[ 8], S32); /* 34 */
222  HH (c, d, a, b, x[ 4], S33); /* 35 */
223  HH (b, c, d, a, x[12], S34); /* 36 */
224  HH (a, b, c, d, x[ 2], S31); /* 37 */
225  HH (d, a, b, c, x[10], S32); /* 38 */
226  HH (c, d, a, b, x[ 6], S33); /* 39 */
227  HH (b, c, d, a, x[14], S34); /* 40 */
228  HH (a, b, c, d, x[ 1], S31); /* 41 */
229  HH (d, a, b, c, x[ 9], S32); /* 42 */
230  HH (c, d, a, b, x[ 5], S33); /* 43 */
231  HH (b, c, d, a, x[13], S34); /* 44 */
232  HH (a, b, c, d, x[ 3], S31); /* 45 */
233  HH (d, a, b, c, x[11], S32); /* 46 */
234  HH (c, d, a, b, x[ 7], S33); /* 47 */
235  HH (b, c, d, a, x[15], S34); /* 48 */
236
237  state[0] += a;
238  state[1] += b;
239  state[2] += c;
240  state[3] += d;
241
242  /* Zeroize sensitive information.
243   */
244  memset(x, 0, sizeof(x));
245}
246
247/* Encodes input (UINT4) into output (unsigned char). Assumes len is
248     a multiple of 4.
249 */
250static void Encode(unsigned char *output, UINT4 *input, unsigned int len)
251{
252  unsigned int i, j;
253
254  for(i = 0, j = 0; j < len; i++, j += 4) {
255    output[j] = (unsigned char)(input[i] & 0xff);
256    output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
257    output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
258    output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
259  }
260}
261
262/* Decodes input (unsigned char) into output (UINT4). Assumes len is
263     a multiple of 4.
264 */
265static void Decode (UINT4 *output, const unsigned char *input,
266                    unsigned int len)
267{
268  unsigned int i, j;
269
270  for(i = 0, j = 0; j < len; i++, j += 4)
271    output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
272      (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
273}
274
275void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len)
276{
277  MD4_CTX ctx;
278  MD4Init(&ctx);
279  MD4Update(&ctx, input, (unsigned int)len);
280  MD4Final(output, &ctx);
281}
282#endif /* USE_NSS */
283