mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-08-08 17:42:09 +03:00
Merge pull request #4276 from gilles-peskine-arm/random-range-uniformity
Backport 2.x: Fix non-uniform random generation in a range
This commit is contained in:
152
library/bignum.c
152
library/bignum.c
@@ -181,6 +181,27 @@ int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Resize X to have exactly n limbs and set it to 0. */
|
||||
static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs )
|
||||
{
|
||||
if( limbs == 0 )
|
||||
{
|
||||
mbedtls_mpi_free( X );
|
||||
return( 0 );
|
||||
}
|
||||
else if( X->n == limbs )
|
||||
{
|
||||
memset( X->p, 0, limbs * ciL );
|
||||
X->s = 1;
|
||||
return( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
mbedtls_mpi_free( X );
|
||||
return( mbedtls_mpi_grow( X, limbs ) );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the contents of Y into X
|
||||
*/
|
||||
@@ -838,14 +859,7 @@ int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
|
||||
size_t const limbs = CHARS_TO_LIMBS( buflen );
|
||||
|
||||
/* Ensure that target MPI has exactly the necessary number of limbs */
|
||||
if( X->n != limbs )
|
||||
{
|
||||
mbedtls_mpi_free( X );
|
||||
mbedtls_mpi_init( X );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
|
||||
}
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
|
||||
|
||||
for( i = 0; i < buflen; i++ )
|
||||
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
|
||||
MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
|
||||
|
||||
/* Ensure that target MPI has exactly the necessary number of limbs */
|
||||
if( X->n != limbs )
|
||||
{
|
||||
mbedtls_mpi_free( X );
|
||||
mbedtls_mpi_init( X );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
|
||||
}
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
|
||||
|
||||
/* Avoid calling `memcpy` with NULL source argument,
|
||||
/* Avoid calling `memcpy` with NULL source or destination argument,
|
||||
* even if buflen is 0. */
|
||||
if( buf != NULL )
|
||||
if( buflen != 0 )
|
||||
{
|
||||
Xp = (unsigned char*) X->p;
|
||||
memcpy( Xp + overhead, buf, buflen );
|
||||
@@ -2395,6 +2403,33 @@ cleanup:
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/* Fill X with n_bytes random bytes.
|
||||
* X must already have room for those bytes.
|
||||
* The ordering of the bytes returned from the RNG is suitable for
|
||||
* deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
|
||||
* The size and sign of X are unchanged.
|
||||
* n_bytes must not be 0.
|
||||
*/
|
||||
static int mpi_fill_random_internal(
|
||||
mbedtls_mpi *X, size_t n_bytes,
|
||||
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
const size_t limbs = CHARS_TO_LIMBS( n_bytes );
|
||||
const size_t overhead = ( limbs * ciL ) - n_bytes;
|
||||
|
||||
if( X->n < limbs )
|
||||
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
|
||||
|
||||
memset( X->p, 0, overhead );
|
||||
memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
|
||||
MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
|
||||
mpi_bigendian_to_host( X->p, limbs );
|
||||
|
||||
cleanup:
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill X with size bytes of random.
|
||||
*
|
||||
@@ -2408,25 +2443,84 @@ int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
size_t const limbs = CHARS_TO_LIMBS( size );
|
||||
size_t const overhead = ( limbs * ciL ) - size;
|
||||
unsigned char *Xp;
|
||||
|
||||
MPI_VALIDATE_RET( X != NULL );
|
||||
MPI_VALIDATE_RET( f_rng != NULL );
|
||||
|
||||
/* Ensure that target MPI has exactly the necessary number of limbs */
|
||||
if( X->n != limbs )
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
|
||||
if( size == 0 )
|
||||
return( 0 );
|
||||
|
||||
ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
|
||||
|
||||
cleanup:
|
||||
return( ret );
|
||||
}
|
||||
|
||||
int mbedtls_mpi_random( mbedtls_mpi *X,
|
||||
mbedtls_mpi_sint min,
|
||||
const mbedtls_mpi *N,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||
int count;
|
||||
unsigned cmp = 0;
|
||||
size_t n_bits = mbedtls_mpi_bitlen( N );
|
||||
size_t n_bytes = ( n_bits + 7 ) / 8;
|
||||
|
||||
if( min < 0 )
|
||||
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
|
||||
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 scalar 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 scalar 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.
|
||||
*/
|
||||
count = ( n_bytes > 4 ? 30 : 250 );
|
||||
|
||||
/* 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. */
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
|
||||
|
||||
/*
|
||||
* Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
|
||||
* when f_rng is a suitably parametrized instance of HMAC_DRBG:
|
||||
* - use the same byte ordering;
|
||||
* - keep the leftmost n_bits bits of the generated octet string;
|
||||
* - try until result is in the desired range.
|
||||
* This also avoids any bias, which is especially important for ECDSA.
|
||||
*/
|
||||
do
|
||||
{
|
||||
mbedtls_mpi_free( X );
|
||||
mbedtls_mpi_init( X );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
|
||||
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 ) );
|
||||
|
||||
if( --count == 0 )
|
||||
{
|
||||
ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &cmp ) );
|
||||
}
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
|
||||
|
||||
Xp = (unsigned char*) X->p;
|
||||
MBEDTLS_MPI_CHK( f_rng( p_rng, Xp + overhead, size ) );
|
||||
|
||||
mpi_bigendian_to_host( X->p, limbs );
|
||||
while( mbedtls_mpi_cmp_int( X, min ) < 0 || cmp != 1 );
|
||||
|
||||
cleanup:
|
||||
return( ret );
|
||||
|
162
library/dhm.c
162
library/dhm.c
@@ -100,22 +100,21 @@ static int dhm_read_bignum( mbedtls_mpi *X,
|
||||
*/
|
||||
static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
|
||||
{
|
||||
mbedtls_mpi L, U;
|
||||
mbedtls_mpi U;
|
||||
int ret = 0;
|
||||
|
||||
mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U );
|
||||
mbedtls_mpi_init( &U );
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
|
||||
|
||||
if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 ||
|
||||
if( mbedtls_mpi_cmp_int( param, 2 ) < 0 ||
|
||||
mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
|
||||
{
|
||||
ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U );
|
||||
mbedtls_mpi_free( &U );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
@@ -151,38 +150,44 @@ int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup and write the ServerKeyExchange parameters
|
||||
* Pick a random R in the range [2, M-2] for blinding or key generation.
|
||||
*/
|
||||
int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
|
||||
unsigned char *output, size_t *olen,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
|
||||
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
|
||||
{
|
||||
int ret, count = 0;
|
||||
size_t n1, n2, n3;
|
||||
unsigned char *p;
|
||||
DHM_VALIDATE_RET( ctx != NULL );
|
||||
DHM_VALIDATE_RET( output != NULL );
|
||||
DHM_VALIDATE_RET( olen != NULL );
|
||||
DHM_VALIDATE_RET( f_rng != NULL );
|
||||
int ret;
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_random( R, 3, M, f_rng, p_rng ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( R, R, 1 ) );
|
||||
|
||||
cleanup:
|
||||
return( ret );
|
||||
}
|
||||
|
||||
static int dhm_make_common( mbedtls_dhm_context *ctx, int x_size,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
|
||||
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
|
||||
if( x_size < 0 )
|
||||
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
|
||||
|
||||
/*
|
||||
* Generate X as large as possible ( < P )
|
||||
*/
|
||||
do
|
||||
if( (unsigned) x_size < mbedtls_mpi_size( &ctx->P ) )
|
||||
{
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
|
||||
|
||||
while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
|
||||
|
||||
if( count++ > 10 )
|
||||
return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
|
||||
}
|
||||
while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
|
||||
else
|
||||
{
|
||||
/* Generate X as large as possible ( <= P - 2 ) */
|
||||
ret = dhm_random_below( &ctx->X, &ctx->P, f_rng, p_rng );
|
||||
if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
|
||||
return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate GX = G^X mod P
|
||||
@@ -193,8 +198,33 @@ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
|
||||
if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
cleanup:
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup and write the ServerKeyExchange parameters
|
||||
*/
|
||||
int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
|
||||
unsigned char *output, size_t *olen,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
int ret;
|
||||
size_t n1, n2, n3;
|
||||
unsigned char *p;
|
||||
DHM_VALIDATE_RET( ctx != NULL );
|
||||
DHM_VALIDATE_RET( output != NULL );
|
||||
DHM_VALIDATE_RET( olen != NULL );
|
||||
DHM_VALIDATE_RET( f_rng != NULL );
|
||||
|
||||
ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
|
||||
/*
|
||||
* export P, G, GX
|
||||
* Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
|
||||
* not required". We omit leading zeros for compactness.
|
||||
*/
|
||||
#define DHM_MPI_EXPORT( X, n ) \
|
||||
do { \
|
||||
@@ -220,11 +250,9 @@ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
|
||||
ctx->len = n1;
|
||||
|
||||
cleanup:
|
||||
|
||||
if( ret != 0 )
|
||||
return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret ) );
|
||||
|
||||
return( 0 );
|
||||
if( ret != 0 && ret > -128 )
|
||||
ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -276,7 +304,7 @@ int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
int ret, count = 0;
|
||||
int ret;
|
||||
DHM_VALIDATE_RET( ctx != NULL );
|
||||
DHM_VALIDATE_RET( output != NULL );
|
||||
DHM_VALIDATE_RET( f_rng != NULL );
|
||||
@@ -284,62 +312,17 @@ int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
|
||||
if( olen < 1 || olen > ctx->len )
|
||||
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
|
||||
|
||||
if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
|
||||
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
|
||||
|
||||
/*
|
||||
* generate X and calculate GX = G^X mod P
|
||||
*/
|
||||
do
|
||||
{
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
|
||||
|
||||
while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
|
||||
|
||||
if( count++ > 10 )
|
||||
return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
|
||||
}
|
||||
while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
|
||||
&ctx->P , &ctx->RP ) );
|
||||
|
||||
if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
|
||||
return( ret );
|
||||
ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
|
||||
if( ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED )
|
||||
return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
|
||||
|
||||
cleanup:
|
||||
|
||||
if( ret != 0 )
|
||||
return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret ) );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick a random R in the range [2, M) for blinding purposes
|
||||
*/
|
||||
static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
|
||||
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
|
||||
{
|
||||
int ret, count;
|
||||
|
||||
count = 0;
|
||||
do
|
||||
{
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) );
|
||||
|
||||
while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 )
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, 1 ) );
|
||||
|
||||
if( count++ > 10 )
|
||||
return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
|
||||
}
|
||||
while( mbedtls_mpi_cmp_int( R, 1 ) <= 0 );
|
||||
|
||||
cleanup:
|
||||
if( ret != 0 && ret > -128 )
|
||||
ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
@@ -390,7 +373,7 @@ static int dhm_update_blinding( mbedtls_dhm_context *ctx,
|
||||
* We need to generate blinding values from scratch
|
||||
*/
|
||||
|
||||
/* Vi = random( 2, P-1 ) */
|
||||
/* Vi = random( 2, P-2 ) */
|
||||
MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
|
||||
|
||||
/* Vf = Vi^-X mod P
|
||||
@@ -454,8 +437,9 @@ int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
|
||||
}
|
||||
|
||||
/* Output the secret without any leading zero byte. This is mandatory
|
||||
* for TLS per RFC 5246 §8.1.2. */
|
||||
*olen = mbedtls_mpi_size( &ctx->K );
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
|
||||
|
||||
cleanup:
|
||||
|
162
library/ecp.c
162
library/ecp.c
@@ -1701,26 +1701,11 @@ static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *p
|
||||
#else
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
mbedtls_mpi l, ll;
|
||||
int count = 0;
|
||||
size_t p_size = ( grp->pbits + 7 ) / 8;
|
||||
|
||||
mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
|
||||
|
||||
/* Generate l such that 1 < l < p */
|
||||
do
|
||||
{
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
|
||||
|
||||
while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
|
||||
|
||||
if( count++ > 10 )
|
||||
{
|
||||
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_random( &l, 2, &grp->P, f_rng, p_rng ) );
|
||||
|
||||
/* Z = l * Z */
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Z, &pt->Z, &l ) );
|
||||
@@ -1736,6 +1721,8 @@ static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *p
|
||||
cleanup:
|
||||
mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
|
||||
|
||||
if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
|
||||
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
|
||||
return( ret );
|
||||
#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) */
|
||||
}
|
||||
@@ -2485,25 +2472,10 @@ static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P
|
||||
#else
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
mbedtls_mpi l;
|
||||
int count = 0;
|
||||
size_t p_size = ( grp->pbits + 7 ) / 8;
|
||||
mbedtls_mpi_init( &l );
|
||||
|
||||
/* Generate l such that 1 < l < p */
|
||||
do
|
||||
{
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
|
||||
|
||||
while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
|
||||
|
||||
if( count++ > 10 )
|
||||
{
|
||||
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_random( &l, 2, &grp->P, f_rng, p_rng ) );
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->X, &P->X, &l ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->Z, &P->Z, &l ) );
|
||||
@@ -2511,6 +2483,8 @@ static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P
|
||||
cleanup:
|
||||
mbedtls_mpi_free( &l );
|
||||
|
||||
if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
|
||||
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
|
||||
return( ret );
|
||||
#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) */
|
||||
}
|
||||
@@ -3040,6 +3014,56 @@ int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp,
|
||||
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
|
||||
MBEDTLS_STATIC_TESTABLE
|
||||
int mbedtls_ecp_gen_privkey_mx( size_t high_bit,
|
||||
mbedtls_mpi *d,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
size_t n_random_bytes = high_bit / 8 + 1;
|
||||
|
||||
/* [Curve25519] page 5 */
|
||||
/* Generate a (high_bit+1)-bit random number by generating just enough
|
||||
* random bytes, then shifting out extra bits from the top (necessary
|
||||
* when (high_bit+1) is not a multiple of 8). */
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_random_bytes,
|
||||
f_rng, p_rng ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_random_bytes - high_bit - 1 ) );
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, high_bit, 1 ) );
|
||||
|
||||
/* Make sure the last two bits are unset for Curve448, three bits for
|
||||
Curve25519 */
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
|
||||
if( high_bit == 254 )
|
||||
{
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
|
||||
}
|
||||
|
||||
cleanup:
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
|
||||
|
||||
#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
|
||||
static int mbedtls_ecp_gen_privkey_sw(
|
||||
const mbedtls_mpi *N, mbedtls_mpi *d,
|
||||
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
|
||||
{
|
||||
int ret = mbedtls_mpi_random( d, 1, N, f_rng, p_rng );
|
||||
switch( ret )
|
||||
{
|
||||
case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE:
|
||||
return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
|
||||
default:
|
||||
return( ret );
|
||||
}
|
||||
}
|
||||
#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
|
||||
|
||||
/*
|
||||
* Generate a private key
|
||||
*/
|
||||
@@ -3048,89 +3072,21 @@ int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
size_t n_size;
|
||||
|
||||
ECP_VALIDATE_RET( grp != NULL );
|
||||
ECP_VALIDATE_RET( d != NULL );
|
||||
ECP_VALIDATE_RET( f_rng != NULL );
|
||||
|
||||
n_size = ( grp->nbits + 7 ) / 8;
|
||||
|
||||
#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
|
||||
if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
|
||||
{
|
||||
/* [M225] page 5 */
|
||||
size_t b;
|
||||
|
||||
do {
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
|
||||
} while( mbedtls_mpi_bitlen( d ) == 0);
|
||||
|
||||
/* Make sure the most significant bit is nbits */
|
||||
b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
|
||||
if( b > grp->nbits )
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
|
||||
else
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
|
||||
|
||||
/* Make sure the last two bits are unset for Curve448, three bits for
|
||||
Curve25519 */
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
|
||||
if( grp->nbits == 254 )
|
||||
{
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
|
||||
}
|
||||
}
|
||||
return( mbedtls_ecp_gen_privkey_mx( grp->nbits, d, f_rng, p_rng ) );
|
||||
#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
|
||||
|
||||
#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
|
||||
if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
|
||||
{
|
||||
/* SEC1 3.2.1: Generate d such that 1 <= n < N */
|
||||
int count = 0;
|
||||
unsigned cmp = 0;
|
||||
|
||||
/*
|
||||
* Match the procedure given in RFC 6979 (deterministic ECDSA):
|
||||
* - use the same byte ordering;
|
||||
* - keep the leftmost nbits bits of the generated octet string;
|
||||
* - try until result is in the desired range.
|
||||
* This also avoids any biais, which is especially important for ECDSA.
|
||||
*/
|
||||
do
|
||||
{
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
|
||||
|
||||
/*
|
||||
* 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).
|
||||
*
|
||||
* For most curves, 1 try is enough with overwhelming probability,
|
||||
* since N starts with a lot of 1s in binary, but some curves
|
||||
* such as secp224k1 are actually very close to the worst case.
|
||||
*/
|
||||
if( ++count > 30 )
|
||||
{
|
||||
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
|
||||
if( ret != 0 )
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
|
||||
}
|
||||
return( mbedtls_ecp_gen_privkey_sw( &grp->N, d, f_rng, p_rng ) );
|
||||
#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
|
||||
|
||||
cleanup:
|
||||
return( ret );
|
||||
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#define MBEDTLS_ECP_INVASIVE_H
|
||||
|
||||
#include "common.h"
|
||||
#include "mbedtls/bignum.h"
|
||||
#include "mbedtls/ecp.h"
|
||||
|
||||
#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_ECP_C)
|
||||
@@ -46,6 +47,35 @@
|
||||
void mbedtls_ecp_fix_negative( mbedtls_mpi *N, signed char c, size_t bits );
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
|
||||
/** Generate a private key on a Montgomery curve (Curve25519 or Curve448).
|
||||
*
|
||||
* This function implements key generation for the set of secret keys
|
||||
* specified in [Curve25519] p. 5 and in [Curve448]. The resulting value
|
||||
* has the lower bits masked but is not necessarily canonical.
|
||||
*
|
||||
* \note - [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf
|
||||
* - [RFC7748] https://tools.ietf.org/html/rfc7748
|
||||
*
|
||||
* \p high_bit The position of the high-order bit of the key to generate.
|
||||
* This is the bit-size of the key minus 1:
|
||||
* 254 for Curve25519 or 447 for Curve448.
|
||||
* \param d The randomly generated key. This is a number of size
|
||||
* exactly \p n_bits + 1 bits, with the least significant bits
|
||||
* masked as specified in [Curve25519] and in [RFC7748] §5.
|
||||
* \param f_rng The RNG function.
|
||||
* \param p_rng The RNG context to be passed to \p f_rng.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return \c MBEDTLS_ERR_ECP_xxx or MBEDTLS_ERR_MPI_xxx on failure.
|
||||
*/
|
||||
int mbedtls_ecp_gen_privkey_mx( size_t n_bits,
|
||||
mbedtls_mpi *d,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng );
|
||||
|
||||
#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
|
||||
|
||||
#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_ECP_C */
|
||||
|
||||
#endif /* MBEDTLS_ECP_INVASIVE_H */
|
||||
|
Reference in New Issue
Block a user