OSDN Git Service

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