source: trunk/third/gnome-keyring/md5.c @ 21094

Revision 21094, 9.7 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21093, which included commits to RCS files with non-trunk default branches.
Line 
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 * GnomeKeyringMD5Context structure, pass it to gnome_keyring_md5_init, call
14 * gnome_keyring_md5_update as needed on buffers full of bytes, and then call
15 * gnome_keyring_md5_final, which will fill a supplied 32-byte array with the
16 * digest in ascii form.
17 *
18 */
19
20#include "md5.h"
21#include <string.h>
22
23static void gnome_keyring_md5_transform (guint32                 buf[4],
24                                         guint32 const           in[16]);
25
26void
27gnome_keyring_md5_string (const char *string, unsigned char digest[16])
28{
29  struct GnomeKeyringMD5Context md5_context;
30 
31  gnome_keyring_md5_init (&md5_context);
32  gnome_keyring_md5_update (&md5_context, string, strlen (string));
33  gnome_keyring_md5_final (digest, &md5_context);
34}
35
36#if G_BYTE_ORDER == G_LITTLE_ENDIAN
37#define byteReverse(buf, len)   /* Nothing */
38#else
39
40/*
41 * Note: this code is harmless on little-endian machines.
42 */
43static void
44byteReverse(unsigned char *buf, unsigned longs)
45{
46    guint32 t;
47    do {
48        t = (guint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
49            ((unsigned) buf[1] << 8 | buf[0]);
50        *(guint32 *) buf = t;
51        buf += 4;
52    } while (--longs);
53}
54
55#endif
56
57char *
58gnome_keyring_md5_digest_to_ascii (unsigned char digest[16])
59{
60  static char hex_digits[] = "0123456789abcdef";
61  unsigned char *res;
62  int i;
63 
64  res = g_malloc (33);
65 
66  for (i = 0; i < 16; i++) {
67    res[2*i] = hex_digits[digest[i] >> 4];
68    res[2*i+1] = hex_digits[digest[i] & 0xf];
69  }
70 
71  res[32] = 0;
72 
73  return res;
74}
75
76
77/*
78 * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
79 * initialization constants.
80 */
81void
82gnome_keyring_md5_init (struct GnomeKeyringMD5Context *ctx)
83{
84    ctx->buf[0] = 0x67452301;
85    ctx->buf[1] = 0xefcdab89;
86    ctx->buf[2] = 0x98badcfe;
87    ctx->buf[3] = 0x10325476;
88
89    ctx->bits[0] = 0;
90    ctx->bits[1] = 0;
91}
92
93/*
94 * Update context to reflect the concatenation of another buffer full
95 * of bytes.
96 */
97void
98gnome_keyring_md5_update (struct GnomeKeyringMD5Context *ctx,
99                          unsigned char const *buf,
100                          unsigned len)
101{
102    guint32 t;
103
104    /* Update bitcount */
105
106    t = ctx->bits[0];
107    if ((ctx->bits[0] = t + ((guint32) len << 3)) < t)
108        ctx->bits[1]++;         /* Carry from low to high */
109    ctx->bits[1] += len >> 29;
110
111    t = (t >> 3) & 0x3f;        /* Bytes already in shsInfo->data */
112
113    /* Handle any leading odd-sized chunks */
114
115    if (t) {
116        unsigned char *p = (unsigned char *) ctx->in + t;
117
118        t = 64 - t;
119        if (len < t) {
120            memcpy (p, buf, len);
121            return;
122        }
123        memcpy (p, buf, t);
124        byteReverse (ctx->in, 16);
125        gnome_keyring_md5_transform (ctx->buf, (guint32 *) ctx->in);
126        buf += t;
127        len -= t;
128    }
129
130    /* Process data in 64-byte chunks */
131
132    while (len >= 64) {
133        memcpy (ctx->in, buf, 64);
134        byteReverse (ctx->in, 16);
135        gnome_keyring_md5_transform (ctx->buf, (guint32 *) ctx->in);
136        buf += 64;
137        len -= 64;
138    }
139
140    /* Handle any remaining bytes of data. */
141
142    memcpy(ctx->in, buf, len);
143}
144
145/*
146 * Final wrapup - pad to 64-byte boundary with the bit pattern
147 * 1 0* (64-bit count of bits processed, MSB-first)
148 */
149void
150gnome_keyring_md5_final (unsigned char digest[16], struct GnomeKeyringMD5Context *ctx)
151{
152    unsigned count;
153    unsigned char *p;
154
155    /* Compute number of bytes mod 64 */
156    count = (ctx->bits[0] >> 3) & 0x3F;
157
158    /* Set the first char of padding to 0x80.  This is safe since there is
159       always at least one byte free */
160    p = ctx->in + count;
161    *p++ = 0x80;
162
163    /* Bytes of padding needed to make 64 bytes */
164    count = 64 - 1 - count;
165
166    /* Pad out to 56 mod 64 */
167    if (count < 8) {
168        /* Two lots of padding:  Pad the first block to 64 bytes */
169        memset (p, 0, count);
170        byteReverse (ctx->in, 16);
171        gnome_keyring_md5_transform (ctx->buf, (guint32 *) ctx->in);
172
173        /* Now fill the next block with 56 bytes */
174        memset(ctx->in, 0, 56);
175    } else {
176        /* Pad block to 56 bytes */
177        memset(p, 0, count - 8);
178    }
179    byteReverse(ctx->in, 14);
180
181    /* Append length in bits and transform */
182    ((guint32 *) ctx->in)[14] = ctx->bits[0];
183    ((guint32 *) ctx->in)[15] = ctx->bits[1];
184
185    gnome_keyring_md5_transform (ctx->buf, (guint32 *) ctx->in);
186    byteReverse ((unsigned char *) ctx->buf, 4);
187    memcpy (digest, ctx->buf, 16);
188    memset (ctx, 0, sizeof(ctx));       /* In case it's sensitive */
189}
190
191
192/* The four core functions - F1 is optimized somewhat */
193
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 gnome_keyring_md5_step(f, w, x, y, z, data, s) \
201        ( w += f(x, y, z) + data,  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.  GnomeKeyringMD5Update blocks
206 * the data and converts bytes into longwords for this routine.
207 */
208static void
209gnome_keyring_md5_transform (guint32 buf[4], guint32 const in[16])
210{
211    register guint32 a, b, c, d;
212
213    a = buf[0];
214    b = buf[1];
215    c = buf[2];
216    d = buf[3];
217
218    gnome_keyring_md5_step(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
219    gnome_keyring_md5_step(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
220    gnome_keyring_md5_step(F1, c, d, a, b, in[2] + 0x242070db, 17);
221    gnome_keyring_md5_step(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
222    gnome_keyring_md5_step(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
223    gnome_keyring_md5_step(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
224    gnome_keyring_md5_step(F1, c, d, a, b, in[6] + 0xa8304613, 17);
225    gnome_keyring_md5_step(F1, b, c, d, a, in[7] + 0xfd469501, 22);
226    gnome_keyring_md5_step(F1, a, b, c, d, in[8] + 0x698098d8, 7);
227    gnome_keyring_md5_step(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
228    gnome_keyring_md5_step(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
229    gnome_keyring_md5_step(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
230    gnome_keyring_md5_step(F1, a, b, c, d, in[12] + 0x6b901122, 7);
231    gnome_keyring_md5_step(F1, d, a, b, c, in[13] + 0xfd987193, 12);
232    gnome_keyring_md5_step(F1, c, d, a, b, in[14] + 0xa679438e, 17);
233    gnome_keyring_md5_step(F1, b, c, d, a, in[15] + 0x49b40821, 22);
234               
235    gnome_keyring_md5_step(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
236    gnome_keyring_md5_step(F2, d, a, b, c, in[6] + 0xc040b340, 9);
237    gnome_keyring_md5_step(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
238    gnome_keyring_md5_step(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
239    gnome_keyring_md5_step(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
240    gnome_keyring_md5_step(F2, d, a, b, c, in[10] + 0x02441453, 9);
241    gnome_keyring_md5_step(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
242    gnome_keyring_md5_step(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
243    gnome_keyring_md5_step(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
244    gnome_keyring_md5_step(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
245    gnome_keyring_md5_step(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
246    gnome_keyring_md5_step(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
247    gnome_keyring_md5_step(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
248    gnome_keyring_md5_step(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
249    gnome_keyring_md5_step(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
250    gnome_keyring_md5_step(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
251               
252    gnome_keyring_md5_step(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
253    gnome_keyring_md5_step(F3, d, a, b, c, in[8] + 0x8771f681, 11);
254    gnome_keyring_md5_step(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
255    gnome_keyring_md5_step(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
256    gnome_keyring_md5_step(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
257    gnome_keyring_md5_step(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
258    gnome_keyring_md5_step(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
259    gnome_keyring_md5_step(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
260    gnome_keyring_md5_step(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
261    gnome_keyring_md5_step(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
262    gnome_keyring_md5_step(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
263    gnome_keyring_md5_step(F3, b, c, d, a, in[6] + 0x04881d05, 23);
264    gnome_keyring_md5_step(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
265    gnome_keyring_md5_step(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
266    gnome_keyring_md5_step(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
267    gnome_keyring_md5_step(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
268               
269    gnome_keyring_md5_step(F4, a, b, c, d, in[0] + 0xf4292244, 6);
270    gnome_keyring_md5_step(F4, d, a, b, c, in[7] + 0x432aff97, 10);
271    gnome_keyring_md5_step(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
272    gnome_keyring_md5_step(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
273    gnome_keyring_md5_step(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
274    gnome_keyring_md5_step(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
275    gnome_keyring_md5_step(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
276    gnome_keyring_md5_step(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
277    gnome_keyring_md5_step(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
278    gnome_keyring_md5_step(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
279    gnome_keyring_md5_step(F4, c, d, a, b, in[6] + 0xa3014314, 15);
280    gnome_keyring_md5_step(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
281    gnome_keyring_md5_step(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
282    gnome_keyring_md5_step(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
283    gnome_keyring_md5_step(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
284    gnome_keyring_md5_step(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
285
286    buf[0] += a;
287    buf[1] += b;
288    buf[2] += c;
289    buf[3] += d;
290}
291
Note: See TracBrowser for help on using the repository browser.