Skip to content

Commit 0c1a42a

Browse files
authored
Merge pull request #4611 from gilles-peskine-arm/random-range-uniformity-3.0
Fix non-uniform random generation in a range
2 parents f9f9cc2 + afb2bd2 commit 0c1a42a

19 files changed

+1037
-259
lines changed

ChangeLog.d/mpi_random.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Features
2+
* The new function mbedtls_mpi_random() generates a random value in a
3+
given range uniformly.

ChangeLog.d/random-range.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Security
2+
* Fix a bias in the generation of finite-field Diffie-Hellman-Merkle (DHM)
3+
private keys and of blinding values for DHM and elliptic curves (ECP)
4+
computations. Reported by FlorianF89 in #4245.

include/mbedtls/bignum.h

+38
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,44 @@ int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
871871
int (*f_rng)(void *, unsigned char *, size_t),
872872
void *p_rng );
873873

874+
/** Generate a random number uniformly in a range.
875+
*
876+
* This function generates a random number between \p min inclusive and
877+
* \p N exclusive.
878+
*
879+
* The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)
880+
* when the RNG is a suitably parametrized instance of HMAC_DRBG
881+
* and \p min is \c 1.
882+
*
883+
* \note There are `N - min` possible outputs. The lower bound
884+
* \p min can be reached, but the upper bound \p N cannot.
885+
*
886+
* \param X The destination MPI. This must point to an initialized MPI.
887+
* \param min The minimum value to return.
888+
* It must be nonnegative.
889+
* \param N The upper bound of the range, exclusive.
890+
* In other words, this is one plus the maximum value to return.
891+
* \p N must be strictly larger than \p min.
892+
* \param f_rng The RNG function to use. This must not be \c NULL.
893+
* \param p_rng The RNG parameter to be passed to \p f_rng.
894+
*
895+
* \return \c 0 if successful.
896+
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
897+
* \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p min or \p N is invalid
898+
* or if they are incompatible.
899+
* \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was
900+
* unable to find a suitable value within a limited number
901+
* of attempts. This has a negligible probability if \p N
902+
* is significantly larger than \p min, which is the case
903+
* for all usual cryptographic applications.
904+
* \return Another negative error code on failure.
905+
*/
906+
int mbedtls_mpi_random( mbedtls_mpi *X,
907+
mbedtls_mpi_sint min,
908+
const mbedtls_mpi *N,
909+
int (*f_rng)(void *, unsigned char *, size_t),
910+
void *p_rng );
911+
874912
/**
875913
* \brief Compute the greatest common divisor: G = gcd(A, B)
876914
*

library/bignum.c

+122-28
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,27 @@ int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
181181
return( 0 );
182182
}
183183

184+
/* Resize X to have exactly n limbs and set it to 0. */
185+
static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs )
186+
{
187+
if( limbs == 0 )
188+
{
189+
mbedtls_mpi_free( X );
190+
return( 0 );
191+
}
192+
else if( X->n == limbs )
193+
{
194+
memset( X->p, 0, limbs * ciL );
195+
X->s = 1;
196+
return( 0 );
197+
}
198+
else
199+
{
200+
mbedtls_mpi_free( X );
201+
return( mbedtls_mpi_grow( X, limbs ) );
202+
}
203+
}
204+
184205
/*
185206
* Copy the contents of Y into X
186207
*/
@@ -838,14 +859,7 @@ int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
838859
size_t const limbs = CHARS_TO_LIMBS( buflen );
839860

840861
/* Ensure that target MPI has exactly the necessary number of limbs */
841-
if( X->n != limbs )
842-
{
843-
mbedtls_mpi_free( X );
844-
mbedtls_mpi_init( X );
845-
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
846-
}
847-
848-
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
862+
MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
849863

850864
for( i = 0; i < buflen; i++ )
851865
X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
@@ -874,17 +888,11 @@ int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t bu
874888
MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
875889

876890
/* Ensure that target MPI has exactly the necessary number of limbs */
877-
if( X->n != limbs )
878-
{
879-
mbedtls_mpi_free( X );
880-
mbedtls_mpi_init( X );
881-
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
882-
}
883-
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
891+
MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
884892

885-
/* Avoid calling `memcpy` with NULL source argument,
893+
/* Avoid calling `memcpy` with NULL source or destination argument,
886894
* even if buflen is 0. */
887-
if( buf != NULL )
895+
if( buflen != 0 )
888896
{
889897
Xp = (unsigned char*) X->p;
890898
memcpy( Xp + overhead, buf, buflen );
@@ -2395,6 +2403,33 @@ int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B
23952403
return( ret );
23962404
}
23972405

