Commit ff40c9684c for openssl.org
commit ff40c9684c5eeb4d4a055e33eead16f22bc05f98
Author: gibKim <gbkim0909@gmail.com>
Date: Sat Oct 31 22:56:58 2026 +0900
crypto/ec/ec_lib.c: handle groups without a generator in EC_GROUP_cmp()
A group created with EC_GROUP_new_curve_GFp() has no generator until
EC_GROUP_set_generator() is called, but EC_GROUP_cmp() passed both
generators to EC_POINT_cmp() unchecked, which dereferenced NULL.
Two groups without a generator now yield an error, and a group
with a generator does not match a group without one.
Resolves: https://github.com/openssl/openssl/issues/33450
Fixes: ada0e717fa36 "new function EC_GROUP_cmp() (used by EVP_PKEY_cmp())"
Assisted-by: Claude:claude-opus-5-5
Assisted-by: Codex:GPT-6
Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
Merge-date: Sun Nov 8 13:35:25 2026
Merged-from: https://github.com/openssl/openssl/pull/33465
diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c
index 6df9774ed9..e9fc64b6c7 100644
--- a/crypto/ec/ec_lib.c
+++ b/crypto/ec/ec_lib.c
@@ -699,10 +699,17 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
if (r || BN_cmp(a1, b1) != 0 || BN_cmp(a2, b2) != 0 || BN_cmp(a3, b3) != 0)
r = 1;
- /* XXX EC_POINT_cmp() assumes that the methods are equal */
/* return 1 if the generators are different */
- if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a), EC_GROUP_get0_generator(b), ctx) != 0)
- r = 1;
+ if (!r) {
+ const EC_POINT *ag = EC_GROUP_get0_generator(a);
+ const EC_POINT *bg = EC_GROUP_get0_generator(b);
+
+ if (ag == NULL || bg == NULL)
+ r = -1;
+ /* XXX EC_POINT_cmp() assumes that the methods are equal */
+ else if (EC_POINT_cmp(a, ag, bg, ctx) != 0)
+ r = 1;
+ }
if (!r) {
const BIGNUM *ao, *bo, *ac, *bc;
diff --git a/test/ectest.c b/test/ectest.c
index 8a138602ca..06ed0fa8ad 100644
--- a/test/ectest.c
+++ b/test/ectest.c
@@ -2002,6 +2002,59 @@ err:
return r;
}
+/*
+ * EC_GROUP_cmp() reports an error if either group has no generator.
+ */
+static int group_cmp_no_generator_test(void)
+{
+ EC_GROUP *named = NULL, *g = NULL, *h = NULL;
+ EC_POINT *gen = NULL;
+ BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL;
+ BN_CTX *ctx = NULL;
+ int r = 0;
+
+ if (!TEST_ptr(ctx = BN_CTX_new())
+ || !TEST_ptr(p = BN_new())
+ || !TEST_ptr(a = BN_new())
+ || !TEST_ptr(b = BN_new())
+ || !TEST_ptr(x = BN_new())
+ || !TEST_ptr(y = BN_new())
+ || !TEST_ptr(named = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1))
+ || !TEST_true(EC_GROUP_get_curve(named, p, a, b, ctx))
+ || !TEST_ptr(g = EC_GROUP_new_curve_GFp(p, a, b, ctx))
+ || !TEST_ptr(h = EC_GROUP_dup(g))
+ || !TEST_ptr_null(EC_GROUP_get0_generator(g))
+ || !TEST_int_eq(EC_GROUP_cmp(g, h, ctx), -1)
+ || !TEST_int_eq(EC_GROUP_cmp(named, named, ctx), 0))
+ goto err;
+
+ if (!TEST_true(EC_POINT_get_affine_coordinates(named,
+ EC_GROUP_get0_generator(named),
+ x, y, ctx))
+ || !TEST_ptr(gen = EC_POINT_new(h))
+ || !TEST_true(EC_POINT_set_affine_coordinates(h, gen, x, y, ctx))
+ || !TEST_true(EC_GROUP_set_generator(h, gen,
+ EC_GROUP_get0_order(named),
+ EC_GROUP_get0_cofactor(named)))
+ || !TEST_int_eq(EC_GROUP_cmp(g, h, ctx), -1)
+ || !TEST_int_eq(EC_GROUP_cmp(h, g, ctx), -1))
+ goto err;
+
+ r = 1;
+err:
+ EC_GROUP_free(named);
+ EC_GROUP_free(g);
+ EC_GROUP_free(h);
+ EC_POINT_free(gen);
+ BN_free(p);
+ BN_free(a);
+ BN_free(b);
+ BN_free(x);
+ BN_free(y);
+ BN_CTX_free(ctx);
+ return r;
+}
+
/*
* This test validates converting an EC_GROUP to an OSSL_PARAM array
* using EC_GROUP_to_params(). A named and an explicit curve are tested.
@@ -3216,6 +3269,7 @@ int setup_tests(void)
return 0;
ADD_TEST(parameter_test);
+ ADD_TEST(group_cmp_no_generator_test);
ADD_TEST(ossl_parameter_test);
ADD_TEST(ossl_explicit_parameter_options_test);
#ifndef OPENSSL_NO_EC_EXPLICIT_CURVES