source: 3DVCSoftware/trunk/source/Lib/libmd5/libmd5.c @ 358

Last change on this file since 358 was 56, checked in by hschwarz, 13 years ago

updated trunk (move to HM6.1)

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