Commit a8036eb1e8 for openssl.org
commit a8036eb1e8a9252444130ac23092b9bbd1809305
Author: Simo Sorce <simo@redhat.com>
Date: Wed Dec 17 14:06:57 2025 -0500
Refactor FIPS self-test dependencies and states
Introduce `SELF_TEST_STATE_IMPLICIT` to handle recursive self-test calls
when an algorithm is used by another algorithm's self-test (e.g., KDF
using HMAC). This prevents unnecessarily running tests when they are
effectively covered by a parent test.
Refactor `SELF_TEST_kats` and `SELF_TEST_kats_execute` to unify
execution logic, dependency resolution, and RNG setup. Remove the
`deferred` flag from test definitions in favor of dynamic state
evaluation. Explicitly add a dependency for AES-128-ECB on AES-256-GCM.
Signed-off-by: Simo Sorce <simo@redhat.com>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/29222)
diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c
index b759bd9249..1a50d45926 100644
--- a/providers/fips/fipsprov.c
+++ b/providers/fips/fipsprov.c
@@ -1304,48 +1304,10 @@ void OSSL_INDICATOR_get_callback(OSSL_LIB_CTX *libctx,
}
}
-static int FIPS_kat_deferred_execute(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx,
- self_test_id_t id)
-{
- /*
- * Dependency chains may cause a test to be referenced multiple times
- * immediately return if any state is present
- */
- if (st_all_tests[id].state != SELF_TEST_STATE_INIT)
- return 1;
-
- /* Mark test as in progress */
- st_all_tests[id].state = SELF_TEST_STATE_IN_PROGRESS;
-
- /* check if there are dependent tests to run */
- if (st_all_tests[id].depends_on) {
- for (int i = 0; st_all_tests[id].depends_on[i] != ST_ID_MAX; i++) {
- self_test_id_t dep_id = st_all_tests[id].depends_on[i];
-
- FIPS_kat_deferred_execute(st, libctx, dep_id);
- switch (st_all_tests[dep_id].state) {
- case SELF_TEST_STATE_PASSED:
- case SELF_TEST_STATE_IN_PROGRESS:
- continue;
- default:
- return 0;
- }
- }
- }
-
- /* may have already been run as a dependency, recheck before executing */
- if (st_all_tests[id].state == SELF_TEST_STATE_IN_PROGRESS)
- if (!SELF_TEST_kats_single(st, libctx, id))
- return 0;
-
- return 1;
-}
-
static int FIPS_kat_deferred(OSSL_LIB_CTX *libctx, self_test_id_t id)
{
FIPS_GLOBAL *fgbl = ossl_lib_ctx_get_data(libctx,
OSSL_LIB_CTX_FIPS_PROV_INDEX);
- int *rt = NULL;
int ret = 0;
if (fgbl == NULL) {
@@ -1357,14 +1319,15 @@ static int FIPS_kat_deferred(OSSL_LIB_CTX *libctx, self_test_id_t id)
* before we do anything, make sure a local test is not already in
* progress or we'll deadlock
*/
- rt = CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_FIPS_DEFERRED_KEY,
- libctx);
- if (rt) {
+ if (CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_FIPS_DEFERRED_KEY,
+ libctx)
+ != NULL) {
/*
* record this test as invoked by the original test, for marking
* it later as also satisfied
*/
- rt[id] = 1;
+ if (st_all_tests[id].state == SELF_TEST_STATE_INIT)
+ st_all_tests[id].state = SELF_TEST_STATE_IMPLICIT;
/*
* A self test is in progress for this thread so we let this
* thread continue and perform the test while all other
@@ -1390,17 +1353,14 @@ static int FIPS_kat_deferred(OSSL_LIB_CTX *libctx, self_test_id_t id)
ret = 1;
goto done;
default:
- /* should not happen, something is broken */
+ /* something is broken */
ret = 0;
goto done;
}
- if ((rt = OPENSSL_calloc(ST_ID_MAX, sizeof(int))) == NULL)
- goto done;
-
/* mark that we are executing a test on the local thread */
if (!CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_FIPS_DEFERRED_KEY,
- libctx, rt))
+ libctx, (void *)0xC001))
goto done;
unset_key = true;
@@ -1411,25 +1371,13 @@ static int FIPS_kat_deferred(OSSL_LIB_CTX *libctx, self_test_id_t id)
if ((st = OSSL_SELF_TEST_new(cb, cb_arg)) == NULL)
goto done;
- /* Handles dependencies via recursion */
- if (!(ret = FIPS_kat_deferred_execute(st, libctx, id)))
- goto done;
-
- /*
- * now mark as passed all the algorithms that have been executed by
- * this test and that we tracked as RECORDED_TESTS
- */
- if (st_all_tests[id].state == SELF_TEST_STATE_PASSED)
- for (int i = 0; i < ST_ID_MAX; i++)
- if (rt[i])
- st_all_tests[i].state = SELF_TEST_STATE_PASSED;
+ ret = SELF_TEST_kats_execute(st, libctx, id, 1);
done:
OSSL_SELF_TEST_free(st);
if (unset_key)
CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_FIPS_DEFERRED_KEY,
libctx, NULL);
- OPENSSL_free(rt);
CRYPTO_THREAD_unlock(fgbl->deferred_lock);
}
return ret;
@@ -1485,11 +1433,15 @@ int ossl_deferred_self_test(OSSL_LIB_CTX *libctx, self_test_id_t id)
return 1;
/*
- * During the initial selftest we do not try to self-test individual
- * algorithms, or we end up in loops.
+ * During the initial selftest a call into this function means
+ * a higher level algorithm test is exercising a lower one.
+ * Immediately mark it and return.
*/
- if (ossl_fips_self_testing())
+ if (ossl_fips_self_testing()) {
+ if (st_all_tests[id].state == SELF_TEST_STATE_INIT)
+ st_all_tests[id].state = SELF_TEST_STATE_IMPLICIT;
return 1;
+ }
/*
* NOTE: that the order in which we check the 'state' here is not important,
diff --git a/providers/fips/self_test.c b/providers/fips/self_test.c
index 84e65bcf4a..2630129795 100644
--- a/providers/fips/self_test.c
+++ b/providers/fips/self_test.c
@@ -199,7 +199,7 @@ static int verify_integrity(OSSL_CORE_BIO *bio, OSSL_FUNC_BIO_read_ex_fn read_ex
EVP_MAC_CTX *ctx = NULL;
OSSL_PARAM params[2], *p = params;
- if (!SELF_TEST_kats_single(ev, libctx, ST_ID_MAC_HMAC))
+ if (!SELF_TEST_kats_execute(ev, libctx, ST_ID_MAC_HMAC, 0))
goto err;
OSSL_SELF_TEST_onbegin(ev, event_type, OSSL_SELF_TEST_DESC_INTEGRITY_HMAC);
@@ -330,7 +330,7 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
for (int i = 0; i < ST_ID_MAX; i++)
st_all_tests[i].state = SELF_TEST_STATE_INIT;
- if (!SELF_TEST_kats(ev, st->libctx, on_demand_test)) {
+ if (on_demand_test && !SELF_TEST_kats(ev, st->libctx)) {
ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_KAT_FAILURE);
goto end;
}
diff --git a/providers/fips/self_test.h b/providers/fips/self_test.h
index a2c14beaa2..f9b6a2531a 100644
--- a/providers/fips/self_test.h
+++ b/providers/fips/self_test.h
@@ -32,8 +32,9 @@ typedef struct self_test_post_params_st {
} SELF_TEST_POST_PARAMS;
int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test);
-int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx, int do_deferred);
-int SELF_TEST_kats_single(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx, int id);
+int SELF_TEST_kats_execute(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx,
+ self_test_id_t id, int switch_rand);
+int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx);
void SELF_TEST_disable_conditional_error_state(void);
@@ -57,11 +58,9 @@ enum st_test_state {
SELF_TEST_STATE_IN_PROGRESS,
SELF_TEST_STATE_PASSED,
SELF_TEST_STATE_FAILED,
+ SELF_TEST_STATE_IMPLICIT,
};
-#define SELF_TEST_ONLOAD 0
-#define SELF_TEST_DEFERRED 1
-
/* used to store raw parameters for keys and algorithms */
typedef struct st_kat_param_st {
const char *name; /* an OSSL_PARAM name */
@@ -154,7 +153,6 @@ typedef struct self_test_st {
const char *algorithm;
const char *desc;
enum st_test_category category;
- int deferred;
enum st_test_state state;
ST_BUFFER pt;
ST_BUFFER expected; /* Set to NULL if this value changes */
diff --git a/providers/fips/self_test_data.c b/providers/fips/self_test_data.c
index 71af012099..59758a7617 100644
--- a/providers/fips/self_test_data.c
+++ b/providers/fips/self_test_data.c
@@ -116,6 +116,11 @@ static const unsigned char aes_128_ecb_ct[] = {
0x4e, 0xaa, 0x6f, 0xb4, 0xdb, 0xf7, 0x84, 0x65
};
+static const self_test_id_t aes_ecb_depends_on[] = {
+ ST_ID_CIPHER_AES_256_GCM,
+ ST_ID_MAX
+};
+
#ifndef OPENSSL_NO_DES
/*
* TDES-ECB test data from
@@ -3331,7 +3336,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"SHA1",
OSSL_SELF_TEST_DESC_MD_SHA1,
SELF_TEST_KAT_DIGEST,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF_STR(sha1_pt),
ITM_BUF(sha1_digest),
@@ -3341,7 +3345,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"SHA256",
OSSL_SELF_TEST_DESC_MD_SHA2,
SELF_TEST_KAT_DIGEST,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF_STR(sha256_pt),
ITM_BUF(sha256_digest),
@@ -3351,7 +3354,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"SHA512",
OSSL_SELF_TEST_DESC_MD_SHA2,
SELF_TEST_KAT_DIGEST,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF_STR(sha512_pt),
ITM_BUF(sha512_digest),
@@ -3361,7 +3363,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"SHA3-256",
OSSL_SELF_TEST_DESC_MD_SHA3,
SELF_TEST_KAT_DIGEST,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF(sha3_256_pt),
ITM_BUF(sha3_256_digest),
@@ -3371,7 +3372,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"AES-256-GCM",
OSSL_SELF_TEST_DESC_CIPHER_AES_GCM,
SELF_TEST_KAT_CIPHER,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF(aes_256_gcm_pt),
ITM_BUF(aes_256_gcm_ct),
@@ -3387,7 +3387,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"AES-128-ECB",
OSSL_SELF_TEST_DESC_CIPHER_AES_ECB,
SELF_TEST_KAT_CIPHER,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF(aes_128_ecb_pt),
ITM_BUF(aes_128_ecb_ct),
@@ -3395,6 +3394,7 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
CIPHER_MODE_DECRYPT,
ITM_BUF(aes_128_ecb_key),
},
+ .depends_on = aes_ecb_depends_on,
},
#ifndef OPENSSL_NO_DES
{
@@ -3402,7 +3402,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"DES-EDE3-ECB",
OSSL_SELF_TEST_DESC_CIPHER_TDES,
SELF_TEST_KAT_CIPHER,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF(tdes_pt),
ITM_BUF(tdes_ct),
@@ -3417,7 +3416,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"RSA-SHA256",
OSSL_SELF_TEST_DESC_SIGN_RSA,
SELF_TEST_KAT_SIGNATURE,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF_STR(rsa_sig_msg),
ITM_BUF(rsa_expected_sig),
@@ -3436,7 +3434,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"ECDSA-SHA256",
OSSL_SELF_TEST_DESC_SIGN_ECDSA,
SELF_TEST_KAT_SIGNATURE,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF_STR(rsa_sig_msg),
ITM_BUF(ecdsa_prime_expected_sig),
@@ -3456,7 +3453,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"ECDSA-SHA256",
OSSL_SELF_TEST_DESC_SIGN_DetECDSA,
SELF_TEST_KAT_SIGNATURE,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF_STR(rsa_sig_msg),
ITM_BUF(ecdsa_prime_expected_detsig),
@@ -3474,7 +3470,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"ECDSA-SHA256",
OSSL_SELF_TEST_DESC_SIGN_ECDSA,
SELF_TEST_KAT_SIGNATURE,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF_STR(rsa_sig_msg),
ITM_BUF(ecdsa_bin_expected_sig),
@@ -3494,7 +3489,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"ED448",
OSSL_SELF_TEST_DESC_SIGN_EDDSA,
SELF_TEST_KAT_SIGNATURE,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF(ecx_sig_msg),
ITM_BUF(ed448_expected_sig),
@@ -3509,7 +3503,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"ED25519",
OSSL_SELF_TEST_DESC_SIGN_EDDSA,
SELF_TEST_KAT_SIGNATURE,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF(ecx_sig_msg),
ITM_BUF(ed25519_expected_sig),
@@ -3527,7 +3520,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"DSA-SHA256",
OSSL_SELF_TEST_DESC_SIGN_DSA,
SELF_TEST_KAT_SIGNATURE,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF_STR(rsa_sig_msg),
ITM_BUF(dsa_expected_sig),
@@ -3547,7 +3539,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"ML-DSA-65",
OSSL_SELF_TEST_DESC_SIGN_ML_DSA,
SELF_TEST_KAT_SIGNATURE,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF(ml_dsa_65_msg),
ITM_BUF(ml_dsa_65_sig),
@@ -3576,7 +3567,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"SLH-DSA-SHA2-128f",
OSSL_SELF_TEST_DESC_SIGN_SLH_DSA,
SELF_TEST_KAT_SIGNATURE,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF(slh_dsa_sha2_sig_msg),
ITM_BUF(slh_dsa_sha2_128f_sig_digest),
@@ -3593,7 +3583,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"SLH-DSA-SHAKE-128f",
OSSL_SELF_TEST_DESC_SIGN_SLH_DSA,
SELF_TEST_KAT_SIGNATURE,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF(slh_dsa_shake_sig_msg),
ITM_BUF(slh_dsa_shake_128f_sig_digest),
@@ -3621,7 +3610,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"LMS",
OSSL_SELF_TEST_DESC_SIGN_LMS,
SELF_TEST_KAT_SIGNATURE,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF(sha256_192_msg),
ITM_BUF(sha256_192_sig),
@@ -3637,7 +3625,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
OSSL_KDF_NAME_TLS1_3_KDF,
OSSL_SELF_TEST_DESC_KDF_TLS13_EXTRACT,
SELF_TEST_KAT_KDF,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.expected = ITM_BUF(tls13_kdf_early_secret),
.u.kdf = {
@@ -3650,7 +3637,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
OSSL_KDF_NAME_TLS1_3_KDF,
OSSL_SELF_TEST_DESC_KDF_TLS13_EXPAND,
SELF_TEST_KAT_KDF,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.expected = ITM_BUF(tls13_kdf_client_early_traffic_secret),
.u.kdf = {
@@ -3663,7 +3649,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
OSSL_KDF_NAME_TLS1_PRF,
OSSL_SELF_TEST_DESC_KDF_TLS12_PRF,
SELF_TEST_KAT_KDF,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.expected = ITM_BUF(tls12prf_expected),
.u.kdf = {
@@ -3675,7 +3660,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
OSSL_KDF_NAME_PBKDF2,
OSSL_SELF_TEST_DESC_KDF_PBKDF2,
SELF_TEST_KAT_KDF,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.expected = ITM_BUF(pbkdf2_expected),
.u.kdf = {
@@ -3688,7 +3672,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
OSSL_KDF_NAME_KBKDF,
OSSL_SELF_TEST_DESC_KDF_KBKDF,
SELF_TEST_KAT_KDF,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.expected = ITM_BUF(kbkdf_expected),
.u.kdf = {
@@ -3701,7 +3684,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
OSSL_KDF_NAME_KBKDF,
OSSL_SELF_TEST_DESC_KDF_KBKDF_KMAC,
SELF_TEST_KAT_KDF,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.expected = ITM_BUF(kbkdf_kmac_expected),
.u.kdf = {
@@ -3715,7 +3697,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
OSSL_KDF_NAME_HKDF,
OSSL_SELF_TEST_DESC_KDF_HKDF,
SELF_TEST_KAT_KDF,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.expected = ITM_BUF(hkdf_expected),
.u.kdf = {
@@ -3729,7 +3710,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
OSSL_KDF_NAME_SNMPKDF,
OSSL_SELF_TEST_DESC_KDF_SNMPKDF,
SELF_TEST_KAT_KDF,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.expected = ITM_BUF(snmpkdf_expected),
.u.kdf = {
@@ -3743,7 +3723,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
OSSL_KDF_NAME_SRTPKDF,
OSSL_SELF_TEST_DESC_KDF_SRTPKDF,
SELF_TEST_KAT_KDF,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.expected = ITM_BUF(srtpkdf_expected),
.u.kdf = {
@@ -3757,7 +3736,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
OSSL_KDF_NAME_SSKDF,
OSSL_SELF_TEST_DESC_KDF_SSKDF,
SELF_TEST_KAT_KDF,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.expected = ITM_BUF(sskdf_expected),
.u.kdf = { sskdf_params },
@@ -3769,7 +3747,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
OSSL_KDF_NAME_X963KDF,
OSSL_SELF_TEST_DESC_KDF_X963KDF,
SELF_TEST_KAT_KDF,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.expected = ITM_BUF(x963kdf_expected),
.u.kdf = { x963kdf_params },
@@ -3781,7 +3758,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
OSSL_KDF_NAME_X942KDF_ASN1,
OSSL_SELF_TEST_DESC_KDF_X942KDF,
SELF_TEST_KAT_KDF,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.expected = ITM_BUF(x942kdf_expected),
.u.kdf = {
@@ -3794,7 +3770,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"HASH-DRBG",
OSSL_SELF_TEST_DESC_DRBG_HASH,
SELF_TEST_DRBG,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.expected = ITM_BUF(drbg_hash_sha256_pr_expected),
.u.drbg = {
@@ -3814,7 +3789,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"CTR-DRBG",
OSSL_SELF_TEST_DESC_DRBG_CTR,
SELF_TEST_DRBG,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.expected = ITM_BUF(drbg_ctr_aes128_pr_df_expected),
.u.drbg = {
@@ -3834,7 +3808,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"HMAC-DRBG",
OSSL_SELF_TEST_DESC_DRBG_HMAC,
SELF_TEST_DRBG,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.expected = ITM_BUF(drbg_hmac_sha2_pr_expected),
.u.drbg = {
@@ -3855,7 +3828,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"DH",
OSSL_SELF_TEST_DESC_KA_DH,
SELF_TEST_KAT_KAS,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.expected = ITM_BUF(dh_secret_expected),
.u.kas = {
@@ -3871,7 +3843,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"EC",
OSSL_SELF_TEST_DESC_KA_ECDH,
SELF_TEST_KAT_KAS,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.expected = ITM_BUF(ecdh_secret_expected),
.u.kas = {
@@ -3891,7 +3862,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"ML-KEM-512",
OSSL_SELF_TEST_DESC_KEYGEN_ML_KEM,
SELF_TEST_KAT_ASYM_KEYGEN,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.u.akgen = {
ml_kem_keygen_params,
@@ -3905,7 +3875,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"ML-DSA-65",
OSSL_SELF_TEST_DESC_KEYGEN_ML_DSA,
SELF_TEST_KAT_ASYM_KEYGEN,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.u.akgen = {
ml_dsa_keygen_params,
@@ -3919,7 +3888,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"SLH-DSA-SHA2-128f",
OSSL_SELF_TEST_DESC_KEYGEN_SLH_DSA,
SELF_TEST_KAT_ASYM_KEYGEN,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.u.akgen = {
slh_dsa_sha2_128f_keygen_init_params,
@@ -3933,7 +3901,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"ML-KEM-512",
OSSL_SELF_TEST_DESC_KEM,
SELF_TEST_KAT_KEM,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
.u.kem = {
ml_kem_key,
@@ -3949,7 +3916,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"RSA",
OSSL_SELF_TEST_DESC_ASYM_RSA_ENC,
SELF_TEST_KAT_ASYM_CIPHER,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF(rsa_asym_plaintext_encrypt),
ITM_BUF(rsa_asym_expected_encrypt),
@@ -3965,7 +3931,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"RSA",
OSSL_SELF_TEST_DESC_ASYM_RSA_DEC,
SELF_TEST_KAT_ASYM_CIPHER,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF(rsa_asym_expected_encrypt),
ITM_BUF(rsa_asym_plaintext_encrypt),
@@ -3981,7 +3946,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"RSA",
OSSL_SELF_TEST_DESC_ASYM_RSA_DEC,
SELF_TEST_KAT_ASYM_CIPHER,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF(rsa_asym_expected_encrypt),
ITM_BUF(rsa_asym_plaintext_encrypt),
@@ -3997,7 +3961,6 @@ ST_DEFINITION st_all_tests[ST_ID_MAX] = {
"HMAC",
OSSL_SELF_TEST_DESC_INTEGRITY_HMAC,
SELF_TEST_KAT_MAC,
- SELF_TEST_DEFERRED,
SELF_TEST_STATE_INIT,
ITM_BUF(hmac_kat_pt),
ITM_BUF(hmac_kat_expected),
diff --git a/providers/fips/self_test_kats.c b/providers/fips/self_test_kats.c
index 20743d144f..fd6363a315 100644
--- a/providers/fips/self_test_kats.c
+++ b/providers/fips/self_test_kats.c
@@ -1086,121 +1086,16 @@ static int setup_main_random(OSSL_LIB_CTX *libctx)
return 1;
err:
EVP_RAND_CTX_free(main_rand);
- return 0;
-}
-
-/*
- * Run the algorithm KAT's.
- * Return 1 is successful, otherwise return 0.
- * This runs all the tests regardless of if any fail.
- * when do_deferred is 1 also run deferred tests, they are normally skipped
- */
-int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx, int do_deferred)
-{
- EVP_RAND_CTX *saved_rand = ossl_rand_get0_private_noncreating(libctx);
- int i, ret = 1;
-
- if (saved_rand != NULL && !EVP_RAND_CTX_up_ref(saved_rand))
- return 0;
- if (!setup_main_random(libctx)
- || !RAND_set0_private(libctx, main_rand)) {
- /* Decrement saved_rand reference counter */
- EVP_RAND_CTX_free(saved_rand);
- EVP_RAND_CTX_free(main_rand);
- /* Ensure this global variable does not reference freed memory */
- main_rand = NULL;
- return 0;
- }
-
- for (i = 0; i < ST_ID_MAX; i++) {
- int res;
-
- if (st_all_tests[i].id != i) {
- ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA);
- return 0;
- }
-
- if (!do_deferred && (st_all_tests[i].deferred == SELF_TEST_DEFERRED) && (st_all_tests[i].state != SELF_TEST_STATE_PASSED))
- continue;
-
- switch (st_all_tests[i].category) {
- case SELF_TEST_KAT_DIGEST:
- res = self_test_digest(&st_all_tests[i], st, libctx);
- break;
- case SELF_TEST_KAT_CIPHER:
- res = self_test_cipher(&st_all_tests[i], st, libctx);
- break;
- case SELF_TEST_KAT_SIGNATURE:
- res = self_test_digest_sign(&st_all_tests[i], st, libctx);
- break;
- case SELF_TEST_KAT_KDF:
- res = self_test_kdf(&st_all_tests[i], st, libctx);
- break;
- case SELF_TEST_DRBG:
- res = self_test_drbg(&st_all_tests[i], st, libctx);
- break;
- case SELF_TEST_KAT_KAS:
- res = self_test_ka(&st_all_tests[i], st, libctx);
- break;
- case SELF_TEST_KAT_ASYM_KEYGEN:
- res = self_test_asym_keygen(&st_all_tests[i], st, libctx);
- break;
- case SELF_TEST_KAT_KEM:
- res = self_test_kem(&st_all_tests[i], st, libctx);
- break;
- case SELF_TEST_KAT_ASYM_CIPHER:
- res = self_test_asym_cipher(&st_all_tests[i], st, libctx);
- break;
- case SELF_TEST_KAT_MAC:
- res = self_test_mac(&st_all_tests[i], st, libctx);
- break;
- default:
- res = 0;
- break;
- }
- if (res)
- st_all_tests[i].state = SELF_TEST_STATE_PASSED;
- else
- ret = 0;
- }
-
- RAND_set0_private(libctx, saved_rand);
- /* The above call will cause main_rand to be freed */
+ /* Ensure this global variable does not reference freed memory */
main_rand = NULL;
- return ret;
+ return 0;
}
-/*
- * Run a single algorithm KAT.
- * This is similar to SELF_TEST_kats() but only runs the test for a single
- * algorithm.
- * Return 1 is successful, otherwise return 0. If no test is found for the
- * algorithm it also returns 0.
- * This runs all the tests for the given algorithm regardless of if any fail.
- *
- * NOTE: currently tests that require the TEST RNG will not work, as we can't
- * replace the working DRBG with the TEST DRB after initialization.
- */
-int SELF_TEST_kats_single(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx, int id)
+static int SELF_TEST_kats_single(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx,
+ self_test_id_t id)
{
- EVP_RAND_CTX *saved_rand = ossl_rand_get0_private_noncreating(libctx);
int ret;
- if (id >= ST_ID_MAX || st_all_tests[id].id != id) {
- ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA);
- return 0;
- }
-
- if (saved_rand != NULL && !EVP_RAND_CTX_up_ref(saved_rand))
- return 0;
- if (!setup_main_random(libctx)
- || !RAND_set0_private(libctx, main_rand)) {
- /* Decrement saved_rand reference counter */
- EVP_RAND_CTX_free(saved_rand);
- EVP_RAND_CTX_free(main_rand);
- return 0;
- }
-
switch (st_all_tests[id].category) {
case SELF_TEST_KAT_DIGEST:
ret = self_test_digest(&st_all_tests[id], st, libctx);
@@ -1238,10 +1133,156 @@ int SELF_TEST_kats_single(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx, int id)
}
if (ret)
st_all_tests[id].state = SELF_TEST_STATE_PASSED;
- else
+ else {
st_all_tests[id].state = SELF_TEST_STATE_FAILED;
+ ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_KAT_FAILURE);
+ }
+
+ return ret;
+}
+
+static int SELF_TEST_kat_deps(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx,
+ ST_DEFINITION *test)
+{
+ if (test->depends_on == NULL)
+ return 0;
+
+ for (int i = 0; test->depends_on[i] != ST_ID_MAX; i++)
+ if (!SELF_TEST_kats_execute(st, libctx, test->depends_on[i], 0))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Run a single algorithm KAT, and its dependencies.
+ * Return 1 if successful, otherwise return 0.
+ */
+int SELF_TEST_kats_execute(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx,
+ self_test_id_t id, int switch_rand)
+{
+ EVP_RAND_CTX *saved_rand = NULL;
+ int ret;
+
+ if (id >= ST_ID_MAX || st_all_tests[id].id != id) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA);
+ return 0;
+ }
+
+ /*
+ * Dependency chains may cause a test to be referenced multiple times,
+ * immediately return if not in initial state.
+ */
+ switch (st_all_tests[id].state) {
+ case SELF_TEST_STATE_INIT:
+ break;
+ case SELF_TEST_STATE_FAILED:
+ return 0;
+ case SELF_TEST_STATE_IN_PROGRESS:
+ case SELF_TEST_STATE_PASSED:
+ case SELF_TEST_STATE_IMPLICIT:
+ return 1;
+ }
+
+ if (switch_rand) {
+ saved_rand = ossl_rand_get0_private_noncreating(libctx);
+ if (saved_rand != NULL && !EVP_RAND_CTX_up_ref(saved_rand))
+ return 0;
+ if (!setup_main_random(libctx)
+ || !RAND_set0_private(libctx, main_rand)) {
+ /* Decrement saved_rand reference counter */
+ EVP_RAND_CTX_free(saved_rand);
+ EVP_RAND_CTX_free(main_rand);
+ /* Ensure this global variable does not reference freed memory */
+ main_rand = NULL;
+ return 0;
+ }
+ }
+
+ /* Mark test as in progress */
+ st_all_tests[id].state = SELF_TEST_STATE_IN_PROGRESS;
+
+ /* check if there are dependent tests to run */
+ if (st_all_tests[id].depends_on) {
+ if (!SELF_TEST_kat_deps(st, libctx, &st_all_tests[id])) {
+ ret = 0;
+ goto done;
+ }
+ }
+
+ /* may have already been run through dependency chains */
+ switch (st_all_tests[id].state) {
+ case SELF_TEST_STATE_IN_PROGRESS:
+ ret = SELF_TEST_kats_single(st, libctx, id);
+ break;
+ case SELF_TEST_STATE_PASSED:
+ ret = 1;
+ break;
+ default:
+ /* ensure all states are set to failed if we get here */
+ st_all_tests[id].state = SELF_TEST_STATE_FAILED;
+ ret = 0;
+ }
+
+ /*
+ * if an implicit algorithm has explicit dependencies we want to
+ * ensure they are all executed as well otherwise we could not
+ * mark it as passed.
+ */
+ if (st_all_tests[id].state == SELF_TEST_STATE_PASSED)
+ for (int i = 0; i < ST_ID_MAX; i++)
+ if (st_all_tests[i].state == SELF_TEST_STATE_IMPLICIT
+ && st_all_tests[i].depends_on != NULL)
+ if (!(ret = SELF_TEST_kat_deps(st, libctx, &st_all_tests[i])))
+ break;
+
+done:
+ /*
+ * now mark (pass or fail) all the algorithm tests that have been marked
+ * by this test implicitly tested.
+ */
+ for (int i = 0; i < ST_ID_MAX; i++)
+ if (st_all_tests[i].state == SELF_TEST_STATE_IMPLICIT)
+ st_all_tests[i].state = st_all_tests[id].state;
+
+ if (switch_rand) {
+ RAND_set0_private(libctx, saved_rand);
+ /* The above call will cause main_rand to be freed */
+ main_rand = NULL;
+ }
+ return ret;
+}
+
+/*
+ * Run the algorithm KAT's.
+ * Return 1 is successful, otherwise return 0.
+ * This runs all the tests regardless of if any fail, but it will not forcibly
+ * run tests that have been implicitly satisfied.
+ */
+int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
+{
+ EVP_RAND_CTX *saved_rand = ossl_rand_get0_private_noncreating(libctx);
+ int i, ret = 1;
+
+ if (saved_rand != NULL && !EVP_RAND_CTX_up_ref(saved_rand))
+ return 0;
+ if (!setup_main_random(libctx)
+ || !RAND_set0_private(libctx, main_rand)) {
+ /* Decrement saved_rand reference counter */
+ EVP_RAND_CTX_free(saved_rand);
+ EVP_RAND_CTX_free(main_rand);
+ /* Ensure this global variable does not reference freed memory */
+ main_rand = NULL;
+ return 0;
+ }
+
+ for (i = 0; i < ST_ID_MAX; i++)
+ if (!SELF_TEST_kats_execute(st, libctx, i, 0))
+ ret = 0;
RAND_set0_private(libctx, saved_rand);
+ /* The above call will cause main_rand to be freed */
+ main_rand = NULL;
return ret;
}