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