Commit 1ca2924749 for openssl.org

commit 1ca29247498a351371149ef0fe02402976373866
Author: Billy Brumley <bbb@iki.fi>
Date:   Sun Mar 22 13:07:20 2026 -0400

    [crypto/ec] optimize fetching affine coordinates when Z is one

    Check the z_is_one flag and early exit if it's set.

    This saves an expensive field inversion in some cases,
    especially when just loading a key and reading it back.

    In fact sometimes it saves two expensive field inversions,
    because sometimes the first call is only for retrieving the size.

    Fixes #29719

    Reviewed-by: Paul Dale <paul.dale@oracle.com>
    Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
    Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
    MergeDate: Thu Mar 26 13:58:10 2026
    (Merged from https://github.com/openssl/openssl/pull/30530)

diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c
index 0760944647..9ab8fc433a 100644
--- a/crypto/ec/ec_lib.c
+++ b/crypto/ec/ec_lib.c
@@ -930,6 +930,9 @@ int EC_POINT_get_affine_coordinates(const EC_GROUP *group,
     const EC_POINT *point, BIGNUM *x, BIGNUM *y,
     BN_CTX *ctx)
 {
+    BN_CTX *new_ctx = NULL;
+    int ret = 0;
+
     if (group->meth->point_get_affine_coordinates == NULL) {
         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
         return 0;
@@ -942,7 +945,24 @@ int EC_POINT_get_affine_coordinates(const EC_GROUP *group,
         ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY);
         return 0;
     }
-    return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
+    if (point->Z_is_one) {
+        if (group->meth->field_decode != NULL) {
+            if (ctx == NULL && (ctx = new_ctx = BN_CTX_new_ex(group->libctx)) == NULL) {
+                ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
+                return 0;
+            }
+            if ((x != NULL && !group->meth->field_decode(group, x, point->X, ctx))
+                || (y != NULL && !group->meth->field_decode(group, y, point->Y, ctx)))
+                goto err;
+        } else if ((x != NULL && BN_copy(x, point->X) == NULL)
+            || (y != NULL && BN_copy(y, point->Y) == NULL))
+            goto err;
+        ret = 1;
+    } else
+        ret = group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
+err:
+    BN_CTX_free(new_ctx);
+    return ret;
 }

 #ifndef OPENSSL_NO_DEPRECATED_3_0
diff --git a/crypto/ec/ecp_s390x_nistp.c b/crypto/ec/ecp_s390x_nistp.c
index 58abc0e83c..d940e9106b 100644
--- a/crypto/ec/ecp_s390x_nistp.c
+++ b/crypto/ec/ecp_s390x_nistp.c
@@ -98,9 +98,7 @@ static int ec_GFp_s390x_nistp_mul(const EC_GROUP *group, EC_POINT *r,

         memset(&param, 0, sizeof(param));

-        if (group->meth->point_get_affine_coordinates(group, point_ptr,
-                x, y, ctx)
-                != 1
+        if (EC_POINT_get_affine_coordinates(group, point_ptr, x, y, ctx) != 1
             || BN_bn2binpad(x, param + S390X_OFF_SRC_X(len), len) == -1
             || BN_bn2binpad(y, param + S390X_OFF_SRC_Y(len), len) == -1
             || BN_bn2binpad(scalar_ptr,
@@ -109,9 +107,7 @@ static int ec_GFp_s390x_nistp_mul(const EC_GROUP *group, EC_POINT *r,
             || s390x_pcc(fc, param) != 0
             || BN_bin2bn(param + S390X_OFF_RES_X(len), len, x) == NULL
             || BN_bin2bn(param + S390X_OFF_RES_Y(len), len, y) == NULL
-            || group->meth->point_set_affine_coordinates(group, r,
-                   x, y, ctx)
-                != 1)
+            || EC_POINT_set_affine_coordinates(group, r, x, y, ctx) != 1)
             goto ret;

         rc = 1;
@@ -333,9 +329,7 @@ static int ecdsa_s390x_nistp_verify_sig(const unsigned char *dgst, int dgstlen,
         goto ret;
     }

-    if (group->meth->point_get_affine_coordinates(group, pubkey,
-            x, y, ctx)
-            != 1
+    if (EC_POINT_get_affine_coordinates(group, pubkey, x, y, ctx) != 1
         || BN_bn2binpad(x, param + S390X_OFF_X(len), len) == -1
         || BN_bn2binpad(y, param + S390X_OFF_Y(len), len) == -1) {
         ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);