/home/dko/projects/mobilec/trunk/src/security/xyssl-0.7/library/md2.c

Go to the documentation of this file.
00001 /*
00002  *  RFC 1115/1319 compliant MD2 implementation
00003  *
00004  *  Copyright (C) 2006-2007  Christophe Devine
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Lesser General Public
00008  *  License, version 2.1 as published by the Free Software Foundation.
00009  *
00010  *  This library is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  *  Lesser General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU Lesser General Public
00016  *  License along with this library; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00018  *  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 #ifndef _CRT_SECURE_NO_DEPRECATE
00028 #define _CRT_SECURE_NO_DEPRECATE 1
00029 #endif
00030 
00031 #include <string.h>
00032 #include <stdio.h>
00033 
00034 #include "xyssl/md2.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] = ctx->buffer[i] ^ ctx->state[i];
00083     }
00084 
00085     for( i = 0; i < 18; i++ )
00086     {
00087         for( j = 0; j < 48; j++ )
00088             t = (ctx->state[j] ^= PI_SUBST[t]);
00089 
00090         t = (t + i) & 0xFF;
00091     }
00092 
00093     t = ctx->cksum[15];
00094 
00095     for( i = 0; i < 16; i++ )
00096         t = (ctx->cksum[i] ^= PI_SUBST[ctx->buffer[i] ^ t]);
00097 }
00098 
00099 /*
00100  * MD2 process buffer
00101  */
00102 void md2_update( md2_context *ctx, unsigned char *input, int ilen )
00103 {
00104     int fill;
00105 
00106     while( ilen > 0 )
00107     {
00108         if( ctx->left + ilen > 16 )
00109             fill = 16 - ctx->left;
00110         else
00111             fill = ilen;
00112 
00113         memcpy( ctx->buffer + ctx->left, input, fill );
00114 
00115         ctx->left += fill;
00116         input += fill;
00117         ilen  -= fill;
00118 
00119         if( ctx->left == 16 )
00120         {
00121             ctx->left = 0;
00122             md2_process( ctx );
00123         }
00124     }
00125 }
00126 
00127 /*
00128  * MD2 final digest
00129  */
00130 void md2_finish( md2_context *ctx, unsigned char *output )
00131 {
00132     int i;
00133     unsigned char x;
00134 
00135     x = (unsigned char)( 16 - ctx->left );
00136 
00137     for( i = ctx->left; i < 16; i++ )
00138         ctx->buffer[i] = x;
00139 
00140     md2_process( ctx );
00141 
00142     memcpy( ctx->buffer, ctx->cksum, 16 );
00143     md2_process( ctx );
00144 
00145     memcpy( output, ctx->state, 16 );
00146 }
00147 
00148 /*
00149  * Output = MD2( input buffer )
00150  */
00151 void md2( unsigned char *input, int ilen,
00152           unsigned char *output )
00153 {
00154     md2_context ctx;
00155 
00156     md2_starts( &ctx );
00157     md2_update( &ctx, input, ilen );
00158     md2_finish( &ctx, output );
00159 
00160     memset( &ctx, 0, sizeof( md2_context ) );
00161 }
00162 
00163 /*
00164  * Output = MD2( file contents )
00165  */
00166 int md2_file( char *path, unsigned char *output )
00167 {
00168     FILE *f;
00169     size_t n;
00170     md2_context ctx;
00171     unsigned char buf[1024];
00172 
00173     if( ( f = fopen( path, "rb" ) ) == NULL )
00174         return( 1 );
00175 
00176     md2_starts( &ctx );
00177 
00178     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
00179         md2_update( &ctx, buf, (int) n );
00180 
00181     md2_finish( &ctx, output );
00182 
00183     memset( &ctx, 0, sizeof( md2_context ) );
00184 
00185     if( ferror( f ) != 0 )
00186     {
00187         fclose( f );
00188         return( 2 );
00189     }
00190 
00191     fclose( f );
00192     return( 0 );
00193 }
00194 
00195 /*
00196  * MD2 HMAC context setup
00197  */
00198 void md2_hmac_starts( md2_context *ctx,
00199                       unsigned char *key, int keylen )
00200 {
00201     int i;
00202 
00203     memset( ctx->ipad, 0x36, 64 );
00204     memset( ctx->opad, 0x5C, 64 );
00205 
00206     for( i = 0; i < keylen; i++ )
00207     {
00208         if( i >= 64 ) break;
00209 
00210         ctx->ipad[i] ^= key[i];
00211         ctx->opad[i] ^= key[i];
00212     }
00213 
00214     md2_starts( ctx );
00215     md2_update( ctx, ctx->ipad, 64 );
00216 }
00217 
00218 /*
00219  * MD2 HMAC process buffer
00220  */
00221 void md2_hmac_update( md2_context *ctx,
00222                       unsigned char *input, int ilen )
00223 {
00224     md2_update( ctx, input, ilen );
00225 }
00226 
00227 /*
00228  * MD2 HMAC final digest
00229  */
00230 void md2_hmac_finish( md2_context *ctx, unsigned char *output )
00231 {
00232     unsigned char tmpbuf[16];
00233 
00234     md2_finish( ctx, tmpbuf );
00235     md2_starts( ctx );
00236     md2_update( ctx, ctx->opad, 64 );
00237     md2_update( ctx, tmpbuf, 16 );
00238     md2_finish( ctx, output );
00239 
00240     memset( tmpbuf, 0, sizeof( tmpbuf ) );
00241 }
00242 
00243 /*
00244  * Output = HMAC-MD2( hmac key, input buffer )
00245  */
00246 void md2_hmac( unsigned char *key, int keylen,
00247                unsigned char *input, int ilen,
00248                unsigned char *output )
00249 {
00250     md2_context ctx;
00251 
00252     md2_hmac_starts( &ctx, key, keylen );
00253     md2_hmac_update( &ctx, input, ilen );
00254     md2_hmac_finish( &ctx, output );
00255 
00256     memset( &ctx, 0, sizeof( md2_context ) );
00257 }
00258 
00259 static const char _md2_src[] = "_md2_src";
00260 
00261 #if defined(SELF_TEST)
00262 /*
00263  * RFC 1319 test vectors
00264  */
00265 static const char md2_test_str[7][81] =
00266 {
00267     { "" },
00268     { "a" },
00269     { "abc" },
00270     { "message digest" },
00271     { "abcdefghijklmnopqrstuvwxyz" },
00272     { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
00273     { "12345678901234567890123456789012345678901234567890123456789012" \
00274       "345678901234567890" }
00275 };
00276 
00277 static const unsigned char md2_test_sum[7][16] =
00278 {
00279     { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D,
00280       0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 },
00281     { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72,
00282       0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 },
00283     { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B,
00284       0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB },
00285     { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B,
00286       0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 },
00287     { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB,
00288       0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B },
00289     { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39,
00290       0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD },
00291     { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D,
00292       0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 }
00293 };
00294 
00295 /*
00296  * Checkup routine
00297  */
00298 int md2_self_test( int verbose )
00299 {
00300     int i;
00301     unsigned char md2sum[16];
00302 
00303     for( i = 0; i < 7; i++ )
00304     {
00305         if( verbose != 0 )
00306             printf( "  MD2 test #%d: ", i + 1 );
00307 
00308         md2( (unsigned char *) md2_test_str[i],
00309              strlen( md2_test_str[i] ), md2sum );
00310 
00311         if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 )
00312         {
00313             if( verbose != 0 )
00314                 printf( "failed\n" );
00315 
00316             return( 1 );
00317         }
00318 
00319         if( verbose != 0 )
00320             printf( "passed\n" );
00321     }
00322 
00323     if( verbose != 0 )
00324         printf( "\n" );
00325 
00326     return( 0 );
00327 }
00328 #else
00329 int md2_self_test( int verbose )
00330 {
00331     return( 0 );
00332 }
00333 #endif

Generated on Fri May 16 14:49:55 2008 for Mobile-C by  doxygen 1.5.4