}
}
+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)
{
int *rt = NULL;
/* mark that we are executing a test on the local thread */
if (!CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_FIPS_DEFERRED_KEY,
- libctx, (void *)0xC001))
+ libctx, rt))
goto done;
unset_key = true;
if ((st = OSSL_SELF_TEST_new(cb, cb_arg)) == NULL)
goto done;
- /*
- * 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) {
-
- /* Mark test as in progress */
- st_all_tests[id].state = SELF_TEST_STATE_IN_PROGRESS;
-
- /* execute test */
- if (!SELF_TEST_kats_single(st, libctx, id))
- 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
* in FIPS_kat_deferred() so this race is of no real consequence.
*/
ret = FIPS_kat_deferred(libctx, id);
- if (!ret)
+ if (!ret || st_all_tests[id].state == SELF_TEST_STATE_FAILED)
deferred_test_error(st_all_tests[id].category);
return ret;
}