PolarSSL v1.1.4
md2.c
Go to the documentation of this file.
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