/* Return 1 if the FIPS self tests are running and 0 otherwise */
int ossl_fips_self_testing(void);
+/* Deferred KAT tests categories */
+
+/*
+ * The Integrity category is used to run test that are required by the
+ * integrity check and are a special category that can therefore never
+ * really be deferred. Keep it commented here as a reminder.
+ * # define FIPS_DEFERRED_KAT_INTEGRITY 0
+ */
+# define FIPS_DEFERRED_KAT_CIPHER 1
+# define FIPS_DEFERRED_KAT_ASYM_CIPHER 2
+# define FIPS_DEFERRED_KAT_ASYM_KEYGEN 3
+# define FIPS_DEFERRED_KAT_KEM 4
+# define FIPS_DEFERRED_KAT_DIGEST 5
+# define FIPS_DEFERRED_KAT_SIGNATURE 6
+# define FIPS_DEFERRED_KAT_KDF 7
+# define FIPS_DEFERRED_KAT_KA 8
+/* Currently unused because all MAC tests are satisfied through other tests */
+# define FIPS_DEFERRED_KAT_MAC 9
+# define FIPS_DEFERRED_DRBG 10
+# define FIPS_DEFERRED_MAX 11
+
+struct fips_deferred_test_st {
+ const char *algorithm;
+ int category;
+ int state;
+};
+
+# define FIPS_DEFERRED_TEST_INIT 0
+# define FIPS_DEFERRED_TEST_IN_PROGRESS 1
+# define FIPS_DEFERRED_TEST_PASSED 2
+# define FIPS_DEFERRED_TEST_FAILED 3
+
+typedef struct fips_deferred_test_st FIPS_DEFERRED_TEST;
+
+int FIPS_deferred_self_tests(OSSL_LIB_CTX *libctx, FIPS_DEFERRED_TEST tests[]);
+
# endif /* FIPS_MODULE */
#endif
CRYPTO_THREAD_LOCAL_ASYNC_CTX_KEY,
CRYPTO_THREAD_LOCAL_ASYNC_POOL_KEY,
CRYPTO_THREAD_LOCAL_TEVENT_KEY,
+ CRYPTO_THREAD_LOCAL_FIPS_DEFERRED_KEY,
CRYPTO_THREAD_LOCAL_KEY_MAX
} CRYPTO_THREAD_LOCAL_KEY_ID;
#include <openssl/rand.h> /* RAND_get0_public() */
#include <openssl/proverr.h>
#include <openssl/indicator.h>
+#include <openssl/self_test.h>
#include "internal/cryptlib.h"
#include "internal/provider.h"
#include "prov/implementations.h"
#include "crypto/context.h"
#include "fipscommon.h"
#include "internal/core.h"
+#include "internal/fips.h"
#include "internal/mem_alloc_utils.h"
+#include "internal/thread_once.h"
+#include "internal/threads_common.h"
static const char FIPS_DEFAULT_PROPERTIES[] = "provider=fips,fips=yes";
static const char FIPS_UNAPPROVED_PROPERTIES[] = "provider=fips,fips=no";
return fgbl;
}
+static void deferred_deinit(void);
+
void ossl_fips_prov_ossl_ctx_free(void *fgbl)
{
+ /* Also free deferred variables when the FIPS Global context is killed */
+ deferred_deinit();
OPENSSL_free(fgbl);
}
*cb = NULL;
}
}
+
+/* Deferred test infrastructure */
+
+/* Guards access to deferred self-test */
+static CRYPTO_RWLOCK *deferred_lock;
+
+static CRYPTO_ONCE deferred_once = CRYPTO_ONCE_STATIC_INIT;
+static void deferred_init(void)
+{
+ if ((deferred_lock = CRYPTO_THREAD_lock_new()) == NULL)
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_CREATE_LOCK);
+}
+static void deferred_deinit(void)
+{
+ if (deferred_lock) {
+ CRYPTO_THREAD_lock_free(deferred_lock);
+ deferred_lock = NULL;
+ }
+}
+
+static int FIPS_kat_deferred(OSSL_LIB_CTX *libctx, FIPS_DEFERRED_TEST *test)
+{
+ int ret = FIPS_DEFERRED_TEST_FAILED;
+
+ if (!CRYPTO_THREAD_run_once(&deferred_once, deferred_init))
+ return FIPS_DEFERRED_TEST_FAILED;
+
+ if (deferred_lock == NULL)
+ return FIPS_DEFERRED_TEST_FAILED;
+
+ /*
+ * before we do anything, make sure a local test is not already in
+ * progress or we'll deadlock
+ */
+ if (CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_FIPS_DEFERRED_KEY,
+ libctx) != NULL)
+ return FIPS_DEFERRED_TEST_IN_PROGRESS;
+
+ if (CRYPTO_THREAD_write_lock(deferred_lock)) {
+ OSSL_SELF_TEST *ev = NULL;
+ bool unset_key = false;
+ OSSL_CALLBACK *cb = NULL;
+ void *cb_arg = NULL;
+
+ /*
+ * check again as another thread may have just performed this
+ * test and marked it as passed
+ */
+ if (test->state == FIPS_DEFERRED_TEST_PASSED) {
+ ret = FIPS_DEFERRED_TEST_PASSED;
+ goto done;
+ }
+
+ /*
+ * mark that we are executing a test on the local thread, does not
+ * matter what value, as long as it is not NULL, Cool?
+ */
+ if (!CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_FIPS_DEFERRED_KEY,
+ libctx, (void *)0xC001))
+ goto done;
+
+ unset_key = true;
+
+ if (c_stcbfn != NULL && c_get_libctx != NULL)
+ c_stcbfn(c_get_libctx(FIPS_get_core_handle(libctx)), &cb, &cb_arg);
+
+ if ((ev = OSSL_SELF_TEST_new(cb, cb_arg)) == NULL)
+ goto done;
+
+ /* Mark test as in progress */
+ test->state = FIPS_DEFERRED_TEST_IN_PROGRESS;
+
+ /* execute test */
+ if (SELF_TEST_kats_single(ev, libctx, test->category, test->algorithm))
+ ret = FIPS_DEFERRED_TEST_PASSED;
+
+ done:
+ /* Mark test as pass or fail */
+ test->state = ret;
+
+ if (ev)
+ OSSL_SELF_TEST_free(ev);
+ if (unset_key)
+ CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_FIPS_DEFERRED_KEY,
+ libctx, NULL);
+ CRYPTO_THREAD_unlock(deferred_lock);
+ }
+ return ret;
+}
+
+static void deferred_test_error(int category)
+{
+ const char *category_name = "Unknown Category Test";
+
+ switch (category) {
+ case FIPS_DEFERRED_KAT_CIPHER:
+ category_name = OSSL_SELF_TEST_TYPE_KAT_CIPHER;
+ break;
+ case FIPS_DEFERRED_KAT_ASYM_CIPHER:
+ category_name = OSSL_SELF_TEST_TYPE_KAT_ASYM_CIPHER;
+ break;
+ case FIPS_DEFERRED_KAT_ASYM_KEYGEN:
+ category_name = OSSL_SELF_TEST_TYPE_KAT_ASYM_KEYGEN;
+ break;
+ case FIPS_DEFERRED_KAT_KEM:
+ category_name = OSSL_SELF_TEST_TYPE_KAT_KEM;
+ break;
+ case FIPS_DEFERRED_KAT_DIGEST:
+ category_name = OSSL_SELF_TEST_TYPE_KAT_DIGEST;
+ break;
+ case FIPS_DEFERRED_KAT_SIGNATURE:
+ category_name = OSSL_SELF_TEST_TYPE_KAT_SIGNATURE;
+ break;
+ case FIPS_DEFERRED_KAT_KDF:
+ category_name = OSSL_SELF_TEST_TYPE_KAT_KDF;
+ break;
+ case FIPS_DEFERRED_KAT_KA:
+ category_name = OSSL_SELF_TEST_TYPE_KAT_KA;
+ break;
+ case FIPS_DEFERRED_DRBG:
+ category_name = OSSL_SELF_TEST_TYPE_DRBG;
+ break;
+ }
+ ossl_set_error_state(category_name);
+}
+
+int FIPS_deferred_self_tests(OSSL_LIB_CTX *libctx, FIPS_DEFERRED_TEST tests[])
+{
+ int i;
+
+ /*
+ * NOTE: that the order in which we check the 'state' here is not important,
+ * if multiple threads are racing to check it the worst case scenario is
+ * that they will all try to run the tests. Proper locking for preventing
+ * concurrent tests runs and saving state from multiple threads is handled
+ * in FIPS_kat_deferred() so this race is of no real consequence.
+ */
+ for (i = 0; tests[i].algorithm != NULL; i++) {
+ if (tests[i].state != FIPS_DEFERRED_TEST_PASSED) {
+ int state;
+
+ /* any other threads that request a self test will lock and wait */
+ state = FIPS_kat_deferred(libctx, &tests[i]);
+ switch (state) {
+ case FIPS_DEFERRED_TEST_IN_PROGRESS:
+ /*
+ * A self test is in progress for this thread so we let this
+ * thread continue and perform the test while all other
+ * threads wait for it to complete.
+ */
+ return 1;
+ case FIPS_DEFERRED_TEST_PASSED:
+ /* success, move on to the next */
+ break;
+ default:
+ deferred_test_error(tests[i].category);
+ return 0;
+ }
+ }
+ }
+
+ /* all tests passed */
+ return 1;
+}
int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test);
int SELF_TEST_kats(OSSL_SELF_TEST *event, OSSL_LIB_CTX *libctx);
+int SELF_TEST_kats_single(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx,
+ int type, const char *alg_name);
void SELF_TEST_disable_conditional_error_state(void);
typedef struct st_kat_st {
const char *desc;
const char *algorithm;
+ int deferred;
const unsigned char *pt;
size_t pt_len;
const unsigned char *expected;
typedef struct st_kat_kdf_st {
const char *desc;
const char *algorithm;
+ int deferred;
const ST_KAT_PARAM *params;
const unsigned char *expected;
size_t expected_len;
typedef struct st_kat_drbg_st {
const char *desc;
const char *algorithm;
+ int deferred;
const char *param_name;
char *param_value;
const unsigned char *entropyin;
typedef struct st_kat_kas_st {
const char *desc;
const char *algorithm;
+ int deferred;
const ST_KAT_PARAM *key_group;
const ST_KAT_PARAM *key_host_data;
const char *desc;
const char *keytype;
const char *sigalgorithm;
+ int deferred;
int mode;
const ST_KAT_PARAM *key;
const unsigned char *msg;
typedef struct st_kat_asym_cipher_st {
const char *desc;
const char *algorithm;
+ int deferred;
int encrypt;
const ST_KAT_PARAM *key;
const ST_KAT_PARAM *postinit;
typedef struct st_kat_keygen_st {
const char *desc;
const char *algorithm;
+ int deferred;
const ST_KAT_PARAM *keygen_params;
const ST_KAT_PARAM *expected_params;
} ST_KAT_ASYM_KEYGEN;
typedef struct st_kat_kem_st {
const char *desc;
const char *algorithm;
+ int deferred;
const ST_KAT_PARAM *key;
const unsigned char *cipher_text;
size_t cipher_text_len;
{
OSSL_SELF_TEST_DESC_MD_SHA1,
"SHA1",
+ 0,
ITM_STR(sha1_pt),
ITM(sha1_digest),
},
{
OSSL_SELF_TEST_DESC_MD_SHA2,
"SHA512",
+ 0,
ITM_STR(sha512_pt),
ITM(sha512_digest),
},
{
OSSL_SELF_TEST_DESC_MD_SHA3,
"SHA3-256",
+ 0,
ITM(sha3_256_pt),
ITM(sha3_256_digest),
},
{
OSSL_SELF_TEST_DESC_CIPHER_AES_GCM,
"AES-256-GCM",
+ 0,
ITM(aes_256_gcm_pt),
ITM(aes_256_gcm_ct)
},
{
OSSL_SELF_TEST_DESC_CIPHER_AES_ECB,
"AES-128-ECB",
+ 0,
ITM(aes_128_ecb_pt),
ITM(aes_128_ecb_ct)
},
{
OSSL_SELF_TEST_DESC_CIPHER_TDES,
"DES-EDE3-ECB",
+ 0,
ITM(tdes_pt),
ITM(tdes_ct)
},
#ifndef OPENSSL_NO_LMS
typedef struct st_kat_lms_s {
+ int deferred;
const unsigned char *pub;
size_t publen;
const unsigned char *msg;
};
static const ST_KAT_LMS st_kat_lms_test = {
+ 0,
ITM(sha256_192_pub),
ITM(sha256_192_msg),
ITM(sha256_192_sig)
{
OSSL_SELF_TEST_DESC_KDF_TLS13_EXTRACT,
OSSL_KDF_NAME_TLS1_3_KDF,
+ 0,
tls13_kdf_early_secret_params,
ITM(tls13_kdf_early_secret)
},
{
OSSL_SELF_TEST_DESC_KDF_TLS13_EXPAND,
OSSL_KDF_NAME_TLS1_3_KDF,
+ 0,
tls13_kdf_client_early_secret_params,
ITM(tls13_kdf_client_early_traffic_secret)
},
{
OSSL_SELF_TEST_DESC_KDF_TLS12_PRF,
OSSL_KDF_NAME_TLS1_PRF,
+ 0,
tls12prf_params,
ITM(tls12prf_expected)
},
{
OSSL_SELF_TEST_DESC_KDF_PBKDF2,
OSSL_KDF_NAME_PBKDF2,
+ 0,
pbkdf2_params,
ITM(pbkdf2_expected)
},
{
OSSL_SELF_TEST_DESC_KDF_KBKDF,
OSSL_KDF_NAME_KBKDF,
+ 0,
kbkdf_params,
ITM(kbkdf_expected)
},
{
OSSL_SELF_TEST_DESC_KDF_KBKDF_KMAC,
OSSL_KDF_NAME_KBKDF,
+ 0,
kbkdf_kmac_params,
ITM(kbkdf_kmac_expected)
},
{
OSSL_SELF_TEST_DESC_KDF_HKDF,
OSSL_KDF_NAME_HKDF,
+ 0,
hkdf_params,
ITM(hkdf_expected)
},
{
OSSL_SELF_TEST_DESC_KDF_SSKDF,
OSSL_KDF_NAME_SSKDF,
+ 0,
sskdf_params,
ITM(sskdf_expected)
},
{
OSSL_SELF_TEST_DESC_KDF_X963KDF,
OSSL_KDF_NAME_X963KDF,
+ 0,
x963kdf_params,
ITM(x963kdf_expected)
},
{
OSSL_SELF_TEST_DESC_KDF_X942KDF,
OSSL_KDF_NAME_X942KDF_ASN1,
+ 0,
x942kdf_params,
ITM(x942kdf_expected)
},
{
{
OSSL_SELF_TEST_DESC_DRBG_HASH,
- "HASH-DRBG", "digest", "SHA256",
+ "HASH-DRBG",
+ 0,
+ "digest", "SHA256",
ITM(drbg_hash_sha256_pr_entropyin),
ITM(drbg_hash_sha256_pr_nonce),
ITM(drbg_hash_sha256_pr_persstr),
},
{
OSSL_SELF_TEST_DESC_DRBG_CTR,
- "CTR-DRBG", "cipher", "AES-128-CTR",
+ "CTR-DRBG",
+ 0,
+ "cipher", "AES-128-CTR",
ITM(drbg_ctr_aes128_pr_df_entropyin),
ITM(drbg_ctr_aes128_pr_df_nonce),
ITM(drbg_ctr_aes128_pr_df_persstr),
},
{
OSSL_SELF_TEST_DESC_DRBG_HMAC,
- "HMAC-DRBG", "digest", "SHA256",
+ "HMAC-DRBG",
+ 0,
+ "digest", "SHA256",
ITM(drbg_hmac_sha2_pr_entropyin),
ITM(drbg_hmac_sha2_pr_nonce),
ITM(drbg_hmac_sha2_pr_persstr),
{
OSSL_SELF_TEST_DESC_KA_DH,
"DH",
+ 0,
dh_group,
dh_host_key,
dh_peer_key,
{
OSSL_SELF_TEST_DESC_KA_ECDH,
"EC",
+ 0,
ecdh_group,
ecdh_host_key,
ecdh_peer_key,
static const ST_KAT_SIGN st_kat_sign_tests[] = {
{
OSSL_SELF_TEST_DESC_SIGN_RSA,
- "RSA", "RSA-SHA256", 0,
+ "RSA", "RSA-SHA256", 0, 0,
rsa_crt_key,
ITM_STR(rsa_sig_msg),
ITM(sig_kat_entropyin),
#ifndef OPENSSL_NO_EC
{
OSSL_SELF_TEST_DESC_SIGN_ECDSA,
- "EC", "ECDSA-SHA256", 0,
+ "EC", "ECDSA-SHA256", 0, 0,
ecdsa_prime_key,
ITM_STR(rsa_sig_msg),
ITM(sig_kat_entropyin),
},
{
OSSL_SELF_TEST_DESC_SIGN_DetECDSA,
- "EC", "ECDSA-SHA256", 0,
+ "EC", "ECDSA-SHA256", 0, 0,
ecdsa_prime_key,
ITM_STR(rsa_sig_msg),
NULL, 0, NULL, 0, NULL, 0,
# ifndef OPENSSL_NO_EC2M
{
OSSL_SELF_TEST_DESC_SIGN_ECDSA,
- "EC", "ECDSA-SHA256", 0,
+ "EC", "ECDSA-SHA256", 0, 0,
ecdsa_bin_key,
ITM_STR(rsa_sig_msg),
ITM(sig_kat_entropyin),
# ifndef OPENSSL_NO_ECX
{
OSSL_SELF_TEST_DESC_SIGN_EDDSA,
- "ED448", "ED448", 0,
+ "ED448", "ED448", 0, 0,
ed448_key,
ITM(ecx_sig_msg),
NULL, 0, NULL, 0, NULL, 0,
},
{
OSSL_SELF_TEST_DESC_SIGN_EDDSA,
- "ED25519", "ED25519", 0,
+ "ED25519", "ED25519", 0, 0,
ed25519_key,
ITM(ecx_sig_msg),
NULL, 0, NULL, 0, NULL, 0,
#ifndef OPENSSL_NO_DSA
{
OSSL_SELF_TEST_DESC_SIGN_DSA,
- "DSA", "DSA-SHA256", SIGNATURE_MODE_VERIFY_ONLY,
+ "DSA", "DSA-SHA256", 0, SIGNATURE_MODE_VERIFY_ONLY,
dsa_key,
ITM_STR(rsa_sig_msg),
ITM(sig_kat_entropyin),
#ifndef OPENSSL_NO_ML_DSA
{
OSSL_SELF_TEST_DESC_SIGN_ML_DSA,
- "ML-DSA-65", "ML-DSA-65", 0,
+ "ML-DSA-65", "ML-DSA-65", 0, 0,
ml_dsa_key,
ITM(ml_dsa_65_msg),
NULL, 0,
*/
{
OSSL_SELF_TEST_DESC_SIGN_SLH_DSA,
- "SLH-DSA-SHA2-128f", "SLH-DSA-SHA2-128f", SIGNATURE_MODE_SIG_DIGESTED,
+ "SLH-DSA-SHA2-128f", "SLH-DSA-SHA2-128f",
+ 0, SIGNATURE_MODE_SIG_DIGESTED,
slh_dsa_sha2_128f_key_params,
ITM(slh_dsa_sha2_sig_msg),
NULL, 0, NULL, 0, NULL, 0,
},
{
OSSL_SELF_TEST_DESC_SIGN_SLH_DSA,
- "SLH-DSA-SHAKE-128f", "SLH-DSA-SHAKE-128f", SIGNATURE_MODE_SIG_DIGESTED,
+ "SLH-DSA-SHAKE-128f", "SLH-DSA-SHAKE-128f",
+ 0, SIGNATURE_MODE_SIG_DIGESTED,
slh_dsa_shake_128f_key_params,
ITM(slh_dsa_shake_sig_msg),
NULL, 0, NULL, 0, NULL, 0,
static const ST_KAT_KEM st_kat_kem_tests[] = {
{
OSSL_SELF_TEST_DESC_KEM,
- "ML-KEM-512",
+ "ML-KEM-512", 0,
ml_kem_key,
ITM(ml_kem_512_cipher_text),
ITM(ml_kem_512_entropy),
*/
{
OSSL_SELF_TEST_DESC_KEYGEN_ML_KEM,
- "ML-KEM-512",
+ "ML-KEM-512", 0,
ml_kem_keygen_params,
ml_kem_key
},
# if !defined(OPENSSL_NO_ML_DSA)
{
OSSL_SELF_TEST_DESC_KEYGEN_ML_DSA,
- "ML-DSA-65",
+ "ML-DSA-65", 0,
ml_dsa_keygen_params,
ml_dsa_key
},
# if !defined(OPENSSL_NO_SLH_DSA)
{
OSSL_SELF_TEST_DESC_KEYGEN_SLH_DSA,
- "SLH-DSA-SHA2-128f",
+ "SLH-DSA-SHA2-128f", 0,
slh_dsa_sha2_128f_keygen_init_params,
slh_dsa_128f_keygen_expected_params
},
static const ST_KAT_ASYM_CIPHER st_kat_asym_cipher_tests[] = {
{
OSSL_SELF_TEST_DESC_ASYM_RSA_ENC,
- "RSA",
+ "RSA", 0,
1,
rsa_pub_key,
rsa_enc_params,
},
{
OSSL_SELF_TEST_DESC_ASYM_RSA_DEC,
- "RSA",
+ "RSA", 0,
0,
rsa_priv_key,
rsa_enc_params,
},
{
OSSL_SELF_TEST_DESC_ASYM_RSA_DEC,
- "RSA",
+ "RSA", 0,
0,
rsa_crt_key,
rsa_enc_params,
#include "self_test.h"
#include "crypto/ml_kem.h"
#include "self_test_data.inc"
+#include "internal/fips.h"
static int set_kat_drbg(OSSL_LIB_CTX *ctx,
const unsigned char *entropy, size_t entropy_len,
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_digest_tests); ++i) {
+ if (st_kat_digest_tests[i].deferred)
+ continue;
if (!self_test_digest(&st_kat_digest_tests[i], st, libctx))
ret = 0;
}
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_cipher_tests); ++i) {
+ if (st_kat_cipher_tests[i].base.deferred)
+ continue;
if (!self_test_cipher(&st_kat_cipher_tests[i], st, libctx))
ret = 0;
}
int i;
for (i = 0; i < (int)OSSL_NELEM(st_kat_kem_tests); ++i) {
+ if (st_kat_kem_tests[i].deferred)
+ continue;
if (!self_test_kem(&st_kat_kem_tests[i], st, libctx))
ret = 0;
}
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_asym_cipher_tests); ++i) {
+ if (st_kat_asym_cipher_tests[i].deferred)
+ continue;
if (!self_test_asym_cipher(&st_kat_asym_cipher_tests[i], st, libctx))
ret = 0;
}
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_kdf_tests); ++i) {
+ if (st_kat_kdf_tests[i].deferred)
+ continue;
if (!self_test_kdf(&st_kat_kdf_tests[i], st, libctx))
ret = 0;
}
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_drbg_tests); ++i) {
+ if (st_kat_drbg_tests[i].deferred)
+ continue;
if (!self_test_drbg(&st_kat_drbg_tests[i], st, libctx))
ret = 0;
}
int i;
for (i = 0; i < (int)OSSL_NELEM(st_kat_kas_tests); ++i) {
+ if (st_kat_kas_tests[i].deferred)
+ continue;
if (!self_test_ka(&st_kat_kas_tests[i], st, libctx))
ret = 0;
}
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_sign_tests); ++i) {
+ if (st_kat_sign_tests[i].deferred)
+ continue;
if (!self_test_digest_sign(&st_kat_sign_tests[i], st, libctx))
ret = 0;
}
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_asym_keygen_tests); ++i) {
+ if (st_kat_asym_keygen_tests[i].deferred)
+ continue;
if (!self_test_asym_keygen(&st_kat_asym_keygen_tests[i], st, libctx))
ret = 0;
}
return ret;
}
+/*
+ * 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 type, const char *alg_name)
+{
+ int ret = 1;
+ int i, found = 0;
+
+ if (alg_name == NULL)
+ return 0;
+
+ switch (type) {
+ case FIPS_DEFERRED_KAT_DIGEST:
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_digest_tests); ++i) {
+ if (strcmp(st_kat_digest_tests[i].algorithm, alg_name) == 0) {
+ found = 1;
+ if (!self_test_digest(&st_kat_digest_tests[i], st, libctx)) {
+ ret = 0;
+ goto done;
+ }
+ }
+ }
+ break;
+
+ case FIPS_DEFERRED_KAT_CIPHER:
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_cipher_tests); ++i) {
+ if (strcmp(st_kat_cipher_tests[i].base.algorithm, alg_name) == 0) {
+ found = 1;
+ if (!self_test_cipher(&st_kat_cipher_tests[i], st, libctx)) {
+ ret = 0;
+ goto done;
+ }
+ }
+ }
+ break;
+
+ case FIPS_DEFERRED_KAT_SIGNATURE:
+
+#ifndef OPENSSL_NO_LMS
+ if (strcmp("LMS", alg_name) == 0) {
+ found = 1;
+ if (!self_test_LMS(st, libctx)) {
+ ret = 0;
+ goto done;
+ }
+ break;
+ }
+#endif /* OPENSSL_NO_LMS */
+
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_sign_tests); ++i) {
+ if (strcmp(st_kat_sign_tests[i].sigalgorithm, alg_name) == 0
+ || strcmp(st_kat_sign_tests[i].keytype, alg_name) == 0) {
+ found = 1;
+ if (!self_test_digest_sign(&st_kat_sign_tests[i], st, libctx)) {
+ ret = 0;
+ goto done;
+ }
+ }
+ }
+ break;
+
+ case FIPS_DEFERRED_KAT_KDF:
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_kdf_tests); ++i) {
+ if (strcmp(st_kat_kdf_tests[i].algorithm, alg_name) == 0) {
+ found = 1;
+ if (!self_test_kdf(&st_kat_kdf_tests[i], st, libctx)) {
+ ret = 0;
+ goto done;
+ }
+ }
+ }
+ break;
+
+#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC)
+ case FIPS_DEFERRED_KAT_KA:
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_kas_tests); ++i) {
+ if (strcmp(st_kat_kas_tests[i].algorithm, alg_name) == 0) {
+ found = 1;
+ if (!self_test_ka(&st_kat_kas_tests[i], st, libctx)) {
+ ret = 0;
+ goto done;
+ }
+ }
+ }
+ break;
+#endif
+
+#if !defined(OPENSSL_NO_ML_DSA) || !defined(OPENSSL_NO_SLH_DSA)
+ case FIPS_DEFERRED_KAT_ASYM_KEYGEN:
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_asym_keygen_tests); ++i) {
+ if (strcmp(st_kat_asym_keygen_tests[i].algorithm, alg_name) == 0) {
+ found = 1;
+ if (!self_test_asym_keygen(&st_kat_asym_keygen_tests[i], st, libctx)) {
+ ret = 0;
+ goto done;
+ }
+ }
+ }
+ break;
+#endif /* OPENSSL_NO_ML_DSA */
+
+#ifndef OPENSSL_NO_ML_KEM
+ case FIPS_DEFERRED_KAT_KEM:
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_kem_tests); ++i) {
+ if (strcmp(st_kat_kem_tests[i].algorithm, alg_name) == 0) {
+ found = 1;
+ if (!self_test_kem(&st_kat_kem_tests[i], st, libctx)) {
+ ret = 0;
+ goto done;
+ }
+ }
+ }
+ break;
+#endif
+
+ case FIPS_DEFERRED_KAT_ASYM_CIPHER:
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_asym_cipher_tests); ++i) {
+ if (strcmp(st_kat_asym_cipher_tests[i].algorithm, alg_name) == 0) {
+ found = 1;
+ if (!self_test_asym_cipher(&st_kat_asym_cipher_tests[i], st, libctx)) {
+ ret = 0;
+ goto done;
+ }
+ }
+ }
+ break;
+
+ case FIPS_DEFERRED_DRBG:
+ for (i = 0; i < (int)OSSL_NELEM(st_kat_drbg_tests); ++i) {
+ if (strcmp(st_kat_drbg_tests[i].algorithm, alg_name) == 0) {
+ found = 1;
+ if (!self_test_drbg(&st_kat_drbg_tests[i], st, libctx)) {
+ ret = 0;
+ goto done;
+ }
+ }
+ }
+ break;
+
+ default:
+ /* not tests yet, or bad type */
+ break;
+ }
+
+done:
+ /* If no test was found for alg_name, it is considered a failure */
+ return ret && found;
+}