Refcount EC_GROUP.
I really need to resurrect the CL to make them entirely static
(https://crbug.com/boringssl/20), but, in the meantime, to make
replacing the EC_METHOD pointer in EC_POINT with EC_GROUP not
*completely* insane, make them refcounted.
OpenSSL did not do this because their EC_GROUPs are mutable
(EC_GROUP_set_asn1_flag and EC_GROUP_set_point_conversion_form). Ours
are immutable but for the two-function dance around custom curves (more
of OpenSSL's habit of making their objects too complex), which is good
enough to refcount.
Change-Id: I3650993737a97da0ddcf0e5fb7a15876e724cadc
Reviewed-on: https://boringssl-review.googlesource.com/22244
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/crypto/fipsmodule/ec/ec.c b/crypto/fipsmodule/ec/ec.c
index 4e8f2d2..7caa5d8 100644
--- a/crypto/fipsmodule/ec/ec.c
+++ b/crypto/fipsmodule/ec/ec.c
@@ -354,6 +354,7 @@
}
OPENSSL_memset(ret, 0, sizeof(EC_GROUP));
+ ret->references = 1;
ret->meth = meth;
BN_init(&ret->order);
@@ -500,11 +501,12 @@
}
void EC_GROUP_free(EC_GROUP *group) {
- if (!group) {
+ if (!group ||
+ !CRYPTO_refcount_dec_and_test_zero(&group->references)) {
return;
}
- if (group->meth->group_finish != 0) {
+ if (group->meth->group_finish != NULL) {
group->meth->group_finish(group);
}
@@ -523,36 +525,11 @@
return NULL;
}
- if (a->meth->group_copy == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- return NULL;
- }
-
- EC_GROUP *ret = ec_group_new(a->meth);
- if (ret == NULL) {
- return NULL;
- }
-
- ret->order_mont = a->order_mont;
- ret->curve_name = a->curve_name;
-
- if (a->generator != NULL) {
- ret->generator = EC_POINT_dup(a->generator, ret);
- if (ret->generator == NULL) {
- goto err;
- }
- }
-
- if (!BN_copy(&ret->order, &a->order) ||
- !ret->meth->group_copy(ret, a)) {
- goto err;
- }
-
- return ret;
-
-err:
- EC_GROUP_free(ret);
- return NULL;
+ // Groups are logically immutable (but for |EC_GROUP_set_generator| which must
+ // be called early on), so we simply take a reference.
+ EC_GROUP *group = (EC_GROUP *)a;
+ CRYPTO_refcount_inc(&group->references);
+ return group;
}
int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ignored) {
diff --git a/crypto/fipsmodule/ec/ec_montgomery.c b/crypto/fipsmodule/ec/ec_montgomery.c
index c5f240b..6670b84 100644
--- a/crypto/fipsmodule/ec/ec_montgomery.c
+++ b/crypto/fipsmodule/ec/ec_montgomery.c
@@ -90,32 +90,6 @@
ec_GFp_simple_group_finish(group);
}
-int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
- BN_MONT_CTX_free(dest->mont);
- dest->mont = NULL;
-
- if (!ec_GFp_simple_group_copy(dest, src)) {
- return 0;
- }
-
- if (src->mont != NULL) {
- dest->mont = BN_MONT_CTX_new();
- if (dest->mont == NULL) {
- return 0;
- }
- if (!BN_MONT_CTX_copy(dest->mont, src->mont)) {
- goto err;
- }
- }
-
- return 1;
-
-err:
- BN_MONT_CTX_free(dest->mont);
- dest->mont = NULL;
- return 0;
-}
-
int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
BN_CTX *new_ctx = NULL;
@@ -293,7 +267,6 @@
DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_mont_method) {
out->group_init = ec_GFp_mont_group_init;
out->group_finish = ec_GFp_mont_group_finish;
- out->group_copy = ec_GFp_mont_group_copy;
out->group_set_curve = ec_GFp_mont_group_set_curve;
out->point_get_affine_coordinates = ec_GFp_mont_point_get_affine_coordinates;
out->mul = ec_wNAF_mul /* XXX: Not constant time. */;
diff --git a/crypto/fipsmodule/ec/internal.h b/crypto/fipsmodule/ec/internal.h
index 22cd42a..1042310 100644
--- a/crypto/fipsmodule/ec/internal.h
+++ b/crypto/fipsmodule/ec/internal.h
@@ -82,7 +82,6 @@
struct ec_method_st {
int (*group_init)(EC_GROUP *);
void (*group_finish)(EC_GROUP *);
- int (*group_copy)(EC_GROUP *, const EC_GROUP *);
int (*group_set_curve)(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *);
int (*point_get_affine_coordinates)(const EC_GROUP *, const EC_POINT *,
@@ -130,6 +129,8 @@
int a_is_minus3; // enable optimized point arithmetics for special case
+ CRYPTO_refcount_t references;
+
BN_MONT_CTX *mont; // Montgomery structure.
BIGNUM one; // The value one.
@@ -145,7 +146,6 @@
} /* EC_POINT */;
EC_GROUP *ec_group_new(const EC_METHOD *meth);
-int ec_group_copy(EC_GROUP *dest, const EC_GROUP *src);
// ec_group_get_order_mont returns a Montgomery context for operations modulo
// |group|'s order. It may return NULL in the case that |group| is not a
@@ -158,7 +158,6 @@
// method functions in simple.c
int ec_GFp_simple_group_init(EC_GROUP *);
void ec_GFp_simple_group_finish(EC_GROUP *);
-int ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *);
int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *);
int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a,
@@ -204,7 +203,6 @@
int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *);
void ec_GFp_mont_group_finish(EC_GROUP *);
-int ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *);
int ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
const BIGNUM *b, BN_CTX *);
int ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
diff --git a/crypto/fipsmodule/ec/p224-64.c b/crypto/fipsmodule/ec/p224-64.c
index ec5a93d..26a94b9 100644
--- a/crypto/fipsmodule/ec/p224-64.c
+++ b/crypto/fipsmodule/ec/p224-64.c
@@ -1151,7 +1151,6 @@
DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistp224_method) {
out->group_init = ec_GFp_simple_group_init;
out->group_finish = ec_GFp_simple_group_finish;
- out->group_copy = ec_GFp_simple_group_copy;
out->group_set_curve = ec_GFp_simple_group_set_curve;
out->point_get_affine_coordinates =
ec_GFp_nistp224_point_get_affine_coordinates;
diff --git a/crypto/fipsmodule/ec/p256-64.c b/crypto/fipsmodule/ec/p256-64.c
index f7d1ff1..04ae56b 100644
--- a/crypto/fipsmodule/ec/p256-64.c
+++ b/crypto/fipsmodule/ec/p256-64.c
@@ -1694,7 +1694,6 @@
DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistp256_method) {
out->group_init = ec_GFp_simple_group_init;
out->group_finish = ec_GFp_simple_group_finish;
- out->group_copy = ec_GFp_simple_group_copy;
out->group_set_curve = ec_GFp_simple_group_set_curve;
out->point_get_affine_coordinates =
ec_GFp_nistp256_point_get_affine_coordinates;
diff --git a/crypto/fipsmodule/ec/p256-x86_64.c b/crypto/fipsmodule/ec/p256-x86_64.c
index 8b51677..0004add 100644
--- a/crypto/fipsmodule/ec/p256-x86_64.c
+++ b/crypto/fipsmodule/ec/p256-x86_64.c
@@ -547,7 +547,6 @@
DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistz256_method) {
out->group_init = ec_GFp_mont_group_init;
out->group_finish = ec_GFp_mont_group_finish;
- out->group_copy = ec_GFp_mont_group_copy;
out->group_set_curve = ec_GFp_mont_group_set_curve;
out->point_get_affine_coordinates = ecp_nistz256_get_affine;
out->mul = ecp_nistz256_points_mul;
diff --git a/crypto/fipsmodule/ec/simple.c b/crypto/fipsmodule/ec/simple.c
index e46550f..36b90c8 100644
--- a/crypto/fipsmodule/ec/simple.c
+++ b/crypto/fipsmodule/ec/simple.c
@@ -104,18 +104,6 @@
BN_free(&group->one);
}
-int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
- if (!BN_copy(&dest->field, &src->field) ||
- !BN_copy(&dest->a, &src->a) ||
- !BN_copy(&dest->b, &src->b) ||
- !BN_copy(&dest->one, &src->one)) {
- return 0;
- }
-
- dest->a_is_minus3 = src->a_is_minus3;
- return 1;
-}
-
int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p,
const BIGNUM *a, const BIGNUM *b,
BN_CTX *ctx) {