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