00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
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
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
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
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
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
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
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
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
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
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
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