/home/dko/projects/mobilec/trunk/src/security/xyssl-0.9/library/dhm.c

Go to the documentation of this file.
00001 /*
00002  * Diffie-Hellman-Merkle key exchange
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  * Reference:
00022  *
00023  * http://www.cacr.math.uwaterloo.ca/hac/ (chapter 12)
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  * helper to validate the mpi size and import it
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  * Parse the ServerKeyExchange parameters
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  * Setup and write the ServerKeyExchange parameters
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  * generate X and calculate GX = G^X mod P
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  * export P, G, GX
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  * 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( 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  * Create own private value X and export G^X
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  * generate X and calculate GX = G^X mod P
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  * Derive and export the shared secret (G^Y)^X mod P
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  * Free the components of a DHM key
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  * Checkup routine
00245  */
00246 int dhm_self_test( int verbose )
00247 {
00248 return( verbose++ );
00249 }
00250 
00251 #endif
00252 
00253 #endif

Generated on Tue Oct 28 17:03:23 2008 for Mobile-C by doxygen 1.5.5

AltStyle によって変換されたページ (->オリジナル) /