Merge remote-tracking branch 'restricted/pr/553' into mbedtls-2.16

* restricted/pr/553:
  Fix mbedtls_ecdh_get_params with new ECDH context
  Add changelog entry for mbedtls_ecdh_get_params robustness
  Fix ecdh_get_params with mismatching group
  Add test case for ecdh_get_params with mismatching group
  Add test case for ecdh_calc_secret
  Fix typo in documentation
This commit is contained in:
Jaeden Amero 2019-03-27 14:54:00 +00:00
commit 186c2c054d
5 changed files with 190 additions and 3 deletions

View File

@ -2,6 +2,14 @@ mbed TLS ChangeLog (Sorted per branch, date)
= mbed TLS 2.x.x branch released xxxx-xx-xx = mbed TLS 2.x.x branch released xxxx-xx-xx
Security
* Make mbedtls_ecdh_get_params return an error if the second key
belongs to a different group from the first. Before, if an application
passed keys that belonged to different group, the first key's data was
interpreted according to the second group, which could lead to either
an error or a meaningless output from mbedtls_ecdh_get_params. In the
latter case, this could expose at most 5 bits of the private key.
Bugfix Bugfix
* Server's RSA certificate in certs.c was SHA-1 signed. In the default * Server's RSA certificate in certs.c was SHA-1 signed. In the default
mbedTLS configuration only SHA-2 signed certificates are accepted. mbedTLS configuration only SHA-2 signed certificates are accepted.

View File

@ -482,7 +482,7 @@ void mbedtls_ecp_point_init( mbedtls_ecp_point *pt );
* *
* \note After this function is called, domain parameters * \note After this function is called, domain parameters
* for various ECP groups can be loaded through the * for various ECP groups can be loaded through the
* mbedtls_ecp_load() or mbedtls_ecp_tls_read_group() * mbedtls_ecp_group_load() or mbedtls_ecp_tls_read_group()
* functions. * functions.
*/ */
void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ); void mbedtls_ecp_group_init( mbedtls_ecp_group *grp );

View File

@ -49,6 +49,16 @@
typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed; typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
#endif #endif
static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
const mbedtls_ecdh_context *ctx )
{
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
return( ctx->grp.id );
#else
return( ctx->grp_id );
#endif
}
#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
/* /*
* Generate public key (restartable version) * Generate public key (restartable version)
@ -442,8 +452,21 @@ int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx,
ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS || ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS ||
side == MBEDTLS_ECDH_THEIRS ); side == MBEDTLS_ECDH_THEIRS );
if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 ) if( mbedtls_ecdh_grp_id( ctx ) == MBEDTLS_ECP_DP_NONE )
return( ret ); {
/* This is the first call to get_params(). Set up the context
* for use with the group. */
if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 )
return( ret );
}
else
{
/* This is not the first call to get_params(). Check that the
* current key's group is the same as the context's, which was set
* from the first key's group. */
if( mbedtls_ecdh_grp_id( ctx ) != key->grp.id )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
}
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
return( ecdh_get_params_internal( ctx, key, side ) ); return( ecdh_get_params_internal( ctx, key, side ) );

View File

@ -79,3 +79,19 @@ ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8A
ECDH exchange legacy context ECDH exchange legacy context
depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
ecdh_exchange_legacy:MBEDTLS_ECP_DP_SECP192R1 ecdh_exchange_legacy:MBEDTLS_ECP_DP_SECP192R1
ECDH calc_secret: ours first, SECP256R1 (RFC 5903)
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
ecdh_exchange_calc_secret:MBEDTLS_ECP_DP_SECP256R1:"c6ef9c5d78ae012a011164acb397ce2088685d8f06bf9be0b283ab46476bee53":"04dad0b65394221cf9b051e1feca5787d098dfe637fc90b9ef945d0c37725811805271a0461cdb8252d61f1c456fa3e59ab1f45b33accf5f58389e0577b8990bb3":0:"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de"
ECDH calc_secret: theirs first, SECP256R1 (RFC 5903)
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
ecdh_exchange_calc_secret:MBEDTLS_ECP_DP_SECP256R1:"c6ef9c5d78ae012a011164acb397ce2088685d8f06bf9be0b283ab46476bee53":"04dad0b65394221cf9b051e1feca5787d098dfe637fc90b9ef945d0c37725811805271a0461cdb8252d61f1c456fa3e59ab1f45b33accf5f58389e0577b8990bb3":1:"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de"
ECDH get_params with mismatched groups: our BP256R1, their SECP256R1
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_BP256R1_ENABLED
ecdh_exchange_get_params_fail:MBEDTLS_ECP_DP_BP256R1:"1234567812345678123456781234567812345678123456781234567812345678":MBEDTLS_ECP_DP_SECP256R1:"04dad0b65394221cf9b051e1feca5787d098dfe637fc90b9ef945d0c37725811805271a0461cdb8252d61f1c456fa3e59ab1f45b33accf5f58389e0577b8990bb3":0:MBEDTLS_ERR_ECP_BAD_INPUT_DATA
ECDH get_params with mismatched groups: their SECP256R1, our BP256R1
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_BP256R1_ENABLED
ecdh_exchange_get_params_fail:MBEDTLS_ECP_DP_BP256R1:"1234567812345678123456781234567812345678123456781234567812345678":MBEDTLS_ECP_DP_SECP256R1:"04dad0b65394221cf9b051e1feca5787d098dfe637fc90b9ef945d0c37725811805271a0461cdb8252d61f1c456fa3e59ab1f45b33accf5f58389e0577b8990bb3":1:MBEDTLS_ERR_ECP_BAD_INPUT_DATA

