Commit 66ead9927d for openssl.org
commit 66ead9927dc7aba0dcfb9068f9288ce1e4feda53
Author: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Fri Jan 23 08:43:54 2026 +0100
s390x: EC: use OpenSSL's RNG for ECDSA nonce 'k' for FIPS module
The KDSA instruction can operate in 2 different modes:
- Deterministic mode - nonce 'k' is supplied by user.
- Non-deterministic mode - nonce 'k' is randomly generated by the instruction
itself.
When running in the FIPS-Module, do not use KDSA's non-deterministic mode,
but generate the nonce 'k' using OpenSSL's random number generator. This
ensures that the nonce is generated using a FIPS-approved random number
generator.
It also makes the FIPS KAT tests work, because those use a pre-setup
deterministic random number generator to produce deterministic ECDSA
signatures even for non-deterministic mode.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/29754)
diff --git a/crypto/ec/ecp_s390x_nistp.c b/crypto/ec/ecp_s390x_nistp.c
index 30754d4e75..fef106e243 100644
--- a/crypto/ec/ecp_s390x_nistp.c
+++ b/crypto/ec/ecp_s390x_nistp.c
@@ -127,6 +127,8 @@ ret:
return rc;
}
+#define MIN_ECDSA_SIGN_ORDERBITS 64
+
static ECDSA_SIG *ecdsa_s390x_nistp_sign_sig(const unsigned char *dgst,
int dgstlen,
const BIGNUM *kinv,
@@ -141,11 +143,16 @@ static ECDSA_SIG *ecdsa_s390x_nistp_sign_sig(const unsigned char *dgst,
const EC_GROUP *group;
const BIGNUM *privkey;
BN_CTX *bn_ctx = NULL;
+ const BIGNUM *order;
+#ifdef FIPS_MODULE
+ int order_bits;
+#endif
int off;
group = EC_KEY_get0_group(eckey);
+ order = EC_GROUP_get0_order(group);
privkey = EC_KEY_get0_private_key(eckey);
- if (group == NULL || privkey == NULL) {
+ if (group == NULL || order == NULL || privkey == NULL) {
ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS);
return NULL;
}
@@ -183,6 +190,42 @@ static ECDSA_SIG *ecdsa_s390x_nistp_sign_sig(const unsigned char *dgst,
ERR_raise(ERR_LIB_EC, EC_R_INVALID_LENGTH);
goto ret;
}
+#ifdef FIPS_MODULE
+ /* get random value of k using OpenSSL's RNG */
+ bn_ctx = BN_CTX_secure_new_ex(ossl_ec_key_get_libctx(eckey));
+ if (bn_ctx == NULL)
+ goto ret;
+
+ /* Preallocate space */
+ order_bits = BN_num_bits(order);
+ /* Check the number of bits here so that an infinite loop is not possible */
+ if (order_bits < MIN_ECDSA_SIGN_ORDERBITS
+ || !BN_set_bit(k, order_bits))
+ goto ret;
+
+ do {
+ int res = 0;
+
+ if (dgst != NULL)
+ res = ossl_bn_gen_dsa_nonce_fixed_top(k, order, privkey,
+ dgst, dgstlen, bn_ctx);
+ else
+ res = ossl_bn_priv_rand_range_fixed_top(k, order, 0, bn_ctx);
+
+ if (!res) {
+ ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED);
+ goto ret;
+ }
+ } while (ossl_bn_is_word_fixed_top(k, 0));
+
+ if (BN_bn2binpad(k, param + S390X_OFF_RN(len), len) == -1) {
+ ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED);
+ goto ret;
+ }
+
+ /* Turns KDSA internal nonce-generation off. */
+ fc |= S390X_KDSA_D;
+#else
/*
* Generate random k and copy to param block. RAND_priv_bytes_ex
* is used instead of BN_priv_rand_range or BN_generate_dsa_nonce
@@ -195,6 +238,7 @@ static ECDSA_SIG *ecdsa_s390x_nistp_sign_sig(const unsigned char *dgst,
ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED);
goto ret;
}
+#endif
} else {
bn_ctx = BN_CTX_secure_new_ex(ossl_ec_key_get_libctx(eckey));
if (bn_ctx == NULL)