/home/dko/projects/mobilec/tags/MobileC-v1.10.2/MobileC-v1.10.2/src/security/xyssl-0.9/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 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

Generated on Fri Jul 11 17:59:46 2008 for Mobile-C by  doxygen 1.5.4