XMMS2
|
00001 /* XMMS2 - X Music Multiplexer System 00002 * Copyright (C) 2003-2011 XMMS2 Team 00003 * 00004 * PLUGINS ARE NOT CONSIDERED TO BE DERIVED WORK !!! 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 */ 00016 00017 #include <glib.h> 00018 #include <string.h> 00019 #include <stdio.h> 00020 #include <stdlib.h> 00021 #include <unistd.h> 00022 #include <sys/time.h> 00023 #include <errno.h> 00024 00025 #include "xmmsc/xmmsc_idnumbers.h" 00026 #include "xmmsc/xmmsc_ipc_transport.h" 00027 #include "xmmsc/xmmsc_ipc_msg.h" 00028 00029 #include "xmms/xmms_log.h" 00030 00031 #include "xmms/xmms_bindata.h" 00032 00033 #include "xmmspriv/xmms_ringbuf.h" 00034 #include "xmmspriv/xmms_ipc.h" 00035 #include "xmmspriv/xmms_playlist.h" 00036 #include "xmmspriv/xmms_config.h" 00037 #include "xmmspriv/xmms_bindata.h" 00038 #include "xmmspriv/xmms_utils.h" 00039 00040 struct xmms_bindata_St { 00041 xmms_object_t obj; 00042 const gchar *bindir; 00043 }; 00044 00045 static xmms_bindata_t *global_bindata; 00046 00047 static void xmms_bindata_destroy (xmms_object_t *obj); 00048 00049 typedef unsigned char md5_byte_t; /* 8-bit byte */ 00050 typedef unsigned int md5_word_t; /* 32-bit word */ 00051 00052 /* Define the state of the MD5 Algorithm. */ 00053 typedef struct md5_state_s { 00054 md5_word_t count[2]; /* message length in bits, lsw first */ 00055 md5_word_t abcd[4]; /* digest buffer */ 00056 md5_byte_t buf[64]; /* accumulate block */ 00057 } md5_state_t; 00058 00059 /* Initialize the algorithm. */ 00060 static void md5_init (md5_state_t *pms); 00061 static void md5_append (md5_state_t *pms, const md5_byte_t *data, int nbytes); 00062 static void md5_finish (md5_state_t *pms, md5_byte_t digest[16]); 00063 00064 static gchar *xmms_bindata_build_path (xmms_bindata_t *bindata, const gchar *hash); 00065 00066 static gchar *xmms_bindata_client_add (xmms_bindata_t *bindata, GString *data, xmms_error_t *err); 00067 static xmmsv_t *xmms_bindata_client_retrieve (xmms_bindata_t *bindata, const gchar *hash, xmms_error_t *err); 00068 static void xmms_bindata_client_remove (xmms_bindata_t *bindata, const gchar *hash, xmms_error_t *); 00069 static GList *xmms_bindata_client_list (xmms_bindata_t *bindata, xmms_error_t *err); 00070 static gboolean _xmms_bindata_add (xmms_bindata_t *bindata, const guchar *data, gsize len, gchar hash[33], xmms_error_t *err); 00071 00072 #include "bindata_ipc.c" 00073 00074 xmms_bindata_t * 00075 xmms_bindata_init () 00076 { 00077 gchar *tmp; 00078 xmms_bindata_t *obj; 00079 xmms_config_property_t *cv; 00080 00081 obj = xmms_object_new (xmms_bindata_t, xmms_bindata_destroy); 00082 00083 xmms_bindata_register_ipc_commands (XMMS_OBJECT (obj)); 00084 00085 tmp = XMMS_BUILD_PATH ("bindata"); 00086 cv = xmms_config_property_register ("bindata.path", tmp, NULL, NULL); 00087 g_free (tmp); 00088 00089 obj->bindir = xmms_config_property_get_string (cv); 00090 00091 if (!g_file_test (obj->bindir, G_FILE_TEST_IS_DIR)) { 00092 if (g_mkdir_with_parents (obj->bindir, 0755) == -1) { 00093 xmms_log_error ("Couldn't create bindir %s", obj->bindir); 00094 } 00095 } 00096 00097 global_bindata = obj; 00098 00099 return obj; 00100 } 00101 00102 static void 00103 xmms_bindata_destroy (xmms_object_t *obj) 00104 { 00105 xmms_bindata_unregister_ipc_commands (); 00106 } 00107 00108 gchar * 00109 xmms_bindata_calculate_md5 (const guchar *data, gsize size, gchar ret[33]) 00110 { 00111 md5_state_t state; 00112 md5_byte_t digest[16]; 00113 int di; 00114 static gchar hex[] = { 00115 '0', '1', '2', '3', '4', '5', '6', '7', 00116 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' 00117 }; 00118 00119 md5_init (&state); 00120 md5_append (&state, (const md5_byte_t *)data, size); 00121 md5_finish (&state, digest); 00122 00123 for (di = 0; di < 16; ++di) { 00124 ret[di * 2] = hex[digest[di] >> 4]; 00125 ret[di * 2 + 1] = hex[digest[di] & 0x0f]; 00126 } 00127 ret[32] = 0; 00128 return ret; 00129 } 00130 00131 static gchar * 00132 xmms_bindata_build_path (xmms_bindata_t *bindata, const gchar *hash) 00133 { 00134 return g_build_path (G_DIR_SEPARATOR_S, bindata->bindir, hash, NULL); 00135 } 00136 00137 /** Add binary data from a plugin */ 00138 gboolean 00139 xmms_bindata_plugin_add (const guchar *data, gsize size, gchar hash[33]) 00140 { 00141 xmms_error_t err; 00142 return _xmms_bindata_add (global_bindata, data, size, hash, &err); 00143 } 00144 00145 static gboolean 00146 _xmms_bindata_add (xmms_bindata_t *bindata, const guchar *data, gsize len, gchar hash[33], xmms_error_t *err) 00147 { 00148 const guchar *ptr; 00149 gsize left; 00150 gchar *path; 00151 FILE *fp; 00152 00153 xmms_bindata_calculate_md5 (data, len, hash); 00154 00155 path = xmms_bindata_build_path (bindata, hash); 00156 00157 if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) { 00158 XMMS_DBG ("file %s is already in bindata dir", hash); 00159 g_free (path); 00160 return TRUE; 00161 } 00162 00163 XMMS_DBG ("Creating %s", path); 00164 fp = fopen (path, "wb"); 00165 if (!fp) { 00166 xmms_log_error ("Couldn't create %s", path); 00167 xmms_error_set (err, XMMS_ERROR_GENERIC, "Couldn't create file on server!"); 00168 g_free (path); 00169 return FALSE; 00170 } 00171 00172 /* write the data to the file */ 00173 ptr = data; 00174 left = len; 00175 00176 while (left > 0) { 00177 size_t w; 00178 00179 w = fwrite (ptr, 1, left, fp); 00180 if (!w && ferror (fp)) { 00181 fclose (fp); 00182 unlink (path); 00183 00184 xmms_log_error ("Couldn't write data"); 00185 xmms_error_set (err, XMMS_ERROR_GENERIC, 00186 "Couldn't write data!"); 00187 g_free (path); 00188 return FALSE; 00189 } 00190 00191 left -= w; 00192 ptr += w; 00193 } 00194 00195 fclose (fp); 00196 g_free (path); 00197 00198 return TRUE; 00199 } 00200 00201 char * 00202 xmms_bindata_client_add (xmms_bindata_t *bindata, GString *data, xmms_error_t *err) 00203 { 00204 gchar hash[33]; 00205 if (_xmms_bindata_add (bindata, (guchar *)data->str, data->len, hash, err)) 00206 return g_strdup (hash); 00207 return NULL; 00208 } 00209 00210 static xmmsv_t * 00211 xmms_bindata_client_retrieve (xmms_bindata_t *bindata, const gchar *hash, 00212 xmms_error_t *err) 00213 { 00214 xmmsv_t *res; 00215 gchar *path; 00216 GString *str; 00217 FILE *fp; 00218 00219 path = xmms_bindata_build_path (bindata, hash); 00220 00221 fp = fopen (path, "rb"); 00222 if (!fp) { 00223 xmms_log_error ("Requesting '%s' which is not on the server", hash); 00224 xmms_error_set (err, XMMS_ERROR_NOENT, "File not found!"); 00225 g_free (path); 00226 return NULL; 00227 } 00228 00229 g_free (path); 00230 00231 str = g_string_new (NULL); 00232 while (!feof (fp)) { 00233 gchar buf[1024]; 00234 gint l; 00235 00236 l = fread (buf, 1, 1024, fp); 00237 if (ferror (fp)) { 00238 g_string_free (str, TRUE); 00239 xmms_log_error ("Error reading bindata '%s'", hash); 00240 xmms_error_set (err, XMMS_ERROR_GENERIC, "Error reading file"); 00241 fclose (fp); 00242 return NULL; 00243 } 00244 g_string_append_len (str, buf, l); 00245 } 00246 00247 fclose (fp); 00248 00249 res = xmmsv_new_bin ((unsigned char *)str->str, str->len); 00250 00251 g_string_free (str, TRUE); 00252 00253 return res; 00254 } 00255 00256 static void 00257 xmms_bindata_client_remove (xmms_bindata_t *bindata, const gchar *hash, 00258 xmms_error_t *err) 00259 { 00260 gchar *path; 00261 path = xmms_bindata_build_path (bindata, hash); 00262 if (unlink (path) == -1) { 00263 xmms_error_set (err, XMMS_ERROR_GENERIC, "Couldn't remove file"); 00264 } 00265 g_free (path); 00266 return; 00267 } 00268 00269 static GList * 00270 xmms_bindata_client_list (xmms_bindata_t *bindata, xmms_error_t *err) 00271 { 00272 GList *entries = NULL; 00273 gchar *path; 00274 const gchar *file; 00275 GDir *dir; 00276 00277 path = xmms_bindata_build_path (bindata, NULL); 00278 dir = g_dir_open (path, 0, NULL); 00279 g_free (path); 00280 00281 if (!dir) { 00282 xmms_error_set (err, XMMS_ERROR_GENERIC, 00283 "Couldn't open bindata directory"); 00284 return NULL; 00285 } 00286 00287 while ((file = g_dir_read_name (dir))) { 00288 entries = g_list_prepend (entries, xmmsv_new_string (file)); 00289 } 00290 00291 g_dir_close (dir); 00292 00293 return entries; 00294 } 00295 00296 /* 00297 Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. 00298 00299 This software is provided 'as-is', without any express or implied 00300 warranty. In no event will the authors be held liable for any damages 00301 arising from the use of this software. 00302 00303 Permission is granted to anyone to use this software for any purpose, 00304 including commercial applications, and to alter it and redistribute it 00305 freely, subject to the following restrictions: 00306 00307 1. The origin of this software must not be misrepresented; you must not 00308 claim that you wrote the original software. If you use this software 00309 in a product, an acknowledgment in the product documentation would be 00310 appreciated but is not required. 00311 2. Altered source versions must be plainly marked as such, and must not be 00312 misrepresented as being the original software. 00313 3. This notice may not be removed or altered from any source distribution. 00314 00315 L. Peter Deutsch 00316 ghost@aladdin.com 00317 00318 */ 00319 /* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ 00320 /* 00321 Independent implementation of MD5 (RFC 1321). 00322 00323 This code implements the MD5 Algorithm defined in RFC 1321, whose 00324 text is available at 00325 http://www.ietf.org/rfc/rfc1321.txt 00326 The code is derived from the text of the RFC, including the test suite 00327 (section A.5) but excluding the rest of Appendix A. It does not include 00328 any code or documentation that is identified in the RFC as being 00329 copyrighted. 00330 00331 The original and principal author of md5.c is L. Peter Deutsch 00332 <ghost@aladdin.com>. Other authors are noted in the change history 00333 that follows (in reverse chronological order): 00334 00335 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order 00336 either statically or dynamically; added missing #include <string.h> 00337 in library. 00338 2002-03-11 lpd Corrected argument list for main(), and added int return 00339 type, in test program and T value program. 00340 2002-02-21 lpd Added missing #include <stdio.h> in test program. 00341 2000-07-03 lpd Patched to eliminate warnings about "constant is 00342 unsigned in ANSI C, signed in traditional"; made test program 00343 self-checking. 00344 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 00345 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). 00346 1999-05-03 lpd Original version. 00347 */ 00348 00349 /* 00350 * This package supports both compile-time and run-time determination of CPU 00351 * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be 00352 * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is 00353 * defined as non-zero, the code will be compiled to run only on big-endian 00354 * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to 00355 * run on either big- or little-endian CPUs, but will run slightly less 00356 * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. 00357 */ 00358 00359 #undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ 00360 #ifdef ARCH_IS_BIG_ENDIAN 00361 # define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) 00362 #else 00363 # define BYTE_ORDER 0 00364 #endif 00365 00366 #define T_MASK ((md5_word_t)~0) 00367 #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) 00368 #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) 00369 #define T3 0x242070db 00370 #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) 00371 #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) 00372 #define T6 0x4787c62a 00373 #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) 00374 #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) 00375 #define T9 0x698098d8 00376 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) 00377 #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) 00378 #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) 00379 #define T13 0x6b901122 00380 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) 00381 #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) 00382 #define T16 0x49b40821 00383 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) 00384 #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) 00385 #define T19 0x265e5a51 00386 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) 00387 #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) 00388 #define T22 0x02441453 00389 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) 00390 #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) 00391 #define T25 0x21e1cde6 00392 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) 00393 #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) 00394 #define T28 0x455a14ed 00395 #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) 00396 #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) 00397 #define T31 0x676f02d9 00398 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) 00399 #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) 00400 #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) 00401 #define T35 0x6d9d6122 00402 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) 00403 #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) 00404 #define T38 0x4bdecfa9 00405 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) 00406 #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) 00407 #define T41 0x289b7ec6 00408 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) 00409 #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) 00410 #define T44 0x04881d05 00411 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) 00412 #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) 00413 #define T47 0x1fa27cf8 00414 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) 00415 #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) 00416 #define T50 0x432aff97 00417 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) 00418 #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) 00419 #define T53 0x655b59c3 00420 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) 00421 #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) 00422 #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) 00423 #define T57 0x6fa87e4f 00424 #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) 00425 #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) 00426 #define T60 0x4e0811a1 00427 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) 00428 #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) 00429 #define T63 0x2ad7d2bb 00430 #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) 00431 00432 00433 static void 00434 md5_process (md5_state_t *pms, const md5_byte_t *data /*[64]*/) 00435 { 00436 md5_word_t 00437 a = pms->abcd[0], b = pms->abcd[1], 00438 c = pms->abcd[2], d = pms->abcd[3]; 00439 md5_word_t t; 00440 #if BYTE_ORDER > 0 00441 /* Define storage only for big-endian CPUs. */ 00442 md5_word_t X[16]; 00443 #else 00444 /* Define storage for little-endian or both types of CPUs. */ 00445 md5_word_t xbuf[16]; 00446 const md5_word_t *X; 00447 #endif 00448 00449 { 00450 #if BYTE_ORDER == 0 00451 /* 00452 * Determine dynamically whether this is a big-endian or 00453 * little-endian machine, since we can use a more efficient 00454 * algorithm on the latter. 00455 */ 00456 static const int w = 1; 00457 00458 if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ 00459 #endif 00460 #if BYTE_ORDER <= 0 /* little-endian */ 00461 { 00462 /* 00463 * On little-endian machines, we can process properly aligned 00464 * data without copying it. 00465 */ 00466 if (!((data - (const md5_byte_t *)0) & 3)) { 00467 /* data are properly aligned */ 00468 X = (const md5_word_t *)data; 00469 } else { 00470 /* not aligned */ 00471 memcpy (xbuf, data, 64); 00472 X = xbuf; 00473 } 00474 } 00475 #endif 00476 #if BYTE_ORDER == 0 00477 else /* dynamic big-endian */ 00478 #endif 00479 #if BYTE_ORDER >= 0 /* big-endian */ 00480 { 00481 /* 00482 * On big-endian machines, we must arrange the bytes in the 00483 * right order. 00484 */ 00485 const md5_byte_t *xp = data; 00486 int i; 00487 00488 # if BYTE_ORDER == 0 00489 X = xbuf;/* (dynamic only) */ 00490 # else 00491 # define xbuf X /* (static only) */ 00492 # endif 00493 for (i = 0; i < 16; ++i, xp += 4) 00494 xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); 00495 } 00496 #endif 00497 } 00498 00499 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) 00500 00501 /* Round 1. */ 00502 /* Let [abcd k s i] denote the operation 00503 a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ 00504 #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) 00505 #define SET(a, b, c, d, k, s, Ti)\ 00506 t = a + F (b,c,d) + X[k] + Ti;\ 00507 a = ROTATE_LEFT (t, s) + b 00508 /* Do the following 16 operations. */ 00509 SET (a, b, c, d, 0, 7, T1); 00510 SET (d, a, b, c, 1, 12, T2); 00511 SET (c, d, a, b, 2, 17, T3); 00512 SET (b, c, d, a, 3, 22, T4); 00513 SET (a, b, c, d, 4, 7, T5); 00514 SET (d, a, b, c, 5, 12, T6); 00515 SET (c, d, a, b, 6, 17, T7); 00516 SET (b, c, d, a, 7, 22, T8); 00517 SET (a, b, c, d, 8, 7, T9); 00518 SET (d, a, b, c, 9, 12, T10); 00519 SET (c, d, a, b, 10, 17, T11); 00520 SET (b, c, d, a, 11, 22, T12); 00521 SET (a, b, c, d, 12, 7, T13); 00522 SET (d, a, b, c, 13, 12, T14); 00523 SET (c, d, a, b, 14, 17, T15); 00524 SET (b, c, d, a, 15, 22, T16); 00525 #undef SET 00526 00527 /* Round 2. */ 00528 /* Let [abcd k s i] denote the operation 00529 a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ 00530 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) 00531 #define SET(a, b, c, d, k, s, Ti)\ 00532 t = a + G (b,c,d) + X[k] + Ti;\ 00533 a = ROTATE_LEFT (t, s) + b 00534 /* Do the following 16 operations. */ 00535 SET (a, b, c, d, 1, 5, T17); 00536 SET (d, a, b, c, 6, 9, T18); 00537 SET (c, d, a, b, 11, 14, T19); 00538 SET (b, c, d, a, 0, 20, T20); 00539 SET (a, b, c, d, 5, 5, T21); 00540 SET (d, a, b, c, 10, 9, T22); 00541 SET (c, d, a, b, 15, 14, T23); 00542 SET (b, c, d, a, 4, 20, T24); 00543 SET (a, b, c, d, 9, 5, T25); 00544 SET (d, a, b, c, 14, 9, T26); 00545 SET (c, d, a, b, 3, 14, T27); 00546 SET (b, c, d, a, 8, 20, T28); 00547 SET (a, b, c, d, 13, 5, T29); 00548 SET (d, a, b, c, 2, 9, T30); 00549 SET (c, d, a, b, 7, 14, T31); 00550 SET (b, c, d, a, 12, 20, T32); 00551 #undef SET 00552 00553 /* Round 3. */ 00554 /* Let [abcd k s t] denote the operation 00555 a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ 00556 #define H(x, y, z) ((x) ^ (y) ^ (z)) 00557 #define SET(a, b, c, d, k, s, Ti)\ 00558 t = a + H (b,c,d) + X[k] + Ti;\ 00559 a = ROTATE_LEFT (t, s) + b 00560 /* Do the following 16 operations. */ 00561 SET (a, b, c, d, 5, 4, T33); 00562 SET (d, a, b, c, 8, 11, T34); 00563 SET (c, d, a, b, 11, 16, T35); 00564 SET (b, c, d, a, 14, 23, T36); 00565 SET (a, b, c, d, 1, 4, T37); 00566 SET (d, a, b, c, 4, 11, T38); 00567 SET (c, d, a, b, 7, 16, T39); 00568 SET (b, c, d, a, 10, 23, T40); 00569 SET (a, b, c, d, 13, 4, T41); 00570 SET (d, a, b, c, 0, 11, T42); 00571 SET (c, d, a, b, 3, 16, T43); 00572 SET (b, c, d, a, 6, 23, T44); 00573 SET (a, b, c, d, 9, 4, T45); 00574 SET (d, a, b, c, 12, 11, T46); 00575 SET (c, d, a, b, 15, 16, T47); 00576 SET (b, c, d, a, 2, 23, T48); 00577 #undef SET 00578 00579 /* Round 4. */ 00580 /* Let [abcd k s t] denote the operation 00581 a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ 00582 #define I(x, y, z) ((y) ^ ((x) | ~(z))) 00583 #define SET(a, b, c, d, k, s, Ti)\ 00584 t = a + I (b,c,d) + X[k] + Ti;\ 00585 a = ROTATE_LEFT (t, s) + b 00586 /* Do the following 16 operations. */ 00587 SET (a, b, c, d, 0, 6, T49); 00588 SET (d, a, b, c, 7, 10, T50); 00589 SET (c, d, a, b, 14, 15, T51); 00590 SET (b, c, d, a, 5, 21, T52); 00591 SET (a, b, c, d, 12, 6, T53); 00592 SET (d, a, b, c, 3, 10, T54); 00593 SET (c, d, a, b, 10, 15, T55); 00594 SET (b, c, d, a, 1, 21, T56); 00595 SET (a, b, c, d, 8, 6, T57); 00596 SET (d, a, b, c, 15, 10, T58); 00597 SET (c, d, a, b, 6, 15, T59); 00598 SET (b, c, d, a, 13, 21, T60); 00599 SET (a, b, c, d, 4, 6, T61); 00600 SET (d, a, b, c, 11, 10, T62); 00601 SET (c, d, a, b, 2, 15, T63); 00602 SET (b, c, d, a, 9, 21, T64); 00603 #undef SET 00604 00605 /* Then perform the following additions. (That is increment each 00606 of the four registers by the value it had before this block 00607 was started.) */ 00608 pms->abcd[0] += a; 00609 pms->abcd[1] += b; 00610 pms->abcd[2] += c; 00611 pms->abcd[3] += d; 00612 } 00613 00614 static void 00615 md5_init (md5_state_t *pms) 00616 { 00617 pms->count[0] = pms->count[1] = 0; 00618 pms->abcd[0] = 0x67452301; 00619 pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; 00620 pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; 00621 pms->abcd[3] = 0x10325476; 00622 } 00623 00624 static void 00625 md5_append (md5_state_t *pms, const md5_byte_t *data, int nbytes) 00626 { 00627 const md5_byte_t *p = data; 00628 int left = nbytes; 00629 int offset = (pms->count[0] >> 3) & 63; 00630 md5_word_t nbits = (md5_word_t)(nbytes << 3); 00631 00632 if (nbytes <= 0) 00633 return; 00634 00635 /* Update the message length. */ 00636 pms->count[1] += nbytes >> 29; 00637 pms->count[0] += nbits; 00638 if (pms->count[0] < nbits) 00639 pms->count[1]++; 00640 00641 /* Process an initial partial block. */ 00642 if (offset) { 00643 int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); 00644 00645 memcpy (pms->buf + offset, p, copy); 00646 if (offset + copy < 64) 00647 return; 00648 p += copy; 00649 left -= copy; 00650 md5_process (pms, pms->buf); 00651 } 00652 00653 /* Process full blocks. */ 00654 for (; left >= 64; p += 64, left -= 64) 00655 md5_process (pms, p); 00656 00657 /* Process a final partial block. */ 00658 if (left) 00659 memcpy (pms->buf, p, left); 00660 } 00661 00662 static void 00663 md5_finish (md5_state_t *pms, md5_byte_t digest[16]) 00664 { 00665 static const md5_byte_t pad[64] = { 00666 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00667 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00668 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00669 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 00670 }; 00671 md5_byte_t data[8]; 00672 int i; 00673 00674 /* Save the length before padding. */ 00675 for (i = 0; i < 8; ++i) 00676 data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); 00677 /* Pad to 56 bytes mod 64. */ 00678 md5_append (pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); 00679 /* Append the length. */ 00680 md5_append (pms, data, 8); 00681 for (i = 0; i < 16; ++i) 00682 digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); 00683 }