Commit 8e28ea9e62 for openssl.org
commit 8e28ea9e6244fb425b948780903a37cde338c2b4
Author: Holger Dengler <dengler@linux.ibm.com>
Date: Wed Nov 26 16:18:49 2025 +0100
s390x: Check and fail on invalid malformed ECDSA signatures
Check parameters of ECDSA signatures on verify and fail for invalid
malformed signatures in the code path for s390x accelerators. Handle
condition code of kdsa instruction for detecting invalid parameters.
For NIST P521 curves, kdsa ignores completely the upper 14 bytes of
the sections for r and s in the parameter-block, so adapt the offset
and length for bignum conversions for these curves. This will detect
cases of malformed signatures which are not covered by the kdsa
parameter checking.
Fixes: #29173
Signed-off-by: Holger Dengler <dengler@linux.ibm.com>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/29214)
diff --git a/crypto/ec/ecp_s390x_nistp.c b/crypto/ec/ecp_s390x_nistp.c
index 9b2cca257c..085b630090 100644
--- a/crypto/ec/ecp_s390x_nistp.c
+++ b/crypto/ec/ecp_s390x_nistp.c
@@ -44,6 +44,8 @@
#define S390X_OFF_RN(n) (4 * n)
#define S390X_OFF_Y(n) (4 * n)
+#define S390X_PAD(n) (n == 80 ? 14 : 0)
+
static int ec_GFp_s390x_nistp_mul(const EC_GROUP *group, EC_POINT *r,
const BIGNUM *scalar,
size_t num, const EC_POINT *points[],
@@ -270,17 +272,29 @@ static int ecdsa_s390x_nistp_verify_sig(const unsigned char *dgst, int dgstlen,
off = len - (dgstlen > len ? len : dgstlen);
memcpy(param + S390X_OFF_H(len) + off, dgst, len - off);
+ /* Check for invalid malformed signatures (r/s negative or too large) */
+ if (BN_is_negative(sig->r) || BN_is_negative(sig->s)
+ || BN_bn2binpad(sig->r, param + S390X_OFF_R(len) + S390X_PAD(len),
+ len - S390X_PAD(len)) == -1
+ || BN_bn2binpad(sig->s, param + S390X_OFF_S(len) + S390X_PAD(len),
+ len - S390X_PAD(len)) == -1) {
+ ERR_raise(ERR_LIB_EC, EC_R_BAD_SIGNATURE);
+ rc = 0;
+ goto ret;
+ }
+
if (group->meth->point_get_affine_coordinates(group, pubkey,
x, y, ctx) != 1
- || BN_bn2binpad(sig->r, param + S390X_OFF_R(len), len) == -1
- || BN_bn2binpad(sig->s, param + S390X_OFF_S(len), len) == -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);
goto ret;
}
- rc = s390x_kdsa(fc, param, NULL, 0) == 0 ? 1 : 0;
+ rc = s390x_kdsa(fc, param, NULL, 0);
+ if (rc == 2)
+ ERR_raise(ERR_LIB_EC, EC_R_BAD_SIGNATURE);
+ rc = rc == 0 ? 1 : 0;
ret:
BN_CTX_end(ctx);
BN_CTX_free(ctx);