X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=fips%2Frand%2Ffips_drbg_selftest.c;h=ee0561bcbeb906fc2d3fda52bb30dfc3b96748f1;hp=40a3ca81629f864c9e79eea865ce457f9d148dfa;hb=43760a2cf02a6d710d40bd6ed43c7bf61918fadd;hpb=7fdcb45745c01b90b256fe97e87eae31453e11e6 diff --git a/fips/rand/fips_drbg_selftest.c b/fips/rand/fips_drbg_selftest.c index 40a3ca8162..ee0561bcbe 100644 --- a/fips/rand/fips_drbg_selftest.c +++ b/fips/rand/fips_drbg_selftest.c @@ -206,6 +206,10 @@ static int fips_drbg_single_kat(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td, /* Initial test without PR */ + /* Instantiate DRBG with test entropy, nonce and personalisation + * string. + */ + if (!FIPS_drbg_init(dctx, td->nid, td->flags)) return 0; if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0)) @@ -227,11 +231,13 @@ static int fips_drbg_single_kat(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td, * ignore bytes after the keylength: so reduce adinlen * to half to ensure invalid data is fed in. */ - if (!fips_post_corrupt(FIPS_TEST_DRBG, dctx->type, &dctx->flags)) + if (!fips_post_corrupt(FIPS_TEST_DRBG, dctx->type, &dctx->iflags)) adinlen = td->adinlen / 2; else adinlen = td->adinlen; - if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0, 0, + + /* Generate with no PR and verify output matches expected data */ + if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0, td->adin, adinlen)) goto err; @@ -240,20 +246,21 @@ static int fips_drbg_single_kat(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td, FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_NOPR_TEST1_FAILURE); goto err2; } - + /* If abbreviated POST end of test */ if (quick) { rv = 1; goto err; } - + /* Reseed DRBG with test entropy and additional input */ t.ent = td->entreseed; t.entlen = td->entreseedlen; if (!FIPS_drbg_reseed(dctx, td->adinreseed, td->adinreseedlen)) goto err; - if (!FIPS_drbg_generate(dctx, randout, td->kat2len, 0, 0, + /* Generate with no PR and verify output matches expected data */ + if (!FIPS_drbg_generate(dctx, randout, td->kat2len, 0, td->adin2, td->adin2len)) goto err; @@ -266,6 +273,10 @@ static int fips_drbg_single_kat(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td, FIPS_drbg_uninstantiate(dctx); /* Now test with PR */ + + /* Instantiate DRBG with test entropy, nonce and personalisation + * string. + */ if (!FIPS_drbg_init(dctx, td->nid, td->flags)) return 0; if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0)) @@ -283,6 +294,10 @@ static int fips_drbg_single_kat(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td, if (!FIPS_drbg_instantiate(dctx, td->pers_pr, td->perslen_pr)) goto err; + /* Now generate with PR: we need to supply entropy as this will + * perform a reseed operation. Check output matches expected value. + */ + t.ent = td->entpr_pr; t.entlen = td->entprlen_pr; @@ -290,11 +305,11 @@ static int fips_drbg_single_kat(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td, * ignore bytes after the keylength: so reduce adinlen * to half to ensure invalid data is fed in. */ - if (!fips_post_corrupt(FIPS_TEST_DRBG, dctx->type, &dctx->flags)) + if (!fips_post_corrupt(FIPS_TEST_DRBG, dctx->type, &dctx->iflags)) adinlen = td->adinlen_pr / 2; else adinlen = td->adinlen_pr; - if (!FIPS_drbg_generate(dctx, randout, td->katlen_pr, 0, 1, + if (!FIPS_drbg_generate(dctx, randout, td->katlen_pr, 1, td->adin_pr, adinlen)) goto err; @@ -304,10 +319,14 @@ static int fips_drbg_single_kat(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td, goto err2; } + /* Now generate again with PR: supply new entropy again. + * Check output matches expected value. + */ + t.ent = td->entg_pr; t.entlen = td->entglen_pr; - if (!FIPS_drbg_generate(dctx, randout, td->kat2len_pr, 0, 1, + if (!FIPS_drbg_generate(dctx, randout, td->kat2len_pr, 1, td->ading_pr, td->adinglen_pr)) goto err; @@ -316,7 +335,7 @@ static int fips_drbg_single_kat(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td, FIPSerr(FIPS_F_FIPS_DRBG_SINGLE_KAT, FIPS_R_PR_TEST2_FAILURE); goto err2; } - + /* All OK, test complete */ rv = 1; err: @@ -329,11 +348,47 @@ static int fips_drbg_single_kat(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td, } -/* This is the "health check" function required by SP800-90. Induce several - * failure modes and check an error condition is set. +/* Initialise a DRBG based on selftest data */ + +static int do_drbg_init(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td, TEST_ENT *t) + { + + if (!FIPS_drbg_init(dctx, td->nid, td->flags)) + return 0; + + if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0)) + return 0; + + FIPS_drbg_set_app_data(dctx, t); + + t->ent = td->ent; + t->entlen = td->entlen; + t->nonce = td->nonce; + t->noncelen = td->noncelen; + t->entcnt = 0; + t->noncecnt = 0; + return 1; + } + +/* Initialise and instantiate DRBG based on selftest data */ +static int do_drbg_instantiate(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td, + TEST_ENT *t) + { + if (!do_drbg_init(dctx, td, t)) + return 0; + if (!FIPS_drbg_instantiate(dctx, td->pers, td->perslen)) + return 0; + + return 1; + } + +/* This function performs extensive error checking as required by SP800-90. + * Induce several failure modes and check an error condition is set. + * This function along with fips_drbg_single_kat peforms the health checking + * operation. */ -static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) +static int fips_drbg_error_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) { unsigned char randout[1024]; TEST_ENT t; @@ -343,91 +398,173 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) /* Initialise DRBG */ - if (!FIPS_drbg_init(dctx, td->nid, td->flags)) - goto err; - - if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0)) + if (!do_drbg_init(dctx, td, &t)) goto err; - FIPS_drbg_set_app_data(dctx, &t); + /* Don't report induced errors */ + dctx->iflags |= DRBG_FLAG_NOERR; - t.ent = td->ent; - t.entlen = td->entlen; - t.nonce = td->nonce; - t.noncelen = td->noncelen; - t.entcnt = 0; - t.noncecnt = 0; + /* Personalisation string tests */ - /* Don't report induced errors */ - dctx->flags |= DRBG_FLAG_NOERR; + /* Test detection of too large personlisation string */ - /* Try too large a personalisation length */ if (FIPS_drbg_instantiate(dctx, td->pers, dctx->max_pers + 1) > 0) { - FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_PERSONALISATION_ERROR_UNDETECTED); + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_PERSONALISATION_ERROR_UNDETECTED); goto err; } - /* Test entropy source failure detection */ + /* Entropy source tests */ + + /* Test entropy source failure detecion: i.e. returns no data */ t.entlen = 0; + if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0) { - FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED); + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED); goto err; } /* Try to generate output from uninstantiated DRBG */ - if (FIPS_drbg_generate(dctx, randout, td->katlen, 0, 0, + if (FIPS_drbg_generate(dctx, randout, td->katlen, 0, td->adin, td->adinlen)) { - FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_GENERATE_ERROR_UNDETECTED); + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_GENERATE_ERROR_UNDETECTED); goto err; } - dctx->flags &= ~DRBG_FLAG_NOERR; + dctx->iflags &= ~DRBG_FLAG_NOERR; if (!FIPS_drbg_uninstantiate(dctx)) { - FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR); + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_UNINSTANTIATE_ERROR); goto err; } - /* Instantiate with valid data. NB: errors now reported again */ - if (!FIPS_drbg_init(dctx, td->nid, td->flags)) + if (!do_drbg_init(dctx, td, &t)) goto err; - if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0)) + + dctx->iflags |= DRBG_FLAG_NOERR; + + /* Test insufficient entropy */ + + t.entlen = dctx->min_entropy - 1; + + if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED); goto err; - FIPS_drbg_set_app_data(dctx, &t); + } - t.entlen = td->entlen; - if (!FIPS_drbg_instantiate(dctx, td->pers, td->perslen)) + dctx->iflags &= ~DRBG_FLAG_NOERR; + if (!FIPS_drbg_uninstantiate(dctx)) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_UNINSTANTIATE_ERROR); goto err; + } - /* Check generation is now OK */ - if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0, 0, - td->adin, td->adinlen)) + /* Test too much entropy */ + + if (!do_drbg_init(dctx, td, &t)) goto err; - /* Try to generate with too high a strength. - */ + dctx->iflags |= DRBG_FLAG_NOERR; + + t.entlen = dctx->max_entropy + 1; - dctx->flags |= DRBG_FLAG_NOERR; - if (dctx->strength != 256) + if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED); + goto err; + } + + dctx->iflags &= ~DRBG_FLAG_NOERR; + if (!FIPS_drbg_uninstantiate(dctx)) { - if (FIPS_drbg_generate(dctx, randout, td->katlen, 256, 0, - td->adin, td->adinlen)) + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_UNINSTANTIATE_ERROR); + goto err; + } + + /* Nonce tests */ + + /* Test too small nonce */ + + if (dctx->min_nonce) + { + + if (!do_drbg_init(dctx, td, &t)) + goto err; + + dctx->iflags |= DRBG_FLAG_NOERR; + + t.noncelen = dctx->min_nonce - 1; + + if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0) { - FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_STRENGTH_ERROR_UNDETECTED); + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_NONCE_ERROR_UNDETECTED); + goto err; + } + dctx->iflags &= ~DRBG_FLAG_NOERR; + if (!FIPS_drbg_uninstantiate(dctx)) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_UNINSTANTIATE_ERROR); goto err; } + } + /* Test too large nonce */ + + if (dctx->max_nonce) + { + + if (!do_drbg_init(dctx, td, &t)) + goto err; + + dctx->iflags |= DRBG_FLAG_NOERR; + + t.noncelen = dctx->max_nonce + 1; + + if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_NONCE_ERROR_UNDETECTED); + goto err; + } + + dctx->iflags &= ~DRBG_FLAG_NOERR; + if (!FIPS_drbg_uninstantiate(dctx)) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_UNINSTANTIATE_ERROR); + goto err; + } + + } + + /* Instantiate with valid data. */ + if (!do_drbg_instantiate(dctx, td, &t)) + goto err; + + /* Check generation is now OK */ + if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0, + td->adin, td->adinlen)) + goto err; + + dctx->iflags |= DRBG_FLAG_NOERR; + /* Request too much data for one request */ - if (FIPS_drbg_generate(dctx, randout, dctx->max_request + 1, 0, 0, + if (FIPS_drbg_generate(dctx, randout, dctx->max_request + 1, 0, td->adin, td->adinlen)) { - FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_REQUEST_LENGTH_ERROR_UNDETECTED); + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_REQUEST_LENGTH_ERROR_UNDETECTED); + goto err; + } + + /* Try too large additional input */ + if (FIPS_drbg_generate(dctx, randout, td->katlen, 0, + td->adin, dctx->max_adin + 1)) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_ADDITIONAL_INPUT_ERROR_UNDETECTED); goto err; } @@ -437,34 +574,90 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) t.entlen = 0; - if (FIPS_drbg_generate(dctx, randout, td->katlen, 0, 1, + if (FIPS_drbg_generate(dctx, randout, td->katlen, 1, td->adin, td->adinlen)) { - FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED); + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED); goto err; } - dctx->flags &= ~DRBG_FLAG_NOERR; + dctx->iflags &= ~DRBG_FLAG_NOERR; if (!FIPS_drbg_uninstantiate(dctx)) { - FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ERROR); + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_UNINSTANTIATE_ERROR); goto err; } /* Instantiate again with valid data */ - if (!FIPS_drbg_init(dctx, td->nid, td->flags)) + if (!do_drbg_instantiate(dctx, td, &t)) + goto err; + /* Test reseed counter works */ + /* Save initial reseed counter */ + reseed_counter_tmp = dctx->reseed_counter; + /* Set reseed counter to beyond interval */ + dctx->reseed_counter = dctx->reseed_interval; + + /* Generate output and check entropy has been requested for reseed */ + t.entcnt = 0; + if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0, + td->adin, td->adinlen)) goto err; - if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0)) + if (t.entcnt != 1) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED); goto err; - FIPS_drbg_set_app_data(dctx, &t); + } + /* Check reseed counter has been reset */ + if (dctx->reseed_counter != reseed_counter_tmp + 1) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_RESEED_COUNTER_ERROR); + goto err; + } - t.entlen = td->entlen; - /* Test reseed counter works */ - if (!FIPS_drbg_instantiate(dctx, td->pers, td->perslen)) + /* Explicit reseed tests */ + + /* Test explicit reseed with too large additional input */ + if (!do_drbg_init(dctx, td, &t)) + goto err; + + dctx->iflags |= DRBG_FLAG_NOERR; + + if (FIPS_drbg_reseed(dctx, td->adin, dctx->max_adin + 1) > 0) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_ADDITIONAL_INPUT_ERROR_UNDETECTED); goto err; + } + + /* Test explicit reseed with entropy source failure */ + + /* Check prediction resistance request fails if entropy source + * failure. + */ + + t.entlen = 0; + + if (FIPS_drbg_generate(dctx, randout, td->katlen, 1, + td->adin, td->adinlen)) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED); + goto err; + } + + dctx->iflags &= ~DRBG_FLAG_NOERR; + + if (!FIPS_drbg_uninstantiate(dctx)) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_UNINSTANTIATE_ERROR); + goto err; + } + + + if (!do_drbg_instantiate(dctx, td, &t)) + goto err; + /* Test reseed counter works */ /* Save initial reseed counter */ reseed_counter_tmp = dctx->reseed_counter; /* Set reseed counter to beyond interval */ @@ -472,22 +665,98 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) /* Generate output and check entropy has been requested for reseed */ t.entcnt = 0; - if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0, 0, + if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0, td->adin, td->adinlen)) goto err; if (t.entcnt != 1) { - FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED); + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED); goto err; } /* Check reseed counter has been reset */ if (dctx->reseed_counter != reseed_counter_tmp + 1) { - FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_RESEED_COUNTER_ERROR); + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_RESEED_COUNTER_ERROR); + goto err; + } + + /* Explicit reseed tests */ + + /* Test explicit reseed with too large additional input */ + if (!do_drbg_init(dctx, td, &t)) + goto err; + + dctx->iflags |= DRBG_FLAG_NOERR; + + if (FIPS_drbg_reseed(dctx, td->adin, dctx->max_adin + 1) > 0) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_ADDITIONAL_INPUT_ERROR_UNDETECTED); + goto err; + } + + /* Test explicit reseed with entropy source failure */ + + if (!do_drbg_init(dctx, td, &t)) + goto err; + + dctx->iflags |= DRBG_FLAG_NOERR; + + t.entlen = 0; + + if (FIPS_drbg_reseed(dctx, td->adin, td->adinlen) > 0) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED); + goto err; + } + + if (!FIPS_drbg_uninstantiate(dctx)) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_UNINSTANTIATE_ERROR); + goto err; + } + + /* Test explicit reseed with too much entropy */ + + if (!do_drbg_init(dctx, td, &t)) + goto err; + + dctx->iflags |= DRBG_FLAG_NOERR; + + t.entlen = dctx->max_entropy + 1; + + if (FIPS_drbg_reseed(dctx, td->adin, td->adinlen) > 0) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED); + goto err; + } + + if (!FIPS_drbg_uninstantiate(dctx)) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_UNINSTANTIATE_ERROR); + goto err; + } + + /* Test explicit reseed with too little entropy */ + + if (!do_drbg_init(dctx, td, &t)) + goto err; + + dctx->iflags |= DRBG_FLAG_NOERR; + + t.entlen = dctx->min_entropy - 1; + + if (FIPS_drbg_reseed(dctx, td->adin, td->adinlen) > 0) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED); + goto err; + } + + if (!FIPS_drbg_uninstantiate(dctx)) + { + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_UNINSTANTIATE_ERROR); goto err; } - FIPS_drbg_uninstantiate(dctx); p = (unsigned char *)&dctx->d; /* Standard says we have to check uninstantiate really zeroes * the data... @@ -496,7 +765,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) { if (*p != 0) { - FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ZEROISE_ERROR); + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_UNINSTANTIATE_ZEROISE_ERROR); goto err; } p++; @@ -508,31 +777,51 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) /* A real error as opposed to an induced one: underlying function will * indicate the error. */ - if (!(dctx->flags & DRBG_FLAG_NOERR)) - FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_FUNCTION_ERROR); + if (!(dctx->iflags & DRBG_FLAG_NOERR)) + FIPSerr(FIPS_F_FIPS_DRBG_ERROR_CHECK, FIPS_R_FUNCTION_ERROR); FIPS_drbg_uninstantiate(dctx); return 0; } - int fips_drbg_kat(DRBG_CTX *dctx, int nid, unsigned int flags) { - int rv; DRBG_SELFTEST_DATA *td; + flags |= DRBG_FLAG_TEST; for (td = drbg_test; td->nid != 0; td++) { if (td->nid == nid && td->flags == flags) { - rv = fips_drbg_single_kat(dctx, td, 0); - if (rv <= 0) - return rv; - return fips_drbg_health_check(dctx, td); + if (!fips_drbg_single_kat(dctx, td, 0)) + return 0; + return fips_drbg_error_check(dctx, td); } } return 0; } +int FIPS_drbg_health_check(DRBG_CTX *dctx) + { + int rv; + DRBG_CTX *tctx = NULL; + tctx = FIPS_drbg_new(0, 0); + fips_post_started(FIPS_TEST_DRBG, dctx->type, &dctx->xflags); + if (!tctx) + return 0; + rv = fips_drbg_kat(tctx, dctx->type, dctx->xflags); + if (tctx) + FIPS_drbg_free(tctx); + if (rv) + fips_post_success(FIPS_TEST_DRBG, dctx->type, &dctx->xflags); + else + fips_post_failed(FIPS_TEST_DRBG, dctx->type, &dctx->xflags); + if (!rv) + dctx->status = DRBG_STATUS_ERROR; + else + dctx->health_check_cnt = 0; + return rv; + } + int FIPS_selftest_drbg(void) { DRBG_CTX *dctx; @@ -561,5 +850,34 @@ int FIPS_selftest_drbg(void) } - +int FIPS_selftest_drbg_all(void) + { + DRBG_CTX *dctx; + DRBG_SELFTEST_DATA *td; + int rv = 1; + dctx = FIPS_drbg_new(0, 0); + if (!dctx) + return 0; + for (td = drbg_test; td->nid != 0; td++) + { + if (!fips_post_started(FIPS_TEST_DRBG, td->nid, &td->flags)) + return 1; + if (!fips_drbg_single_kat(dctx, td, 0)) + { + fips_post_failed(FIPS_TEST_DRBG, td->nid, &td->flags); + rv = 0; + continue; + } + if (!fips_drbg_error_check(dctx, td)) + { + fips_post_failed(FIPS_TEST_DRBG, td->nid, &td->flags); + rv = 0; + continue; + } + if (!fips_post_success(FIPS_TEST_DRBG, td->nid, &td->flags)) + return 0; + } + FIPS_drbg_free(dctx); + return rv; + }