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(¶m, 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);