00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "dbus-internals.h"
00038 #include "dbus-md5.h"
00039 #include <string.h>
00040
00062 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00063
00064
00065
00066 #ifdef COMPUTE_T_VALUES
00067 #include <math.h>
00068 int
00069 main(int argc, char **argv)
00070 {
00071 int i;
00072 for (i = 1; i <= 64; ++i)
00073 {
00074 unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i)));
00075
00076
00077
00078
00079
00080 if (v >> 31)
00081 {
00082 printf("#define T%d /* 0x%08lx */ (T_MASK ^ 0x%08lx)\n", i,
00083 v, (unsigned long)(unsigned int)(~v));
00084 } else {
00085 printf("#define T%d 0x%08lx\n", i, v);
00086 }
00087 }
00088 return 0;
00089 }
00090 #endif
00091
00092
00093
00094
00095 #define T_MASK ((dbus_uint32_t)~0)
00096 #define T1 (T_MASK ^ 0x28955b87)
00097 #define T2 (T_MASK ^ 0x173848a9)
00098 #define T3 0x242070db
00099 #define T4 (T_MASK ^ 0x3e423111)
00100 #define T5 (T_MASK ^ 0x0a83f050)
00101 #define T6 0x4787c62a
00102 #define T7 (T_MASK ^ 0x57cfb9ec)
00103 #define T8 (T_MASK ^ 0x02b96afe)
00104 #define T9 0x698098d8
00105 #define T10 (T_MASK ^ 0x74bb0850)
00106 #define T11 (T_MASK ^ 0x0000a44e)
00107 #define T12 (T_MASK ^ 0x76a32841)
00108 #define T13 0x6b901122
00109 #define T14 (T_MASK ^ 0x02678e6c)
00110 #define T15 (T_MASK ^ 0x5986bc71)
00111 #define T16 0x49b40821
00112 #define T17 (T_MASK ^ 0x09e1da9d)
00113 #define T18 (T_MASK ^ 0x3fbf4cbf)
00114 #define T19 0x265e5a51
00115 #define T20 (T_MASK ^ 0x16493855)
00116 #define T21 (T_MASK ^ 0x29d0efa2)
00117 #define T22 0x02441453
00118 #define T23 (T_MASK ^ 0x275e197e)
00119 #define T24 (T_MASK ^ 0x182c0437)
00120 #define T25 0x21e1cde6
00121 #define T26 (T_MASK ^ 0x3cc8f829)
00122 #define T27 (T_MASK ^ 0x0b2af278)
00123 #define T28 0x455a14ed
00124 #define T29 (T_MASK ^ 0x561c16fa)
00125 #define T30 (T_MASK ^ 0x03105c07)
00126 #define T31 0x676f02d9
00127 #define T32 (T_MASK ^ 0x72d5b375)
00128 #define T33 (T_MASK ^ 0x0005c6bd)
00129 #define T34 (T_MASK ^ 0x788e097e)
00130 #define T35 0x6d9d6122
00131 #define T36 (T_MASK ^ 0x021ac7f3)
00132 #define T37 (T_MASK ^ 0x5b4115bb)
00133 #define T38 0x4bdecfa9
00134 #define T39 (T_MASK ^ 0x0944b49f)
00135 #define T40 (T_MASK ^ 0x4140438f)
00136 #define T41 0x289b7ec6
00137 #define T42 (T_MASK ^ 0x155ed805)
00138 #define T43 (T_MASK ^ 0x2b10cf7a)
00139 #define T44 0x04881d05
00140 #define T45 (T_MASK ^ 0x262b2fc6)
00141 #define T46 (T_MASK ^ 0x1924661a)
00142 #define T47 0x1fa27cf8
00143 #define T48 (T_MASK ^ 0x3b53a99a)
00144 #define T49 (T_MASK ^ 0x0bd6ddbb)
00145 #define T50 0x432aff97
00146 #define T51 (T_MASK ^ 0x546bdc58)
00147 #define T52 (T_MASK ^ 0x036c5fc6)
00148 #define T53 0x655b59c3
00149 #define T54 (T_MASK ^ 0x70f3336d)
00150 #define T55 (T_MASK ^ 0x00100b82)
00151 #define T56 (T_MASK ^ 0x7a7ba22e)
00152 #define T57 0x6fa87e4f
00153 #define T58 (T_MASK ^ 0x01d3191f)
00154 #define T59 (T_MASK ^ 0x5cfebceb)
00155 #define T60 0x4e0811a1
00156 #define T61 (T_MASK ^ 0x08ac817d)
00157 #define T62 (T_MASK ^ 0x42c50dca)
00158 #define T63 0x2ad7d2bb
00159 #define T64 (T_MASK ^ 0x14792c6e)
00160 #endif
00161
00162 static void
00163 md5_process(DBusMD5Context *context, const unsigned char *data )
00164 {
00165 dbus_uint32_t
00166 a = context->abcd[0], b = context->abcd[1],
00167 c = context->abcd[2], d = context->abcd[3];
00168 dbus_uint32_t t;
00169
00170 #ifdef WORDS_BIGENDIAN
00171
00172
00173
00174
00175 dbus_uint32_t X[16];
00176 const unsigned char *xp = data;
00177 int i;
00178
00179 for (i = 0; i < 16; ++i, xp += 4)
00180 X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
00181
00182 #else
00183
00184
00185
00186
00187 dbus_uint32_t xbuf[16];
00188 const dbus_uint32_t *X;
00189
00190 if (!((data - (const unsigned char *)0) & 3))
00191 {
00192
00193 X = (const dbus_uint32_t *)data;
00194 }
00195 else
00196 {
00197
00198 memcpy(xbuf, data, 64);
00199 X = xbuf;
00200 }
00201 #endif
00202
00203 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
00204
00205
00206
00207
00208 #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
00209 #define SET(a, b, c, d, k, s, Ti) \
00210 t = a + F(b,c,d) + X[k] + Ti; \
00211 a = ROTATE_LEFT(t, s) + b
00212
00213 SET(a, b, c, d, 0, 7, T1);
00214 SET(d, a, b, c, 1, 12, T2);
00215 SET(c, d, a, b, 2, 17, T3);
00216 SET(b, c, d, a, 3, 22, T4);
00217 SET(a, b, c, d, 4, 7, T5);
00218 SET(d, a, b, c, 5, 12, T6);
00219 SET(c, d, a, b, 6, 17, T7);
00220 SET(b, c, d, a, 7, 22, T8);
00221 SET(a, b, c, d, 8, 7, T9);
00222 SET(d, a, b, c, 9, 12, T10);
00223 SET(c, d, a, b, 10, 17, T11);
00224 SET(b, c, d, a, 11, 22, T12);
00225 SET(a, b, c, d, 12, 7, T13);
00226 SET(d, a, b, c, 13, 12, T14);
00227 SET(c, d, a, b, 14, 17, T15);
00228 SET(b, c, d, a, 15, 22, T16);
00229 #undef SET
00230
00231
00232
00233
00234 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
00235 #define SET(a, b, c, d, k, s, Ti) \
00236 t = a + G(b,c,d) + X[k] + Ti; \
00237 a = ROTATE_LEFT(t, s) + b
00238
00239 SET(a, b, c, d, 1, 5, T17);
00240 SET(d, a, b, c, 6, 9, T18);
00241 SET(c, d, a, b, 11, 14, T19);
00242 SET(b, c, d, a, 0, 20, T20);
00243 SET(a, b, c, d, 5, 5, T21);
00244 SET(d, a, b, c, 10, 9, T22);
00245 SET(c, d, a, b, 15, 14, T23);
00246 SET(b, c, d, a, 4, 20, T24);
00247 SET(a, b, c, d, 9, 5, T25);
00248 SET(d, a, b, c, 14, 9, T26);
00249 SET(c, d, a, b, 3, 14, T27);
00250 SET(b, c, d, a, 8, 20, T28);
00251 SET(a, b, c, d, 13, 5, T29);
00252 SET(d, a, b, c, 2, 9, T30);
00253 SET(c, d, a, b, 7, 14, T31);
00254 SET(b, c, d, a, 12, 20, T32);
00255 #undef SET
00256
00257
00258
00259
00260 #define H(x, y, z) ((x) ^ (y) ^ (z))
00261 #define SET(a, b, c, d, k, s, Ti) \
00262 t = a + H(b,c,d) + X[k] + Ti; \
00263 a = ROTATE_LEFT(t, s) + b
00264
00265 SET(a, b, c, d, 5, 4, T33);
00266 SET(d, a, b, c, 8, 11, T34);
00267 SET(c, d, a, b, 11, 16, T35);
00268 SET(b, c, d, a, 14, 23, T36);
00269 SET(a, b, c, d, 1, 4, T37);
00270 SET(d, a, b, c, 4, 11, T38);
00271 SET(c, d, a, b, 7, 16, T39);
00272 SET(b, c, d, a, 10, 23, T40);
00273 SET(a, b, c, d, 13, 4, T41);
00274 SET(d, a, b, c, 0, 11, T42);
00275 SET(c, d, a, b, 3, 16, T43);
00276 SET(b, c, d, a, 6, 23, T44);
00277 SET(a, b, c, d, 9, 4, T45);
00278 SET(d, a, b, c, 12, 11, T46);
00279 SET(c, d, a, b, 15, 16, T47);
00280 SET(b, c, d, a, 2, 23, T48);
00281 #undef SET
00282
00283
00284
00285
00286 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
00287 #define SET(a, b, c, d, k, s, Ti) \
00288 t = a + I(b,c,d) + X[k] + Ti; \
00289 a = ROTATE_LEFT(t, s) + b
00290
00291 SET(a, b, c, d, 0, 6, T49);
00292 SET(d, a, b, c, 7, 10, T50);
00293 SET(c, d, a, b, 14, 15, T51);
00294 SET(b, c, d, a, 5, 21, T52);
00295 SET(a, b, c, d, 12, 6, T53);
00296 SET(d, a, b, c, 3, 10, T54);
00297 SET(c, d, a, b, 10, 15, T55);
00298 SET(b, c, d, a, 1, 21, T56);
00299 SET(a, b, c, d, 8, 6, T57);
00300 SET(d, a, b, c, 15, 10, T58);
00301 SET(c, d, a, b, 6, 15, T59);
00302 SET(b, c, d, a, 13, 21, T60);
00303 SET(a, b, c, d, 4, 6, T61);
00304 SET(d, a, b, c, 11, 10, T62);
00305 SET(c, d, a, b, 2, 15, T63);
00306 SET(b, c, d, a, 9, 21, T64);
00307 #undef SET
00308
00309
00310
00311
00312 context->abcd[0] += a;
00313 context->abcd[1] += b;
00314 context->abcd[2] += c;
00315 context->abcd[3] += d;
00316 }
00317
00318 static void
00319 md5_init (DBusMD5Context *context)
00320 {
00321 context->count[0] = context->count[1] = 0;
00322 context->abcd[0] = 0x67452301;
00323 context->abcd[1] = T_MASK ^ 0x10325476;
00324 context->abcd[2] = T_MASK ^ 0x67452301;
00325 context->abcd[3] = 0x10325476;
00326 }
00327
00328 static void
00329 md5_append (DBusMD5Context *context, const unsigned char *data, int nbytes)
00330 {
00331 const unsigned char *p = data;
00332 int left = nbytes;
00333 int offset = (context->count[0] >> 3) & 63;
00334 dbus_uint32_t nbits = (dbus_uint32_t)(nbytes << 3);
00335
00336 if (nbytes <= 0)
00337 return;
00338
00339
00340 context->count[1] += nbytes >> 29;
00341 context->count[0] += nbits;
00342 if (context->count[0] < nbits)
00343 context->count[1]++;
00344
00345
00346 if (offset)
00347 {
00348 int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
00349
00350 memcpy(context->buf + offset, p, copy);
00351 if (offset + copy < 64)
00352 return;
00353 p += copy;
00354 left -= copy;
00355 md5_process(context, context->buf);
00356 }
00357
00358
00359 for (; left >= 64; p += 64, left -= 64)
00360 md5_process(context, p);
00361
00362
00363 if (left)
00364 memcpy(context->buf, p, left);
00365 }
00366
00367 static void
00368 md5_finish (DBusMD5Context *context, unsigned char digest[16])
00369 {
00370 static const unsigned char pad[64] = {
00371 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00372 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00373 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00374 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00375 };
00376 unsigned char data[8];
00377 int i;
00378
00379
00380 for (i = 0; i < 8; ++i)
00381 data[i] = (unsigned char)(context->count[i >> 2] >> ((i & 3) << 3));
00382
00383 md5_append(context, pad, ((55 - (context->count[0] >> 3)) & 63) + 1);
00384
00385 md5_append(context, data, 8);
00386 for (i = 0; i < 16; ++i)
00387 digest[i] = (unsigned char)(context->abcd[i >> 2] >> ((i & 3) << 3));
00388 }
00389
00391
00403 void
00404 _dbus_md5_init (DBusMD5Context *context)
00405 {
00406 md5_init (context);
00407 }
00408
00409
00416 void
00417 _dbus_md5_update (DBusMD5Context *context,
00418 const DBusString *data)
00419 {
00420 unsigned int inputLen;
00421 unsigned char *input;
00422
00423 _dbus_string_get_const_data (data, (const char**) &input);
00424 inputLen = _dbus_string_get_length (data);
00425
00426 md5_append (context, input, inputLen);
00427 }
00428
00440 dbus_bool_t
00441 _dbus_md5_final (DBusMD5Context *context,
00442 DBusString *results)
00443 {
00444 unsigned char digest[16];
00445
00446 md5_finish (context, digest);
00447
00448 if (!_dbus_string_append_len (results, digest, 16))
00449 return FALSE;
00450
00451
00452
00453
00454 memset ((void*)context, '\0', sizeof (DBusMD5Context));
00455
00456 return TRUE;
00457 }
00458
00467 dbus_bool_t
00468 _dbus_md5_compute (const DBusString *data,
00469 DBusString *ascii_output)
00470 {
00471 DBusMD5Context context;
00472 DBusString digest;
00473
00474 _dbus_md5_init (&context);
00475
00476 _dbus_md5_update (&context, data);
00477
00478 if (!_dbus_string_init (&digest))
00479 return FALSE;
00480
00481 if (!_dbus_md5_final (&context, &digest))
00482 goto error;
00483
00484 if (!_dbus_string_hex_encode (&digest, 0, ascii_output,
00485 _dbus_string_get_length (ascii_output)))
00486 goto error;
00487
00488 _dbus_string_free (&digest);
00489
00490 return TRUE;
00491
00492 error:
00493 _dbus_string_free (&digest);
00494 return FALSE;
00495 }
00496
00498
00499 #ifdef DBUS_BUILD_TESTS
00500 #include "dbus-test.h"
00501 #include <stdio.h>
00502
00503 static dbus_bool_t
00504 check_md5_binary (const unsigned char *input,
00505 int input_len,
00506 const char *expected)
00507 {
00508 DBusString input_str;
00509 DBusString expected_str;
00510 DBusString results;
00511
00512 _dbus_string_init_const_len (&input_str, input, input_len);
00513 _dbus_string_init_const (&expected_str, expected);
00514
00515 if (!_dbus_string_init (&results))
00516 _dbus_assert_not_reached ("no memory for md5 results");
00517
00518 if (!_dbus_md5_compute (&input_str, &results))
00519 _dbus_assert_not_reached ("no memory for md5 results");
00520
00521 if (!_dbus_string_equal (&expected_str, &results))
00522 {
00523 const char *s;
00524 _dbus_string_get_const_data (&results, &s);
00525 _dbus_warn ("Expected hash %s got %s for md5 sum\n",
00526 expected, s);
00527 _dbus_string_free (&results);
00528 return FALSE;
00529 }
00530
00531 _dbus_string_free (&results);
00532 return TRUE;
00533 }
00534
00535 static dbus_bool_t
00536 check_md5_str (const char *input,
00537 const char *expected)
00538 {
00539 return check_md5_binary (input, strlen (input), expected);
00540 }
00541
00548 dbus_bool_t
00549 _dbus_md5_test (void)
00550 {
00551 unsigned char all_bytes[256];
00552 int i;
00553
00554 i = 0;
00555 while (i < 256)
00556 {
00557 all_bytes[i] = i;
00558 ++i;
00559 }
00560
00561 if (!check_md5_binary (all_bytes, 256,
00562 "e2c865db4162bed963bfaa9ef6ac18f0"))
00563 return FALSE;
00564
00565 #define CHECK(input,expected) if (!check_md5_str (input, expected)) return FALSE
00566
00567 CHECK ("", "d41d8cd98f00b204e9800998ecf8427e");
00568 CHECK ("a", "0cc175b9c0f1b6a831c399e269772661");
00569 CHECK ("abc", "900150983cd24fb0d6963f7d28e17f72");
00570 CHECK ("message digest", "f96b697d7cb7938d525a2f31aaf161d0");
00571 CHECK ("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b");
00572 CHECK ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
00573 "d174ab98d277d9f5a5611c2c9f419d9f");
00574 CHECK ("12345678901234567890123456789012345678901234567890123456789012345678901234567890",
00575 "57edf4a22be3c955ac49da2e2107b67a");
00576
00577 return TRUE;
00578 }
00579
00580 #endif