md5.c

Go to the documentation of this file.
00001 /*
00002  *  RFC 1321 compliant MD5 implementation
00003  *
00004  *  Copyright (C) 2006-2007  Christophe Devine
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, version 2.1 as published by the Free Software Foundation.
00009  *
00010  *  This library is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  *  Lesser General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU Lesser General Public
00016  *  License along with this library.  If not, see
00017  *  <http://www.gnu.org/licenses/>.
00018  */
00019 /*
00020  *  The MD5 algorithm was designed by Ron Rivest in 1991.
00021  *
00022  *  http://www.ietf.org/rfc/rfc1321.txt
00023  */
00024 /*
00025  *  Pacman Notes:
00026  *
00027  *  Taken from the XySSL project at www.xyssl.org under terms of the
00028  *  LGPL. This is from version 0.7 of the library, and has been modified
00029  *  as following, which may be helpful for future updates:
00030  *  * change include from "xyssl/md5.h" to "md5.h"
00031  *  * removal of HMAC code
00032  *  * removal of SELF_TEST code
00033  *  * removal of ipad and opad from the md5_context struct in md5.h
00034  *  * change of md5_file prototype from
00035  *        int md5_file( char *path, unsigned char *output )
00036  *      to
00037  *        int md5_file( const char *path, unsigned char *output )
00038  */
00039 
00040 #ifndef _CRT_SECURE_NO_DEPRECATE
00041 #define _CRT_SECURE_NO_DEPRECATE 1
00042 #endif
00043 
00044 #include <string.h>
00045 #include <stdio.h>
00046 
00047 #include "md5.h"
00048 
00049 /*
00050  * 32-bit integer manipulation macros (little endian)
00051  */
00052 #ifndef GET_UINT32_LE
00053 #define GET_UINT32_LE(n,b,i)                            \
00054 {                                                       \
00055     (n) = ( (unsigned long) (b)[(i)    ]       )        \
00056         | ( (unsigned long) (b)[(i) + 1] <<  8 )        \
00057         | ( (unsigned long) (b)[(i) + 2] << 16 )        \
00058         | ( (unsigned long) (b)[(i) + 3] << 24 );       \
00059 }
00060 #endif
00061 
00062 #ifndef PUT_UINT32_LE
00063 #define PUT_UINT32_LE(n,b,i)                            \
00064 {                                                       \
00065     (b)[(i)    ] = (unsigned char) ( (n)       );       \
00066     (b)[(i) + 1] = (unsigned char) ( (n) >>  8 );       \
00067     (b)[(i) + 2] = (unsigned char) ( (n) >> 16 );       \
00068     (b)[(i) + 3] = (unsigned char) ( (n) >> 24 );       \
00069 }
00070 #endif
00071 
00072 /*
00073  * MD5 context setup
00074  */
00075 static inline void md5_starts( md5_context *ctx )
00076 {
00077     ctx->total[0] = 0;
00078     ctx->total[1] = 0;
00079 
00080     ctx->state[0] = 0x67452301;
00081     ctx->state[1] = 0xEFCDAB89;
00082     ctx->state[2] = 0x98BADCFE;
00083     ctx->state[3] = 0x10325476;
00084 }
00085 
00086 static inline void md5_process( md5_context *ctx, unsigned char data[64] )
00087 {
00088     unsigned long X[16], A, B, C, D;
00089 
00090     GET_UINT32_LE( X[ 0], data,  0 );
00091     GET_UINT32_LE( X[ 1], data,  4 );
00092     GET_UINT32_LE( X[ 2], data,  8 );
00093     GET_UINT32_LE( X[ 3], data, 12 );
00094     GET_UINT32_LE( X[ 4], data, 16 );
00095     GET_UINT32_LE( X[ 5], data, 20 );
00096     GET_UINT32_LE( X[ 6], data, 24 );
00097     GET_UINT32_LE( X[ 7], data, 28 );
00098     GET_UINT32_LE( X[ 8], data, 32 );
00099     GET_UINT32_LE( X[ 9], data, 36 );
00100     GET_UINT32_LE( X[10], data, 40 );
00101     GET_UINT32_LE( X[11], data, 44 );
00102     GET_UINT32_LE( X[12], data, 48 );
00103     GET_UINT32_LE( X[13], data, 52 );
00104     GET_UINT32_LE( X[14], data, 56 );
00105     GET_UINT32_LE( X[15], data, 60 );
00106 
00107 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
00108 
00109 #define P(a,b,c,d,k,s,t)                                \
00110 {                                                       \
00111     a += F(b,c,d) + X[k] + t; a = S(a,s) + b;           \
00112 }
00113 
00114     A = ctx->state[0];
00115     B = ctx->state[1];
00116     C = ctx->state[2];
00117     D = ctx->state[3];
00118 
00119 #define F(x,y,z) (z ^ (x & (y ^ z)))
00120 
00121     P( A, B, C, D,  0,  7, 0xD76AA478 );
00122     P( D, A, B, C,  1, 12, 0xE8C7B756 );
00123     P( C, D, A, B,  2, 17, 0x242070DB );
00124     P( B, C, D, A,  3, 22, 0xC1BDCEEE );
00125     P( A, B, C, D,  4,  7, 0xF57C0FAF );
00126     P( D, A, B, C,  5, 12, 0x4787C62A );
00127     P( C, D, A, B,  6, 17, 0xA8304613 );
00128     P( B, C, D, A,  7, 22, 0xFD469501 );
00129     P( A, B, C, D,  8,  7, 0x698098D8 );
00130     P( D, A, B, C,  9, 12, 0x8B44F7AF );
00131     P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
00132     P( B, C, D, A, 11, 22, 0x895CD7BE );
00133     P( A, B, C, D, 12,  7, 0x6B901122 );
00134     P( D, A, B, C, 13, 12, 0xFD987193 );
00135     P( C, D, A, B, 14, 17, 0xA679438E );
00136     P( B, C, D, A, 15, 22, 0x49B40821 );
00137 
00138 #undef F
00139 
00140 #define F(x,y,z) (y ^ (z & (x ^ y)))
00141 
00142     P( A, B, C, D,  1,  5, 0xF61E2562 );
00143     P( D, A, B, C,  6,  9, 0xC040B340 );
00144     P( C, D, A, B, 11, 14, 0x265E5A51 );
00145     P( B, C, D, A,  0, 20, 0xE9B6C7AA );
00146     P( A, B, C, D,  5,  5, 0xD62F105D );
00147     P( D, A, B, C, 10,  9, 0x02441453 );
00148     P( C, D, A, B, 15, 14, 0xD8A1E681 );
00149     P( B, C, D, A,  4, 20, 0xE7D3FBC8 );
00150     P( A, B, C, D,  9,  5, 0x21E1CDE6 );
00151     P( D, A, B, C, 14,  9, 0xC33707D6 );
00152     P( C, D, A, B,  3, 14, 0xF4D50D87 );
00153     P( B, C, D, A,  8, 20, 0x455A14ED );
00154     P( A, B, C, D, 13,  5, 0xA9E3E905 );
00155     P( D, A, B, C,  2,  9, 0xFCEFA3F8 );
00156     P( C, D, A, B,  7, 14, 0x676F02D9 );
00157     P( B, C, D, A, 12, 20, 0x8D2A4C8A );
00158 
00159 #undef F
00160 
00161 #define F(x,y,z) (x ^ y ^ z)
00162 
00163     P( A, B, C, D,  5,  4, 0xFFFA3942 );
00164     P( D, A, B, C,  8, 11, 0x8771F681 );
00165     P( C, D, A, B, 11, 16, 0x6D9D6122 );
00166     P( B, C, D, A, 14, 23, 0xFDE5380C );
00167     P( A, B, C, D,  1,  4, 0xA4BEEA44 );
00168     P( D, A, B, C,  4, 11, 0x4BDECFA9 );
00169     P( C, D, A, B,  7, 16, 0xF6BB4B60 );
00170     P( B, C, D, A, 10, 23, 0xBEBFBC70 );
00171     P( A, B, C, D, 13,  4, 0x289B7EC6 );
00172     P( D, A, B, C,  0, 11, 0xEAA127FA );
00173     P( C, D, A, B,  3, 16, 0xD4EF3085 );
00174     P( B, C, D, A,  6, 23, 0x04881D05 );
00175     P( A, B, C, D,  9,  4, 0xD9D4D039 );
00176     P( D, A, B, C, 12, 11, 0xE6DB99E5 );
00177     P( C, D, A, B, 15, 16, 0x1FA27CF8 );
00178     P( B, C, D, A,  2, 23, 0xC4AC5665 );
00179 
00180 #undef F
00181 
00182 #define F(x,y,z) (y ^ (x | ~z))
00183 
00184     P( A, B, C, D,  0,  6, 0xF4292244 );
00185     P( D, A, B, C,  7, 10, 0x432AFF97 );
00186     P( C, D, A, B, 14, 15, 0xAB9423A7 );
00187     P( B, C, D, A,  5, 21, 0xFC93A039 );
00188     P( A, B, C, D, 12,  6, 0x655B59C3 );
00189     P( D, A, B, C,  3, 10, 0x8F0CCC92 );
00190     P( C, D, A, B, 10, 15, 0xFFEFF47D );
00191     P( B, C, D, A,  1, 21, 0x85845DD1 );
00192     P( A, B, C, D,  8,  6, 0x6FA87E4F );
00193     P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
00194     P( C, D, A, B,  6, 15, 0xA3014314 );
00195     P( B, C, D, A, 13, 21, 0x4E0811A1 );
00196     P( A, B, C, D,  4,  6, 0xF7537E82 );
00197     P( D, A, B, C, 11, 10, 0xBD3AF235 );
00198     P( C, D, A, B,  2, 15, 0x2AD7D2BB );
00199     P( B, C, D, A,  9, 21, 0xEB86D391 );
00200 
00201 #undef F
00202 
00203     ctx->state[0] += A;
00204     ctx->state[1] += B;
00205     ctx->state[2] += C;
00206     ctx->state[3] += D;
00207 }
00208 
00209 /*
00210  * MD5 process buffer
00211  */
00212 static inline void md5_update( md5_context *ctx, unsigned char *input, int ilen )
00213 {
00214     int fill;
00215     unsigned long left;
00216 
00217     if( ilen <= 0 )
00218         return;
00219 
00220     left = ctx->total[0] & 0x3F;
00221     fill = 64 - left;
00222 
00223     ctx->total[0] += ilen;
00224     ctx->total[0] &= 0xFFFFFFFF;
00225 
00226     if( ctx->total[0] < (unsigned long) ilen )
00227         ctx->total[1]++;
00228 
00229     if( left && ilen >= fill )
00230     {
00231         memcpy( (void *) (ctx->buffer + left),
00232                 (void *) input, fill );
00233         md5_process( ctx, ctx->buffer );
00234         input += fill;
00235         ilen  -= fill;
00236         left = 0;
00237     }
00238 
00239     while( ilen >= 64 )
00240     {
00241         md5_process( ctx, input );
00242         input += 64;
00243         ilen  -= 64;
00244     }
00245 
00246     if( ilen > 0 )
00247     {
00248         memcpy( (void *) (ctx->buffer + left),
00249                 (void *) input, ilen );
00250     }
00251 }
00252 
00253 static unsigned char md5_padding[64] =
00254 {
00255  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00256     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00257     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00258     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00259 };
00260 
00261 /*
00262  * MD5 final digest
00263  */
00264 static inline void md5_finish( md5_context *ctx, unsigned char *output )
00265 {
00266     unsigned long last, padn;
00267     unsigned long high, low;
00268     unsigned char msglen[8];
00269 
00270     high = ( ctx->total[0] >> 29 )
00271          | ( ctx->total[1] <<  3 );
00272     low  = ( ctx->total[0] <<  3 );
00273 
00274     PUT_UINT32_LE( low,  msglen, 0 );
00275     PUT_UINT32_LE( high, msglen, 4 );
00276 
00277     last = ctx->total[0] & 0x3F;
00278     padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
00279 
00280     md5_update( ctx, (unsigned char *) md5_padding, padn );
00281     md5_update( ctx, msglen, 8 );
00282 
00283     PUT_UINT32_LE( ctx->state[0], output,  0 );
00284     PUT_UINT32_LE( ctx->state[1], output,  4 );
00285     PUT_UINT32_LE( ctx->state[2], output,  8 );
00286     PUT_UINT32_LE( ctx->state[3], output, 12 );
00287 }
00288 
00289 /*
00290  * Output = MD5( input buffer )
00291  */
00292 void md5( unsigned char *input, int ilen,
00293           unsigned char *output )
00294 {
00295     md5_context ctx;
00296 
00297     md5_starts( &ctx );
00298     md5_update( &ctx, input, ilen );
00299     md5_finish( &ctx, output );
00300 
00301     memset( &ctx, 0, sizeof( md5_context ) );
00302 }
00303 
00304 /*
00305  * Output = MD5( file contents )
00306  */
00307 int md5_file( const char *path, unsigned char *output )
00308 {
00309     FILE *f;
00310     size_t n;
00311     md5_context ctx;
00312     unsigned char buf[1024];
00313 
00314     if( ( f = fopen( path, "rb" ) ) == NULL )
00315         return( 1 );
00316 
00317     md5_starts( &ctx );
00318 
00319     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
00320         md5_update( &ctx, buf, (int) n );
00321 
00322     md5_finish( &ctx, output );
00323 
00324     memset( &ctx, 0, sizeof( md5_context ) );
00325 
00326     if( ferror( f ) != 0 )
00327     {
00328         fclose( f );
00329         return( 2 );
00330     }
00331 
00332     fclose( f );
00333     return( 0 );
00334 }

Generated on Mon Jan 14 23:53:40 2008 for libalpm by  doxygen 1.5.4