提交 f54be179 编写于 作者: A Andy Polyakov

Reserve option to use BN_mod_exp_mont_consttime in ECDSA.

Submitted by Shay Gueron, Intel Corp.
RT: 3149
Reviewed-by: NRich Salz <rsalz@openssl.org>
上级 902b30df
...@@ -245,6 +245,12 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIG ...@@ -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); 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 /** Gets the order of a EC_GROUP
* \param group EC_GROUP object * \param group EC_GROUP object
* \param order BIGNUM to which the order is copied * \param order BIGNUM to which the order is copied
......
...@@ -235,6 +235,8 @@ struct ec_group_st { ...@@ -235,6 +235,8 @@ struct ec_group_st {
void *field_data1; /* method-specific (e.g., Montgomery structure) */ void *field_data1; /* method-specific (e.g., Montgomery structure) */
void *field_data2; /* method-specific */ void *field_data2; /* method-specific */
int (*field_mod_func)(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); /* 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 */; } /* EC_GROUP */;
struct ec_key_st { struct ec_key_st {
...@@ -444,3 +446,12 @@ void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array, ...@@ -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 (*felem_contract)(void *out, const void *in));
void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, unsigned char *digit, unsigned char in); void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, unsigned char *digit, unsigned char in);
#endif #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
...@@ -101,6 +101,7 @@ EC_GROUP *EC_GROUP_new(const EC_METHOD *meth) ...@@ -101,6 +101,7 @@ EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
ret->meth = meth; ret->meth = meth;
ret->extra_data = NULL; ret->extra_data = NULL;
ret->mont_data = NULL;
ret->generator = NULL; ret->generator = NULL;
BN_init(&ret->order); BN_init(&ret->order);
...@@ -132,6 +133,9 @@ void EC_GROUP_free(EC_GROUP *group) ...@@ -132,6 +133,9 @@ void EC_GROUP_free(EC_GROUP *group)
EC_EX_DATA_free_all_data(&group->extra_data); EC_EX_DATA_free_all_data(&group->extra_data);
if (group->mont_data)
BN_MONT_CTX_free(group->mont_data);
if (group->generator != NULL) if (group->generator != NULL)
EC_POINT_free(group->generator); EC_POINT_free(group->generator);
BN_free(&group->order); BN_free(&group->order);
...@@ -155,6 +159,9 @@ void EC_GROUP_clear_free(EC_GROUP *group) ...@@ -155,6 +159,9 @@ void EC_GROUP_clear_free(EC_GROUP *group)
EC_EX_DATA_clear_free_all_data(&group->extra_data); 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) if (group->generator != NULL)
EC_POINT_clear_free(group->generator); EC_POINT_clear_free(group->generator);
BN_clear_free(&group->order); BN_clear_free(&group->order);
...@@ -200,6 +207,25 @@ int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) ...@@ -200,6 +207,25 @@ int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
return 0; 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 (src->generator != NULL)
{ {
if (dest->generator == NULL) if (dest->generator == NULL)
...@@ -309,6 +335,11 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIG ...@@ -309,6 +335,11 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIG
else else
BN_zero(&group->cofactor); 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; return 1;
} }
...@@ -318,6 +349,10 @@ const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) ...@@ -318,6 +349,10 @@ const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
return group->generator; 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) 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) ...@@ -1097,3 +1132,39 @@ int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
else else
return 0; /* cannot tell whether precomputation has been performed */ 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;
}
...@@ -219,11 +219,37 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, ...@@ -219,11 +219,37 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
while (BN_is_zero(r)); while (BN_is_zero(r));
/* compute the inverse of k */ /* compute the inverse of k */
if (!BN_mod_inverse(k, k, order, ctx)) if (EC_GROUP_get_mont_data(group) != NULL)
{ {
ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); /* We want inverse in constant time, therefore we utilize the
goto err; * 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 */ /* clear old values if necessary */
if (*rp != NULL) if (*rp != NULL)
BN_clear_free(*rp); BN_clear_free(*rp);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册