Move BN_nnmod calls out of low-level group_set_curve.
group_set_curve is called when instantiating the built-in curves and
when creating arbitrary curves. The former has non-NULL BN_CTXs and
fully reduced inputs. Move the logic for this to the deprecated
EC_GROUP_new_curve_GFp function so it can be dropped from most binaries.
Change-Id: I5ff60d6d51acb79fbcb32588e6324a5b2627b6d2
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40544
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/fipsmodule/ec/ec.c b/crypto/fipsmodule/ec/ec.c
index 158d66c..d32ac7e 100644
--- a/crypto/fipsmodule/ec/ec.c
+++ b/crypto/fipsmodule/ec/ec.c
@@ -321,20 +321,37 @@
return NULL;
}
- EC_GROUP *ret = ec_group_new(EC_GFp_mont_method());
- if (ret == NULL) {
- return NULL;
+ BN_CTX *new_ctx = NULL;
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ return NULL;
+ }
}
- if (ret->meth->group_set_curve == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- EC_GROUP_free(ret);
- return NULL;
+ // Historically, |a| and |b| were not required to be fully reduced.
+ // TODO(davidben): Can this be removed?
+ EC_GROUP *ret = NULL;
+ BN_CTX_start(ctx);
+ BIGNUM *a_reduced = BN_CTX_get(ctx);
+ BIGNUM *b_reduced = BN_CTX_get(ctx);
+ if (a_reduced == NULL || b_reduced == NULL ||
+ !BN_nnmod(a_reduced, a, p, ctx) ||
+ !BN_nnmod(b_reduced, b, p, ctx)) {
+ goto err;
}
- if (!ret->meth->group_set_curve(ret, p, a, b, ctx)) {
+
+ ret = ec_group_new(EC_GFp_mont_method());
+ if (ret == NULL ||
+ !ret->meth->group_set_curve(ret, p, a_reduced, b_reduced, ctx)) {
EC_GROUP_free(ret);
- return NULL;
+ ret = NULL;
+ goto err;
}
+
+err:
+ BN_CTX_end(ctx);
+ BN_CTX_free(new_ctx);
return ret;
}
diff --git a/crypto/fipsmodule/ec/ec_montgomery.c b/crypto/fipsmodule/ec/ec_montgomery.c
index 5553f05..22251e0 100644
--- a/crypto/fipsmodule/ec/ec_montgomery.c
+++ b/crypto/fipsmodule/ec/ec_montgomery.c
@@ -92,35 +92,20 @@
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;
- int ret = 0;
-
BN_MONT_CTX_free(group->mont);
- group->mont = NULL;
-
- if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL) {
- return 0;
- }
- }
-
group->mont = BN_MONT_CTX_new_for_modulus(p, ctx);
if (group->mont == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
- goto err;
+ return 0;
}
- ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
-
- if (!ret) {
+ if (!ec_GFp_simple_group_set_curve(group, p, a, b, ctx)) {
BN_MONT_CTX_free(group->mont);
group->mont = NULL;
+ return 0;
}
-err:
- BN_CTX_free(new_ctx);
- return ret;
+ return 1;
}
static void ec_GFp_mont_felem_to_montgomery(const EC_GROUP *group,
diff --git a/crypto/fipsmodule/ec/ec_test.cc b/crypto/fipsmodule/ec/ec_test.cc
index 1c8a9ce..6a6a71b 100644
--- a/crypto/fipsmodule/ec/ec_test.cc
+++ b/crypto/fipsmodule/ec/ec_test.cc
@@ -330,6 +330,23 @@
EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group4.get(), NULL));
#endif
+
+ // group5 is the same group, but the curve coefficients are passed in
+ // unreduced and the caller does not pass in a |BN_CTX|.
+ ASSERT_TRUE(BN_sub(a.get(), a.get(), p.get()));
+ ASSERT_TRUE(BN_add(b.get(), b.get(), p.get()));
+ bssl::UniquePtr<EC_GROUP> group5(
+ EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), NULL));
+ ASSERT_TRUE(group5);
+ bssl::UniquePtr<EC_POINT> generator5(EC_POINT_new(group5.get()));
+ ASSERT_TRUE(generator5);
+ ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
+ group5.get(), generator5.get(), gx.get(), gy.get(), ctx.get()));
+ ASSERT_TRUE(EC_GROUP_set_generator(group5.get(), generator5.get(),
+ order.get(), BN_value_one()));
+
+ EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group.get(), NULL));
+ EXPECT_EQ(0, EC_GROUP_cmp(group5.get(), group.get(), NULL));
}
TEST(ECTest, SetKeyWithoutGroup) {
diff --git a/crypto/fipsmodule/ec/simple.c b/crypto/fipsmodule/ec/simple.c
index 8536b80..af91da9 100644
--- a/crypto/fipsmodule/ec/simple.c
+++ b/crypto/fipsmodule/ec/simple.c
@@ -101,22 +101,13 @@
int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p,
const BIGNUM *a, const BIGNUM *b,
BN_CTX *ctx) {
- int ret = 0;
- BN_CTX *new_ctx = NULL;
-
// p must be a prime > 3
if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) {
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FIELD);
return 0;
}
- if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL) {
- return 0;
- }
- }
-
+ int ret = 0;
BN_CTX_start(ctx);
BIGNUM *tmp = BN_CTX_get(ctx);
if (tmp == NULL) {
@@ -131,33 +122,23 @@
// Store the field in minimal form, so it can be used with |BN_ULONG| arrays.
bn_set_minimal_width(&group->field);
- // group->a
- if (!BN_nnmod(tmp, a, &group->field, ctx) ||
- !ec_bignum_to_felem(group, &group->a, tmp)) {
+ if (!ec_bignum_to_felem(group, &group->a, a) ||
+ !ec_bignum_to_felem(group, &group->b, b) ||
+ !ec_bignum_to_felem(group, &group->one, BN_value_one())) {
goto err;
}
// group->a_is_minus3
- if (!BN_add_word(tmp, 3)) {
+ if (!BN_copy(tmp, a) ||
+ !BN_add_word(tmp, 3)) {
goto err;
}
group->a_is_minus3 = (0 == BN_cmp(tmp, &group->field));
- // group->b
- if (!BN_nnmod(tmp, b, &group->field, ctx) ||
- !ec_bignum_to_felem(group, &group->b, tmp)) {
- goto err;
- }
-
- if (!ec_bignum_to_felem(group, &group->one, BN_value_one())) {
- goto err;
- }
-
ret = 1;
err:
BN_CTX_end(ctx);
- BN_CTX_free(new_ctx);
return ret;
}