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
00027
00028
00029 #include "polarssl/config.h"
00030
00031 #if defined(POLARSSL_DHM_C)
00032
00033 #include "polarssl/dhm.h"
00034
00035 #include <string.h>
00036
00037
00038
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( POLARSSL_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( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
00054
00055 if( ( ret = mpi_read_binary( X, *p, n ) ) != 0 )
00056 return( POLARSSL_ERR_DHM_READ_PARAMS_FAILED | ret );
00057
00058 (*p) += n;
00059
00060 return( 0 );
00061 }
00062
00063
00064
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_size( &ctx->P );
00080
00081 if( end - *p < 2 )
00082 return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
00083
00084 n = ( (*p)[0] << 8 ) | (*p)[1];
00085 (*p) += 2;
00086
00087 if( end != *p + n )
00088 return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
00089
00090 return( 0 );
00091 }
00092
00093
00094
00095
00096 int dhm_make_params( dhm_context *ctx, int x_size,
00097 unsigned char *output, int *olen,
00098 int (*f_rng)(void *), void *p_rng )
00099 {
00100 int i, ret, n, n1, n2, n3;
00101 unsigned char *p;
00102
00103
00104
00105
00106 n = x_size / sizeof( t_int );
00107 MPI_CHK( mpi_grow( &ctx->X, n ) );
00108 MPI_CHK( mpi_lset( &ctx->X, 0 ) );
00109
00110 n = x_size - 1;
00111 p = (unsigned char *) ctx->X.p;
00112 for( i = 0; i < n; i++ )
00113 *p++ = (unsigned char) f_rng( p_rng );
00114
00115 while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
00116 mpi_shift_r( &ctx->X, 1 );
00117
00118 MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
00119 &ctx->P , &ctx->RP ) );
00120
00121
00122
00123
00124 #define DHM_MPI_EXPORT(X,n) \
00125 MPI_CHK( mpi_write_binary( X, p + 2, n ) ); \
00126 *p++ = (unsigned char)( n >> 8 ); \
00127 *p++ = (unsigned char)( n ); p += n;
00128
00129 n1 = mpi_size( &ctx->P );
00130 n2 = mpi_size( &ctx->G );
00131 n3 = mpi_size( &ctx->GX );
00132
00133 p = output;
00134 DHM_MPI_EXPORT( &ctx->P , n1 );
00135 DHM_MPI_EXPORT( &ctx->G , n2 );
00136 DHM_MPI_EXPORT( &ctx->GX, n3 );
00137
00138 *olen = p - output;
00139
00140 ctx->len = n1;
00141
00142 cleanup:
00143
00144 if( ret != 0 )
00145 return( ret | POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED );
00146
00147 return( 0 );
00148 }
00149
00150
00151
00152
00153 int dhm_read_public( dhm_context *ctx,
00154 unsigned char *input, int ilen )
00155 {
00156 int ret;
00157
00158 if( ctx == NULL || ilen < 1 || ilen > ctx->len )
00159 return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
00160
00161 if( ( ret = mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
00162 return( POLARSSL_ERR_DHM_READ_PUBLIC_FAILED | ret );
00163
00164 return( 0 );
00165 }
00166
00167
00168
00169
00170 int dhm_make_public( dhm_context *ctx, int x_size,
00171 unsigned char *output, int olen,
00172 int (*f_rng)(void *), void *p_rng )
00173 {
00174 int ret, i, n;
00175 unsigned char *p;
00176
00177 if( ctx == NULL || olen < 1 || olen > ctx->len )
00178 return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
00179
00180
00181
00182
00183 n = x_size / sizeof( t_int );
00184 MPI_CHK( mpi_grow( &ctx->X, n ) );
00185 MPI_CHK( mpi_lset( &ctx->X, 0 ) );
00186
00187 n = x_size - 1;
00188 p = (unsigned char *) ctx->X.p;
00189 for( i = 0; i < n; i++ )
00190 *p++ = (unsigned char) f_rng( p_rng );
00191
00192 while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
00193 mpi_shift_r( &ctx->X, 1 );
00194
00195 MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
00196 &ctx->P , &ctx->RP ) );
00197
00198 MPI_CHK( mpi_write_binary( &ctx->GX, output, olen ) );
00199
00200 cleanup:
00201
00202 if( ret != 0 )
00203 return( POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED | ret );
00204
00205 return( 0 );
00206 }
00207
00208
00209
00210
00211 int dhm_calc_secret( dhm_context *ctx,
00212 unsigned char *output, int *olen )
00213 {
00214 int ret;
00215
00216 if( ctx == NULL || *olen < ctx->len )
00217 return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
00218
00219 MPI_CHK( mpi_exp_mod( &ctx->K, &ctx->GY, &ctx->X,
00220 &ctx->P, &ctx->RP ) );
00221
00222 *olen = mpi_size( &ctx->K );
00223
00224 MPI_CHK( mpi_write_binary( &ctx->K, output, *olen ) );
00225
00226 cleanup:
00227
00228 if( ret != 0 )
00229 return( POLARSSL_ERR_DHM_CALC_SECRET_FAILED | ret );
00230
00231 return( 0 );
00232 }
00233
00234
00235
00236
00237 void dhm_free( dhm_context *ctx )
00238 {
00239 mpi_free( &ctx->RP, &ctx->K, &ctx->GY,
00240 &ctx->GX, &ctx->X, &ctx->G,
00241 &ctx->P, NULL );
00242 }
00243
00244 #if defined(POLARSSL_SELF_TEST)
00245
00246
00247
00248
00249 int dhm_self_test( int verbose )
00250 {
00251 return( verbose++ );
00252 }
00253
00254 #endif
00255
00256 #endif