/home/dko/projects/mobilec/trunk/src/security/xyssl-0.7/library/dhm.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  *  Diffie-Hellman-Merkle key exchange
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  *  Reference:
00025  *
00026  *  http://www.cacr.math.uwaterloo.ca/hac/ (chapter 12)
00027  */
00028 
00029 #ifndef _CRT_SECURE_NO_DEPRECATE
00030 #define _CRT_SECURE_NO_DEPRECATE 1
00031 #endif
00032 
00033 #include <string.h>
00034 
00035 #include "xyssl/dhm.h"
00036 
00037 /*
00038  * helper to validate the mpi size and import it
00039  */
00040 static int dhm_read_bignum( mpi *X,
00041                             unsigned char **p,
00042                             unsigned char *end )
00043 {
00044     int ret, n;
00045 
00046     if( end - *p < 2 )
00047         return( ERR_DHM_BAD_INPUT_DATA );
00048 
00049     n = ( (*p)[0] << 8 ) | (*p)[1];
00050     (*p) += 2;
00051 
00052     if( (int)( end - *p ) < n )
00053         return( ERR_DHM_BAD_INPUT_DATA );
00054 
00055     if( ( ret = mpi_read_binary( X, *p, n ) ) != 0 )
00056         return( ERR_DHM_READ_PARAMS_FAILED | ret );
00057 
00058     (*p) += n;
00059 
00060     return( 0 );
00061 }
00062 
00063 /*
00064  * Parse the ServerKeyExchange parameters
00065  */
00066 int dhm_read_params( dhm_context *ctx,
00067                      unsigned char **p,
00068                      unsigned char *end )
00069 {
00070     int ret, n;
00071 
00072     memset( ctx, 0, sizeof( dhm_context ) );
00073 
00074     if( ( ret = dhm_read_bignum( &ctx->P,  p, end ) ) != 0 ||
00075         ( ret = dhm_read_bignum( &ctx->G,  p, end ) ) != 0 ||
00076         ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
00077         return( ret );
00078 
00079     ctx->len = ( mpi_msb( &ctx->P ) + 7 ) >> 3;
00080 
00081     if( end - *p < 2 )
00082         return( ERR_DHM_BAD_INPUT_DATA );
00083 
00084     n = ( (*p)[0] << 8 ) | (*p)[1];
00085     (*p) += 2;
00086 
00087     if( end != *p + n )
00088         return( ERR_DHM_BAD_INPUT_DATA );
00089 
00090     return( 0 );
00091 }
00092 
00093 /*
00094  * Setup and write the ServerKeyExchange parameters
00095  */
00096 int dhm_make_params( dhm_context *ctx,
00097                      int (*rng_f)(void *), void *rng_d,
00098                      unsigned char *output, int *olen )
00099 {
00100     int i, ret, n, n1, n2, n3;
00101     unsigned char *p;
00102 
00103     /*
00104      * generate X and calculate GX = G^X mod P
00105      */
00106     n = 48 / sizeof( t_int );
00107     CHK( mpi_grow( &ctx->X, n ) );
00108 
00109     p = (unsigned char *) ctx->X.p;
00110     for( i = 0; i < ciL * ctx->X.n; i++ )
00111         *p++ = rng_f( rng_d );
00112 
00113     while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
00114         mpi_shift_r( &ctx->X, 1 );
00115 
00116     CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
00117                       &ctx->P , &ctx->RP ) );
00118 
00119     /*
00120      * export P, G, GX
00121      */
00122 #define DHM_MPI_EXPORT(X,n)                     \
00123     CHK( mpi_write_binary( X, p + 2, &n ) );    \
00124     *p++ = ( n >> 8 ); *p++ = n; p += n;
00125 
00126     n1 = ( mpi_msb( &ctx->P  ) + 7 ) >> 3;
00127     n2 = ( mpi_msb( &ctx->G  ) + 7 ) >> 3;
00128     n3 = ( mpi_msb( &ctx->GX ) + 7 ) >> 3;
00129 
00130     p = output;
00131     DHM_MPI_EXPORT( &ctx->P , n1 );
00132     DHM_MPI_EXPORT( &ctx->G , n2 );
00133     DHM_MPI_EXPORT( &ctx->GX, n3 );
00134 
00135     *olen  = p - output;
00136 
00137     ctx->len = n1;
00138 
00139 cleanup:
00140 
00141     if( ret != 0 )
00142         return( ret | ERR_DHM_MAKE_PARAMS_FAILED );
00143 
00144     return( 0 );
00145 }
00146 
00147 /*
00148  * Import the peer's public value (G^Y)
00149  */
00150 int dhm_read_public( dhm_context *ctx,
00151                      unsigned char *input, int ilen )
00152 {
00153     int ret;
00154 
00155     if( ctx == NULL || ilen < 1 || ilen > ctx->len )
00156         return( ERR_DHM_BAD_INPUT_DATA );
00157 
00158     if( ( ret = mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
00159         return( ERR_DHM_READ_PUBLIC_FAILED | ret );
00160 
00161     return( 0 );
00162 }
00163 
00164 /*
00165  * Create own private (X) and public (G^X) values
00166  */
00167 int dhm_make_public( dhm_context *ctx,
00168                      unsigned char *output, int olen,
00169                      int (*rng_f)(void *), void *rng_d )
00170 {
00171     int ret, i, n;
00172     unsigned char *p;
00173 
00174     if( ctx == NULL || olen < 1 || olen > ctx->len )
00175         return( ERR_DHM_BAD_INPUT_DATA );
00176 
00177     /*
00178      * Get 384 bytes of entropy for the private value
00179      */
00180     n = 48 / sizeof( t_int );
00181     CHK( mpi_grow( &ctx->X, n ) );
00182 
00183     p = (unsigned char *) ctx->X.p;
00184     for( i = 0; i < ciL * ctx->X.n; i++ )
00185         *p++ = rng_f( rng_d );
00186 
00187     while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
00188         mpi_shift_r( &ctx->X, 1 );
00189 
00190     CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
00191                       &ctx->P , &ctx->RP ) );
00192 
00193     CHK( mpi_write_binary( &ctx->GX, output, &olen ) );
00194 
00195 cleanup:
00196 
00197     if( ret != 0 )
00198         return( ERR_DHM_MAKE_PUBLIC_FAILED | ret );
00199 
00200     return( 0 );
00201 }
00202 
00203 /*
00204  * Derive and export the shared secret (G^Y)^X mod P
00205  */
00206 int dhm_calc_secret( dhm_context *ctx,
00207                      unsigned char *output, int *olen )
00208 {
00209     int ret;
00210 
00211     if( ctx == NULL || *olen < ctx->len )
00212         return( ERR_DHM_BAD_INPUT_DATA );
00213 
00214     CHK( mpi_exp_mod( &ctx->K, &ctx->GY, &ctx->X,
00215                       &ctx->P, &ctx->RP ) );
00216 
00217     *olen = ( mpi_msb( &ctx->K ) + 7 ) >> 3;
00218 
00219     CHK( mpi_write_binary( &ctx->K, output, olen ) );
00220 
00221 cleanup:
00222 
00223     if( ret != 0 )
00224         return( ERR_DHM_CALC_SECRET_FAILED | ret );
00225 
00226     return( 0 );
00227 }
00228 
00229 /*
00230  * Free the components of a DHM key
00231  */
00232 void dhm_free( dhm_context *ctx )
00233 {
00234     mpi_free( &ctx->RP, &ctx->K, &ctx->GY,
00235               &ctx->GX, &ctx->X, &ctx->G,
00236               &ctx->P, NULL );    
00237 }
00238 
00239 static const char _dhm_src[] = "_dhm_src";
00240 
00241 #if defined(SELF_TEST)
00242 #endif
00243 /*
00244  * Checkup routine
00245  */
00246 int dhm_self_test( int verbose )
00247 {
00248     return( verbose = 0 );
00249 }

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