2406+
/* Fill X with n_bytes random bytes.
2407+
* X must already have room for those bytes.
2408+
* The ordering of the bytes returned from the RNG is suitable for
2409+
* deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
2410+
* The size and sign of X are unchanged.
2411+
* n_bytes must not be 0.
2412+
*/
2413+
static int mpi_fill_random_internal(
2414+
mbedtls_mpi *X, size_t n_bytes,
2415+
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2416+
{
2417+
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2418+
const size_t limbs = CHARS_TO_LIMBS( n_bytes );
2419+
const size_t overhead = ( limbs * ciL ) - n_bytes;
2420+
2421+
if( X->n < limbs )
2422+
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2423+
2424+
memset( X->p, 0, overhead );
2425+
memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
2426+
MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
2427+
mpi_bigendian_to_host( X->p, limbs );
2428+
2429+
cleanup:
2430+
return( ret );
2431+
}
2432+
23982433
/*
23992434
* Fill X with size bytes of random.
24002435
*
@@ -2408,25 +2443,84 @@ int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
24082443
{
24092444
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
24102445
size_t const limbs = CHARS_TO_LIMBS( size );
2411-
size_t const overhead = ( limbs * ciL ) - size;
2412-
unsigned char *Xp;
24132446

24142447
MPI_VALIDATE_RET( X != NULL );
24152448
MPI_VALIDATE_RET( f_rng != NULL );
24162449

24172450
/* Ensure that target MPI has exactly the necessary number of limbs */
2418-
if( X->n != limbs )
2451+
MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
2452+
if( size == 0 )
2453+
return( 0 );
2454+
2455+
ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
2456+
2457+
cleanup:
2458+
return( ret );
2459+
}
2460+
2461+
int mbedtls_mpi_random( mbedtls_mpi *X,
2462+
mbedtls_mpi_sint min,
2463+
const mbedtls_mpi *N,
2464+
int (*f_rng)(void *, unsigned char *, size_t),
2465+
void *p_rng )
2466+
{
2467+
int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2468+
int count;
2469+
unsigned cmp = 0;
2470+
size_t n_bits = mbedtls_mpi_bitlen( N );
2471+
size_t n_bytes = ( n_bits + 7 ) / 8;
2472+
2473+
if( min < 0 )
2474+
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2475+
if( mbedtls_mpi_cmp_int( N, min ) <= 0 )
2476+
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2477+
2478+
/*
2479+
* When min == 0, each try has at worst a probability 1/2 of failing
2480+
* (the msb has a probability 1/2 of being 0, and then the result will
2481+
* be < N), so after 30 tries failure probability is a most 2**(-30).
2482+
*
2483+
* When N is just below a power of 2, as is the case when generating
2484+
* a random scalar on most elliptic curves, 1 try is enough with
2485+
* overwhelming probability. When N is just above a power of 2,
2486+
* as when generating a random scalar on secp224k1, each try has
2487+
* a probability of failing that is almost 1/2.
2488+
*
2489+
* The probabilities are almost the same if min is nonzero but negligible
2490+
* compared to N. This is always the case when N is crypto-sized, but
2491+
* it's convenient to support small N for testing purposes. When N
2492+
* is small, use a higher repeat count, otherwise the probability of
2493+
* failure is macroscopic.
2494+
*/
2495+
count = ( n_bytes > 4 ? 30 : 250 );
2496+
2497+
/* Ensure that target MPI has exactly the same number of limbs
2498+
* as the upper bound, even if the upper bound has leading zeros.
2499+
* This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
2500+
MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
2501+
2502+
/*
2503+
* Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2504+
* when f_rng is a suitably parametrized instance of HMAC_DRBG:
2505+
* - use the same byte ordering;
2506+
* - keep the leftmost n_bits bits of the generated octet string;
2507+
* - try until result is in the desired range.
2508+
* This also avoids any bias, which is especially important for ECDSA.
2509+
*/
2510+
do
24192511
{
2420-
mbedtls_mpi_free( X );
2421-
mbedtls_mpi_init( X );
2422-
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
2423-
}
2424-
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
2512+
MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
2513+
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
24252514

2426-
Xp = (unsigned char*) X->p;
2427-
MBEDTLS_MPI_CHK( f_rng( p_rng, Xp + overhead, size ) );
2515+
if( --count == 0 )
2516+
{
2517+
ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2518+
goto cleanup;
2519+
}
24282520

2429-
mpi_bigendian_to_host( X->p, limbs );
2521+
MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &cmp ) );
2522+
}
2523+
while( mbedtls_mpi_cmp_int( X, min ) < 0 || cmp != 1 );
24302524

24312525
cleanup:
24322526
return( ret );

0 commit comments

Comments
 (0)