source: 3DVCSoftware/tags/0.2/source/Lib/libmd5/libmd5.c @ 9

Last change on this file since 9 was 2, checked in by hhi, 13 years ago

inital import

  • Property svn:eol-style set to native
File size: 8.0 KB
Line 
1/*
2 * This code implements the MD5 message-digest algorithm.  The algorithm was
3 * written by Ron Rivest.  This code was written by Colin Plumb in 1993, our
4 * understanding is that no copyright is claimed and that this code is in the
5 * public domain.
6 *
7 * Equivalent code is available from RSA Data Security, Inc.
8 * This code has been tested against that, and is functionally equivalent,
9 *
10 * To compute the message digest of a chunk of bytes, declare an MD5Context
11 * structure, pass it to MD5Init, call MD5Update as needed on buffers full of
12 * bytes, and then call MD5Final, which will fill a supplied 16-byte array with
13 * the digest.
14 */
15
16#include <stdint.h>
17#include <string.h>
18#include "libmd5.h"
19
20static void MD5Transform(uint32_t buf[4], uint32_t const in[16]);
21
22#ifndef __BIG_ENDIAN__
23# define byteReverse(buf, len)    /* Nothing */
24#else
25void byteReverse(unsigned char *buf, unsigned longs);
26/*
27 * Note: this code is harmless on little-endian machines.
28 */
29void byteReverse(unsigned char *buf, unsigned longs)
30{
31  uint32_t t;
32  do {
33    t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
34        ((unsigned) buf[1] << 8 | buf[0]);
35    *(uint32_t *) buf = t;
36    buf += 4;
37  } while (--longs);
38}
39#endif
40
41/*
42 * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
43 * initialization constants.
44 */
45void MD5Init(context_md5_t *ctx)
46{
47  ctx->buf[0] = 0x67452301;
48  ctx->buf[1] = 0xefcdab89;
49  ctx->buf[2] = 0x98badcfe;
50  ctx->buf[3] = 0x10325476;
51
52  ctx->bits[0] = 0;
53  ctx->bits[1] = 0;
54}
55
56/*
57 * Update context to reflect the concatenation of another buffer full
58 * of bytes.
59 */
60void MD5Update(context_md5_t *ctx, unsigned char *buf, unsigned len)
61{
62  uint32_t t;
63
64  /* Update bitcount */
65
66  t = ctx->bits[0];
67  if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t)
68    ctx->bits[1]++;        /* Carry from low to high */
69  ctx->bits[1] += len >> 29;
70
71  t = (t >> 3) & 0x3f;    /* Bytes already in shsInfo->data */
72
73  /* Handle any leading odd-sized chunks */
74
75  if (t) {
76    unsigned char *p = (unsigned char *) ctx->in + t;
77
78    t = 64 - t;
79    if (len < t) {
80      memcpy(p, buf, len);
81      return;
82    }
83    memcpy(p, buf, t);
84    byteReverse(ctx->in, 16);
85    MD5Transform(ctx->buf, (uint32_t *) ctx->in);
86    buf += t;
87    len -= t;
88  }
89  /* Process data in 64-byte chunks */
90
91  while (len >= 64) {
92    memcpy(ctx->in, buf, 64);
93    byteReverse(ctx->in, 16);
94    MD5Transform(ctx->buf, (uint32_t *) ctx->in);
95    buf += 64;
96    len -= 64;
97  }
98
99    /* Handle any remaining bytes of data. */
100
101  memcpy(ctx->in, buf, len);
102}
103
104/*
105 * Final wrapup - pad to 64-byte boundary with the bit pattern
106 * 1 0* (64-bit count of bits processed, MSB-first)
107 */
108void MD5Final(unsigned char digest[16], context_md5_t *ctx)
109{
110  unsigned count;
111  unsigned char *p;
112
113  /* Compute number of bytes mod 64 */
114  count = (ctx->bits[0] >> 3) & 0x3F;
115
116  /* Set the first char of padding to 0x80.  This is safe since there is
117     always at least one byte free */
118  p = ctx->in + count;
119  *p++ = 0x80;
120
121  /* Bytes of padding needed to make 64 bytes */
122  count = 64 - 1 - count;
123
124  /* Pad out to 56 mod 64 */
125  if (count < 8) {
126    /* Two lots of padding:  Pad the first block to 64 bytes */
127    memset(p, 0, count);
128    byteReverse(ctx->in, 16);
129    MD5Transform(ctx->buf, (uint32_t *) ctx->in);
130
131    /* Now fill the next block with 56 bytes */
132    memset(ctx->in, 0, 56);
133  } else {
134    /* Pad block to 56 bytes */
135    memset(p, 0, count - 8);
136  }
137  byteReverse(ctx->in, 14);
138
139  /* Append length in bits and transform */
140  ((uint32_t *) ctx->in)[14] = ctx->bits[0];
141  ((uint32_t *) ctx->in)[15] = ctx->bits[1];
142
143  MD5Transform(ctx->buf, (uint32_t *) ctx->in);
144  byteReverse((unsigned char *) ctx->buf, 4);
145  memcpy(digest, ctx->buf, 16);
146
147  memset(ctx, 0, sizeof(* ctx));    /* In case it's sensitive */
148  /* The original version of this code omitted the asterisk. In
149     effect, only the first part of ctx was wiped with zeros, not
150     the whole thing. Bug found by Derek Jones. Original line: */
151  // memset(ctx, 0, sizeof(ctx));    /* In case it's sensitive */
152}
153
154/* The four core functions - F1 is optimized somewhat */
155
156/* #define F1(x, y, z) (x & y | ~x & z) */
157#define F1(x, y, z) (z ^ (x & (y ^ z)))
158#define F2(x, y, z) F1(z, x, y)
159#define F3(x, y, z) (x ^ y ^ z)
160#define F4(x, y, z) (y ^ (x | ~z))
161
162/* This is the central step in the MD5 algorithm. */
163#define MD5STEP(f, w, x, y, z, data, s) \
164    ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
165
166/*
167 * The core of the MD5 algorithm, this alters an existing MD5 hash to
168 * reflect the addition of 16 longwords of new data.  MD5Update blocks
169 * the data and converts bytes into longwords for this routine.
170 */
171static void MD5Transform(uint32_t buf[4], uint32_t const in[16])
172{
173  register uint32_t a, b, c, d;
174
175  a = buf[0];
176  b = buf[1];
177  c = buf[2];
178  d = buf[3];
179
180  MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
181  MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
182  MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
183  MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
184  MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
185  MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
186  MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
187  MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
188  MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
189  MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
190  MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
191  MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
192  MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
193  MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
194  MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
195  MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
196
197  MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
198  MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
199  MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
200  MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
201  MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
202  MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
203  MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
204  MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
205  MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
206  MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
207  MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
208  MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
209  MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
210  MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
211  MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
212  MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
213
214  MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
215  MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
216  MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
217  MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
218  MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
219  MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
220  MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
221  MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
222  MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
223  MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
224  MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
225  MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
226  MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
227  MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
228  MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
229  MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
230
231  MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
232  MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
233  MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
234  MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
235  MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
236  MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
237  MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
238  MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
239  MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
240  MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
241  MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
242  MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
243  MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
244  MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
245  MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
246  MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
247
248  buf[0] += a;
249  buf[1] += b;
250  buf[2] += c;
251  buf[3] += d;
252}
Note: See TracBrowser for help on using the repository browser.