~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to mysys/md5.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

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