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

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

Generated on Tue Jul 1 15:29:59 2008 for Mobile-C by  doxygen 1.5.4