md5.c revision 145510
1235848Sissyl0/*	$NetBSD$	*/
2235848Sissyl0
3235848Sissyl0
4235848Sissyl0
5235848Sissyl0/*
6235848Sissyl0 ***********************************************************************
7235848Sissyl0 ** md5.c -- the source code for MD5 routines                         **
8235848Sissyl0 ** RSA Data Security, Inc. MD5 Message-Digest Algorithm              **
9235848Sissyl0 ** Created: 2/17/90 RLR                                              **
10235848Sissyl0 ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. **
11235848Sissyl0 ***********************************************************************
12235848Sissyl0 */
13235848Sissyl0
14235848Sissyl0/*
15235848Sissyl0 ***********************************************************************
16235848Sissyl0 ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved.  **
17235848Sissyl0 **                                                                   **
18235848Sissyl0 ** License to copy and use this software is granted provided that    **
19235848Sissyl0 ** it is identified as the "RSA Data Security, Inc. MD5 Message-     **
20235848Sissyl0 ** Digest Algorithm" in all material mentioning or referencing this  **
21235848Sissyl0 ** software or this function.                                        **
22235848Sissyl0 **                                                                   **
23235848Sissyl0 ** License is also granted to make and use derivative works          **
24235848Sissyl0 ** provided that such works are identified as "derived from the RSA  **
25235848Sissyl0 ** Data Security, Inc. MD5 Message-Digest Algorithm" in all          **
26235848Sissyl0 ** material mentioning or referencing the derived work.              **
27235848Sissyl0 **                                                                   **
28235848Sissyl0 ** RSA Data Security, Inc. makes no representations concerning       **
29235848Sissyl0 ** either the merchantability of this software or the suitability    **
30235848Sissyl0 ** of this software for any particular purpose.  It is provided "as  **
31235848Sissyl0 ** is" without express or implied warranty of any kind.              **
32235848Sissyl0 **                                                                   **
33235848Sissyl0 ** These notices must be retained in any copies of any part of this  **
34235848Sissyl0 ** documentation and/or software.                                    **
35235848Sissyl0 ***********************************************************************
36235848Sissyl0 */
37235848Sissyl0
38235848Sissyl0#if defined(_KERNEL) && !defined(__sgi)
39235848Sissyl0# include <sys/systm.h>
40235848Sissyl0#else
41235848Sissyl0# include <string.h>
42258245Seadler#endif
43235848Sissyl0
44235848Sissyl0#include "md5.h"
45235848Sissyl0
46235848Sissyl0/*
47235848Sissyl0 ***********************************************************************
48235848Sissyl0 **  Message-digest routines:                                         **
49235848Sissyl0 **  To form the message digest for a message M                       **
50235848Sissyl0 **    (1) Initialize a context buffer mdContext using MD5Init        **
51235848Sissyl0 **    (2) Call MD5Update on mdContext and M                          **
52235848Sissyl0 **    (3) Call MD5Final on mdContext                                 **
53235848Sissyl0 **  The message digest is now in mdContext->digest[0...15]           **
54235848Sissyl0 ***********************************************************************
55235848Sissyl0 */
56235848Sissyl0
57235848Sissyl0/* forward declaration */
58235848Sissyl0static void Transform __P((UINT4 *, UINT4 *));
59235848Sissyl0
60235848Sissyl0static unsigned char PADDING[64] = {
61240518Seadler  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62235848Sissyl0  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63235848Sissyl0  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64235848Sissyl0  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65235848Sissyl0  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66235848Sissyl0  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67235848Sissyl0  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68235848Sissyl0  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
69235848Sissyl0};
70235848Sissyl0
71235848Sissyl0/* F, G, H and I are basic MD5 functions */
72#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
73#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
74#define H(x, y, z) ((x) ^ (y) ^ (z))
75#define I(x, y, z) ((y) ^ ((x) | (~z)))
76
77/* ROTATE_LEFT rotates x left n bits */
78#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
79
80/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
81/* Rotation is separate from addition to prevent recomputation */
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#ifdef __STDC__
104#define UL(x)	x##U
105#else
106#define UL(x)	x
107#endif
108
109/* The routine MD5Init initializes the message-digest context
110   mdContext. All fields are set to zero.
111 */
112void MD5Init (mdContext)
113MD5_CTX *mdContext;
114{
115  mdContext->i[0] = mdContext->i[1] = (UINT4)0;
116
117  /* Load magic initialization constants.
118   */
119  mdContext->buf[0] = (UINT4)0x67452301;
120  mdContext->buf[1] = (UINT4)0xefcdab89;
121  mdContext->buf[2] = (UINT4)0x98badcfe;
122  mdContext->buf[3] = (UINT4)0x10325476;
123}
124
125/* The routine MD5Update updates the message-digest context to
126   account for the presence of each of the characters inBuf[0..inLen-1]
127   in the message whose digest is being computed.
128 */
129void MD5Update (mdContext, inBuf, inLen)
130MD5_CTX *mdContext;
131unsigned char *inBuf;
132unsigned int inLen;
133{
134  UINT4 in[16];
135  int mdi;
136  unsigned int i, ii;
137
138  /* compute number of bytes mod 64 */
139  mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
140
141  /* update number of bits */
142  if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
143    mdContext->i[1]++;
144  mdContext->i[0] += ((UINT4)inLen << 3);
145  mdContext->i[1] += ((UINT4)inLen >> 29);
146
147  while (inLen--) {
148    /* add new character to buffer, increment mdi */
149    mdContext->in[mdi++] = *inBuf++;
150
151    /* transform if necessary */
152    if (mdi == 0x40) {
153      for (i = 0, ii = 0; i < 16; i++, ii += 4)
154        in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
155                (((UINT4)mdContext->in[ii+2]) << 16) |
156                (((UINT4)mdContext->in[ii+1]) << 8) |
157                ((UINT4)mdContext->in[ii]);
158      Transform (mdContext->buf, in);
159      mdi = 0;
160    }
161  }
162}
163
164/* The routine MD5Final terminates the message-digest computation and
165   ends with the desired message digest in mdContext->digest[0...15].
166 */
167void MD5Final (hash, mdContext)
168unsigned char hash[];
169MD5_CTX *mdContext;
170{
171  UINT4 in[16];
172  int mdi;
173  unsigned int i, ii;
174  unsigned int padLen;
175
176  /* save number of bits */
177  in[14] = mdContext->i[0];
178  in[15] = mdContext->i[1];
179
180  /* compute number of bytes mod 64 */
181  mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
182
183  /* pad out to 56 mod 64 */
184  padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
185  MD5Update (mdContext, PADDING, padLen);
186
187  /* append length in bits and transform */
188  for (i = 0, ii = 0; i < 14; i++, ii += 4)
189    in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
190            (((UINT4)mdContext->in[ii+2]) << 16) |
191            (((UINT4)mdContext->in[ii+1]) << 8) |
192            ((UINT4)mdContext->in[ii]);
193  Transform (mdContext->buf, in);
194
195  /* store buffer in digest */
196  for (i = 0, ii = 0; i < 4; i++, ii += 4) {
197    mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
198    mdContext->digest[ii+1] =
199      (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
200    mdContext->digest[ii+2] =
201      (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
202    mdContext->digest[ii+3] =
203      (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
204  }
205  bcopy((char *)mdContext->digest, (char *)hash, 16);
206}
207
208/* Basic MD5 step. Transforms buf based on in.
209 */
210static void Transform (buf, in)
211UINT4 *buf;
212UINT4 *in;
213{
214  UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
215
216  /* Round 1 */
217#define S11 7
218#define S12 12
219#define S13 17
220#define S14 22
221  FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */
222  FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */
223  FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */
224  FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */
225  FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */
226  FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */
227  FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */
228  FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */
229  FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */
230  FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */
231  FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */
232  FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */
233  FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */
234  FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */
235  FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */
236  FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */
237
238  /* Round 2 */
239#define S21 5
240#define S22 9
241#define S23 14
242#define S24 20
243  GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */
244  GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */
245  GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */
246  GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */
247  GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */
248  GG ( d, a, b, c, in[10], S22, UL(  38016083)); /* 22 */
249  GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */
250  GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */
251  GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */
252  GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */
253  GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */
254  GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */
255  GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */
256  GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */
257  GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */
258  GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */
259
260  /* Round 3 */
261#define S31 4
262#define S32 11
263#define S33 16
264#define S34 23
265  HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */
266  HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */
267  HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */
268  HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */
269  HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */
270  HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */
271  HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */
272  HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */
273  HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */
274  HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */
275  HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */
276  HH ( b, c, d, a, in[ 6], S34, UL(  76029189)); /* 44 */
277  HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */
278  HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */
279  HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */
280  HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */
281
282  /* Round 4 */
283#define S41 6
284#define S42 10
285#define S43 15
286#define S44 21
287  II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */
288  II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */
289  II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */
290  II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */
291  II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */
292  II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */
293  II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */
294  II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */
295  II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */
296  II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */
297  II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */
298  II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */
299  II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */
300  II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */
301  II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */
302  II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */
303
304  buf[0] += a;
305  buf[1] += b;
306  buf[2] += c;
307  buf[3] += d;
308}
309
310/*
311 ***********************************************************************
312 ** End of md5.c                                                      **
313 ******************************** (cut) ********************************
314 */
315