source: proiecte/PPPP/gdm/common/gdm-md5.c @ 134

Last change on this file since 134 was 134, checked in by (none), 14 years ago

gdm sources with the modifications for webcam

File size: 15.1 KB
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * gdm-md5.c md5 implementation (based on L Peter Deutsch implementation)
4 *
5 * Copyright (C) 2003 Red Hat Inc.
6 * Copyright (C) 1999, 2000 Aladdin Enterprises.  All rights reserved.
7 *
8 * This software is provided 'as-is', without any express or implied
9 * warranty.  In no event will the authors be held liable for any damages
10 * arising from the use of this software.
11 *
12 * Permission is granted to anyone to use this software for any purpose,
13 * including commercial applications, and to alter it and redistribute it
14 * freely, subject to the following restrictions:
15 *
16 * 1. The origin of this software must not be misrepresented; you must not
17 *    claim that you wrote the original software. If you use this software
18 *    in a product, an acknowledgment in the product documentation would be
19 *    appreciated but is not required.
20 * 2. Altered source versions must be plainly marked as such, and must not be
21 *    misrepresented as being the original software.
22 * 3. This notice may not be removed or altered from any source distribution.
23 *
24 * L. Peter Deutsch
25 * ghost@aladdin.com
26 */
27/*
28 * Independent implementation of MD5 (RFC 1321).
29 *
30 * This code implements the MD5 Algorithm defined in RFC 1321.
31 * It is derived directly from the text of the RFC and not from the
32 * reference implementation.
33 *
34 * The original and principal author of md5.c is L. Peter Deutsch
35 * <ghost@aladdin.com>.
36 */
37
38/* This GDM version was modified for glib from dbus-md5.c */
39
40#include <string.h>
41#include <glib.h>
42
43#include "gdm-md5.h"
44
45/**
46 * @defgroup GdmMD5Internals MD5 implementation details
47 * @ingroup  GdmInternals
48 * @brief Internals of MD5 implementation.
49 *
50 * The implementation of MD5 (see http://www.ietf.org/rfc/rfc1321.txt).
51 * This MD5 implementation was written by L. Peter Deutsch and
52 * is not derived from the RSA reference implementation in the
53 * RFC. The version included in D-Bus comes from the Ghostscript
54 * 7.05 distribution.
55 *
56 * @{
57 */
58#ifndef DOXYGEN_SHOULD_SKIP_THIS
59/*
60 * For reference, here is the program that computed the T values.
61 */
62#ifdef COMPUTE_T_VALUES
63#include <math.h>
64int
65main(int argc, char **argv)
66{
67        int i;
68        for (i = 1; i <= 64; ++i)
69                {
70                        unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i)));
71
72                        /*
73                         * The following nonsense is only to avoid compiler warnings about
74                         * "integer constant is unsigned in ANSI C, signed with -traditional".
75                         */
76                        if (v >> 31)
77                                {
78                                        printf("#define T%d /* 0x%08lx */ (T_MASK ^ 0x%08lx)\n", i,
79                                               v, (unsigned long)(unsigned int)(~v));
80                                } else {
81                                printf("#define T%d    0x%08lx\n", i, v);
82                        }
83                }
84        return 0;
85}
86#endif /* COMPUTE_T_VALUES */
87/*
88 * End of T computation program.
89 */
90
91#define T_MASK ((guint32)~0)
92#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
93#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
94#define T3    0x242070db
95#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
96#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
97#define T6    0x4787c62a
98#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
99#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
100#define T9    0x698098d8
101#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
102#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
103#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
104#define T13    0x6b901122
105#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
106#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
107#define T16    0x49b40821
108#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
109#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
110#define T19    0x265e5a51
111#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
112#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
113#define T22    0x02441453
114#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
115#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
116#define T25    0x21e1cde6
117#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
118#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
119#define T28    0x455a14ed
120#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
121#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
122#define T31    0x676f02d9
123#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
124#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
125#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
126#define T35    0x6d9d6122
127#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
128#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
129#define T38    0x4bdecfa9
130#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
131#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
132#define T41    0x289b7ec6
133#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
134#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
135#define T44    0x04881d05
136#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
137#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
138#define T47    0x1fa27cf8
139#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
140#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
141#define T50    0x432aff97
142#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
143#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
144#define T53    0x655b59c3
145#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
146#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
147#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
148#define T57    0x6fa87e4f
149#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
150#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
151#define T60    0x4e0811a1
152#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
153#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
154#define T63    0x2ad7d2bb
155#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
156#endif /* !DOXYGEN_SHOULD_SKIP_THIS */
157
158static void
159md5_process (GdmMD5Context *context,
160             const unsigned char *data /*[64]*/)
161{
162        guint32
163                a = context->abcd[0], b = context->abcd[1],
164                c = context->abcd[2], d = context->abcd[3];
165        guint32 t;
166
167#ifdef WORDS_BIGENDIAN
168        /*
169         * On big-endian machines, we must arrange the bytes in the right
170         * order.  (This also works on machines of unknown byte order.)
171         */
172        guint32 X[16];
173        const unsigned char *xp = data;
174        int i;
175
176        for (i = 0; i < 16; ++i, xp += 4)
177                X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
178
179#else  /* !WORDS_BIGENDIAN */
180        /*
181         * On little-endian machines, we can process properly aligned data
182         * without copying it.
183         */
184        guint32 xbuf[16];
185        const guint32 *X;
186
187        if (!((data - (const unsigned char *)0) & 3))
188                {
189                        /* data are properly aligned */
190                        X = (const guint32 *)data;
191                }
192        else
193                {
194                        /* not aligned */
195                        memcpy(xbuf, data, 64);
196                        X = xbuf;
197                }
198#endif
199
200#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
201
202        /* Round 1. */
203        /* Let [abcd k s i] denote the operation
204           a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
205#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
206#define SET(a, b, c, d, k, s, Ti)               \
207        t = a + F(b,c,d) + X[k] + Ti;           \
208        a = ROTATE_LEFT(t, s) + b
209        /* Do the following 16 operations. */
210        SET(a, b, c, d,  0,  7,  T1);
211        SET(d, a, b, c,  1, 12,  T2);
212        SET(c, d, a, b,  2, 17,  T3);
213        SET(b, c, d, a,  3, 22,  T4);
214        SET(a, b, c, d,  4,  7,  T5);
215        SET(d, a, b, c,  5, 12,  T6);
216        SET(c, d, a, b,  6, 17,  T7);
217        SET(b, c, d, a,  7, 22,  T8);
218        SET(a, b, c, d,  8,  7,  T9);
219        SET(d, a, b, c,  9, 12, T10);
220        SET(c, d, a, b, 10, 17, T11);
221        SET(b, c, d, a, 11, 22, T12);
222        SET(a, b, c, d, 12,  7, T13);
223        SET(d, a, b, c, 13, 12, T14);
224        SET(c, d, a, b, 14, 17, T15);
225        SET(b, c, d, a, 15, 22, T16);
226#undef SET
227
228        /* Round 2. */
229        /* Let [abcd k s i] denote the operation
230           a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
231#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
232#define SET(a, b, c, d, k, s, Ti)               \
233        t = a + G(b,c,d) + X[k] + Ti;           \
234        a = ROTATE_LEFT(t, s) + b
235        /* Do the following 16 operations. */
236        SET(a, b, c, d,  1,  5, T17);
237        SET(d, a, b, c,  6,  9, T18);
238        SET(c, d, a, b, 11, 14, T19);
239        SET(b, c, d, a,  0, 20, T20);
240        SET(a, b, c, d,  5,  5, T21);
241        SET(d, a, b, c, 10,  9, T22);
242        SET(c, d, a, b, 15, 14, T23);
243        SET(b, c, d, a,  4, 20, T24);
244        SET(a, b, c, d,  9,  5, T25);
245        SET(d, a, b, c, 14,  9, T26);
246        SET(c, d, a, b,  3, 14, T27);
247        SET(b, c, d, a,  8, 20, T28);
248        SET(a, b, c, d, 13,  5, T29);
249        SET(d, a, b, c,  2,  9, T30);
250        SET(c, d, a, b,  7, 14, T31);
251        SET(b, c, d, a, 12, 20, T32);
252#undef SET
253
254        /* Round 3. */
255        /* Let [abcd k s t] denote the operation
256           a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
257#define H(x, y, z) ((x) ^ (y) ^ (z))
258#define SET(a, b, c, d, k, s, Ti)               \
259        t = a + H(b,c,d) + X[k] + Ti;           \
260        a = ROTATE_LEFT(t, s) + b
261        /* Do the following 16 operations. */
262        SET(a, b, c, d,  5,  4, T33);
263        SET(d, a, b, c,  8, 11, T34);
264        SET(c, d, a, b, 11, 16, T35);
265        SET(b, c, d, a, 14, 23, T36);
266        SET(a, b, c, d,  1,  4, T37);
267        SET(d, a, b, c,  4, 11, T38);
268        SET(c, d, a, b,  7, 16, T39);
269        SET(b, c, d, a, 10, 23, T40);
270        SET(a, b, c, d, 13,  4, T41);
271        SET(d, a, b, c,  0, 11, T42);
272        SET(c, d, a, b,  3, 16, T43);
273        SET(b, c, d, a,  6, 23, T44);
274        SET(a, b, c, d,  9,  4, T45);
275        SET(d, a, b, c, 12, 11, T46);
276        SET(c, d, a, b, 15, 16, T47);
277        SET(b, c, d, a,  2, 23, T48);
278#undef SET
279
280        /* Round 4. */
281        /* Let [abcd k s t] denote the operation
282           a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
283#define I(x, y, z) ((y) ^ ((x) | ~(z)))
284#define SET(a, b, c, d, k, s, Ti)               \
285        t = a + I(b,c,d) + X[k] + Ti;           \
286        a = ROTATE_LEFT(t, s) + b
287        /* Do the following 16 operations. */
288        SET(a, b, c, d,  0,  6, T49);
289        SET(d, a, b, c,  7, 10, T50);
290        SET(c, d, a, b, 14, 15, T51);
291        SET(b, c, d, a,  5, 21, T52);
292        SET(a, b, c, d, 12,  6, T53);
293        SET(d, a, b, c,  3, 10, T54);
294        SET(c, d, a, b, 10, 15, T55);
295        SET(b, c, d, a,  1, 21, T56);
296        SET(a, b, c, d,  8,  6, T57);
297        SET(d, a, b, c, 15, 10, T58);
298        SET(c, d, a, b,  6, 15, T59);
299        SET(b, c, d, a, 13, 21, T60);
300        SET(a, b, c, d,  4,  6, T61);
301        SET(d, a, b, c, 11, 10, T62);
302        SET(c, d, a, b,  2, 15, T63);
303        SET(b, c, d, a,  9, 21, T64);
304#undef SET
305
306        /* Then perform the following additions. (That is increment each
307           of the four registers by the value it had before this block
308           was started.) */
309        context->abcd[0] += a;
310        context->abcd[1] += b;
311        context->abcd[2] += c;
312        context->abcd[3] += d;
313}
314
315static void
316md5_init (GdmMD5Context *context)
317{
318        context->count[0] = context->count[1] = 0;
319        context->abcd[0] = 0x67452301;
320        context->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
321        context->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
322        context->abcd[3] = 0x10325476;
323}
324
325static void
326md5_append (GdmMD5Context       *context,
327            const unsigned char *data,
328            int                  nbytes)
329{
330        const unsigned char *p = data;
331        int left = nbytes;
332        int offset = (context->count[0] >> 3) & 63;
333        guint32 nbits = (guint32)(nbytes << 3);
334
335        if (nbytes <= 0)
336                return;
337
338        /* Update the message length. */
339        context->count[1] += nbytes >> 29;
340        context->count[0] += nbits;
341        if (context->count[0] < nbits)
342                context->count[1]++;
343
344        /* Process an initial partial block. */
345        if (offset)
346                {
347                        int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
348
349                        memcpy(context->buf + offset, p, copy);
350                        if (offset + copy < 64)
351                                return;
352                        p += copy;
353                        left -= copy;
354                        md5_process(context, context->buf);
355                }
356
357        /* Process full blocks. */
358        for (; left >= 64; p += 64, left -= 64)
359                md5_process(context, p);
360
361        /* Process a final partial block. */
362        if (left)
363                memcpy(context->buf, p, left);
364}
365
366static void
367md5_finish (GdmMD5Context *context,
368            unsigned char  digest[16])
369{
370        static const unsigned char pad[64] = {
371                0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
372                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
373                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
374                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
375        };
376        unsigned char data[8];
377        int i;
378
379        /* Save the length before padding. */
380        for (i = 0; i < 8; ++i)
381                data[i] = (unsigned char)(context->count[i >> 2] >> ((i & 3) << 3));
382        /* Pad to 56 bytes mod 64. */
383        md5_append(context, pad, ((55 - (context->count[0] >> 3)) & 63) + 1);
384        /* Append the length. */
385        md5_append(context, data, 8);
386        for (i = 0; i < 16; ++i)
387                digest[i] = (unsigned char)(context->abcd[i >> 2] >> ((i & 3) << 3));
388}
389
390/** @} */ /* End of internals */
391
392/**
393 * @addtogroup GdmMD5
394 *
395 * @{
396 */
397
398/**
399 * Initializes the MD5 context.
400 *
401 * @param context an uninitialized context, typically on the stack.
402 */
403void
404gdm_md5_init (GdmMD5Context *context)
405{
406        md5_init (context);
407}
408
409
410/**
411 * Feeds more data into an existing md5sum computation.
412 *
413 * @param context the MD5 context
414 * @param data the additional data to hash
415 */
416void
417gdm_md5_update (GdmMD5Context *context,
418                const GString *data)
419{
420        unsigned int   inputLen;
421        unsigned char *input;
422
423        input = (unsigned char *)data->str;
424        inputLen = data->len;
425
426        md5_append (context, input, inputLen);
427}
428
429/**
430 * MD5 finalization. Ends an MD5 message-digest operation, writing the
431 * the message digest and zeroing the context.  The results are
432 * returned as a raw 16-byte digest, not as the ascii-hex-digits
433 * string form of the digest.
434 *
435 * @param context the MD5 context
436 * @param results string to append the 16-byte MD5 digest to
437 * @returns #FALSE if not enough memory to append the digest
438 *
439 */
440gboolean
441gdm_md5_final (GdmMD5Context *context,
442               GString       *results)
443{
444        unsigned char digest[16];
445
446        md5_finish (context, digest);
447
448        if (!g_string_append_len (results, (char *)digest, 16))
449                return FALSE;
450
451        /* some kind of security paranoia, though it seems pointless
452         * to me given the nonzeroed stuff flying around
453         */
454        memset ((void*)context, '\0', sizeof (GdmMD5Context));
455
456        return TRUE;
457}
Note: See TracBrowser for help on using the repository browser.