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