00001 /* 00002 * RFC 1115/1319 compliant MD2 implementation 00003 * 00004 * Copyright (C) 2006-2007 Christophe Devine 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program 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 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License along 00017 * with this program; if not, write to the Free Software Foundation, Inc., 00018 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00019 */ 00020 /* 00021 * The MD2 algorithm was designed by Ron Rivest in 1989. 00022 * 00023 * http://www.ietf.org/rfc/rfc1115.txt 00024 * http://www.ietf.org/rfc/rfc1319.txt 00025 */ 00026 00027 #include "xyssl/config.h" 00028 00029 #if defined(XYSSL_MD2_C) 00030 00031 #include "xyssl/md2.h" 00032 00033 #include <string.h> 00034 #include <stdio.h> 00035 00036 static const unsigned char PI_SUBST[256] = 00037 { 00038 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 00039 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, 00040 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 00041 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, 00042 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, 00043 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, 00044 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 00045 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, 00046 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 00047 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, 00048 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 00049 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, 00050 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, 00051 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 00052 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 00053 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, 00054 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, 00055 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, 00056 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 00057 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 00058 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, 00059 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, 00060 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 00061 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, 00062 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 00063 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 00064 }; 00065 00066 /* 00067 * MD2 context setup 00068 */ 00069 void md2_starts( md2_context *ctx ) 00070 { 00071 memset( ctx, 0, sizeof( md2_context ) ); 00072 } 00073 00074 static void md2_process( md2_context *ctx ) 00075 { 00076 int i, j; 00077 unsigned char t = 0; 00078 00079 for( i = 0; i < 16; i++ ) 00080 { 00081 ctx->state[i + 16] = ctx->buffer[i]; 00082 ctx->state[i + 32] = 00083 (unsigned char)( ctx->buffer[i] ^ ctx->state[i]); 00084 } 00085 00086 for( i = 0; i < 18; i++ ) 00087 { 00088 for( j = 0; j < 48; j++ ) 00089 { 00090 ctx->state[j] = (unsigned char) 00091 ( ctx->state[j] ^ PI_SUBST[t] ); 00092 t = ctx->state[j]; 00093 } 00094 00095 t = (unsigned char)( t + i ); 00096 } 00097 00098 t = ctx->cksum[15]; 00099 00100 for( i = 0; i < 16; i++ ) 00101 { 00102 ctx->cksum[i] = (unsigned char) 00103 ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] ); 00104 t = ctx->cksum[i]; 00105 } 00106 } 00107 00108 /* 00109 * MD2 process buffer 00110 */ 00111 void md2_update( md2_context *ctx, unsigned char *input, int ilen ) 00112 { 00113 int fill; 00114 00115 while( ilen > 0 ) 00116 { 00117 if( ctx->left + ilen > 16 ) 00118 fill = 16 - ctx->left; 00119 else 00120 fill = ilen; 00121 00122 memcpy( ctx->buffer + ctx->left, input, fill ); 00123 00124 ctx->left += fill; 00125 input += fill; 00126 ilen -= fill; 00127 00128 if( ctx->left == 16 ) 00129 { 00130 ctx->left = 0; 00131 md2_process( ctx ); 00132 } 00133 } 00134 } 00135 00136 /* 00137 * MD2 final digest 00138 */ 00139 void md2_finish( md2_context *ctx, unsigned char output[16] ) 00140 { 00141 int i; 00142 unsigned char x; 00143 00144 x = (unsigned char)( 16 - ctx->left ); 00145 00146 for( i = ctx->left; i < 16; i++ ) 00147 ctx->buffer[i] = x; 00148 00149 md2_process( ctx ); 00150 00151 memcpy( ctx->buffer, ctx->cksum, 16 ); 00152 md2_process( ctx ); 00153 00154 memcpy( output, ctx->state, 16 ); 00155 } 00156 00157 /* 00158 * output = MD2( input buffer ) 00159 */ 00160 void md2( unsigned char *input, int ilen, unsigned char output[16] ) 00161 { 00162 md2_context ctx; 00163 00164 md2_starts( &ctx ); 00165 md2_update( &ctx, input, ilen ); 00166 md2_finish( &ctx, output ); 00167 00168 memset( &ctx, 0, sizeof( md2_context ) ); 00169 } 00170 00171 /* 00172 * output = MD2( file contents ) 00173 */ 00174 int md2_file( char *path, unsigned char output[16] ) 00175 { 00176 FILE *f; 00177 size_t n; 00178 md2_context ctx; 00179 unsigned char buf[1024]; 00180 00181 if( ( f = fopen( path, "rb" ) ) == NULL ) 00182 return( 1 ); 00183 00184 md2_starts( &ctx ); 00185 00186 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) 00187 md2_update( &ctx, buf, (int) n ); 00188 00189 md2_finish( &ctx, output ); 00190 00191 memset( &ctx, 0, sizeof( md2_context ) ); 00192 00193 if( ferror( f ) != 0 ) 00194 { 00195 fclose( f ); 00196 return( 2 ); 00197 } 00198 00199 fclose( f ); 00200 return( 0 ); 00201 } 00202 00203 /* 00204 * MD2 HMAC context setup 00205 */ 00206 void md2_hmac_starts( md2_context *ctx, unsigned char *key, int keylen ) 00207 { 00208 int i; 00209 unsigned char sum[16]; 00210 00211 if( keylen > 64 ) 00212 { 00213 md2( key, keylen, sum ); 00214 keylen = 16; 00215 key = sum; 00216 } 00217 00218 memset( ctx->ipad, 0x36, 64 ); 00219 memset( ctx->opad, 0x5C, 64 ); 00220 00221 for( i = 0; i < keylen; i++ ) 00222 { 00223 ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); 00224 ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); 00225 } 00226 00227 md2_starts( ctx ); 00228 md2_update( ctx, ctx->ipad, 64 ); 00229 00230 memset( sum, 0, sizeof( sum ) ); 00231 } 00232 00233 /* 00234 * MD2 HMAC process buffer 00235 */ 00236 void md2_hmac_update( md2_context *ctx, unsigned char *input, int ilen ) 00237 { 00238 md2_update( ctx, input, ilen ); 00239 } 00240 00241 /* 00242 * MD2 HMAC final digest 00243 */ 00244 void md2_hmac_finish( md2_context *ctx, unsigned char output[16] ) 00245 { 00246 unsigned char tmpbuf[16]; 00247 00248 md2_finish( ctx, tmpbuf ); 00249 md2_starts( ctx ); 00250 md2_update( ctx, ctx->opad, 64 ); 00251 md2_update( ctx, tmpbuf, 16 ); 00252 md2_finish( ctx, output ); 00253 00254 memset( tmpbuf, 0, sizeof( tmpbuf ) ); 00255 } 00256 00257 /* 00258 * output = HMAC-MD2( hmac key, input buffer ) 00259 */ 00260 void md2_hmac( unsigned char *key, int keylen, unsigned char *input, int ilen, 00261 unsigned char output[16] ) 00262 { 00263 md2_context ctx; 00264 00265 md2_hmac_starts( &ctx, key, keylen ); 00266 md2_hmac_update( &ctx, input, ilen ); 00267 md2_hmac_finish( &ctx, output ); 00268 00269 memset( &ctx, 0, sizeof( md2_context ) ); 00270 } 00271 00272 #if defined(XYSSL_SELF_TEST) 00273 00274 /* 00275 * RFC 1319 test vectors 00276 */ 00277 static const char md2_test_str[7][81] = 00278 { 00279 { "" }, 00280 { "a" }, 00281 { "abc" }, 00282 { "message digest" }, 00283 { "abcdefghijklmnopqrstuvwxyz" }, 00284 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, 00285 { "12345678901234567890123456789012345678901234567890123456789012" \ 00286 "345678901234567890" } 00287 }; 00288 00289 static const unsigned char md2_test_sum[7][16] = 00290 { 00291 { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D, 00292 0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 }, 00293 { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72, 00294 0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 }, 00295 { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B, 00296 0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB }, 00297 { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B, 00298 0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 }, 00299 { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB, 00300 0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B }, 00301 { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39, 00302 0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD }, 00303 { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D, 00304 0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 } 00305 }; 00306 00307 /* 00308 * Checkup routine 00309 */ 00310 int md2_self_test( int verbose ) 00311 { 00312 int i; 00313 unsigned char md2sum[16]; 00314 00315 for( i = 0; i < 7; i++ ) 00316 { 00317 if( verbose != 0 ) 00318 printf( " MD2 test #%d: ", i + 1 ); 00319 00320 md2( (unsigned char *) md2_test_str[i], 00321 strlen( md2_test_str[i] ), md2sum ); 00322 00323 if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 ) 00324 { 00325 if( verbose != 0 ) 00326 printf( "failed\n" ); 00327 00328 return( 1 ); 00329 } 00330 00331 if( verbose != 0 ) 00332 printf( "passed\n" ); 00333 } 00334 00335 if( verbose != 0 ) 00336 printf( "\n" ); 00337 00338 return( 0 ); 00339 } 00340 00341 #endif 00342 00343 #endif