Commit ee9d1e532c for openssl.org

commit ee9d1e532cb603615174bb2178e856b16255f38e
Author: slontis <shane.lontis@oracle.com>
Date:   Tue Jun 2 11:21:54 2026 +1000

    FIPS: Make keygen PCT failures recoverable

    Key generation pairwise consistency tests (PCT) no longer cause the
    FIPS provider to enter a non recoverable error state.

    Originally I considered that the pairwise tests should never fail, so a
    failure was considered as a fatal error. Unfortunately this is not true,
    since the RSA pairwise test was changed to call
    rsa_ossl_public_encrypt(). This function can return -1 based on the
    values of n and e, resulting in a DOS for bad inputs.
    Under NIST FIPS 186-5, the public exponent (e) must be an odd positive
    integer greater than (e > 65536) and less than 2^256. The OpenSSL code
    however returns an error if e > 2^64 when n > 3072.
    (This check was added to prevent a CVE DOS).

    While FIPS 140-3 mandates that a module must transition into an error
    state upon self-test failures, a PCT is classified as a conditional
    self-test, not a pre-operational self-test
    (like an integrity test or a Known Answer Test)
    The cryptographic module is only required to immediately discard the
    faulty key pair and output a local error. The module is allowed to
    immediately attempt generating a new key pair using fresh entropy,
    without needing a full system reboot or module reset.

    Detected by Oracle during Jipher testing.

    Reviewed-by: Simo Sorce <simo@redhat.com>
    Reviewed-by: Paul Dale <paul.dale@oracle.com>
    MergeDate: Thu Jun 11 16:03:42 2026
    (Merged from https://github.com/openssl/openssl/pull/31359)

diff --git a/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c
index aa69c3eea8..a07f866a21 100644
--- a/crypto/dsa/dsa_key.c
+++ b/crypto/dsa/dsa_key.c
@@ -198,7 +198,6 @@ static int dsa_keygen(DSA *dsa)
         ok = dsa_keygen_pairwise_test(dsa, cb, cbarg)
             && dsa_keygen_knownanswer_test(dsa, ctx, cb, cbarg);
         if (!ok) {
-            ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
             BN_free(dsa->pub_key);
             BN_clear_free(dsa->priv_key);
             dsa->pub_key = NULL;
diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c
index 48e08e7de4..8deaa3b930 100644
--- a/crypto/ec/ec_key.c
+++ b/crypto/ec/ec_key.c
@@ -366,7 +366,6 @@ static int ec_generate_key(EC_KEY *eckey, int pairwise_test)
 err:
     /* Step (9): If there is an error return an invalid keypair. */
     if (!ok) {
-        ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
         BN_clear(eckey->priv_key);
         if (eckey->pub_key != NULL)
             EC_POINT_set_to_infinity(group, eckey->pub_key);
diff --git a/crypto/rsa/rsa_gen.c b/crypto/rsa/rsa_gen.c
index 9e053edb7c..df44f50a76 100644
--- a/crypto/rsa/rsa_gen.c
+++ b/crypto/rsa/rsa_gen.c
@@ -645,7 +645,6 @@ static int rsa_keygen(OSSL_LIB_CTX *libctx, RSA *rsa, int bits, int primes,
         OSSL_SELF_TEST_get_callback(libctx, &stcb, &stcbarg);
         ok = rsa_keygen_pairwise_test(rsa, stcb, stcbarg);
         if (!ok) {
-            ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
             /* Clear intermediate results */
             BN_clear_free(rsa->d);
             BN_clear_free(rsa->p);
diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c
index b090695eda..8901f14e31 100644
--- a/providers/implementations/keymgmt/dh_kmgmt.c
+++ b/providers/implementations/keymgmt/dh_kmgmt.c
@@ -843,10 +843,8 @@ static void *dh_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
 #ifdef FIPS_MODULE
         if (!ossl_fips_self_testing()) {
             ret = ossl_dh_check_pairwise(dh, 0);
-            if (ret <= 0) {
-                ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
+            if (ret <= 0)
                 goto end;
-            }
         }
 #endif /* FIPS_MODULE */
     }
diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c
index d203a0c171..03c7ea3529 100644
--- a/providers/implementations/keymgmt/ec_kmgmt.c
+++ b/providers/implementations/keymgmt/ec_kmgmt.c
@@ -1326,12 +1326,10 @@ static void *ec_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)

         ret = bnctx != NULL && ossl_ec_key_pairwise_check(ec, bnctx);
         BN_CTX_free(bnctx);
-        if (ret <= 0)
-            ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
     }
 #endif /* FIPS_MODULE */

-    if (ret)
+    if (ret > 0)
         return ec;
 err:
     /* Something went wrong, throw the key away */
diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c
index 7087498934..dd9c029a4a 100644
--- a/providers/implementations/keymgmt/ecx_kmgmt.c
+++ b/providers/implementations/keymgmt/ecx_kmgmt.c
@@ -797,7 +797,6 @@ static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
     if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0))
         return key;
     if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED25519, 1) != 1) {
-        ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
         ossl_ecx_key_free(key);
         return NULL;
     }
