00001 /*!@file Util/md5.C general md5 (128-bit) message-digest implementation */ 00002 00003 // This code is from http://www.cr0.net:8040/code/crypto/md5/, also 00004 // under the GPL (see original copyright notice below) 00005 00006 /* 00007 * RFC 1321 compliant MD5 implementation 00008 * 00009 * Copyright (C) 2001-2003 Christophe Devine 00010 * 00011 * This program is free software; you can redistribute it and/or modify 00012 * it under the terms of the GNU General Public License as published by 00013 * the Free Software Foundation; either version 2 of the License, or 00014 * (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software 00023 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00024 */ 00025 00026 // 00027 // Primary maintainer for this file: Rob Peters <rjpeters at usc dot edu> 00028 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Util/md5.C $ 00029 // $Id: md5.C 5368 2005-08-22 21:51:52Z rjpeters $ 00030 // 00031 00032 #ifndef UTIL_MD5_C_DEFINED 00033 #define UTIL_MD5_C_DEFINED 00034 00035 #include "Util/md5.H" 00036 00037 #include <string.h> 00038 00039 typedef byte uint8; 00040 00041 #define GET_UINT32(n,b,i) \ 00042 { \ 00043 (n) = ( (uint32) (b)[(i) ] ) \ 00044 | ( (uint32) (b)[(i) + 1] << 8 ) \ 00045 | ( (uint32) (b)[(i) + 2] << 16 ) \ 00046 | ( (uint32) (b)[(i) + 3] << 24 ); \ 00047 } 00048 00049 #define PUT_UINT32(n,b,i) \ 00050 { \ 00051 (b)[(i) ] = (uint8) ( (n) ); \ 00052 (b)[(i) + 1] = (uint8) ( (n) >> 8 ); \ 00053 (b)[(i) + 2] = (uint8) ( (n) >> 16 ); \ 00054 (b)[(i) + 3] = (uint8) ( (n) >> 24 ); \ 00055 } 00056 00057 void md5_starts( md5_context *ctx ) 00058 { 00059 ctx->total[0] = 0; 00060 ctx->total[1] = 0; 00061 00062 ctx->state[0] = 0x67452301; 00063 ctx->state[1] = 0xEFCDAB89; 00064 ctx->state[2] = 0x98BADCFE; 00065 ctx->state[3] = 0x10325476; 00066 } 00067 00068 void md5_process( md5_context *ctx, const uint8 data[64] ) 00069 { 00070 uint32 X[16], A, B, C, D; 00071 00072 GET_UINT32( X[0], data, 0 ); 00073 GET_UINT32( X[1], data, 4 ); 00074 GET_UINT32( X[2], data, 8 ); 00075 GET_UINT32( X[3], data, 12 ); 00076 GET_UINT32( X[4], data, 16 ); 00077 GET_UINT32( X[5], data, 20 ); 00078 GET_UINT32( X[6], data, 24 ); 00079 GET_UINT32( X[7], data, 28 ); 00080 GET_UINT32( X[8], data, 32 ); 00081 GET_UINT32( X[9], data, 36 ); 00082 GET_UINT32( X[10], data, 40 ); 00083 GET_UINT32( X[11], data, 44 ); 00084 GET_UINT32( X[12], data, 48 ); 00085 GET_UINT32( X[13], data, 52 ); 00086 GET_UINT32( X[14], data, 56 ); 00087 GET_UINT32( X[15], data, 60 ); 00088 00089 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) 00090 00091 #define P(a,b,c,d,k,s,t) \ 00092 { \ 00093 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ 00094 } 00095 00096 A = ctx->state[0]; 00097 B = ctx->state[1]; 00098 C = ctx->state[2]; 00099 D = ctx->state[3]; 00100 00101 #define F(x,y,z) (z ^ (x & (y ^ z))) 00102 00103 P( A, B, C, D, 0, 7, 0xD76AA478 ); 00104 P( D, A, B, C, 1, 12, 0xE8C7B756 ); 00105 P( C, D, A, B, 2, 17, 0x242070DB ); 00106 P( B, C, D, A, 3, 22, 0xC1BDCEEE ); 00107 P( A, B, C, D, 4, 7, 0xF57C0FAF ); 00108 P( D, A, B, C, 5, 12, 0x4787C62A ); 00109 P( C, D, A, B, 6, 17, 0xA8304613 ); 00110 P( B, C, D, A, 7, 22, 0xFD469501 ); 00111 P( A, B, C, D, 8, 7, 0x698098D8 ); 00112 P( D, A, B, C, 9, 12, 0x8B44F7AF ); 00113 P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); 00114 P( B, C, D, A, 11, 22, 0x895CD7BE ); 00115 P( A, B, C, D, 12, 7, 0x6B901122 ); 00116 P( D, A, B, C, 13, 12, 0xFD987193 ); 00117 P( C, D, A, B, 14, 17, 0xA679438E ); 00118 P( B, C, D, A, 15, 22, 0x49B40821 ); 00119 00120 #undef F 00121 00122 #define F(x,y,z) (y ^ (z & (x ^ y))) 00123 00124 P( A, B, C, D, 1, 5, 0xF61E2562 ); 00125 P( D, A, B, C, 6, 9, 0xC040B340 ); 00126 P( C, D, A, B, 11, 14, 0x265E5A51 ); 00127 P( B, C, D, A, 0, 20, 0xE9B6C7AA ); 00128 P( A, B, C, D, 5, 5, 0xD62F105D ); 00129 P( D, A, B, C, 10, 9, 0x02441453 ); 00130 P( C, D, A, B, 15, 14, 0xD8A1E681 ); 00131 P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); 00132 P( A, B, C, D, 9, 5, 0x21E1CDE6 ); 00133 P( D, A, B, C, 14, 9, 0xC33707D6 ); 00134 P( C, D, A, B, 3, 14, 0xF4D50D87 ); 00135 P( B, C, D, A, 8, 20, 0x455A14ED ); 00136 P( A, B, C, D, 13, 5, 0xA9E3E905 ); 00137 P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); 00138 P( C, D, A, B, 7, 14, 0x676F02D9 ); 00139 P( B, C, D, A, 12, 20, 0x8D2A4C8A ); 00140 00141 #undef F 00142 00143 #define F(x,y,z) (x ^ y ^ z) 00144 00145 P( A, B, C, D, 5, 4, 0xFFFA3942 ); 00146 P( D, A, B, C, 8, 11, 0x8771F681 ); 00147 P( C, D, A, B, 11, 16, 0x6D9D6122 ); 00148 P( B, C, D, A, 14, 23, 0xFDE5380C ); 00149 P( A, B, C, D, 1, 4, 0xA4BEEA44 ); 00150 P( D, A, B, C, 4, 11, 0x4BDECFA9 ); 00151 P( C, D, A, B, 7, 16, 0xF6BB4B60 ); 00152 P( B, C, D, A, 10, 23, 0xBEBFBC70 ); 00153 P( A, B, C, D, 13, 4, 0x289B7EC6 ); 00154 P( D, A, B, C, 0, 11, 0xEAA127FA ); 00155 P( C, D, A, B, 3, 16, 0xD4EF3085 ); 00156 P( B, C, D, A, 6, 23, 0x04881D05 ); 00157 P( A, B, C, D, 9, 4, 0xD9D4D039 ); 00158 P( D, A, B, C, 12, 11, 0xE6DB99E5 ); 00159 P( C, D, A, B, 15, 16, 0x1FA27CF8 ); 00160 P( B, C, D, A, 2, 23, 0xC4AC5665 ); 00161 00162 #undef F 00163 00164 #define F(x,y,z) (y ^ (x | ~z)) 00165 00166 P( A, B, C, D, 0, 6, 0xF4292244 ); 00167 P( D, A, B, C, 7, 10, 0x432AFF97 ); 00168 P( C, D, A, B, 14, 15, 0xAB9423A7 ); 00169 P( B, C, D, A, 5, 21, 0xFC93A039 ); 00170 P( A, B, C, D, 12, 6, 0x655B59C3 ); 00171 P( D, A, B, C, 3, 10, 0x8F0CCC92 ); 00172 P( C, D, A, B, 10, 15, 0xFFEFF47D ); 00173 P( B, C, D, A, 1, 21, 0x85845DD1 ); 00174 P( A, B, C, D, 8, 6, 0x6FA87E4F ); 00175 P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); 00176 P( C, D, A, B, 6, 15, 0xA3014314 ); 00177 P( B, C, D, A, 13, 21, 0x4E0811A1 ); 00178 P( A, B, C, D, 4, 6, 0xF7537E82 ); 00179 P( D, A, B, C, 11, 10, 0xBD3AF235 ); 00180 P( C, D, A, B, 2, 15, 0x2AD7D2BB ); 00181 P( B, C, D, A, 9, 21, 0xEB86D391 ); 00182 00183 #undef F 00184 00185 ctx->state[0] += A; 00186 ctx->state[1] += B; 00187 ctx->state[2] += C; 00188 ctx->state[3] += D; 00189 } 00190 00191 void md5_update( md5_context *ctx, const uint8 *input, uint32 length ) 00192 { 00193 uint32 left, fill; 00194 00195 if( ! length ) return; 00196 00197 left = ctx->total[0] & 0x3F; 00198 fill = 64 - left; 00199 00200 ctx->total[0] += length; 00201 ctx->total[0] &= 0xFFFFFFFF; 00202 00203 if( ctx->total[0] < length ) 00204 ctx->total[1]++; 00205 00206 if( left && length >= fill ) 00207 { 00208 memcpy( (void *) (ctx->buffer + left), 00209 (void *) input, fill ); 00210 md5_process( ctx, ctx->buffer ); 00211 length -= fill; 00212 input += fill; 00213 left = 0; 00214 } 00215 00216 while( length >= 64 ) 00217 { 00218 md5_process( ctx, input ); 00219 length -= 64; 00220 input += 64; 00221 } 00222 00223 if( length ) 00224 { 00225 memcpy( (void *) (ctx->buffer + left), 00226 (void *) input, length ); 00227 } 00228 } 00229 00230 static uint8 md5_padding[64] = 00231 { 00232 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00233 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00234 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00235 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 00236 }; 00237 00238 void md5_finish( md5_context *ctx, uint8 digest[16] ) 00239 { 00240 uint32 last, padn; 00241 uint32 high, low; 00242 uint8 msglen[8]; 00243 00244 high = ( ctx->total[0] >> 29 ) 00245 | ( ctx->total[1] << 3 ); 00246 low = ( ctx->total[0] << 3 ); 00247 00248 PUT_UINT32( low, msglen, 0 ); 00249 PUT_UINT32( high, msglen, 4 ); 00250 00251 last = ctx->total[0] & 0x3F; 00252 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); 00253 00254 md5_update( ctx, md5_padding, padn ); 00255 md5_update( ctx, msglen, 8 ); 00256 00257 PUT_UINT32( ctx->state[0], digest, 0 ); 00258 PUT_UINT32( ctx->state[1], digest, 4 ); 00259 PUT_UINT32( ctx->state[2], digest, 8 ); 00260 PUT_UINT32( ctx->state[3], digest, 12 ); 00261 } 00262 00263 // ###################################################################### 00264 /* So things look consistent in everyone's emacs... */ 00265 /* Local Variables: */ 00266 /* indent-tabs-mode: nil */ 00267 /* End: */ 00268 00269 #endif // UTIL_MD5_C_DEFINED