libalpm
Arch Linux Package Manager Library
|
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 }