Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / uip / md5.c
1 #ifndef lint
2 static char md5ident[]="@(#)$Id: md5.c,v 1.4 1992/10/26 16:48:02 jromine Exp $";
3 #endif
4 /* taken from RFC-1321/Appendix A.3 */
5
6 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
7  */
8
9 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
10 rights reserved.
11
12 License to copy and use this software is granted provided that it
13 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
14 Algorithm" in all material mentioning or referencing this software
15 or this function.
16
17 License is also granted to make and use derivative works provided
18 that such works are identified as "derived from the RSA Data
19 Security, Inc. MD5 Message-Digest Algorithm" in all material
20 mentioning or referencing the derived work.
21
22 RSA Data Security, Inc. makes no representations concerning either
23 the merchantability of this software or the suitability of this
24 software for any particular purpose. It is provided "as is"
25 without express or implied warranty of any kind.
26
27 These notices must be retained in any copies of any part of this
28 documentation and/or software.
29  */
30
31 /* #include "global.h" */
32 #include "../h/md5.h"
33
34 /* Constants for MD5Transform routine.
35  */
36 #define S11 7
37 #define S12 12
38 #define S13 17
39 #define S14 22
40 #define S21 5
41 #define S22 9
42 #define S23 14
43 #define S24 20
44 #define S31 4
45 #define S32 11
46 #define S33 16
47 #define S34 23
48 #define S41 6
49 #define S42 10
50 #define S43 15
51 #define S44 21
52
53 static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
54 static void Encode PROTO_LIST
55   ((unsigned char *, UINT4 *, unsigned int));
56 static void Decode PROTO_LIST
57   ((UINT4 *, unsigned char *, unsigned int));
58 static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
59 static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
60
61 static unsigned char PADDING[64] = {
62   0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
63   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
65 };
66
67 /* F, G, H and I are basic MD5 functions.
68  */
69 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
70 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
71 #define H(x, y, z) ((x) ^ (y) ^ (z))
72 #define I(x, y, z) ((y) ^ ((x) | (~z)))
73
74 /* ROTATE_LEFT rotates x left n bits.
75  */
76 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
77
78 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
79 Rotation is separate from addition to prevent recomputation.
80  */
81 #define FF(a, b, c, d, x, s, ac) { \
82  (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
83  (a) = ROTATE_LEFT ((a), (s)); \
84  (a) += (b); \
85   }
86 #define GG(a, b, c, d, x, s, ac) { \
87  (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
88  (a) = ROTATE_LEFT ((a), (s)); \
89  (a) += (b); \
90   }
91 #define HH(a, b, c, d, x, s, ac) { \
92  (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
93  (a) = ROTATE_LEFT ((a), (s)); \
94  (a) += (b); \
95   }
96 #define II(a, b, c, d, x, s, ac) { \
97  (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
98  (a) = ROTATE_LEFT ((a), (s)); \
99  (a) += (b); \
100   }
101
102 /* MD5 initialization. Begins an MD5 operation, writing a new context.
103  */
104 void MD5Init (context)
105 MD5_CTX *context;                                        /* context */
106 {
107   context->count[0] = context->count[1] = 0;
108   /* Load magic initialization constants.
109 */
110   context->state[0] = 0x67452301;
111   context->state[1] = 0xefcdab89;
112   context->state[2] = 0x98badcfe;
113   context->state[3] = 0x10325476;
114 }
115
116 /* MD5 block update operation. Continues an MD5 message-digest
117   operation, processing another message block, and updating the
118   context.
119  */
120 void MD5Update (context, input, inputLen)
121 MD5_CTX *context;                                        /* context */
122 unsigned char *input;                                /* input block */
123 unsigned int inputLen;                     /* length of input block */
124 {
125   unsigned int i, index, partLen;
126
127   /* Compute number of bytes mod 64 */
128   index = (unsigned int)((context->count[0] >> 3) & 0x3F);
129
130   /* Update number of bits */
131   if ((context->count[0] += ((UINT4)inputLen << 3))
132    < ((UINT4)inputLen << 3))
133  context->count[1]++;
134   context->count[1] += ((UINT4)inputLen >> 29);
135
136   partLen = 64 - index;
137
138   /* Transform as many times as possible.
139 */
140   if (inputLen >= partLen) {
141  MD5_memcpy
142    ((POINTER)&context->buffer[index], (POINTER)input, partLen);
143  MD5Transform (context->state, context->buffer);
144
145  for (i = partLen; i + 63 < inputLen; i += 64)
146    MD5Transform (context->state, &input[i]);
147
148  index = 0;
149   }
150   else
151  i = 0;
152
153   /* Buffer remaining input */
154   MD5_memcpy
155  ((POINTER)&context->buffer[index], (POINTER)&input[i],
156   inputLen-i);
157 }
158
159 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
160   the message digest and zeroizing the context.
161  */
162 void MD5Final (digest, context)
163 unsigned char digest[16];                         /* message digest */
164 MD5_CTX *context;                                       /* context */
165 {
166   unsigned char bits[8];
167   unsigned int index, padLen;
168
169   /* Save number of bits */
170   Encode (bits, context->count, 8);
171
172   /* Pad out to 56 mod 64.
173 */
174   index = (unsigned int)((context->count[0] >> 3) & 0x3f);
175   padLen = (index < 56) ? (56 - index) : (120 - index);
176   MD5Update (context, PADDING, padLen);
177
178   /* Append length (before padding) */
179   MD5Update (context, bits, 8);
180   /* Store state in digest */
181   Encode (digest, context->state, 16);
182
183   /* Zeroize sensitive information.
184 */
185   MD5_memset ((POINTER)context, 0, sizeof (*context));
186 }
187
188 /* MD5 basic transformation. Transforms state based on block.
189  */
190 static void MD5Transform (state, block)
191 UINT4 state[4];
192 unsigned char block[64];
193 {
194   UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
195
196   Decode (x, block, 64);
197
198   /* Round 1 */
199   FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
200   FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
201   FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
202   FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
203   FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
204   FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
205   FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
206   FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
207   FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
208   FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
209   FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
210   FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
211   FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
212   FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
213   FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
214   FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
215
216  /* Round 2 */
217   GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
218   GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
219   GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
220   GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
221   GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
222   GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
223   GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
224   GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
225   GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
226   GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
227   GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
228   GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
229   GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
230   GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
231   GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
232   GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
233
234   /* Round 3 */
235   HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
236   HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
237   HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
238   HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
239   HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
240   HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
241   HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
242   HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
243   HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
244   HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
245   HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
246   HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
247   HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
248   HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
249   HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
250   HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
251
252   /* Round 4 */
253   II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
254   II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
255   II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
256   II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
257   II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
258   II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
259   II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
260   II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
261   II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
262   II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
263   II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
264   II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
265   II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
266   II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
267   II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
268   II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
269
270   state[0] += a;
271   state[1] += b;
272   state[2] += c;
273   state[3] += d;
274
275   /* Zeroize sensitive information.
276 */
277   MD5_memset ((POINTER)x, 0, sizeof (x));
278 }
279
280 /* Encodes input (UINT4) into output (unsigned char). Assumes len is
281   a multiple of 4.
282  */
283 static void Encode (output, input, len)
284 unsigned char *output;
285 UINT4 *input;
286 unsigned int len;
287 {
288   unsigned int i, j;
289
290   for (i = 0, j = 0; j < len; i++, j += 4) {
291  output[j] = (unsigned char)(input[i] & 0xff);
292  output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
293  output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
294  output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
295   }
296 }
297
298 /* Decodes input (unsigned char) into output (UINT4). Assumes len is
299   a multiple of 4.
300  */
301 static void Decode (output, input, len)
302 UINT4 *output;
303 unsigned char *input;
304 unsigned int len;
305 {
306   unsigned int i, j;
307
308   for (i = 0, j = 0; j < len; i++, j += 4)
309  output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
310    (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
311 }
312
313 /* Note: Replace "for loop" with standard memcpy if possible.
314  */
315
316 static void MD5_memcpy (output, input, len)
317 POINTER output;
318 POINTER input;
319 unsigned int len;
320 {
321   unsigned int i;
322
323   for (i = 0; i < len; i++)
324  output[i] = input[i];
325 }
326
327 /* Note: Replace "for loop" with standard memset if possible.
328  */
329 static void MD5_memset (output, value, len)
330 POINTER output;
331 int value;
332 unsigned int len;
333 {
334   unsigned int i;
335
336   for (i = 0; i < len; i++)
337  ((char *)output)[i] = (char)value;
338 }