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