From: Simo Sorce Date: Wed, 17 Dec 2025 19:06:57 +0000 (-0500) Subject: Refactor FIPS self-test dependencies and states X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a8036eb1e8a9252444130ac23092b9bbd1809305;p=thirdparty%2Fopenssl.git 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 Reviewed-by: Dmitry Belyavskiy (Merged from https://github.com/openssl/openssl/pull/29222) --- diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index b759bd92491..1a50d459268 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 84e65bcf4aa..2630129795b 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 a2c14beaa28..f9b6a2531ad 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 71af012099e..59758a76175 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 20743d144f4..fd6363a3158 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; }