171a7efd02
The private keys used in ECDH differ in the case of Weierstrass and Montgomery curves. They have different constraints, the former is based on big endian, the latter little endian byte order. The fundamental approach is different too: - Weierstrass keys have to be in the right interval, otherwise they are rejected. - Any byte array of the right size is a valid Montgomery key and it needs to be masked before interpreting it as a number. Historically it was sufficient to use mbedtls_mpi_read_binary() to read private keys, but as a preparation to improve support for Montgomery curves we add mbedtls_ecp_read_key() to enable uniform treatment of EC keys. For the masking the `mbedtls_mpi_set_bit()` function is used. This is suboptimal but seems to provide the best trade-off at this time. Alternatives considered: - Making a copy of the input buffer (less efficient) - removing the `const` constraint from the input buffer (breaks the api and makes it less user friendly) - applying the mask directly to the limbs (violates the api between the modules and creates and unwanted dependency)
606 lines
23 KiB
Plaintext
606 lines
23 KiB
Plaintext
/* BEGIN_HEADER */
|
|
#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_read_key( grp_id, ecp,
|
|
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 */
|
|
|
|
/* BEGIN_DEPENDENCIES
|
|
* depends_on:MBEDTLS_ECDH_C
|
|
* END_DEPENDENCIES
|
|
*/
|
|
|
|
/* BEGIN_CASE */
|
|
void ecdh_valid_param( )
|
|
{
|
|
TEST_VALID_PARAM( mbedtls_ecdh_free( NULL ) );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE depends_on:MBEDTLS_CHECK_PARAMS:!MBEDTLS_PARAM_FAILED_ALT */
|
|
void ecdh_invalid_param( )
|
|
{
|
|
mbedtls_ecp_group grp;
|
|
mbedtls_ecdh_context ctx;
|
|
mbedtls_mpi m;
|
|
mbedtls_ecp_point P;
|
|
mbedtls_ecp_keypair kp;
|
|
size_t olen;
|
|
unsigned char buf[42] = { 0 };
|
|
const unsigned char *buf_null = NULL;
|
|
size_t const buflen = sizeof( buf );
|
|
int invalid_side = 42;
|
|
mbedtls_ecp_group_id valid_grp = MBEDTLS_ECP_DP_SECP192R1;
|
|
|
|
TEST_INVALID_PARAM( mbedtls_ecdh_init( NULL ) );
|
|
|
|
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
|
TEST_INVALID_PARAM( mbedtls_ecdh_enable_restart( NULL ) );
|
|
#endif /* MBEDTLS_ECP_RESTARTABLE */
|
|
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_gen_public( NULL, &m, &P,
|
|
rnd_std_rand, NULL ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_gen_public( &grp, NULL, &P,
|
|
rnd_std_rand, NULL ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_gen_public( &grp, &m, NULL,
|
|
rnd_std_rand, NULL ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_gen_public( &grp, &m, &P,
|
|
NULL, NULL ) );
|
|
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_compute_shared( NULL, &m, &P, &m,
|
|
rnd_std_rand, NULL ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_compute_shared( &grp, NULL, &P, &m,
|
|
rnd_std_rand, NULL ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_compute_shared( &grp, &m, NULL, &m,
|
|
rnd_std_rand, NULL ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_compute_shared( &grp, &m, &P, NULL,
|
|
rnd_std_rand, NULL ) );
|
|
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_setup( NULL, valid_grp ) );
|
|
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_make_params( NULL, &olen,
|
|
buf, buflen,
|
|
rnd_std_rand, NULL ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_make_params( &ctx, NULL,
|
|
buf, buflen,
|
|
rnd_std_rand, NULL ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_make_params( &ctx, &olen,
|
|
NULL, buflen,
|
|
rnd_std_rand, NULL ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_make_params( &ctx, &olen,
|
|
buf, buflen,
|
|
NULL, NULL ) );
|
|
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_read_params( NULL,
|
|
(const unsigned char**) &buf,
|
|
buf ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_read_params( &ctx, &buf_null,
|
|
buf ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_read_params( &ctx, NULL, buf ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_read_params( &ctx,
|
|
(const unsigned char**) &buf,
|
|
NULL ) );
|
|
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_get_params( NULL, &kp,
|
|
MBEDTLS_ECDH_OURS ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_get_params( &ctx, NULL,
|
|
MBEDTLS_ECDH_OURS ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_get_params( &ctx, &kp,
|
|
invalid_side ) );
|
|
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_make_public( NULL, &olen,
|
|
buf, buflen,
|
|
rnd_std_rand,
|
|
NULL ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_make_public( &ctx, NULL,
|
|
buf, buflen,
|
|
rnd_std_rand,
|
|
NULL ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_make_public( &ctx, &olen,
|
|
NULL, buflen,
|
|
rnd_std_rand,
|
|
NULL ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_make_public( &ctx, &olen,
|
|
buf, buflen,
|
|
NULL,
|
|
NULL ) );
|
|
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_read_public( NULL, buf, buflen ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_read_public( &ctx, NULL, buflen ) );
|
|
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_calc_secret( NULL, &olen, buf, buflen,
|
|
rnd_std_rand,
|
|
NULL ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_calc_secret( &ctx, NULL, buf, buflen,
|
|
rnd_std_rand,
|
|
NULL ) );
|
|
TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
|
|
mbedtls_ecdh_calc_secret( &ctx, &olen, NULL, buflen,
|
|
rnd_std_rand,
|
|
NULL ) );
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void ecdh_primitive_random( int id )
|
|
{
|
|
mbedtls_ecp_group grp;
|
|
mbedtls_ecp_point qA, qB;
|
|
mbedtls_mpi dA, dB, zA, zB;
|
|
rnd_pseudo_info rnd_info;
|
|
|
|
mbedtls_ecp_group_init( &grp );
|
|
mbedtls_ecp_point_init( &qA ); mbedtls_ecp_point_init( &qB );
|
|
mbedtls_mpi_init( &dA ); mbedtls_mpi_init( &dB );
|
|
mbedtls_mpi_init( &zA ); mbedtls_mpi_init( &zB );
|
|
memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
|
|
|
|
TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
|
|
|
|
TEST_ASSERT( mbedtls_ecdh_gen_public( &grp, &dA, &qA, &rnd_pseudo_rand, &rnd_info )
|
|
== 0 );
|
|
TEST_ASSERT( mbedtls_ecdh_gen_public( &grp, &dB, &qB, &rnd_pseudo_rand, &rnd_info )
|
|
== 0 );
|
|
TEST_ASSERT( mbedtls_ecdh_compute_shared( &grp, &zA, &qB, &dA,
|
|
&rnd_pseudo_rand, &rnd_info ) == 0 );
|
|
TEST_ASSERT( mbedtls_ecdh_compute_shared( &grp, &zB, &qA, &dB,
|
|
NULL, NULL ) == 0 );
|
|
|
|
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &zA, &zB ) == 0 );
|
|
|
|
exit:
|
|
mbedtls_ecp_group_free( &grp );
|
|
mbedtls_ecp_point_free( &qA ); mbedtls_ecp_point_free( &qB );
|
|
mbedtls_mpi_free( &dA ); mbedtls_mpi_free( &dB );
|
|
mbedtls_mpi_free( &zA ); mbedtls_mpi_free( &zB );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void ecdh_primitive_testvec( int id, data_t * rnd_buf_A, char * xA_str,
|
|
char * yA_str, data_t * rnd_buf_B,
|
|
char * xB_str, char * yB_str, char * z_str )
|
|
{
|
|
mbedtls_ecp_group grp;
|
|
mbedtls_ecp_point qA, qB;
|
|
mbedtls_mpi dA, dB, zA, zB, check;
|
|
rnd_buf_info rnd_info_A, rnd_info_B;
|
|
|
|
mbedtls_ecp_group_init( &grp );
|
|
mbedtls_ecp_point_init( &qA ); mbedtls_ecp_point_init( &qB );
|
|
mbedtls_mpi_init( &dA ); mbedtls_mpi_init( &dB );
|
|
mbedtls_mpi_init( &zA ); mbedtls_mpi_init( &zB ); mbedtls_mpi_init( &check );
|
|
|
|
TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
|
|
|
|
rnd_info_A.buf = rnd_buf_A->x;
|
|
rnd_info_A.length = rnd_buf_A->len;
|
|
|
|
/* Fix rnd_buf_A->x by shifting it left if necessary */
|
|
if( grp.nbits % 8 != 0 )
|
|
{
|
|
unsigned char shift = 8 - ( grp.nbits % 8 );
|
|
size_t i;
|
|
|
|
for( i = 0; i < rnd_info_A.length - 1; i++ )
|
|
rnd_buf_A->x[i] = rnd_buf_A->x[i] << shift
|
|
| rnd_buf_A->x[i+1] >> ( 8 - shift );
|
|
|
|
rnd_buf_A->x[rnd_info_A.length-1] <<= shift;
|
|
}
|
|
|
|
rnd_info_B.buf = rnd_buf_B->x;
|
|
rnd_info_B.length = rnd_buf_B->len;
|
|
|
|
/* Fix rnd_buf_B->x by shifting it left if necessary */
|
|
if( grp.nbits % 8 != 0 )
|
|
{
|
|
unsigned char shift = 8 - ( grp.nbits % 8 );
|
|
size_t i;
|
|
|
|
for( i = 0; i < rnd_info_B.length - 1; i++ )
|
|
rnd_buf_B->x[i] = rnd_buf_B->x[i] << shift
|
|
| rnd_buf_B->x[i+1] >> ( 8 - shift );
|
|
|
|
rnd_buf_B->x[rnd_info_B.length-1] <<= shift;
|
|
}
|
|
|
|
TEST_ASSERT( mbedtls_ecdh_gen_public( &grp, &dA, &qA,
|
|
rnd_buffer_rand, &rnd_info_A ) == 0 );
|
|
TEST_ASSERT( ! mbedtls_ecp_is_zero( &qA ) );
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &check, 16, xA_str ) == 0 );
|
|
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &qA.X, &check ) == 0 );
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &check, 16, yA_str ) == 0 );
|
|
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &qA.Y, &check ) == 0 );
|
|
|
|
TEST_ASSERT( mbedtls_ecdh_gen_public( &grp, &dB, &qB,
|
|
rnd_buffer_rand, &rnd_info_B ) == 0 );
|
|
TEST_ASSERT( ! mbedtls_ecp_is_zero( &qB ) );
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &check, 16, xB_str ) == 0 );
|
|
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &qB.X, &check ) == 0 );
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &check, 16, yB_str ) == 0 );
|
|
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &qB.Y, &check ) == 0 );
|
|
|
|
TEST_ASSERT( mbedtls_mpi_read_string( &check, 16, z_str ) == 0 );
|
|
TEST_ASSERT( mbedtls_ecdh_compute_shared( &grp, &zA, &qB, &dA, NULL, NULL ) == 0 );
|
|
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &zA, &check ) == 0 );
|
|
TEST_ASSERT( mbedtls_ecdh_compute_shared( &grp, &zB, &qA, &dB, NULL, NULL ) == 0 );
|
|
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &zB, &check ) == 0 );
|
|
|
|
exit:
|
|
mbedtls_ecp_group_free( &grp );
|
|
mbedtls_ecp_point_free( &qA ); mbedtls_ecp_point_free( &qB );
|
|
mbedtls_mpi_free( &dA ); mbedtls_mpi_free( &dB );
|
|
mbedtls_mpi_free( &zA ); mbedtls_mpi_free( &zB ); mbedtls_mpi_free( &check );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void ecdh_exchange( int id )
|
|
{
|
|
mbedtls_ecdh_context srv, cli;
|
|
unsigned char buf[1000];
|
|
const unsigned char *vbuf;
|
|
size_t len;
|
|
rnd_pseudo_info rnd_info;
|
|
unsigned char res_buf[1000];
|
|
size_t res_len;
|
|
|
|
mbedtls_ecdh_init( &srv );
|
|
mbedtls_ecdh_init( &cli );
|
|
memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
|
|
|
|
TEST_ASSERT( mbedtls_ecdh_setup( &srv, id ) == 0 );
|
|
|
|
memset( buf, 0x00, sizeof( buf ) ); vbuf = buf;
|
|
TEST_ASSERT( mbedtls_ecdh_make_params( &srv, &len, buf, 1000,
|
|
&rnd_pseudo_rand, &rnd_info ) == 0 );
|
|
TEST_ASSERT( mbedtls_ecdh_read_params( &cli, &vbuf, buf + len ) == 0 );
|
|
|
|
memset( buf, 0x00, sizeof( buf ) );
|
|
TEST_ASSERT( mbedtls_ecdh_make_public( &cli, &len, buf, 1000,
|
|
&rnd_pseudo_rand, &rnd_info ) == 0 );
|
|
TEST_ASSERT( mbedtls_ecdh_read_public( &srv, buf, len ) == 0 );
|
|
|
|
TEST_ASSERT( mbedtls_ecdh_calc_secret( &srv, &len, buf, 1000,
|
|
&rnd_pseudo_rand, &rnd_info ) == 0 );
|
|
TEST_ASSERT( mbedtls_ecdh_calc_secret( &cli, &res_len, res_buf, 1000,
|
|
NULL, NULL ) == 0 );
|
|
TEST_ASSERT( len == res_len );
|
|
TEST_ASSERT( memcmp( buf, res_buf, len ) == 0 );
|
|
|
|
exit:
|
|
mbedtls_ecdh_free( &srv );
|
|
mbedtls_ecdh_free( &cli );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
|
|
void ecdh_restart( int id, char *dA_str, char *dB_str, char *z_str,
|
|
int enable, int max_ops, int min_restart, int max_restart )
|
|
{
|
|
int ret;
|
|
mbedtls_ecdh_context srv, cli;
|
|
unsigned char buf[1000];
|
|
const unsigned char *vbuf;
|
|
size_t len;
|
|
unsigned char z[MBEDTLS_ECP_MAX_BYTES];
|
|
size_t z_len;
|
|
unsigned char rnd_buf_A[MBEDTLS_ECP_MAX_BYTES];
|
|
unsigned char rnd_buf_B[MBEDTLS_ECP_MAX_BYTES];
|
|
rnd_buf_info rnd_info_A, rnd_info_B;
|
|
int cnt_restart;
|
|
mbedtls_ecp_group grp;
|
|
|
|
mbedtls_ecp_group_init( &grp );
|
|
mbedtls_ecdh_init( &srv );
|
|
mbedtls_ecdh_init( &cli );
|
|
|
|
z_len = unhexify( z, z_str );
|
|
|
|
rnd_info_A.buf = rnd_buf_A;
|
|
rnd_info_A.length = unhexify( rnd_buf_A, dA_str );
|
|
|
|
rnd_info_B.buf = rnd_buf_B;
|
|
rnd_info_B.length = unhexify( rnd_buf_B, dB_str );
|
|
|
|
/* The ECDH context is not guaranteed ot have an mbedtls_ecp_group structure
|
|
* in every configuration, therefore we load it separately. */
|
|
TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
|
|
|
|
/* Otherwise we would have to fix the random buffer,
|
|
* as in ecdh_primitive_testvec. */
|
|
TEST_ASSERT( grp.nbits % 8 == 0 );
|
|
|
|
TEST_ASSERT( mbedtls_ecdh_setup( &srv, id ) == 0 );
|
|
|
|
/* set up restart parameters */
|
|
mbedtls_ecp_set_max_ops( max_ops );
|
|
|
|
if( enable )
|
|
{
|
|
mbedtls_ecdh_enable_restart( &srv );
|
|
mbedtls_ecdh_enable_restart( &cli );
|
|
}
|
|
|
|
/* server writes its parameters */
|
|
memset( buf, 0x00, sizeof( buf ) );
|
|
len = 0;
|
|
|
|
cnt_restart = 0;
|
|
do {
|
|
ret = mbedtls_ecdh_make_params( &srv, &len, buf, sizeof( buf ),
|
|
rnd_buffer_rand, &rnd_info_A );
|
|
} while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart );
|
|
|
|
TEST_ASSERT( ret == 0 );
|
|
TEST_ASSERT( cnt_restart >= min_restart );
|
|
TEST_ASSERT( cnt_restart <= max_restart );
|
|
|
|
/* client read server params */
|
|
vbuf = buf;
|
|
TEST_ASSERT( mbedtls_ecdh_read_params( &cli, &vbuf, buf + len ) == 0 );
|
|
|
|
/* client writes its key share */
|
|
memset( buf, 0x00, sizeof( buf ) );
|
|
len = 0;
|
|
|
|
cnt_restart = 0;
|
|
do {
|
|
ret = mbedtls_ecdh_make_public( &cli, &len, buf, sizeof( buf ),
|
|
rnd_buffer_rand, &rnd_info_B );
|
|
} while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart );
|
|
|
|
TEST_ASSERT( ret == 0 );
|
|
TEST_ASSERT( cnt_restart >= min_restart );
|
|
TEST_ASSERT( cnt_restart <= max_restart );
|
|
|
|
/* server reads client key share */
|
|
TEST_ASSERT( mbedtls_ecdh_read_public( &srv, buf, len ) == 0 );
|
|
|
|
/* server computes shared secret */
|
|
memset( buf, 0, sizeof( buf ) );
|
|
len = 0;
|
|
|
|
cnt_restart = 0;
|
|
do {
|
|
ret = mbedtls_ecdh_calc_secret( &srv, &len, buf, sizeof( buf ),
|
|
NULL, NULL );
|
|
} while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart );
|
|
|
|
TEST_ASSERT( ret == 0 );
|
|
TEST_ASSERT( cnt_restart >= min_restart );
|
|
TEST_ASSERT( cnt_restart <= max_restart );
|
|
|
|
TEST_ASSERT( len == z_len );
|
|
TEST_ASSERT( memcmp( buf, z, len ) == 0 );
|
|
|
|
/* client computes shared secret */
|
|
memset( buf, 0, sizeof( buf ) );
|
|
len = 0;
|
|
|
|
cnt_restart = 0;
|
|
do {
|
|
ret = mbedtls_ecdh_calc_secret( &cli, &len, buf, sizeof( buf ),
|
|
NULL, NULL );
|
|
} while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart );
|
|
|
|
TEST_ASSERT( ret == 0 );
|
|
TEST_ASSERT( cnt_restart >= min_restart );
|
|
TEST_ASSERT( cnt_restart <= max_restart );
|
|
|
|
TEST_ASSERT( len == z_len );
|
|
TEST_ASSERT( memcmp( buf, z, len ) == 0 );
|
|
|
|
exit:
|
|
mbedtls_ecp_group_free( &grp );
|
|
mbedtls_ecdh_free( &srv );
|
|
mbedtls_ecdh_free( &cli );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE depends_on:MBEDTLS_ECDH_LEGACY_CONTEXT */
|
|
void ecdh_exchange_legacy( int id )
|
|
{
|
|
mbedtls_ecdh_context srv, cli;
|
|
unsigned char buf[1000];
|
|
const unsigned char *vbuf;
|
|
size_t len;
|
|
|
|
rnd_pseudo_info rnd_info;
|
|
|
|
mbedtls_ecdh_init( &srv );
|
|
mbedtls_ecdh_init( &cli );
|
|
memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
|
|
|
|
TEST_ASSERT( mbedtls_ecp_group_load( &srv.grp, id ) == 0 );
|
|
|
|
memset( buf, 0x00, sizeof( buf ) ); vbuf = buf;
|
|
TEST_ASSERT( mbedtls_ecdh_make_params( &srv, &len, buf, 1000,
|
|
&rnd_pseudo_rand, &rnd_info ) == 0 );
|
|
TEST_ASSERT( mbedtls_ecdh_read_params( &cli, &vbuf, buf + len ) == 0 );
|
|
|
|
memset( buf, 0x00, sizeof( buf ) );
|
|
TEST_ASSERT( mbedtls_ecdh_make_public( &cli, &len, buf, 1000,
|
|
&rnd_pseudo_rand, &rnd_info ) == 0 );
|
|
TEST_ASSERT( mbedtls_ecdh_read_public( &srv, buf, len ) == 0 );
|
|
|
|
TEST_ASSERT( mbedtls_ecdh_calc_secret( &srv, &len, buf, 1000,
|
|
&rnd_pseudo_rand, &rnd_info ) == 0 );
|
|
TEST_ASSERT( mbedtls_ecdh_calc_secret( &cli, &len, buf, 1000, NULL,
|
|
NULL ) == 0 );
|
|
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &srv.z, &cli.z ) == 0 );
|
|
|
|
exit:
|
|
mbedtls_ecdh_free( &srv );
|
|
mbedtls_ecdh_free( &cli );
|
|
}
|
|
/* 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 */
|