diff --git a/library/bignum_mod.c b/library/bignum_mod.c index 0057ebae2..3eef4e700 100644 --- a/library/bignum_mod.c +++ b/library/bignum_mod.c @@ -214,6 +214,17 @@ int mbedtls_mpi_mod_add( mbedtls_mpi_mod_residue *X, /* BEGIN MERGE SLOT 6 */ +int mbedtls_mpi_mod_random( mbedtls_mpi_mod_residue *X, + mbedtls_mpi_uint min, + const mbedtls_mpi_mod_modulus *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + if( X->limbs != N->limbs ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + return( mbedtls_mpi_mod_raw_random( X->p, min, N, f_rng, p_rng ) ); +} + /* END MERGE SLOT 6 */ /* BEGIN MERGE SLOT 7 */ diff --git a/library/bignum_mod.h b/library/bignum_mod.h index f089f650e..bf00a36fc 100644 --- a/library/bignum_mod.h +++ b/library/bignum_mod.h @@ -290,6 +290,39 @@ int mbedtls_mpi_mod_add( mbedtls_mpi_mod_residue *X, /* BEGIN MERGE SLOT 6 */ +/** Generate a random number uniformly in a range. + * + * This function generates a random number between \p min inclusive and + * \p N exclusive. + * + * The procedure complies with RFC 6979 ยง3.3 (deterministic ECDSA) + * when the RNG is a suitably parametrized instance of HMAC_DRBG + * and \p min is \c 1. + * + * \note There are `N - min` possible outputs. The lower bound + * \p min can be reached, but the upper bound \p N cannot. + * + * \param X The destination residue. + * \param min The minimum value to return. It must be strictly smaller + * than \b N. + * \param N The modulus. + * This is the upper bound of the output range, exclusive. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was + * unable to find a suitable value within a limited number + * of attempts. This has a negligible probability if \p N + * is significantly larger than \p min, which is the case + * for all usual cryptographic applications. + */ +int mbedtls_mpi_mod_random( mbedtls_mpi_mod_residue *X, + mbedtls_mpi_uint min, + const mbedtls_mpi_mod_modulus *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + /* END MERGE SLOT 6 */ /* BEGIN MERGE SLOT 7 */ diff --git a/tests/suites/test_suite_bignum_random.function b/tests/suites/test_suite_bignum_random.function index 5064a62d0..4ee26adb7 100644 --- a/tests/suites/test_suite_bignum_random.function +++ b/tests/suites/test_suite_bignum_random.function @@ -169,8 +169,12 @@ void mpi_mod_random_values( int min, char *max_hex ) 0, 0}; mbedtls_test_rnd_pseudo_info rnd_mod_raw; memcpy( &rnd_mod_raw, &rnd_core, sizeof( rnd_core ) ); + mbedtls_test_rnd_pseudo_info rnd_mod; + memcpy( &rnd_mod, &rnd_core, sizeof( rnd_core ) ); mbedtls_mpi_uint *R_core = NULL; mbedtls_mpi_uint *R_mod_raw = NULL; + mbedtls_mpi_uint *R_mod_digits = NULL; + mbedtls_mpi_mod_residue R_mod; mbedtls_mpi_mod_modulus N; mbedtls_mpi_mod_modulus_init( &N ); @@ -179,6 +183,10 @@ void mpi_mod_random_values( int min, char *max_hex ) 0 ); ASSERT_ALLOC( R_core, N.limbs ); ASSERT_ALLOC( R_mod_raw, N.limbs ); + ASSERT_ALLOC( R_mod_digits, N.limbs ); + TEST_EQUAL( mbedtls_mpi_mod_residue_setup( &R_mod, &N, + R_mod_digits, N.limbs ), + 0 ); /* Call the core and mod random() functions with the same random stream. */ int core_ret = mbedtls_mpi_core_random( R_core, @@ -189,15 +197,23 @@ void mpi_mod_random_values( int min, char *max_hex ) min, &N, mbedtls_test_rnd_pseudo_rand, &rnd_mod_raw ); + int mod_ret = mbedtls_mpi_mod_random( &R_mod, + min, &N, + mbedtls_test_rnd_pseudo_rand, + &rnd_mod ); /* They must return the same status, and, on success, output the * same number, with the same limb count. */ TEST_EQUAL( core_ret, mod_raw_ret ); + TEST_EQUAL( core_ret, mod_ret ); if( core_ret == 0 ) { TEST_EQUAL( mbedtls_mpi_mod_raw_from_mont_rep( R_mod_raw, &N ), 0 ); ASSERT_COMPARE( R_core, N.limbs * ciL, R_mod_raw, N.limbs * ciL ); + TEST_EQUAL( mbedtls_mpi_mod_raw_from_mont_rep( R_mod_digits, &N ), 0 ); + ASSERT_COMPARE( R_core, N.limbs * ciL, + R_mod_digits, N.limbs * ciL ); } /* Also check that they have consumed the RNG in the same way. */ @@ -206,11 +222,14 @@ void mpi_mod_random_values( int min, char *max_hex ) * field-by-field comparison. */ ASSERT_COMPARE( &rnd_core, sizeof( rnd_core ), &rnd_mod_raw, sizeof( rnd_mod_raw ) ); + ASSERT_COMPARE( &rnd_core, sizeof( rnd_core ), + &rnd_mod, sizeof( rnd_mod ) ); exit: mbedtls_test_mpi_mod_modulus_free_with_limbs( &N ); mbedtls_free( R_core ); mbedtls_free( R_mod_raw ); + mbedtls_free( R_mod_digits ); } /* END_CASE */