00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 #include "xyssl/config.h"
00027 
00028 #if defined(XYSSL_DHM_C)
00029 
00030 #include "xyssl/dhm.h"
00031 
00032 #include <string.h>
00033 
00034 
00035 
00036 
00037 static int dhm_read_bignum( mpi *X,
00038                             unsigned char **p,
00039                             unsigned char *end )
00040 {
00041     int ret, n;
00042 
00043     if( end - *p < 2 )
00044         return( XYSSL_ERR_DHM_BAD_INPUT_DATA );
00045 
00046     n = ( (*p)[0] << 8 ) | (*p)[1];
00047     (*p) += 2;
00048 
00049     if( (int)( end - *p ) < n )
00050         return( XYSSL_ERR_DHM_BAD_INPUT_DATA );
00051 
00052     if( ( ret = mpi_read_binary( X, *p, n ) ) != 0 )
00053         return( XYSSL_ERR_DHM_READ_PARAMS_FAILED | ret );
00054 
00055     (*p) += n;
00056 
00057     return( 0 );
00058 }
00059 
00060 
00061 
00062 
00063 int dhm_read_params( dhm_context *ctx,
00064                      unsigned char **p,
00065                      unsigned char *end )
00066 {
00067     int ret, n;
00068 
00069     memset( ctx, 0, sizeof( dhm_context ) );
00070 
00071     if( ( ret = dhm_read_bignum( &ctx->P,  p, end ) ) != 0 ||
00072         ( ret = dhm_read_bignum( &ctx->G,  p, end ) ) != 0 ||
00073         ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
00074         return( ret );
00075 
00076     ctx->len = mpi_size( &ctx->P );
00077 
00078     if( end - *p < 2 )
00079         return( XYSSL_ERR_DHM_BAD_INPUT_DATA );
00080 
00081     n = ( (*p)[0] << 8 ) | (*p)[1];
00082     (*p) += 2;
00083 
00084     if( end != *p + n )
00085         return( XYSSL_ERR_DHM_BAD_INPUT_DATA );
00086 
00087     return( 0 );
00088 }
00089 
00090 
00091 
00092 
00093 int dhm_make_params( dhm_context *ctx, int x_size,
00094                      unsigned char *output, int *olen,
00095                      int (*f_rng)(void *), void *p_rng )
00096 {
00097     int i, ret, n, n1, n2, n3;
00098     unsigned char *p;
00099 
00100     
00101 
00102 
00103     n = x_size / sizeof( t_int );
00104     MPI_CHK( mpi_grow( &ctx->X, n ) );
00105     MPI_CHK( mpi_lset( &ctx->X, 0 ) );
00106 
00107     n = x_size >> 3;
00108     p = (unsigned char *) ctx->X.p;
00109     for( i = 0; i < n; i++ )
00110         *p++ = (unsigned char) f_rng( p_rng );
00111 
00112     while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
00113            mpi_shift_r( &ctx->X, 1 );
00114 
00115     MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
00116                           &ctx->P , &ctx->RP ) );
00117 
00118     
00119 
00120 
00121 #define DHM_MPI_EXPORT(X,n)                     \
00122     MPI_CHK( mpi_write_binary( X, p + 2, n ) ); \
00123     *p++ = (unsigned char)( n >> 8 );           \
00124     *p++ = (unsigned char)( n      ); p += n;
00125 
00126     n1 = mpi_size( &ctx->P  );
00127     n2 = mpi_size( &ctx->G  );
00128     n3 = mpi_size( &ctx->GX );
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 | XYSSL_ERR_DHM_MAKE_PARAMS_FAILED );
00143 
00144     return( 0 );
00145 }
00146 
00147 
00148 
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( XYSSL_ERR_DHM_BAD_INPUT_DATA );
00157 
00158     if( ( ret = mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
00159         return( XYSSL_ERR_DHM_READ_PUBLIC_FAILED | ret );
00160 
00161     return( 0 );
00162 }
00163 
00164 
00165 
00166 
00167 int dhm_make_public( dhm_context *ctx, int x_size,
00168                      unsigned char *output, int olen,
00169                      int (*f_rng)(void *), void *p_rng )
00170 {
00171     int ret, i, n;
00172     unsigned char *p;
00173 
00174     if( ctx == NULL || olen < 1 || olen > ctx->len )
00175         return( XYSSL_ERR_DHM_BAD_INPUT_DATA );
00176 
00177     
00178 
00179 
00180     n = x_size / sizeof( t_int );
00181     MPI_CHK( mpi_grow( &ctx->X, n ) );
00182     MPI_CHK( mpi_lset( &ctx->X, 0 ) );
00183 
00184     n = x_size >> 3;
00185     p = (unsigned char *) ctx->X.p;
00186     for( i = 0; i < n; i++ )
00187         *p++ = (unsigned char) f_rng( p_rng );
00188 
00189     while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
00190            mpi_shift_r( &ctx->X, 1 );
00191 
00192     MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
00193                           &ctx->P , &ctx->RP ) );
00194 
00195     MPI_CHK( mpi_write_binary( &ctx->GX, output, olen ) );
00196 
00197 cleanup:
00198 
00199     if( ret != 0 )
00200         return( XYSSL_ERR_DHM_MAKE_PUBLIC_FAILED | ret );
00201 
00202     return( 0 );
00203 }
00204 
00205 
00206 
00207 
00208 int dhm_calc_secret( dhm_context *ctx,
00209                      unsigned char *output, int *olen )
00210 {
00211     int ret;
00212 
00213     if( ctx == NULL || *olen < ctx->len )
00214         return( XYSSL_ERR_DHM_BAD_INPUT_DATA );
00215 
00216     MPI_CHK( mpi_exp_mod( &ctx->K, &ctx->GY, &ctx->X,
00217                           &ctx->P, &ctx->RP ) );
00218 
00219     *olen = mpi_size( &ctx->K );
00220 
00221     MPI_CHK( mpi_write_binary( &ctx->K, output, *olen ) );
00222 
00223 cleanup:
00224 
00225     if( ret != 0 )
00226         return( XYSSL_ERR_DHM_CALC_SECRET_FAILED | ret );
00227 
00228     return( 0 );
00229 }
00230 
00231 
00232 
00233 
00234 void dhm_free( dhm_context *ctx )
00235 {
00236     mpi_free( &ctx->RP, &ctx->K, &ctx->GY,
00237               &ctx->GX, &ctx->X, &ctx->G,
00238               &ctx->P, NULL );    
00239 }
00240 
00241 #if defined(XYSSL_SELF_TEST)
00242 
00243 
00244 
00245 
00246 int dhm_self_test( int verbose )
00247 {
00248     return( verbose++ );
00249 }
00250 
00251 #endif
00252 
00253 #endif