summaryrefslogtreecommitdiffstats
path: root/crypto/ec
diff options
context:
space:
mode:
authorAndy Polyakov <appro@openssl.org>2014-09-12 00:13:20 +0200
committerAndy Polyakov <appro@openssl.org>2014-09-22 00:07:44 +0200
commit8aed2a7548362e88e84a7feb795a3a97e8395008 (patch)
tree63b547c414c388873b7955303ae2ad51bd0c1eb2 /crypto/ec
parentf7835e1c20836f286f00d6bcc69f154493e01475 (diff)
Reserve option to use BN_mod_exp_mont_consttime in ECDSA.
Submitted by Shay Gueron, Intel Corp. RT: 3149 Reviewed-by: Rich Salz <rsalz@openssl.org> (cherry picked from commit f54be179aa4cbbd944728771d7d59ed588158a12)
Diffstat (limited to 'crypto/ec')
-rw-r--r--crypto/ec/ec.h6
-rw-r--r--crypto/ec/ec_lcl.h11
-rw-r--r--crypto/ec/ec_lib.c71
3 files changed, 88 insertions, 0 deletions
diff --git a/crypto/ec/ec.h b/crypto/ec/ec.h
index 7ae8e8ad58..b8551c527e 100644
--- a/crypto/ec/ec.h
+++ b/crypto/ec/ec.h
@@ -243,6 +243,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
diff --git a/crypto/ec/ec_lcl.h b/crypto/ec/ec_lcl.h
index b0d48b6b5c..22b53d28a9 100644
--- a/crypto/ec/ec_lcl.h
+++ b/crypto/ec/ec_lcl.h
@@ -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
diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c
index e2c4741b5b..7fe31157ca 100644
--- a/crypto/ec/ec_lib.c
+++ b/crypto/ec/ec_lib.c
@@ -98,6 +98,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);
@@ -129,6 +130,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);
@@ -152,6 +156,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);
@@ -197,6 +204,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)
@@ -306,6 +332,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;
}
@@ -315,6 +346,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)
{
@@ -1094,3 +1129,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;
+ }