From e39ee8e0a2c3d451ac38158859ca8c75acea5efe Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 13 Apr 2021 21:23:25 +0200 Subject: [PATCH] MPI random test: use more iterations for small numbers In real life, min << N and the probability that mbedtls_mpi_random() fails to find a suitable value after 30 iterations is less than one in a billion. But at least for testing purposes, it's useful to not outright reject "silly" small values of N, and for such values, 30 iterations is not enough to have a good probability of success. Pick 250 iterations, which is enough for cases like (min=3, N=4), but not for cases like (min=255, N=256). Signed-off-by: Gilles Peskine --- library/bignum.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/library/bignum.c b/library/bignum.c index a995bbee1..244725ced 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -2460,7 +2460,7 @@ int mbedtls_mpi_random( mbedtls_mpi *X, { /* SEC1 3.2.1: Generate X such that 1 <= n < N */ int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - int count = 0; + int count; unsigned cmp = 0; size_t n_bits = mbedtls_mpi_bitlen( N ); size_t n_bytes = ( n_bits + 7 ) / 8; @@ -2470,6 +2470,28 @@ int mbedtls_mpi_random( mbedtls_mpi *X, if( mbedtls_mpi_cmp_int( N, min ) <= 0 ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + /* + * When min == 0, each try has at worst a probability 1/2 of failing + * (the msb has a probability 1/2 of being 0, and then the result will + * be < N), so after 30 tries failure probability is a most 2**(-30). + * + * When N is just below a power of 2, as is the case when generating + * a random point on most elliptic curves, 1 try is enough with + * overwhelming probability. When N is just above a power of 2, + * as when generating a random point on secp224k1, each try has + * a probability of failing that is almost 1/2. + * + * The probabilities are almost the same if min is nonzero but negligible + * compared to N. This is always the case when N is crypto-sized, but + * it's convenient to support small N for testing purposes. When N + * is small, use a higher repeat count, otherwise the probability of + * failure is macroscopic. + */ + if( n_bytes <= 4 ) + count = 250; + else + count = 30; + /* Ensure that target MPI has exactly the same number of limbs * as the upper bound, even if the upper bound has leading zeros. * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */ @@ -2493,18 +2515,7 @@ int mbedtls_mpi_random( mbedtls_mpi *X, MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) ); - /* - * Each try has at worst a probability 1/2 of failing (the msb has - * a probability 1/2 of being 0, and then the result will be < N), - * so after 30 tries failure probability is a most 2**(-30). - * - * When N is just below a power of 2, as is the case when generating - * a random point on most elliptic curves, 1 try is enough with - * overwhelming probability. When N is just above a power of 2, - * as when generating a random point on secp224k1, each try has - * a probability of failing that is almost 1/2. - */ - if( ++count > 30 ) + if( --count == 0 ) { ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; goto cleanup;