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
00030
00031 #include "polarssl/config.h"
00032
00033 #if defined(POLARSSL_DHM_C)
00034
00035 #include "polarssl/dhm.h"
00036
00037 #if defined(POLARSSL_PEM_PARSE_C)
00038 #include "polarssl/pem.h"
00039 #endif
00040
00041 #if defined(POLARSSL_ASN1_PARSE_C)
00042 #include "polarssl/asn1.h"
00043 #endif
00044
00045 #if defined(POLARSSL_MEMORY_C)
00046 #include "polarssl/memory.h"
00047 #else
00048 #include <stdlib.h>
00049 #define polarssl_malloc malloc
00050 #define polarssl_free free
00051 #endif
00052
00053
00054
00055
00056 static int dhm_read_bignum( mpi *X,
00057 unsigned char **p,
00058 const unsigned char *end )
00059 {
00060 int ret, n;
00061
00062 if( end - *p < 2 )
00063 return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
00064
00065 n = ( (*p)[0] << 8 ) | (*p)[1];
00066 (*p) += 2;
00067
00068 if( (int)( end - *p ) < n )
00069 return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
00070
00071 if( ( ret = mpi_read_binary( X, *p, n ) ) != 0 )
00072 return( POLARSSL_ERR_DHM_READ_PARAMS_FAILED + ret );
00073
00074 (*p) += n;
00075
00076 return( 0 );
00077 }
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 static int dhm_check_range( const mpi *param, const mpi *P )
00089 {
00090 mpi L, U;
00091 int ret = POLARSSL_ERR_DHM_BAD_INPUT_DATA;
00092
00093 mpi_init( &L ); mpi_init( &U );
00094 mpi_lset( &L, 2 );
00095 mpi_sub_int( &U, P, 2 );
00096
00097 if( mpi_cmp_mpi( param, &L ) >= 0 &&
00098 mpi_cmp_mpi( param, &U ) <= 0 )
00099 {
00100 ret = 0;
00101 }
00102
00103 mpi_free( &L ); mpi_free( &U );
00104
00105 return( ret );
00106 }
00107
00108
00109
00110
00111 int dhm_read_params( dhm_context *ctx,
00112 unsigned char **p,
00113 const unsigned char *end )
00114 {
00115 int ret;
00116
00117 dhm_free( ctx );
00118
00119 if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
00120 ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
00121 ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
00122 return( ret );
00123
00124 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
00125 return( ret );
00126
00127 ctx->len = mpi_size( &ctx->P );
00128
00129 return( 0 );
00130 }
00131
00132
00133
00134
00135 int dhm_make_params( dhm_context *ctx, int x_size,
00136 unsigned char *output, size_t *olen,
00137 int (*f_rng)(void *, unsigned char *, size_t),
00138 void *p_rng )
00139 {
00140 int ret, count = 0;
00141 size_t n1, n2, n3;
00142 unsigned char *p;
00143
00144 if( mpi_cmp_int( &ctx->P, 0 ) == 0 )
00145 return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
00146
00147
00148
00149
00150 do
00151 {
00152 mpi_fill_random( &ctx->X, x_size, f_rng, p_rng );
00153
00154 while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
00155 mpi_shift_r( &ctx->X, 1 );
00156
00157 if( count++ > 10 )
00158 return( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED );
00159 }
00160 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
00161
00162
00163
00164
00165 MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
00166 &ctx->P , &ctx->RP ) );
00167
00168 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
00169 return( ret );
00170
00171
00172
00173
00174 #define DHM_MPI_EXPORT(X,n) \
00175 MPI_CHK( mpi_write_binary( X, p + 2, n ) ); \
00176 *p++ = (unsigned char)( n >> 8 ); \
00177 *p++ = (unsigned char)( n ); p += n;
00178
00179 n1 = mpi_size( &ctx->P );
00180 n2 = mpi_size( &ctx->G );
00181 n3 = mpi_size( &ctx->GX );
00182
00183 p = output;
00184 DHM_MPI_EXPORT( &ctx->P , n1 );
00185 DHM_MPI_EXPORT( &ctx->G , n2 );
00186 DHM_MPI_EXPORT( &ctx->GX, n3 );
00187
00188 *olen = p - output;
00189
00190 ctx->len = n1;
00191
00192 cleanup:
00193
00194 if( ret != 0 )
00195 return( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED + ret );
00196
00197 return( 0 );
00198 }
00199
00200
00201
00202
00203 int dhm_read_public( dhm_context *ctx,
00204 const unsigned char *input, size_t ilen )
00205 {
00206 int ret;
00207
00208 if( ctx == NULL || ilen < 1 || ilen > ctx->len )
00209 return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
00210
00211 if( ( ret = mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
00212 return( POLARSSL_ERR_DHM_READ_PUBLIC_FAILED + ret );
00213
00214 return( 0 );
00215 }
00216
00217
00218
00219
00220 int dhm_make_public( dhm_context *ctx, int x_size,
00221 unsigned char *output, size_t olen,
00222 int (*f_rng)(void *, unsigned char *, size_t),
00223 void *p_rng )
00224 {
00225 int ret, count = 0;
00226
00227 if( ctx == NULL || olen < 1 || olen > ctx->len )
00228 return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
00229
00230 if( mpi_cmp_int( &ctx->P, 0 ) == 0 )
00231 return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
00232
00233
00234
00235
00236 do
00237 {
00238 mpi_fill_random( &ctx->X, x_size, f_rng, p_rng );
00239
00240 while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
00241 mpi_shift_r( &ctx->X, 1 );
00242
00243 if( count++ > 10 )
00244 return( POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED );
00245 }
00246 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
00247
00248 MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
00249 &ctx->P , &ctx->RP ) );
00250
00251 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
00252 return( ret );
00253
00254 MPI_CHK( mpi_write_binary( &ctx->GX, output, olen ) );
00255
00256 cleanup:
00257
00258 if( ret != 0 )
00259 return( POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
00260
00261 return( 0 );
00262 }
00263
00264
00265
00266
00267
00268
00269
00270 static int dhm_update_blinding( dhm_context *ctx,
00271 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
00272 {
00273 int ret, count;
00274
00275
00276
00277
00278
00279 if( mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
00280 {
00281 MPI_CHK( mpi_copy( &ctx->pX, &ctx->X ) );
00282 MPI_CHK( mpi_lset( &ctx->Vi, 1 ) );
00283 MPI_CHK( mpi_lset( &ctx->Vf, 1 ) );
00284
00285 return( 0 );
00286 }
00287
00288
00289
00290
00291
00292 if( mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
00293 {
00294 MPI_CHK( mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
00295 MPI_CHK( mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
00296
00297 MPI_CHK( mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
00298 MPI_CHK( mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
00299
00300 return( 0 );
00301 }
00302
00303
00304
00305
00306
00307
00308 count = 0;
00309 do
00310 {
00311 mpi_fill_random( &ctx->Vi, mpi_size( &ctx->P ), f_rng, p_rng );
00312
00313 while( mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 )
00314 mpi_shift_r( &ctx->Vi, 1 );
00315
00316 if( count++ > 10 )
00317 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
00318 }
00319 while( mpi_cmp_int( &ctx->Vi, 1 ) <= 0 );
00320
00321
00322 MPI_CHK( mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) );
00323 MPI_CHK( mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) );
00324
00325 cleanup:
00326 return( ret );
00327 }
00328
00329
00330
00331
00332 int dhm_calc_secret( dhm_context *ctx,
00333 unsigned char *output, size_t *olen,
00334 int (*f_rng)(void *, unsigned char *, size_t),
00335 void *p_rng )
00336 {
00337 int ret;
00338 mpi GYb;
00339
00340 if( ctx == NULL || *olen < ctx->len )
00341 return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
00342
00343 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
00344 return( ret );
00345
00346 mpi_init( &GYb );
00347
00348
00349 if( f_rng != NULL )
00350 {
00351 MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
00352 MPI_CHK( mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
00353 MPI_CHK( mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
00354 }
00355 else
00356 MPI_CHK( mpi_copy( &GYb, &ctx->GY ) );
00357
00358
00359 MPI_CHK( mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
00360 &ctx->P, &ctx->RP ) );
00361
00362
00363 if( f_rng != NULL )
00364 {
00365 MPI_CHK( mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
00366 MPI_CHK( mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
00367 }
00368
00369 *olen = mpi_size( &ctx->K );
00370
00371 MPI_CHK( mpi_write_binary( &ctx->K, output, *olen ) );
00372
00373 cleanup:
00374 mpi_free( &GYb );
00375
00376 if( ret != 0 )
00377 return( POLARSSL_ERR_DHM_CALC_SECRET_FAILED + ret );
00378
00379 return( 0 );
00380 }
00381
00382
00383
00384
00385 void dhm_free( dhm_context *ctx )
00386 {
00387 mpi_free( &ctx->pX); mpi_free( &ctx->Vf ); mpi_free( &ctx->Vi );
00388 mpi_free( &ctx->RP ); mpi_free( &ctx->K ); mpi_free( &ctx->GY );
00389 mpi_free( &ctx->GX ); mpi_free( &ctx->X ); mpi_free( &ctx->G );
00390 mpi_free( &ctx->P );
00391
00392 memset( ctx, 0, sizeof( dhm_context ) );
00393 }
00394
00395 #if defined(POLARSSL_ASN1_PARSE_C)
00396
00397
00398
00399 int dhm_parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen )
00400 {
00401 int ret;
00402 size_t len;
00403 unsigned char *p, *end;
00404 #if defined(POLARSSL_PEM_PARSE_C)
00405 pem_context pem;
00406
00407 pem_init( &pem );
00408 memset( dhm, 0, sizeof( dhm_context ) );
00409
00410 ret = pem_read_buffer( &pem,
00411 "-----BEGIN DH PARAMETERS-----",
00412 "-----END DH PARAMETERS-----",
00413 dhmin, NULL, 0, &dhminlen );
00414
00415 if( ret == 0 )
00416 {
00417
00418
00419
00420 dhminlen = pem.buflen;
00421 }
00422 else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
00423 goto exit;
00424
00425 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
00426 #else
00427 p = (unsigned char *) dhmin;
00428 #endif
00429 end = p + dhminlen;
00430
00431
00432
00433
00434
00435
00436
00437 if( ( ret = asn1_get_tag( &p, end, &len,
00438 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
00439 {
00440 ret = POLARSSL_ERR_DHM_INVALID_FORMAT + ret;
00441 goto exit;
00442 }
00443
00444 end = p + len;
00445
00446 if( ( ret = asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
00447 ( ret = asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
00448 {
00449 ret = POLARSSL_ERR_DHM_INVALID_FORMAT + ret;
00450 goto exit;
00451 }
00452
00453 if( p != end )
00454 {
00455 ret = POLARSSL_ERR_DHM_INVALID_FORMAT +
00456 POLARSSL_ERR_ASN1_LENGTH_MISMATCH;
00457 goto exit;
00458 }
00459
00460 ret = 0;
00461
00462 exit:
00463 #if defined(POLARSSL_PEM_PARSE_C)
00464 pem_free( &pem );
00465 #endif
00466 if( ret != 0 )
00467 dhm_free( dhm );
00468
00469 return( ret );
00470 }
00471
00472 #if defined(POLARSSL_FS_IO)
00473
00474
00475
00476 static int load_file( const char *path, unsigned char **buf, size_t *n )
00477 {
00478 FILE *f;
00479 long size;
00480
00481 if( ( f = fopen( path, "rb" ) ) == NULL )
00482 return( POLARSSL_ERR_DHM_FILE_IO_ERROR );
00483
00484 fseek( f, 0, SEEK_END );
00485 if( ( size = ftell( f ) ) == -1 )
00486 {
00487 fclose( f );
00488 return( POLARSSL_ERR_DHM_FILE_IO_ERROR );
00489 }
00490 fseek( f, 0, SEEK_SET );
00491
00492 *n = (size_t) size;
00493
00494 if( *n + 1 == 0 ||
00495 ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL )
00496 {
00497 fclose( f );
00498 return( POLARSSL_ERR_DHM_MALLOC_FAILED );
00499 }
00500
00501 if( fread( *buf, 1, *n, f ) != *n )
00502 {
00503 fclose( f );
00504 polarssl_free( *buf );
00505 return( POLARSSL_ERR_DHM_FILE_IO_ERROR );
00506 }
00507
00508 fclose( f );
00509
00510 (*buf)[*n] = '\0';
00511
00512 return( 0 );
00513 }
00514
00515
00516
00517
00518 int dhm_parse_dhmfile( dhm_context *dhm, const char *path )
00519 {
00520 int ret;
00521 size_t n;
00522 unsigned char *buf;
00523
00524 if ( ( ret = load_file( path, &buf, &n ) ) != 0 )
00525 return( ret );
00526
00527 ret = dhm_parse_dhm( dhm, buf, n );
00528
00529 memset( buf, 0, n + 1 );
00530 polarssl_free( buf );
00531
00532 return( ret );
00533 }
00534 #endif
00535 #endif
00536
00537 #if defined(POLARSSL_SELF_TEST)
00538
00539 #include "polarssl/certs.h"
00540
00541
00542
00543
00544 int dhm_self_test( int verbose )
00545 {
00546 #if defined(POLARSSL_CERTS_C)
00547 int ret;
00548 dhm_context dhm;
00549
00550 if( verbose != 0 )
00551 printf( " DHM parameter load: " );
00552
00553 if( ( ret = dhm_parse_dhm( &dhm, (const unsigned char *) test_dhm_params,
00554 strlen( test_dhm_params ) ) ) != 0 )
00555 {
00556 if( verbose != 0 )
00557 printf( "failed\n" );
00558
00559 return( ret );
00560 }
00561
00562 if( verbose != 0 )
00563 printf( "passed\n\n" );
00564
00565 dhm_free( &dhm );
00566
00567 return( 0 );
00568 #else
00569 ((void) verbose);
00570 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
00571 #endif
00572 }
00573
00574 #endif
00575
00576 #endif