source: SHVCSoftware/trunk/source/Lib/libmd5/libmd5.c @ 217

Last change on this file since 217 was 125, checked in by seregin, 12 years ago

copy from HM-10.0-dev-SHM

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