@@ -830,7 +829,6 @@ static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
     if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0))
         return key;
     if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED448, 1) != 1) {
-        ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
         ossl_ecx_key_free(key);
         return NULL;
     }
diff --git a/providers/implementations/keymgmt/ml_dsa_kmgmt.c b/providers/implementations/keymgmt/ml_dsa_kmgmt.c
index 34710a4a2f..83217066aa 100644
--- a/providers/implementations/keymgmt/ml_dsa_kmgmt.c
+++ b/providers/implementations/keymgmt/ml_dsa_kmgmt.c
@@ -304,10 +304,8 @@ static int ml_dsa_import(void *keydata, int selection, const OSSL_PARAM params[]
 #ifdef FIPS_MODULE
     if (res > 0) {
         res = ml_dsa_pairwise_test(key);
-        if (!res) {
+        if (!res)
             ossl_ml_dsa_key_reset(key);
-            ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT_IMPORT);
-        }
     }
 #endif /* FIPS_MODULE */
     return res;
@@ -508,10 +506,8 @@ static void *ml_dsa_gen(void *genctx, int evp_type)
         goto err;
     }
 #ifdef FIPS_MODULE
-    if (!ml_dsa_pairwise_test(key)) {
-        ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
+    if (!ml_dsa_pairwise_test(key))
         goto err;
-    }
 #endif
     return key;
 err:
diff --git a/providers/implementations/keymgmt/ml_kem_kmgmt.c b/providers/implementations/keymgmt/ml_kem_kmgmt.c
index 8477cd9340..f82f3e6f68 100644
--- a/providers/implementations/keymgmt/ml_kem_kmgmt.c
+++ b/providers/implementations/keymgmt/ml_kem_kmgmt.c
@@ -499,9 +499,6 @@ static int ml_kem_import(void *vkey, int selection, const OSSL_PARAM params[])
     res = ml_kem_key_fromdata(key, params, include_private);
     if (res > 0 && include_private
         && !ml_kem_pairwise_test(key, key->prov_flags)) {
-#ifdef FIPS_MODULE
-        ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT_IMPORT);
-#endif
         ossl_ml_kem_key_reset(key);
         res = 0;
     }
@@ -792,7 +789,6 @@ static void *ml_kem_gen(void *vgctx, OSSL_CALLBACK *osslcb, void *cbarg)
     if (genok) {
 #ifdef FIPS_MODULE
         if (!ml_kem_pairwise_test(key, ML_KEM_KEY_FIXED_PCT)) {
-            ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
             ossl_ml_kem_key_free(key);
             return NULL;
         }
diff --git a/providers/implementations/keymgmt/slh_dsa_kmgmt.c b/providers/implementations/keymgmt/slh_dsa_kmgmt.c
index 5e7be8afd3..766953d265 100644
--- a/providers/implementations/keymgmt/slh_dsa_kmgmt.c
+++ b/providers/implementations/keymgmt/slh_dsa_kmgmt.c
@@ -372,10 +372,8 @@ static void *slh_dsa_gen(void *genctx, const char *alg)
             gctx->entropy, gctx->entropy_len))
         goto err;
 #ifdef FIPS_MODULE
-    if (!slh_dsa_fips140_pairwise_test(key, ctx)) {
-        ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
+    if (!slh_dsa_fips140_pairwise_test(key, ctx))
         goto err;
-    }
 #endif /* FIPS_MODULE */
     ossl_slh_dsa_hash_ctx_free(ctx);
     return key;