PageRenderTime 75ms CodeModel.GetById 15ms app.highlight 55ms RepoModel.GetById 1ms app.codeStats 1ms

/contrib/cvs/lib/md5.c

https://bitbucket.org/freebsd/freebsd-head/
C | 332 lines | 219 code | 45 blank | 68 comment | 10 complexity | 033190fb87014ff6a22d96d4f4866617 MD5 | raw file
  1/*
  2 * This code implements the MD5 message-digest algorithm.
  3 * The algorithm is due to Ron Rivest.  This code was
  4 * written by Colin Plumb in 1993, no copyright is claimed.
  5 * This code is in the public domain; do with it what you wish.
  6 *
  7 * Equivalent code is available from RSA Data Security, Inc.
  8 * This code has been tested against that, and is equivalent,
  9 * except that you don't need to include two pages of legalese
 10 * with every copy.
 11 *
 12 * To compute the message digest of a chunk of bytes, declare an
 13 * MD5Context structure, pass it to MD5Init, call MD5Update as
 14 * needed on buffers full of bytes, and then call MD5Final, which
 15 * will fill a supplied 16-byte array with the digest.
 16 */
 17
 18/* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
 19   not require an integer type which is exactly 32 bits.  This work
 20   draws on the changes for the same purpose by Tatu Ylonen
 21   <ylo@cs.hut.fi> as part of SSH, but since I didn't actually use
 22   that code, there is no copyright issue.  I hereby disclaim
 23   copyright in any changes I have made; this code remains in the
 24   public domain.  */
 25
 26/* Note regarding cvs_* namespace: this avoids potential conflicts
 27   with libraries such as some versions of Kerberos.  No particular
 28   need to worry about whether the system supplies an MD5 library, as
 29   this file is only about 3k of object code.  */
 30
 31#ifdef HAVE_CONFIG_H
 32#include "config.h"
 33#endif
 34
 35#include <string.h>	/* for memcpy() and memset() */
 36
 37/* Add prototype support.  */
 38#ifndef PROTO
 39#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
 40#define PROTO(ARGS) ARGS
 41#else
 42#define PROTO(ARGS) ()
 43#endif
 44#endif
 45
 46#include "md5.h"
 47
 48/* Little-endian byte-swapping routines.  Note that these do not
 49   depend on the size of datatypes such as cvs_uint32, nor do they require
 50   us to detect the endianness of the machine we are running on.  It
 51   is possible they should be macros for speed, but I would be
 52   surprised if they were a performance bottleneck for MD5.  */
 53
 54static cvs_uint32
 55getu32 (addr)
 56     const unsigned char *addr;
 57{
 58	return (((((unsigned long)addr[3] << 8) | addr[2]) << 8)
 59		| addr[1]) << 8 | addr[0];
 60}
 61
 62static void
 63putu32 (data, addr)
 64     cvs_uint32 data;
 65     unsigned char *addr;
 66{
 67	addr[0] = (unsigned char)data;
 68	addr[1] = (unsigned char)(data >> 8);
 69	addr[2] = (unsigned char)(data >> 16);
 70	addr[3] = (unsigned char)(data >> 24);
 71}
 72
 73/*
 74 * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
 75 * initialization constants.
 76 */
 77void
 78cvs_MD5Init (ctx)
 79     struct cvs_MD5Context *ctx;
 80{
 81	ctx->buf[0] = 0x67452301;
 82	ctx->buf[1] = 0xefcdab89;
 83	ctx->buf[2] = 0x98badcfe;
 84	ctx->buf[3] = 0x10325476;
 85
 86	ctx->bits[0] = 0;
 87	ctx->bits[1] = 0;
 88}
 89
 90/*
 91 * Update context to reflect the concatenation of another buffer full
 92 * of bytes.
 93 */
 94void
 95cvs_MD5Update (ctx, buf, len)
 96     struct cvs_MD5Context *ctx;
 97     unsigned char const *buf;
 98     unsigned len;
 99{
100	cvs_uint32 t;
101
102	/* Update bitcount */
103
104	t = ctx->bits[0];
105	if ((ctx->bits[0] = (t + ((cvs_uint32)len << 3)) & 0xffffffff) < t)
106		ctx->bits[1]++;	/* Carry from low to high */
107	ctx->bits[1] += len >> 29;
108
109	t = (t >> 3) & 0x3f;	/* Bytes already in shsInfo->data */
110
111	/* Handle any leading odd-sized chunks */
112
113	if ( t ) {
114		unsigned char *p = ctx->in + t;
115
116		t = 64-t;
117		if (len < t) {
118			memcpy(p, buf, len);
119			return;
120		}
121		memcpy(p, buf, t);
122		cvs_MD5Transform (ctx->buf, ctx->in);
123		buf += t;
124		len -= t;
125	}
126
127	/* Process data in 64-byte chunks */
128
129	while (len >= 64) {
130		memcpy(ctx->in, buf, 64);
131		cvs_MD5Transform (ctx->buf, ctx->in);
132		buf += 64;
133		len -= 64;
134	}
135
136	/* Handle any remaining bytes of data. */
137
138	memcpy(ctx->in, buf, len);
139}
140
141/*
142 * Final wrapup - pad to 64-byte boundary with the bit pattern 
143 * 1 0* (64-bit count of bits processed, MSB-first)
144 */
145void
146cvs_MD5Final (digest, ctx)
147     unsigned char digest[16];
148     struct cvs_MD5Context *ctx;
149{
150	unsigned count;
151	unsigned char *p;
152
153	/* Compute number of bytes mod 64 */
154	count = (ctx->bits[0] >> 3) & 0x3F;
155
156	/* Set the first char of padding to 0x80.  This is safe since there is
157	   always at least one byte free */
158	p = ctx->in + count;
159	*p++ = 0x80;
160
161	/* Bytes of padding needed to make 64 bytes */
162	count = 64 - 1 - count;
163
164	/* Pad out to 56 mod 64 */
165	if (count < 8) {
166		/* Two lots of padding:  Pad the first block to 64 bytes */
167		memset(p, 0, count);
168		cvs_MD5Transform (ctx->buf, ctx->in);
169
170		/* Now fill the next block with 56 bytes */
171		memset(ctx->in, 0, 56);
172	} else {
173		/* Pad block to 56 bytes */
174		memset(p, 0, count-8);
175	}
176
177	/* Append length in bits and transform */
178	putu32(ctx->bits[0], ctx->in + 56);
179	putu32(ctx->bits[1], ctx->in + 60);
180
181	cvs_MD5Transform (ctx->buf, ctx->in);
182	putu32(ctx->buf[0], digest);
183	putu32(ctx->buf[1], digest + 4);
184	putu32(ctx->buf[2], digest + 8);
185	putu32(ctx->buf[3], digest + 12);
186	memset(ctx, 0, sizeof(ctx));	/* In case it's sensitive */
187}
188
189#ifndef ASM_MD5
190
191/* The four core functions - F1 is optimized somewhat */
192
193/* #define F1(x, y, z) (x & y | ~x & z) */
194#define F1(x, y, z) (z ^ (x & (y ^ z)))
195#define F2(x, y, z) F1(z, x, y)
196#define F3(x, y, z) (x ^ y ^ z)
197#define F4(x, y, z) (y ^ (x | ~z))
198
199/* This is the central step in the MD5 algorithm. */
200#define MD5STEP(f, w, x, y, z, data, s) \
201	( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x )
202
203/*
204 * The core of the MD5 algorithm, this alters an existing MD5 hash to
205 * reflect the addition of 16 longwords of new data.  MD5Update blocks
206 * the data and converts bytes into longwords for this routine.
207 */
208void
209cvs_MD5Transform (buf, inraw)
210     cvs_uint32 buf[4];
211     const unsigned char inraw[64];
212{
213	register cvs_uint32 a, b, c, d;
214	cvs_uint32 in[16];
215	int i;
216
217	for (i = 0; i < 16; ++i)
218		in[i] = getu32 (inraw + 4 * i);
219
220	a = buf[0];
221	b = buf[1];
222	c = buf[2];
223	d = buf[3];
224
225	MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478,  7);
226	MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
227	MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
228	MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
229	MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf,  7);
230	MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
231	MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
232	MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
233	MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8,  7);
234	MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
235	MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
236	MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
237	MD5STEP(F1, a, b, c, d, in[12]+0x6b901122,  7);
238	MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
239	MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
240	MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
241
242	MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562,  5);
243	MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340,  9);
244	MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
245	MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
246	MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d,  5);
247	MD5STEP(F2, d, a, b, c, in[10]+0x02441453,  9);
248	MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
249	MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
250	MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6,  5);
251	MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6,  9);
252	MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
253	MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
254	MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905,  5);
255	MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8,  9);
256	MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
257	MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
258
259	MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942,  4);
260	MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
261	MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
262	MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
263	MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44,  4);
264	MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
265	MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
266	MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
267	MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6,  4);
268	MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
269	MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
270	MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
271	MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039,  4);
272	MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
273	MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
274	MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
275
276	MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244,  6);
277	MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
278	MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
279	MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
280	MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3,  6);
281	MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
282	MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
283	MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
284	MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f,  6);
285	MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
286	MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
287	MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
288	MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82,  6);
289	MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
290	MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
291	MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
292
293	buf[0] += a;
294	buf[1] += b;
295	buf[2] += c;
296	buf[3] += d;
297}
298#endif
299
300#ifdef TEST
301/* Simple test program.  Can use it to manually run the tests from
302   RFC1321 for example.  */
303#include <stdio.h>
304
305int
306main (int argc, char **argv)
307{
308	struct cvs_MD5Context context;
309	unsigned char checksum[16];
310	int i;
311	int j;
312
313	if (argc < 2)
314	{
315		fprintf (stderr, "usage: %s string-to-hash\n", argv[0]);
316		exit (1);
317	}
318	for (j = 1; j < argc; ++j)
319	{
320		printf ("MD5 (\"%s\") = ", argv[j]);
321		cvs_MD5Init (&context);
322		cvs_MD5Update (&context, argv[j], strlen (argv[j]));
323		cvs_MD5Final (checksum, &context);
324		for (i = 0; i < 16; i++)
325		{
326			printf ("%02x", (unsigned int) checksum[i]);
327		}
328		printf ("\n");
329	}
330	return 0;
331}
332#endif /* TEST */