1145519Sdarrenr/*	$FreeBSD$	*/
2145510Sdarrenr
3145510Sdarrenr
4145510Sdarrenr
5145510Sdarrenr/*
6145510Sdarrenr ***********************************************************************
7145510Sdarrenr ** md5.c -- the source code for MD5 routines                         **
8145510Sdarrenr ** RSA Data Security, Inc. MD5 Message-Digest Algorithm              **
9145510Sdarrenr ** Created: 2/17/90 RLR                                              **
10145510Sdarrenr ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. **
11145510Sdarrenr ***********************************************************************
12145510Sdarrenr */
13145510Sdarrenr
14145510Sdarrenr/*
15145510Sdarrenr ***********************************************************************
16145510Sdarrenr ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved.  **
17145510Sdarrenr **                                                                   **
18145510Sdarrenr ** License to copy and use this software is granted provided that    **
19145510Sdarrenr ** it is identified as the "RSA Data Security, Inc. MD5 Message-     **
20145510Sdarrenr ** Digest Algorithm" in all material mentioning or referencing this  **
21145510Sdarrenr ** software or this function.                                        **
22145510Sdarrenr **                                                                   **
23145510Sdarrenr ** License is also granted to make and use derivative works          **
24145510Sdarrenr ** provided that such works are identified as "derived from the RSA  **
25145510Sdarrenr ** Data Security, Inc. MD5 Message-Digest Algorithm" in all          **
26145510Sdarrenr ** material mentioning or referencing the derived work.              **
27145510Sdarrenr **                                                                   **
28145510Sdarrenr ** RSA Data Security, Inc. makes no representations concerning       **
29145510Sdarrenr ** either the merchantability of this software or the suitability    **
30145510Sdarrenr ** of this software for any particular purpose.  It is provided "as  **
31145510Sdarrenr ** is" without express or implied warranty of any kind.              **
32145510Sdarrenr **                                                                   **
33145510Sdarrenr ** These notices must be retained in any copies of any part of this  **
34145510Sdarrenr ** documentation and/or software.                                    **
35145510Sdarrenr ***********************************************************************
36145510Sdarrenr */
37145510Sdarrenr
38145510Sdarrenr#if defined(_KERNEL) && !defined(__sgi)
39145510Sdarrenr# include <sys/systm.h>
40145510Sdarrenr#else
41145510Sdarrenr# include <string.h>
42145510Sdarrenr#endif
43145510Sdarrenr
44145510Sdarrenr#include "md5.h"
45145510Sdarrenr
46145510Sdarrenr/*
47145510Sdarrenr ***********************************************************************
48145510Sdarrenr **  Message-digest routines:                                         **
49145510Sdarrenr **  To form the message digest for a message M                       **
50145510Sdarrenr **    (1) Initialize a context buffer mdContext using MD5Init        **
51145510Sdarrenr **    (2) Call MD5Update on mdContext and M                          **
52145510Sdarrenr **    (3) Call MD5Final on mdContext                                 **
53145510Sdarrenr **  The message digest is now in mdContext->digest[0...15]           **
54145510Sdarrenr ***********************************************************************
55145510Sdarrenr */
56145510Sdarrenr
57145510Sdarrenr/* forward declaration */
58145510Sdarrenrstatic void Transform __P((UINT4 *, UINT4 *));
59145510Sdarrenr
60145510Sdarrenrstatic unsigned char PADDING[64] = {
61145510Sdarrenr  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62145510Sdarrenr  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63145510Sdarrenr  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64145510Sdarrenr  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65145510Sdarrenr  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66145510Sdarrenr  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67145510Sdarrenr  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68145510Sdarrenr  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
69145510Sdarrenr};
70145510Sdarrenr
71145510Sdarrenr/* F, G, H and I are basic MD5 functions */
72145510Sdarrenr#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
73145510Sdarrenr#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
74145510Sdarrenr#define H(x, y, z) ((x) ^ (y) ^ (z))
75145510Sdarrenr#define I(x, y, z) ((y) ^ ((x) | (~z)))
76145510Sdarrenr
77145510Sdarrenr/* ROTATE_LEFT rotates x left n bits */
78145510Sdarrenr#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
79145510Sdarrenr
80145510Sdarrenr/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
81145510Sdarrenr/* Rotation is separate from addition to prevent recomputation */
82145510Sdarrenr#define FF(a, b, c, d, x, s, ac) \
83145510Sdarrenr  {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
84145510Sdarrenr   (a) = ROTATE_LEFT ((a), (s)); \
85145510Sdarrenr   (a) += (b); \
86145510Sdarrenr  }
87145510Sdarrenr#define GG(a, b, c, d, x, s, ac) \
88145510Sdarrenr  {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
89145510Sdarrenr   (a) = ROTATE_LEFT ((a), (s)); \
90145510Sdarrenr   (a) += (b); \
91145510Sdarrenr  }
92145510Sdarrenr#define HH(a, b, c, d, x, s, ac) \
93145510Sdarrenr  {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
94145510Sdarrenr   (a) = ROTATE_LEFT ((a), (s)); \
95145510Sdarrenr   (a) += (b); \
96145510Sdarrenr  }
97145510Sdarrenr#define II(a, b, c, d, x, s, ac) \
98145510Sdarrenr  {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
99145510Sdarrenr   (a) = ROTATE_LEFT ((a), (s)); \
100145510Sdarrenr   (a) += (b); \
101145510Sdarrenr  }
102145510Sdarrenr
103145510Sdarrenr#ifdef __STDC__
104145510Sdarrenr#define UL(x)	x##U
105145510Sdarrenr#else
106145510Sdarrenr#define UL(x)	x
107145510Sdarrenr#endif
108145510Sdarrenr
109145510Sdarrenr/* The routine MD5Init initializes the message-digest context
110145510Sdarrenr   mdContext. All fields are set to zero.
111145510Sdarrenr */
112145510Sdarrenrvoid MD5Init (mdContext)
113145510SdarrenrMD5_CTX *mdContext;
114145510Sdarrenr{
115145510Sdarrenr  mdContext->i[0] = mdContext->i[1] = (UINT4)0;
116145510Sdarrenr
117145510Sdarrenr  /* Load magic initialization constants.
118145510Sdarrenr   */
119145510Sdarrenr  mdContext->buf[0] = (UINT4)0x67452301;
120145510Sdarrenr  mdContext->buf[1] = (UINT4)0xefcdab89;
121145510Sdarrenr  mdContext->buf[2] = (UINT4)0x98badcfe;
122145510Sdarrenr  mdContext->buf[3] = (UINT4)0x10325476;
123145510Sdarrenr}
124145510Sdarrenr
125145510Sdarrenr/* The routine MD5Update updates the message-digest context to
126145510Sdarrenr   account for the presence of each of the characters inBuf[0..inLen-1]
127145510Sdarrenr   in the message whose digest is being computed.
128145510Sdarrenr */
129145510Sdarrenrvoid MD5Update (mdContext, inBuf, inLen)
130145510SdarrenrMD5_CTX *mdContext;
131145510Sdarrenrunsigned char *inBuf;
132145510Sdarrenrunsigned int inLen;
133145510Sdarrenr{
134145510Sdarrenr  UINT4 in[16];
135145510Sdarrenr  int mdi;
136145510Sdarrenr  unsigned int i, ii;
137145510Sdarrenr
138145510Sdarrenr  /* compute number of bytes mod 64 */
139145510Sdarrenr  mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
140145510Sdarrenr
141145510Sdarrenr  /* update number of bits */
142145510Sdarrenr  if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
143145510Sdarrenr    mdContext->i[1]++;
144145510Sdarrenr  mdContext->i[0] += ((UINT4)inLen << 3);
145145510Sdarrenr  mdContext->i[1] += ((UINT4)inLen >> 29);
146145510Sdarrenr
147145510Sdarrenr  while (inLen--) {
148145510Sdarrenr    /* add new character to buffer, increment mdi */
149145510Sdarrenr    mdContext->in[mdi++] = *inBuf++;
150145510Sdarrenr
151145510Sdarrenr    /* transform if necessary */
152145510Sdarrenr    if (mdi == 0x40) {
153145510Sdarrenr      for (i = 0, ii = 0; i < 16; i++, ii += 4)
154145510Sdarrenr        in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
155145510Sdarrenr                (((UINT4)mdContext->in[ii+2]) << 16) |
156145510Sdarrenr                (((UINT4)mdContext->in[ii+1]) << 8) |
157145510Sdarrenr                ((UINT4)mdContext->in[ii]);
158145510Sdarrenr      Transform (mdContext->buf, in);
159145510Sdarrenr      mdi = 0;
160145510Sdarrenr    }
161145510Sdarrenr  }
162145510Sdarrenr}
163145510Sdarrenr
164145510Sdarrenr/* The routine MD5Final terminates the message-digest computation and
165145510Sdarrenr   ends with the desired message digest in mdContext->digest[0...15].
166145510Sdarrenr */
167145510Sdarrenrvoid MD5Final (hash, mdContext)
168145510Sdarrenrunsigned char hash[];
169145510SdarrenrMD5_CTX *mdContext;
170145510Sdarrenr{
171145510Sdarrenr  UINT4 in[16];
172145510Sdarrenr  int mdi;
173145510Sdarrenr  unsigned int i, ii;
174145510Sdarrenr  unsigned int padLen;
175145510Sdarrenr
176145510Sdarrenr  /* save number of bits */
177145510Sdarrenr  in[14] = mdContext->i[0];
178145510Sdarrenr  in[15] = mdContext->i[1];
179145510Sdarrenr
180145510Sdarrenr  /* compute number of bytes mod 64 */
181145510Sdarrenr  mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
182145510Sdarrenr
183145510Sdarrenr  /* pad out to 56 mod 64 */
184145510Sdarrenr  padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
185145510Sdarrenr  MD5Update (mdContext, PADDING, padLen);
186145510Sdarrenr
187145510Sdarrenr  /* append length in bits and transform */
188145510Sdarrenr  for (i = 0, ii = 0; i < 14; i++, ii += 4)
189145510Sdarrenr    in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
190145510Sdarrenr            (((UINT4)mdContext->in[ii+2]) << 16) |
191145510Sdarrenr            (((UINT4)mdContext->in[ii+1]) << 8) |
192145510Sdarrenr            ((UINT4)mdContext->in[ii]);
193145510Sdarrenr  Transform (mdContext->buf, in);
194145510Sdarrenr
195145510Sdarrenr  /* store buffer in digest */
196145510Sdarrenr  for (i = 0, ii = 0; i < 4; i++, ii += 4) {
197145510Sdarrenr    mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
198145510Sdarrenr    mdContext->digest[ii+1] =
199145510Sdarrenr      (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
200145510Sdarrenr    mdContext->digest[ii+2] =
201145510Sdarrenr      (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
202145510Sdarrenr    mdContext->digest[ii+3] =
203145510Sdarrenr      (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
204145510Sdarrenr  }
205145510Sdarrenr  bcopy((char *)mdContext->digest, (char *)hash, 16);
206145510Sdarrenr}
207145510Sdarrenr
208145510Sdarrenr/* Basic MD5 step. Transforms buf based on in.
209145510Sdarrenr */
210145510Sdarrenrstatic void Transform (buf, in)
211145510SdarrenrUINT4 *buf;
212145510SdarrenrUINT4 *in;
213145510Sdarrenr{
214145510Sdarrenr  UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
215145510Sdarrenr
216145510Sdarrenr  /* Round 1 */
217145510Sdarrenr#define S11 7
218145510Sdarrenr#define S12 12
219145510Sdarrenr#define S13 17
220145510Sdarrenr#define S14 22
221145510Sdarrenr  FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */
222145510Sdarrenr  FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */
223145510Sdarrenr  FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */
224145510Sdarrenr  FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */
225145510Sdarrenr  FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */
226145510Sdarrenr  FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */
227145510Sdarrenr  FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */
228145510Sdarrenr  FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */
229145510Sdarrenr  FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */
230145510Sdarrenr  FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */
231145510Sdarrenr  FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */
232145510Sdarrenr  FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */
233145510Sdarrenr  FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */
234145510Sdarrenr  FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */
235145510Sdarrenr  FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */
236145510Sdarrenr  FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */
237145510Sdarrenr
238145510Sdarrenr  /* Round 2 */
239145510Sdarrenr#define S21 5
240145510Sdarrenr#define S22 9
241145510Sdarrenr#define S23 14
242145510Sdarrenr#define S24 20
243145510Sdarrenr  GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */
244145510Sdarrenr  GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */
245145510Sdarrenr  GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */
246145510Sdarrenr  GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */
247145510Sdarrenr  GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */
248145510Sdarrenr  GG ( d, a, b, c, in[10], S22, UL(  38016083)); /* 22 */
249145510Sdarrenr  GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */
250145510Sdarrenr  GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */
251145510Sdarrenr  GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */
252145510Sdarrenr  GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */
253145510Sdarrenr  GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */
254145510Sdarrenr  GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */
255145510Sdarrenr  GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */
256145510Sdarrenr  GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */
257145510Sdarrenr  GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */
258145510Sdarrenr  GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */
259145510Sdarrenr
260145510Sdarrenr  /* Round 3 */
261145510Sdarrenr#define S31 4
262145510Sdarrenr#define S32 11
263145510Sdarrenr#define S33 16
264145510Sdarrenr#define S34 23
265145510Sdarrenr  HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */
266145510Sdarrenr  HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */
267145510Sdarrenr  HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */
268145510Sdarrenr  HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */
269145510Sdarrenr  HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */
270145510Sdarrenr  HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */
271145510Sdarrenr  HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */
272145510Sdarrenr  HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */
273145510Sdarrenr  HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */
274145510Sdarrenr  HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */
275145510Sdarrenr  HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */
276145510Sdarrenr  HH ( b, c, d, a, in[ 6], S34, UL(  76029189)); /* 44 */
277145510Sdarrenr  HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */
278145510Sdarrenr  HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */
279145510Sdarrenr  HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */
280145510Sdarrenr  HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */
281145510Sdarrenr
282145510Sdarrenr  /* Round 4 */
283145510Sdarrenr#define S41 6
284145510Sdarrenr#define S42 10
285145510Sdarrenr#define S43 15
286145510Sdarrenr#define S44 21
287145510Sdarrenr  II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */
288145510Sdarrenr  II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */
289145510Sdarrenr  II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */
290145510Sdarrenr  II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */
291145510Sdarrenr  II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */
292145510Sdarrenr  II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */
293145510Sdarrenr  II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */
294145510Sdarrenr  II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */
295145510Sdarrenr  II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */
296145510Sdarrenr  II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */
297145510Sdarrenr  II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */
298145510Sdarrenr  II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */
299145510Sdarrenr  II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */
300145510Sdarrenr  II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */
301145510Sdarrenr  II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */
302145510Sdarrenr  II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */
303145510Sdarrenr
304145510Sdarrenr  buf[0] += a;
305145510Sdarrenr  buf[1] += b;
306145510Sdarrenr  buf[2] += c;
307145510Sdarrenr  buf[3] += d;
308145510Sdarrenr}
309145510Sdarrenr
310145510Sdarrenr/*
311145510Sdarrenr ***********************************************************************
312145510Sdarrenr ** End of md5.c                                                      **
313145510Sdarrenr ******************************** (cut) ********************************
314145510Sdarrenr */
315