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