Commit f54be179 authored by Andy Polyakov's avatar Andy Polyakov
Browse files

Reserve option to use BN_mod_exp_mont_consttime in ECDSA.



Submitted by Shay Gueron, Intel Corp.
RT: 3149

Reviewed-by: default avatarRich Salz <rsalz@openssl.org>
parent 902b30df
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -245,6 +245,12 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIG
 */
const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group);

/** Returns the montgomery data for order(Generator)
 *  \param  group  EC_GROUP object
 *  \return the currently used generator (possibly NULL).
*/
BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group);

/** Gets the order of a EC_GROUP
 *  \param  group  EC_GROUP object
 *  \param  order  BIGNUM to which the order is copied
+11 −0
Original line number Diff line number Diff line
@@ -235,6 +235,8 @@ struct ec_group_st {
	void *field_data1; /* method-specific (e.g., Montgomery structure) */
	void *field_data2; /* method-specific */
	int (*field_mod_func)(BIGNUM *, const BIGNUM *, const BIGNUM *,	BN_CTX *); /* method-specific */

	BN_MONT_CTX *mont_data;    /* data for ECDSA inverse */
} /* EC_GROUP */;

struct ec_key_st {
@@ -444,3 +446,12 @@ void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array,
	void (*felem_contract)(void *out, const void *in));
void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, unsigned char *digit, unsigned char in);
#endif
int ec_precompute_mont_data(EC_GROUP *);

#ifdef ECP_NISTZ256_ASM
/** Returns GFp methods using montgomery multiplication, with x86-64 optimized
 * P256. See http://eprint.iacr.org/2013/816.
 *  \return  EC_METHOD object
 */
const EC_METHOD *EC_GFp_nistz256_method(void);
#endif
+71 −0
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
	ret->meth = meth;

	ret->extra_data = NULL;
	ret->mont_data = NULL;

	ret->generator = NULL;
	BN_init(&ret->order);
@@ -132,6 +133,9 @@ void EC_GROUP_free(EC_GROUP *group)

	EC_EX_DATA_free_all_data(&group->extra_data);

	if (group->mont_data)
		BN_MONT_CTX_free(group->mont_data);

	if (group->generator != NULL)
		EC_POINT_free(group->generator);
	BN_free(&group->order);
@@ -155,6 +159,9 @@ void EC_GROUP_clear_free(EC_GROUP *group)

	EC_EX_DATA_clear_free_all_data(&group->extra_data);

	if (group->mont_data)
		BN_MONT_CTX_free(group->mont_data);

	if (group->generator != NULL)
		EC_POINT_clear_free(group->generator);
	BN_clear_free(&group->order);
@@ -200,6 +207,25 @@ int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
			return 0;
		}

	if (src->mont_data != NULL)
		{
		if (dest->mont_data == NULL)
			{
			dest->mont_data = BN_MONT_CTX_new();
			if (dest->mont_data == NULL) return 0;
			}
		if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data)) return 0;
		}
	else
		{
		/* src->generator == NULL */
		if (dest->mont_data != NULL)
			{
			BN_MONT_CTX_free(dest->mont_data);
			dest->mont_data = NULL;
			}
		}

	if (src->generator != NULL)
		{
		if (dest->generator == NULL)
@@ -309,6 +335,11 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIG
	else
		BN_zero(&group->cofactor);

	/* We ignore the return value because some groups have an order with
	 * factors of two, which makes the Montgomery setup fail.
	 * |group->mont_data| will be NULL in this case. */
	ec_precompute_mont_data(group);

	return 1;
	}

@@ -318,6 +349,10 @@ const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
	return group->generator;
	}

BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group)
	{
	return group->mont_data;
	}

int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
	{
@@ -1097,3 +1132,39 @@ int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
	else
		return 0; /* cannot tell whether precomputation has been performed */
	}

/* ec_precompute_mont_data sets |group->mont_data| from |group->order| and
 * returns one on success. On error it returns zero. */
int ec_precompute_mont_data(EC_GROUP *group)
	{
	BN_CTX *ctx = BN_CTX_new();
	int ret = 0;

	if (group->mont_data)
		{
		BN_MONT_CTX_free(group->mont_data);
		group->mont_data = NULL;
		}

	if (ctx == NULL)
		goto err;

	group->mont_data = BN_MONT_CTX_new();
	if (!group->mont_data)
		goto err;

	if (!BN_MONT_CTX_set(group->mont_data, &group->order, ctx))
		{
		BN_MONT_CTX_free(group->mont_data);
		group->mont_data = NULL;
		goto err;
		}

	ret = 1;

err:

	if (ctx)
		BN_CTX_free(ctx);
	return ret;
	}
+31 −5
Original line number Diff line number Diff line
@@ -219,11 +219,37 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
	while (BN_is_zero(r));

	/* compute the inverse of k */
	if (EC_GROUP_get_mont_data(group) != NULL)
		{
		/* We want inverse in constant time, therefore we utilize the
		 * fact order must be prime and use Fermats Little Theorem
		 * instead. */
		if (!BN_set_word(X, 2) )
			{
			ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
			goto err;
			}
		if (!BN_mod_sub(X, order, X, order, ctx))
			{
			ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
			goto err;
			}
		BN_set_flags(X, BN_FLG_CONSTTIME);
		if (!BN_mod_exp_mont_consttime(k, k, X, order, ctx, EC_GROUP_get_mont_data(group)))
			{
			ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
			goto err;
			}
		}
	else
		{
		if (!BN_mod_inverse(k, k, order, ctx))
			{
			ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
			goto err;	
			}
		}

	/* clear old values if necessary */
	if (*rp != NULL)
		BN_clear_free(*rp);