View File

@ -1,5 +1,41 @@
/* BEGIN_HEADER */ /* BEGIN_HEADER */
#include "mbedtls/ecdh.h" #include "mbedtls/ecdh.h"
static int load_public_key( int grp_id, data_t *point,
mbedtls_ecp_keypair *ecp )
{
int ok = 0;
TEST_ASSERT( mbedtls_ecp_group_load( &ecp->grp, grp_id ) == 0 );
TEST_ASSERT( mbedtls_ecp_point_read_binary( &ecp->grp,
&ecp->Q,
point->x,
point->len ) == 0 );
TEST_ASSERT( mbedtls_ecp_check_pubkey( &ecp->grp,
&ecp->Q ) == 0 );
ok = 1;
exit:
return( ok );
}
static int load_private_key( int grp_id, data_t *private_key,
mbedtls_ecp_keypair *ecp,
rnd_pseudo_info *rnd_info )
{
int ok = 0;
TEST_ASSERT( mbedtls_ecp_group_load( &ecp->grp, grp_id ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_binary( &ecp->d,
private_key->x,
private_key->len ) == 0 );
TEST_ASSERT( mbedtls_ecp_check_privkey( &ecp->grp, &ecp->d ) == 0 );
/* Calculate the public key from the private key. */
TEST_ASSERT( mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d,
&ecp->grp.G,
&rnd_pseudo_rand, rnd_info ) == 0 );
ok = 1;
exit:
return( ok );
}
/* END_HEADER */ /* END_HEADER */
/* BEGIN_DEPENDENCIES /* BEGIN_DEPENDENCIES
@ -464,3 +500,107 @@ exit:
mbedtls_ecdh_free( &cli ); mbedtls_ecdh_free( &cli );
} }
/* END_CASE */ /* END_CASE */
/* BEGIN_CASE */
void ecdh_exchange_calc_secret( int grp_id,
data_t *our_private_key,
data_t *their_point,
int ours_first,
data_t *expected )
{
rnd_pseudo_info rnd_info;
mbedtls_ecp_keypair our_key;
mbedtls_ecp_keypair their_key;
mbedtls_ecdh_context ecdh;
unsigned char shared_secret[MBEDTLS_ECP_MAX_BYTES];
size_t shared_secret_length = 0;
memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
mbedtls_ecdh_init( &ecdh );
mbedtls_ecp_keypair_init( &our_key );
mbedtls_ecp_keypair_init( &their_key );
if( ! load_private_key( grp_id, our_private_key, &our_key, &rnd_info ) )
goto exit;
if( ! load_public_key( grp_id, their_point, &their_key ) )
goto exit;
/* Import the keys to the ECDH calculation. */
if( ours_first )
{
TEST_ASSERT( mbedtls_ecdh_get_params(
&ecdh, &our_key, MBEDTLS_ECDH_OURS ) == 0 );
TEST_ASSERT( mbedtls_ecdh_get_params(
&ecdh, &their_key, MBEDTLS_ECDH_THEIRS ) == 0 );
}
else
{
TEST_ASSERT( mbedtls_ecdh_get_params(
&ecdh, &their_key, MBEDTLS_ECDH_THEIRS ) == 0 );
TEST_ASSERT( mbedtls_ecdh_get_params(
&ecdh, &our_key, MBEDTLS_ECDH_OURS ) == 0 );
}
/* Perform the ECDH calculation. */
TEST_ASSERT( mbedtls_ecdh_calc_secret(
&ecdh,
&shared_secret_length,
shared_secret, sizeof( shared_secret ),
&rnd_pseudo_rand, &rnd_info ) == 0 );
TEST_ASSERT( shared_secret_length == expected->len );
TEST_ASSERT( memcmp( expected->x, shared_secret,
shared_secret_length ) == 0 );
exit:
mbedtls_ecdh_free( &ecdh );
mbedtls_ecp_keypair_free( &our_key );
mbedtls_ecp_keypair_free( &their_key );
}
/* END_CASE */
/* BEGIN_CASE */
void ecdh_exchange_get_params_fail( int our_grp_id,
data_t *our_private_key,
int their_grp_id,
data_t *their_point,
int ours_first,
int expected_ret )
{
rnd_pseudo_info rnd_info;
mbedtls_ecp_keypair our_key;
mbedtls_ecp_keypair their_key;
mbedtls_ecdh_context ecdh;
memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
mbedtls_ecdh_init( &ecdh );
mbedtls_ecp_keypair_init( &our_key );
mbedtls_ecp_keypair_init( &their_key );
if( ! load_private_key( our_grp_id, our_private_key, &our_key, &rnd_info ) )
goto exit;
if( ! load_public_key( their_grp_id, their_point, &their_key ) )
goto exit;
if( ours_first )
{
TEST_ASSERT( mbedtls_ecdh_get_params(
&ecdh, &our_key, MBEDTLS_ECDH_OURS ) == 0 );
TEST_ASSERT( mbedtls_ecdh_get_params(
&ecdh, &their_key, MBEDTLS_ECDH_THEIRS ) ==
expected_ret );
}
else
{
TEST_ASSERT( mbedtls_ecdh_get_params(
&ecdh, &their_key, MBEDTLS_ECDH_THEIRS ) == 0 );
TEST_ASSERT( mbedtls_ecdh_get_params(
&ecdh, &our_key, MBEDTLS_ECDH_OURS ) ==
expected_ret );
}
exit:
mbedtls_ecdh_free( &ecdh );
mbedtls_ecp_keypair_free( &our_key );
mbedtls_ecp_keypair_free( &their_key );
}
/* END_CASE */