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