mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-11-22 22:25:47 +01:00
Implement DH blinding
This commit is contained in:
parent
2d627649bf
commit
143b5028a5
@ -147,6 +147,9 @@ typedef struct
|
|||||||
mpi GY; /*!< peer = G^Y mod P */
|
mpi GY; /*!< peer = G^Y mod P */
|
||||||
mpi K; /*!< key = GY^X mod P */
|
mpi K; /*!< key = GY^X mod P */
|
||||||
mpi RP; /*!< cached R^2 mod P */
|
mpi RP; /*!< cached R^2 mod P */
|
||||||
|
mpi Vi; /*!< blinding value */
|
||||||
|
mpi Vf; /*!< un-blinding value */
|
||||||
|
mpi _X; /*!< previous X */
|
||||||
}
|
}
|
||||||
dhm_context;
|
dhm_context;
|
||||||
|
|
||||||
@ -223,6 +226,9 @@ int dhm_make_public( dhm_context *ctx, int x_size,
|
|||||||
* \param p_rng RNG parameter
|
* \param p_rng RNG parameter
|
||||||
*
|
*
|
||||||
* \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code
|
* \return 0 if successful, or an POLARSSL_ERR_DHM_XXX error code
|
||||||
|
*
|
||||||
|
* \note If f_rng is not NULL, it is used to blind the input as
|
||||||
|
* countermeasure against timing attacks.
|
||||||
*/
|
*/
|
||||||
int dhm_calc_secret( dhm_context *ctx,
|
int dhm_calc_secret( dhm_context *ctx,
|
||||||
unsigned char *output, size_t *olen,
|
unsigned char *output, size_t *olen,
|
||||||
|
@ -245,6 +245,60 @@ cleanup:
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use the blinding method and optimisation suggested in section 10 of:
|
||||||
|
* KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
|
||||||
|
* DSS, and other systems. In : Advances in Cryptology—CRYPTO’96. Springer
|
||||||
|
* Berlin Heidelberg, 1996. p. 104-113.
|
||||||
|
*/
|
||||||
|
static int dhm_update_blinding( dhm_context *ctx,
|
||||||
|
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
|
||||||
|
{
|
||||||
|
int ret, count;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We can just update the previous values (by squaring them) if:
|
||||||
|
* - the values are initialized, and
|
||||||
|
* - our secret exponent did not change.
|
||||||
|
*/
|
||||||
|
if( ctx->Vi.p != NULL &&
|
||||||
|
mpi_cmp_mpi( &ctx->X, &ctx->_X ) == 0 )
|
||||||
|
{
|
||||||
|
MPI_CHK( mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
|
||||||
|
MPI_CHK( mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Otherwise, we need to generate new values from scratch for this secret
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Vi = random( 2, P-1 ) */
|
||||||
|
count = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
mpi_fill_random( &ctx->Vi, mpi_size( &ctx->P ), f_rng, p_rng );
|
||||||
|
|
||||||
|
while( mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 )
|
||||||
|
mpi_shift_r( &ctx->Vi, 1 );
|
||||||
|
|
||||||
|
if( count++ > 10 )
|
||||||
|
return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
|
||||||
|
}
|
||||||
|
while( mpi_cmp_int( &ctx->Vi, 1 ) <= 0 );
|
||||||
|
|
||||||
|
/* Vf = Vi^-X mod P */
|
||||||
|
MPI_CHK( mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) );
|
||||||
|
MPI_CHK( mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) );
|
||||||
|
|
||||||
|
/* Remember secret associated with Vi and Vf */
|
||||||
|
MPI_CHK( mpi_copy( &ctx->_X, &ctx->X ) );;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Derive and export the shared secret (G^Y)^X mod P
|
* Derive and export the shared secret (G^Y)^X mod P
|
||||||
*/
|
*/
|
||||||
@ -254,24 +308,43 @@ int dhm_calc_secret( dhm_context *ctx,
|
|||||||
void *p_rng )
|
void *p_rng )
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
mpi GYb;
|
||||||
(void) f_rng;
|
|
||||||
(void) p_rng;
|
|
||||||
|
|
||||||
if( ctx == NULL || *olen < ctx->len )
|
if( ctx == NULL || *olen < ctx->len )
|
||||||
return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
|
return( POLARSSL_ERR_DHM_BAD_INPUT_DATA );
|
||||||
|
|
||||||
MPI_CHK( mpi_exp_mod( &ctx->K, &ctx->GY, &ctx->X,
|
|
||||||
&ctx->P, &ctx->RP ) );
|
|
||||||
|
|
||||||
if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
|
if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
|
||||||
return( ret );
|
return( ret );
|
||||||
|
|
||||||
|
mpi_init( &GYb );
|
||||||
|
|
||||||
|
/* Blind peer's value */
|
||||||
|
if( f_rng != 0 )
|
||||||
|
{
|
||||||
|
MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
|
||||||
|
MPI_CHK( mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
|
||||||
|
MPI_CHK( mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
MPI_CHK( mpi_copy( &GYb, &ctx->GY ) );
|
||||||
|
|
||||||
|
/* Do modular exponentiation */
|
||||||
|
MPI_CHK( mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
|
||||||
|
&ctx->P, &ctx->RP ) );
|
||||||
|
|
||||||
|
/* Unblind secret value */
|
||||||
|
if( f_rng != 0 )
|
||||||
|
{
|
||||||
|
MPI_CHK( mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
|
||||||
|
MPI_CHK( mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
|
||||||
|
}
|
||||||
|
|
||||||
*olen = mpi_size( &ctx->K );
|
*olen = mpi_size( &ctx->K );
|
||||||
|
|
||||||
MPI_CHK( mpi_write_binary( &ctx->K, output, *olen ) );
|
MPI_CHK( mpi_write_binary( &ctx->K, output, *olen ) );
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
mpi_free( &GYb );
|
||||||
|
|
||||||
if( ret != 0 )
|
if( ret != 0 )
|
||||||
return( POLARSSL_ERR_DHM_CALC_SECRET_FAILED + ret );
|
return( POLARSSL_ERR_DHM_CALC_SECRET_FAILED + ret );
|
||||||
@ -284,6 +357,7 @@ cleanup:
|
|||||||
*/
|
*/
|
||||||
void dhm_free( dhm_context *ctx )
|
void dhm_free( dhm_context *ctx )
|
||||||
{
|
{
|
||||||
|
mpi_free( &ctx->Vi ); mpi_free( &ctx->Vf );
|
||||||
mpi_free( &ctx->RP ); mpi_free( &ctx->K ); mpi_free( &ctx->GY );
|
mpi_free( &ctx->RP ); mpi_free( &ctx->K ); mpi_free( &ctx->GY );
|
||||||
mpi_free( &ctx->GX ); mpi_free( &ctx->X ); mpi_free( &ctx->G );
|
mpi_free( &ctx->GX ); mpi_free( &ctx->X ); mpi_free( &ctx->G );
|
||||||
mpi_free( &ctx->P );
|
mpi_free( &ctx->P );
|
||||||
|
@ -4,5 +4,5 @@ dhm_do_dhm:1024:10:"23":10:"5"
|
|||||||
Diffie-Hellman full exchange #2
|
Diffie-Hellman full exchange #2
|
||||||
dhm_do_dhm:1024:10:"93450983094850938450983409623":10:"9345098304850938450983409622"
|
dhm_do_dhm:1024:10:"93450983094850938450983409623":10:"9345098304850938450983409622"
|
||||||
|
|
||||||
Diffie-Hellman full exchange #2
|
Diffie-Hellman full exchange #3
|
||||||
dhm_do_dhm:1024:10:"93450983094850938450983409623982317398171298719873918739182739712938719287391879381271":10:"9345098309485093845098340962223981329819812792137312973297123912791271"
|
dhm_do_dhm:1024:10:"93450983094850938450983409623982317398171298719873918739182739712938719287391879381271":10:"9345098309485093845098340962223981329819812792137312973297123912791271"
|
||||||
|
@ -35,18 +35,53 @@ void dhm_do_dhm( int NOTUSED, int radix_P, char *input_P,
|
|||||||
memset( sec_cli, 0x00, 1000 );
|
memset( sec_cli, 0x00, 1000 );
|
||||||
memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
|
memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set params
|
||||||
|
*/
|
||||||
TEST_ASSERT( mpi_read_string( &ctx_srv.P, radix_P, input_P ) == 0 );
|
TEST_ASSERT( mpi_read_string( &ctx_srv.P, radix_P, input_P ) == 0 );
|
||||||
TEST_ASSERT( mpi_read_string( &ctx_srv.G, radix_G, input_G ) == 0 );
|
TEST_ASSERT( mpi_read_string( &ctx_srv.G, radix_G, input_G ) == 0 );
|
||||||
x_size = mpi_size( &ctx_srv.P );
|
x_size = mpi_size( &ctx_srv.P );
|
||||||
|
pub_cli_len = x_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First key exchange
|
||||||
|
*/
|
||||||
|
TEST_ASSERT( dhm_make_params( &ctx_srv, x_size, ske, &ske_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
|
||||||
|
ske[ske_len++] = 0;
|
||||||
|
ske[ske_len++] = 0;
|
||||||
|
TEST_ASSERT( dhm_read_params( &ctx_cli, &p, ske + ske_len ) == 0 );
|
||||||
|
|
||||||
|
TEST_ASSERT( dhm_make_public( &ctx_cli, x_size, pub_cli, pub_cli_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
|
||||||
|
TEST_ASSERT( dhm_read_public( &ctx_srv, pub_cli, pub_cli_len ) == 0 );
|
||||||
|
|
||||||
|
TEST_ASSERT( dhm_calc_secret( &ctx_srv, sec_srv, &sec_srv_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
|
||||||
|
TEST_ASSERT( dhm_calc_secret( &ctx_cli, sec_cli, &sec_cli_len, NULL, NULL ) == 0 );
|
||||||
|
|
||||||
|
TEST_ASSERT( sec_srv_len == sec_cli_len );
|
||||||
|
TEST_ASSERT( sec_srv_len != 0 );
|
||||||
|
TEST_ASSERT( memcmp( sec_srv, sec_cli, sec_srv_len ) == 0 );
|
||||||
|
|
||||||
|
/* Re-do calc_secret on server to test update of blinding values */
|
||||||
|
sec_srv_len = 1000;
|
||||||
|
TEST_ASSERT( dhm_calc_secret( &ctx_srv, sec_srv, &sec_srv_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
|
||||||
|
|
||||||
|
TEST_ASSERT( sec_srv_len == sec_cli_len );
|
||||||
|
TEST_ASSERT( sec_srv_len != 0 );
|
||||||
|
TEST_ASSERT( memcmp( sec_srv, sec_cli, sec_srv_len ) == 0 );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Second key exchange to test change of blinding values on server
|
||||||
|
*/
|
||||||
|
sec_cli_len = 1000;
|
||||||
|
sec_srv_len = 1000;
|
||||||
|
p = ske;
|
||||||
|
|
||||||
TEST_ASSERT( dhm_make_params( &ctx_srv, x_size, ske, &ske_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
|
TEST_ASSERT( dhm_make_params( &ctx_srv, x_size, ske, &ske_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
|
||||||
ske[ske_len++] = 0;
|
ske[ske_len++] = 0;
|
||||||
ske[ske_len++] = 0;
|
ske[ske_len++] = 0;
|
||||||
TEST_ASSERT( dhm_read_params( &ctx_cli, &p, ske + ske_len ) == 0 );
|
TEST_ASSERT( dhm_read_params( &ctx_cli, &p, ske + ske_len ) == 0 );
|
||||||
|
|
||||||
pub_cli_len = x_size;
|
|
||||||
TEST_ASSERT( dhm_make_public( &ctx_cli, x_size, pub_cli, pub_cli_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
|
TEST_ASSERT( dhm_make_public( &ctx_cli, x_size, pub_cli, pub_cli_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
|
||||||
|
|
||||||
TEST_ASSERT( dhm_read_public( &ctx_srv, pub_cli, pub_cli_len ) == 0 );
|
TEST_ASSERT( dhm_read_public( &ctx_srv, pub_cli, pub_cli_len ) == 0 );
|
||||||
|
|
||||||
TEST_ASSERT( dhm_calc_secret( &ctx_srv, sec_srv, &sec_srv_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
|
TEST_ASSERT( dhm_calc_secret( &ctx_srv, sec_srv, &sec_srv_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
|
||||||
|
Loading…
Reference in New Issue
Block a user