libalpm
Arch Linux Package Manager Library
md5.c
Go to the documentation of this file.
00001 /*
00002  *  RFC 1321 compliant MD5 implementation
00003  *
00004  *  Copyright (C) 2006-2010, Brainspark B.V.
00005  *
00006  *  This file is part of PolarSSL (http://www.polarssl.org)
00007  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
00008  *
00009  *  All rights reserved.
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, see <http://www.gnu.org/licenses/>.
00023  */
00024 /*
00025  *  The MD5 algorithm was designed by Ron Rivest in 1991.
00026  *
00027  *  http://www.ietf.org/rfc/rfc1321.txt
00028  */
00029 /*
00030  *  Pacman Notes:
00031  *
00032  *  Taken from the PolarSSL project at http://polarssl.org under terms of the
00033  *  GPL. This is from version 1.0.0 of the library, and has been modified
00034  *  as following, which may be helpful for future updates:
00035  *  * remove "polarssl/config.h" include
00036  *  * change include from "polarssl/md5.h" to "md5.h"
00037  *  * removal of HMAC code
00038  *  * removal of SELF_TEST code
00039  *  * removal of ipad and opad from the md5_context struct in md5.h
00040  *  * increase the size of buffer for performance reasons
00041  *  * change 'unsigned long' to uint32_t
00042  */
00043 
00044 #include <stdio.h>
00045 #include <stdint.h>
00046 
00047 #include "md5.h"
00048 
00049 /*
00050  * 32-bit integer manipulation macros (little endian)
00051  */
00052 #ifndef GET_U32_LE
00053 #define GET_U32_LE(n,b,i)                               \
00054 {                                                       \
00055     (n) = ( (uint32_t) (b)[(i)    ]       )             \
00056         | ( (uint32_t) (b)[(i) + 1] <<  8 )             \
00057         | ( (uint32_t) (b)[(i) + 2] << 16 )             \
00058         | ( (uint32_t) (b)[(i) + 3] << 24 );            \
00059 }
00060 #endif
00061 
00062 #ifndef PUT_U32_LE
00063 #define PUT_U32_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 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 void md5_process( md5_context *ctx, const unsigned char data[64] )
00087 {
00088     uint32_t X[16], A, B, C, D;
00089 
00090     GET_U32_LE( X[ 0], data,  0 );
00091     GET_U32_LE( X[ 1], data,  4 );
00092     GET_U32_LE( X[ 2], data,  8 );
00093     GET_U32_LE( X[ 3], data, 12 );
00094     GET_U32_LE( X[ 4], data, 16 );
00095     GET_U32_LE( X[ 5], data, 20 );
00096     GET_U32_LE( X[ 6], data, 24 );
00097     GET_U32_LE( X[ 7], data, 28 );
00098     GET_U32_LE( X[ 8], data, 32 );
00099     GET_U32_LE( X[ 9], data, 36 );
00100     GET_U32_LE( X[10], data, 40 );
00101     GET_U32_LE( X[11], data, 44 );
00102     GET_U32_LE( X[12], data, 48 );
00103     GET_U32_LE( X[13], data, 52 );
00104     GET_U32_LE( X[14], data, 56 );
00105     GET_U32_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 void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen )
00213 {
00214     size_t fill;
00215     uint32_t left;
00216 
00217     if( ilen <= 0 )
00218         return;
00219 
00220     left = ctx->total[0] & 0x3F;
00221     fill = 64 - left;
00222 
00223     ctx->total[0] += (uint32_t) ilen;
00224     ctx->total[0] &= 0xFFFFFFFF;
00225 
00226     if( ctx->total[0] < (uint32_t) 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 const 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 void md5_finish( md5_context *ctx, unsigned char output[16] )
00265 {
00266     uint32_t last, padn;
00267     uint32_t 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_U32_LE( low,  msglen, 0 );
00275     PUT_U32_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_U32_LE( ctx->state[0], output,  0 );
00284     PUT_U32_LE( ctx->state[1], output,  4 );
00285     PUT_U32_LE( ctx->state[2], output,  8 );
00286     PUT_U32_LE( ctx->state[3], output, 12 );
00287 }
00288 
00289 /*
00290  * output = MD5( input buffer )
00291  */
00292 void md5( const unsigned char *input, size_t ilen, unsigned char output[16] )
00293 {
00294     md5_context ctx;
00295 
00296     md5_starts( &ctx );
00297     md5_update( &ctx, input, ilen );
00298     md5_finish( &ctx, output );
00299 
00300     memset( &ctx, 0, sizeof( md5_context ) );
00301 }
00302 
00303 /*
00304  * output = MD5( file contents )
00305  */
00306 int md5_file( const char *path, unsigned char output[16] )
00307 {
00308     FILE *f;
00309     size_t n;
00310     md5_context ctx;
00311     unsigned char buf[4096];
00312 
00313     if( ( f = fopen( path, "rb" ) ) == NULL )
00314         return( 1 );
00315 
00316     md5_starts( &ctx );
00317 
00318     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
00319         md5_update( &ctx, buf, n );
00320 
00321     md5_finish( &ctx, output );
00322 
00323     memset( &ctx, 0, sizeof( md5_context ) );
00324 
00325     if( ferror( f ) != 0 )
00326     {
00327         fclose( f );
00328         return( 2 );
00329     }
00330 
00331     fclose( f );
00332     return( 0 );
00333 }