diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index 2d20693b60..6c52f9622f 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -309,6 +309,22 @@ int ecp_sub( const ecp_group *grp, ecp_point *R, int ecp_mul( const ecp_group *grp, ecp_point *R, const mpi *m, const ecp_point *P ); +/** + * \brief Generate a keypair + * + * \param grp ECP group + * \param d Destination MPI (secret part) + * \param Q Destination point (public part) + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code + */ +int ecp_gen_keypair( const ecp_group *grp, mpi *d, ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + /** * \brief Checkup routine * diff --git a/library/ecp.c b/library/ecp.c index 119c75470d..9153f11ade 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1127,6 +1127,33 @@ cleanup: return( ret ); } +/* + * Generate a keypair (SEC1 3.2.1) + */ +int ecp_gen_keypair( const ecp_group *grp, mpi *d, ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int count = 0; + size_t n_size = (grp->nbits + 7) / 8; + + /* + * Generate d such that 1 <= n < N + */ + do + { + mpi_fill_random( d, n_size, f_rng, p_rng ); + + while( mpi_cmp_mpi( d, &grp->N ) >= 0 ) + mpi_shift_r( d, 1 ); + + if( count++ > 10 ) + return( POLARSSL_ERR_ECP_GENERIC ); + } + while( mpi_cmp_int( d, 1 ) < 0 ); + + return( ecp_mul( grp, Q, d, &grp->G ) ); +} #if defined(POLARSSL_SELF_TEST) diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 605af820e4..08a5e2bc7c 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -184,6 +184,9 @@ ecp_read_binary:SECP192R1:"0548d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ce ECP read binary #6 (non-zero, OK) ecp_read_binary:SECP192R1:"0448d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":UNCOMPRESSED:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":0 +ECP gen keypair +ecp_gen_keypair:SECP192R1 + ECP mod p192 readable ecp_fast_mod:SECP192R1:"000000000000010500000000000001040000000000000103000000000000010200000000000001010000000000000100" diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index fdd3da2a96..290b786def 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -295,6 +295,33 @@ ecp_read_binary:id:input:format:x:y:z:ret } END_CASE +BEGIN_CASE +ecp_gen_keypair:id +{ + ecp_group grp; + ecp_point Q; + mpi d; + rnd_pseudo_info rnd_info; + + ecp_group_init( &grp ); + ecp_point_init( &Q ); + mpi_init( &d ); + memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) ); + + TEST_ASSERT( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_{id} ) == 0 ); + + TEST_ASSERT( ecp_gen_keypair( &grp, &d, &Q, &rnd_pseudo_rand, &rnd_info ) + == 0 ); + + TEST_ASSERT( mpi_cmp_mpi( &d, &grp.N ) < 0 ); + TEST_ASSERT( mpi_cmp_int( &d, 1 ) >= 0 ); + + ecp_group_free( &grp ); + ecp_point_free( &Q ); + mpi_free( &d ); +} +END_CASE + BEGIN_CASE ecp_selftest: {