source: trunk/third/nmh/uip/md5.c @ 12455

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