]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/cvs/lib/md5.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / cvs / lib / md5.c
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
54 static cvs_uint32
55 getu32 (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
62 static void
63 putu32 (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  */
77 void
78 cvs_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  */
94 void
95 cvs_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  */
145 void
146 cvs_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  */
208 void
209 cvs_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
305 int
306 main (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 */