mbedtls/tests/suites/test_suite_ecdh.function
Janos Follath 36c5f7fe9b ECDH: Hide context from tests
The tests for the ECDH key exchange that use the context accessed it
directly. This can't work with the new context, where we can't make any
assumptions about the implementation of the context. This commit works
around this problem and comes with the cost of allocating an extra
structures on the stack when executing the test.

One of the tests is testing an older interface for the sake of backward
compatibility. The new ECDH context is not backward compatible and this
test doesn't make any sense for it, therefore we skip this test in
non-legacy mode.
2018-12-06 12:22:46 +00:00

325 lines
11 KiB
Plaintext

/* BEGIN_HEADER */
#include "mbedtls/ecdh.h"
/* END_HEADER */
/* BEGIN_DEPENDENCIES
* depends_on:MBEDTLS_ECDH_C
* END_DEPENDENCIES
*/
/* 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 paramaters */
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 */