From 4420b3b17acf19f78f4fdea1a69d5f0a644c8154 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Wed, 21 Sep 2011 17:04:56 +0000 Subject: [PATCH] Revise DRBG to split between internal and external flags. One demand health check function. Perform generation test in fips_test_suite. Option to skip dh test if fips_test_suite. --- CHANGES | 7 ++ fips/fips_test_suite.c | 117 +++++++++++++++++++++++++++++++-- fips/rand/fips_drbg_ctr.c | 8 +-- fips/rand/fips_drbg_ec.c | 4 +- fips/rand/fips_drbg_hash.c | 2 +- fips/rand/fips_drbg_hmac.c | 2 +- fips/rand/fips_drbg_lib.c | 31 +++++---- fips/rand/fips_drbg_selftest.c | 61 +++++++++++------ fips/rand/fips_rand.h | 4 +- fips/rand/fips_rand_lcl.h | 12 ++-- 10 files changed, 193 insertions(+), 55 deletions(-) diff --git a/CHANGES b/CHANGES index c4e8639122..85dabd2713 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,13 @@ Changes between 1.0.1 and 1.1.0 [xx XXX xxxx] + *) Use separate DRBG fields for internal and external flags. New function + FIPS_drbg_test() to perform on demand health checking. Add generation + tests to fips_test_suite with reduced health check interval to + demonstrate periodic health checking. Add "nodh" option to + fips_test_suite to skip very slow DH test. + [Steve Henson] + *) New function FIPS_get_cipherbynid() to lookup FIPS supported ciphers based on NID. [Steve Henson] diff --git a/fips/fips_test_suite.c b/fips/fips_test_suite.c index c829d184a7..447d1088bd 100644 --- a/fips/fips_test_suite.c +++ b/fips/fips_test_suite.c @@ -43,6 +43,7 @@ int main(int argc, char *argv[]) #include #include +#include #include "fips_utl.h" /* AES: encrypt and decrypt known plaintext, verify result matches original plaintext @@ -653,6 +654,103 @@ static int Zeroize() return 1; } +/* Dummy Entropy for DRBG tests. WARNING: THIS IS TOTALLY BOGUS + * HAS ZERO SECURITY AND MUST NOT BE USED IN REAL APPLICATIONS. + */ + +static unsigned char dummy_drbg_entropy[1024]; + +static size_t drbg_test_cb(DRBG_CTX *ctx, unsigned char **pout, + int entropy, size_t min_len, size_t max_len) + { + *pout = dummy_drbg_entropy; + /* Round up to multiple of block size */ + return (min_len + 0xf) & ~0xf; + } + +/* DRBG test: just generate lots of data and trigger health checks */ + +static int do_drbg_test(int type, int flags) + { + DRBG_CTX *dctx; + int rv = 0; + size_t i; + unsigned char randout[1024]; + dctx = FIPS_drbg_new(type, flags); + if (!dctx) + return 0; + FIPS_drbg_set_callbacks(dctx, drbg_test_cb, 0, 0x10, drbg_test_cb, 0); + for (i = 0; i < sizeof(dummy_drbg_entropy); i++) + { + dummy_drbg_entropy[i] = i & 0xff; + } + if (!FIPS_drbg_instantiate(dctx, dummy_drbg_entropy, 10)) + goto err; + FIPS_drbg_set_check_interval(dctx, 10); + for (i = 0; i < 32; i++) + { + if (!FIPS_drbg_generate(dctx, randout, sizeof(randout), 0, NULL, 0)) + goto err; + if (!FIPS_drbg_generate(dctx, randout, sizeof(randout), 0, dummy_drbg_entropy, 1)) + goto err; + } + rv = 1; + err: + FIPS_drbg_uninstantiate(dctx); + return rv; + } + +typedef struct + { + int type, flags; + } DRBG_LIST; + +static int do_drbg_all(void) + { + static DRBG_LIST drbg_types[] = + { + {NID_sha1, 0}, + {NID_sha224, 0}, + {NID_sha256, 0}, + {NID_sha384, 0}, + {NID_sha512, 0}, + {NID_hmacWithSHA1, 0}, + {NID_hmacWithSHA224, 0}, + {NID_hmacWithSHA256, 0}, + {NID_hmacWithSHA384, 0}, + {NID_hmacWithSHA512, 0}, + {NID_aes_128_ctr, 0}, + {NID_aes_192_ctr, 0}, + {NID_aes_256_ctr, 0}, + {NID_aes_128_ctr, DRBG_FLAG_CTR_USE_DF}, + {NID_aes_192_ctr, DRBG_FLAG_CTR_USE_DF}, + {NID_aes_256_ctr, DRBG_FLAG_CTR_USE_DF}, + {(NID_X9_62_prime256v1 << 16)|NID_sha1, 0}, + {(NID_X9_62_prime256v1 << 16)|NID_sha224, 0}, + {(NID_X9_62_prime256v1 << 16)|NID_sha256, 0}, + {(NID_X9_62_prime256v1 << 16)|NID_sha384, 0}, + {(NID_X9_62_prime256v1 << 16)|NID_sha512, 0}, + {(NID_secp384r1 << 16)|NID_sha224, 0}, + {(NID_secp384r1 << 16)|NID_sha256, 0}, + {(NID_secp384r1 << 16)|NID_sha384, 0}, + {(NID_secp384r1 << 16)|NID_sha512, 0}, + {(NID_secp521r1 << 16)|NID_sha256, 0}, + {(NID_secp521r1 << 16)|NID_sha384, 0}, + {(NID_secp521r1 << 16)|NID_sha512, 0}, + {0, 0} + }; + DRBG_LIST *lst; + int rv = 1; + for (lst = drbg_types;; lst++) + { + if (lst->type == 0) + break; + if (!do_drbg_test(lst->type, lst->flags)) + rv = 0; + } + return rv; + } + static int Error; static const char * Fail(const char *msg) { @@ -885,7 +983,7 @@ int main(int argc,char **argv) int do_rng_stick = 0; int do_drbg_stick = 0; int no_exit = 0; - + int no_dh = 0; FIPS_post_set_callback(post_cb); @@ -944,6 +1042,9 @@ int main(int argc,char **argv) fail_id = FIPS_TEST_DRBG; } else if (!strcmp(argv[1], "rng")) { fail_id = FIPS_TEST_X931; + } else if (!strcmp(argv[1], "nodh")) { + no_dh = 1; + no_exit = 1; } else if (!strcmp(argv[1], "post")) { fail_id = -1; } else if (!strcmp(argv[1], "rngstick")) { @@ -976,7 +1077,10 @@ int main(int argc,char **argv) /* Non-Approved cryptographic operation */ printf("1. Non-Approved cryptographic operation test...\n"); - test_msg("\ta. Included algorithm (D-H)...", dh_test()); + if (no_dh) + printf("\t D-H test skipped\n"); + else + test_msg("\ta. Included algorithm (D-H)...", dh_test()); /* Power-up self test */ @@ -1068,6 +1172,7 @@ int main(int argc,char **argv) */ printf("9. Non-Approved cryptographic operation test...\n"); printf("\ta. Included algorithm (D-H)...%s\n", + no_dh ? "skipped" : dh_test() ? "successful as expected" : Fail("failed INCORRECTLY!") ); @@ -1077,8 +1182,12 @@ int main(int argc,char **argv) Zeroize() ? "successful as expected" : Fail("failed INCORRECTLY!") ); - printf("11. Complete DRBG health check...\n\t%s\n", - FIPS_selftest_drbg_all() ? "successful as expected" + printf("11. Complete DRBG health check...\n"); + printf("\t%s\n", FIPS_selftest_drbg_all() ? "successful as expected" + : Fail("failed INCORRECTLY!") ); + + printf("12. DRBG generation check...\n"); + printf("\t%s\n", do_drbg_all() ? "successful as expected" : Fail("failed INCORRECTLY!") ); printf("\nAll tests completed with %d errors\n", Error); diff --git a/fips/rand/fips_drbg_ctr.c b/fips/rand/fips_drbg_ctr.c index 47abec651d..4483681f63 100644 --- a/fips/rand/fips_drbg_ctr.c +++ b/fips/rand/fips_drbg_ctr.c @@ -263,7 +263,7 @@ static void ctr_Update(DRBG_CTX *dctx, memcpy(cctx->V, cctx->K + 24, 8); } - if (dctx->flags & DRBG_FLAG_CTR_USE_DF) + if (dctx->xflags & DRBG_FLAG_CTR_USE_DF) { /* If no input reuse existing derived value */ if (in1 || nonce || in2) @@ -316,7 +316,7 @@ static int drbg_ctr_generate(DRBG_CTX *dctx, { ctr_Update(dctx, adin, adinlen, NULL, 0, NULL, 0); /* This means we reuse derived value */ - if (dctx->flags & DRBG_FLAG_CTR_USE_DF) + if (dctx->xflags & DRBG_FLAG_CTR_USE_DF) { adin = NULL; adinlen = 1; @@ -328,7 +328,7 @@ static int drbg_ctr_generate(DRBG_CTX *dctx, for (;;) { inc_128(cctx); - if (!(dctx->flags & DRBG_FLAG_TEST) && !dctx->lb_valid) + if (!(dctx->xflags & DRBG_FLAG_TEST) && !dctx->lb_valid) { AES_encrypt(cctx->V, dctx->lb, &cctx->ks); dctx->lb_valid = 1; @@ -398,7 +398,7 @@ int fips_drbg_ctr_init(DRBG_CTX *dctx) dctx->blocklength = 16; dctx->seedlen = keylen + 16; - if (dctx->flags & DRBG_FLAG_CTR_USE_DF) + if (dctx->xflags & DRBG_FLAG_CTR_USE_DF) { /* df initialisation */ static unsigned char df_key[32] = diff --git a/fips/rand/fips_drbg_ec.c b/fips/rand/fips_drbg_ec.c index 57344314a1..fb5f77c897 100644 --- a/fips/rand/fips_drbg_ec.c +++ b/fips/rand/fips_drbg_ec.c @@ -337,7 +337,7 @@ static int drbg_ec_generate(DRBG_CTX *dctx, dctx->reseed_counter++; /* Get rightmost bits of r to output buffer */ - if (!(dctx->flags & DRBG_FLAG_TEST) && !dctx->lb_valid) + if (!(dctx->xflags & DRBG_FLAG_TEST) && !dctx->lb_valid) { if (!bn2binpad(dctx->lb, dctx->blocklength, r)) goto err; @@ -499,7 +499,7 @@ int fips_drbg_ec_init(DRBG_CTX *dctx) return -2; } - dctx->flags |= DRBG_CUSTOM_RESEED; + dctx->iflags |= DRBG_CUSTOM_RESEED; dctx->reseed_counter = 0; dctx->instantiate = drbg_ec_instantiate; dctx->reseed = drbg_ec_reseed; diff --git a/fips/rand/fips_drbg_hash.c b/fips/rand/fips_drbg_hash.c index 07873ca02d..4b3b723407 100644 --- a/fips/rand/fips_drbg_hash.c +++ b/fips/rand/fips_drbg_hash.c @@ -193,7 +193,7 @@ static int hash_gen(DRBG_CTX *dctx, unsigned char *out, size_t outlen) { FIPS_digestinit(&hctx->mctx, hctx->md); FIPS_digestupdate(&hctx->mctx, hctx->vtmp, dctx->seedlen); - if (!(dctx->flags & DRBG_FLAG_TEST) && !dctx->lb_valid) + if (!(dctx->xflags & DRBG_FLAG_TEST) && !dctx->lb_valid) { FIPS_digestfinal(&hctx->mctx, dctx->lb, NULL); dctx->lb_valid = 1; diff --git a/fips/rand/fips_drbg_hmac.c b/fips/rand/fips_drbg_hmac.c index 7733386b92..3984782f5f 100644 --- a/fips/rand/fips_drbg_hmac.c +++ b/fips/rand/fips_drbg_hmac.c @@ -182,7 +182,7 @@ static int drbg_hmac_generate(DRBG_CTX *dctx, return 0; if (!HMAC_Update(hctx, Vtmp, dctx->blocklength)) return 0; - if (!(dctx->flags & DRBG_FLAG_TEST) && !dctx->lb_valid) + if (!(dctx->xflags & DRBG_FLAG_TEST) && !dctx->lb_valid) { if (!HMAC_Final(hctx, dctx->lb, NULL)) return 0; diff --git a/fips/rand/fips_drbg_lib.c b/fips/rand/fips_drbg_lib.c index 07f8b12179..c2e42896d1 100644 --- a/fips/rand/fips_drbg_lib.c +++ b/fips/rand/fips_drbg_lib.c @@ -66,9 +66,10 @@ int FIPS_drbg_init(DRBG_CTX *dctx, int type, unsigned int flags) int rv; memset(dctx, 0, sizeof(DRBG_CTX)); dctx->status = DRBG_STATUS_UNINITIALISED; - dctx->flags = flags; + dctx->xflags = flags; dctx->type = type; + dctx->iflags = 0; dctx->entropy_blocklen = 0; dctx->health_check_cnt = 0; dctx->health_check_interval = DRBG_HEALTH_INTERVAL; @@ -92,7 +93,7 @@ int FIPS_drbg_init(DRBG_CTX *dctx, int type, unsigned int flags) /* If not in test mode run selftests on DRBG of the same type */ - if (!(dctx->flags & DRBG_FLAG_TEST)) + if (!(dctx->xflags & DRBG_FLAG_TEST)) { DRBG_CTX tctx; if (!fips_drbg_kat(&tctx, type, flags | DRBG_FLAG_TEST)) @@ -146,7 +147,7 @@ static size_t fips_get_entropy(DRBG_CTX *dctx, unsigned char **pout, { unsigned char *tout, *p; size_t bl = dctx->entropy_blocklen, rv; - if (dctx->flags & DRBG_FLAG_TEST || !bl) + if (dctx->xflags & DRBG_FLAG_TEST || !bl) return dctx->get_entropy(dctx, pout, entropy, min_len, max_len); rv = dctx->get_entropy(dctx, &tout, entropy + bl, min_len + bl, max_len + bl); @@ -172,7 +173,7 @@ static void fips_cleanup_entropy(DRBG_CTX *dctx, unsigned char *out, size_t olen) { size_t bl; - if (dctx->flags & DRBG_FLAG_TEST) + if (dctx->xflags & DRBG_FLAG_TEST) bl = 0; else bl = dctx->entropy_blocklen; @@ -251,7 +252,7 @@ int FIPS_drbg_instantiate(DRBG_CTX *dctx, dctx->status = DRBG_STATUS_READY; - if (!(dctx->flags & DRBG_CUSTOM_RESEED)) + if (!(dctx->iflags & DRBG_CUSTOM_RESEED)) dctx->reseed_counter = 1; end: @@ -265,7 +266,7 @@ int FIPS_drbg_instantiate(DRBG_CTX *dctx, if (dctx->status == DRBG_STATUS_READY) return 1; - if (r && !(dctx->flags & DRBG_FLAG_NOERR)) + if (r && !(dctx->iflags & DRBG_FLAG_NOERR)) FIPSerr(FIPS_F_FIPS_DRBG_INSTANTIATE, r); return 0; @@ -316,7 +317,7 @@ int FIPS_drbg_reseed(DRBG_CTX *dctx, goto end; dctx->status = DRBG_STATUS_READY; - if (!(dctx->flags & DRBG_CUSTOM_RESEED)) + if (!(dctx->iflags & DRBG_CUSTOM_RESEED)) dctx->reseed_counter = 1; end: @@ -326,7 +327,7 @@ int FIPS_drbg_reseed(DRBG_CTX *dctx, if (dctx->status == DRBG_STATUS_READY) return 1; - if (r && !(dctx->flags & DRBG_FLAG_NOERR)) + if (r && !(dctx->iflags & DRBG_FLAG_NOERR)) FIPSerr(FIPS_F_FIPS_DRBG_RESEED, r); return 0; @@ -334,14 +335,12 @@ int FIPS_drbg_reseed(DRBG_CTX *dctx, static int fips_drbg_check(DRBG_CTX *dctx) { - if (dctx->flags & DRBG_FLAG_TEST) + if (dctx->xflags & DRBG_FLAG_TEST) return 1; dctx->health_check_cnt++; if (dctx->health_check_cnt >= dctx->health_check_interval) { - DRBG_CTX tctx; - if (!fips_drbg_kat(&tctx, dctx->type, - dctx->flags | DRBG_FLAG_TEST)) + if (FIPS_drbg_test(dctx) <= 0) { FIPSerr(FIPS_F_FIPS_DRBG_CHECK, FIPS_R_SELFTEST_FAILURE); dctx->status = DRBG_STATUS_ERROR; @@ -383,7 +382,7 @@ int FIPS_drbg_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen, goto end; } - if (dctx->flags & DRBG_CUSTOM_RESEED) + if (dctx->iflags & DRBG_CUSTOM_RESEED) dctx->generate(dctx, NULL, outlen, NULL, 0); else if (dctx->reseed_counter >= dctx->reseed_interval) dctx->status = DRBG_STATUS_RESEED; @@ -405,7 +404,7 @@ int FIPS_drbg_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen, dctx->status = DRBG_STATUS_ERROR; goto end; } - if (!(dctx->flags & DRBG_CUSTOM_RESEED)) + if (!(dctx->iflags & DRBG_CUSTOM_RESEED)) { if (dctx->reseed_counter >= dctx->reseed_interval) dctx->status = DRBG_STATUS_RESEED; @@ -416,7 +415,7 @@ int FIPS_drbg_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen, end: if (r) { - if (!(dctx->flags & DRBG_FLAG_NOERR)) + if (!(dctx->iflags & DRBG_FLAG_NOERR)) FIPSerr(FIPS_F_FIPS_DRBG_GENERATE, r); return 0; } @@ -516,7 +515,7 @@ void FIPS_drbg_stick(void) int fips_drbg_cprng_test(DRBG_CTX *dctx, const unsigned char *out) { /* No CPRNG in test mode */ - if (dctx->flags & DRBG_FLAG_TEST) + if (dctx->xflags & DRBG_FLAG_TEST) return 1; /* Check block is valid: should never happen */ if (dctx->lb_valid == 0) diff --git a/fips/rand/fips_drbg_selftest.c b/fips/rand/fips_drbg_selftest.c index 3a91e6007b..76667a0167 100644 --- a/fips/rand/fips_drbg_selftest.c +++ b/fips/rand/fips_drbg_selftest.c @@ -227,7 +227,7 @@ 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; @@ -290,7 +290,7 @@ 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; @@ -381,7 +381,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) goto err; /* Don't report induced errors */ - dctx->flags |= DRBG_FLAG_NOERR; + dctx->iflags |= DRBG_FLAG_NOERR; /* Personalisation string tests */ @@ -413,7 +413,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) 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); @@ -423,7 +423,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) if (!do_drbg_init(dctx, td, &t)) goto err; - dctx->flags |= DRBG_FLAG_NOERR; + dctx->iflags |= DRBG_FLAG_NOERR; /* Test insufficient entropy */ @@ -435,7 +435,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) 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); @@ -447,7 +447,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) if (!do_drbg_init(dctx, td, &t)) goto err; - dctx->flags |= DRBG_FLAG_NOERR; + dctx->iflags |= DRBG_FLAG_NOERR; t.entlen = dctx->max_entropy + 1; @@ -457,7 +457,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) 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); @@ -474,7 +474,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) if (!do_drbg_init(dctx, td, &t)) goto err; - dctx->flags |= DRBG_FLAG_NOERR; + dctx->iflags |= DRBG_FLAG_NOERR; t.noncelen = dctx->min_nonce - 1; @@ -484,7 +484,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) 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); @@ -501,7 +501,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) if (!do_drbg_init(dctx, td, &t)) goto err; - dctx->flags |= DRBG_FLAG_NOERR; + dctx->iflags |= DRBG_FLAG_NOERR; t.noncelen = dctx->max_nonce + 1; @@ -511,7 +511,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) 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); @@ -529,7 +529,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) td->adin, td->adinlen)) goto err; - dctx->flags |= DRBG_FLAG_NOERR; + dctx->iflags |= DRBG_FLAG_NOERR; /* Request too much data for one request */ if (FIPS_drbg_generate(dctx, randout, dctx->max_request + 1, 0, @@ -560,7 +560,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) goto err; } - dctx->flags &= ~DRBG_FLAG_NOERR; + dctx->iflags &= ~DRBG_FLAG_NOERR; if (!FIPS_drbg_uninstantiate(dctx)) { @@ -602,7 +602,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) if (!do_drbg_init(dctx, td, &t)) goto err; - dctx->flags |= DRBG_FLAG_NOERR; + dctx->iflags |= DRBG_FLAG_NOERR; if (FIPS_drbg_reseed(dctx, td->adin, dctx->max_adin + 1) > 0) { @@ -625,7 +625,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) goto err; } - dctx->flags &= ~DRBG_FLAG_NOERR; + dctx->iflags &= ~DRBG_FLAG_NOERR; if (!FIPS_drbg_uninstantiate(dctx)) { @@ -665,7 +665,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) if (!do_drbg_init(dctx, td, &t)) goto err; - dctx->flags |= DRBG_FLAG_NOERR; + dctx->iflags |= DRBG_FLAG_NOERR; if (FIPS_drbg_reseed(dctx, td->adin, dctx->max_adin + 1) > 0) { @@ -678,7 +678,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) if (!do_drbg_init(dctx, td, &t)) goto err; - dctx->flags |= DRBG_FLAG_NOERR; + dctx->iflags |= DRBG_FLAG_NOERR; t.entlen = 0; @@ -699,7 +699,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) if (!do_drbg_init(dctx, td, &t)) goto err; - dctx->flags |= DRBG_FLAG_NOERR; + dctx->iflags |= DRBG_FLAG_NOERR; t.entlen = dctx->max_entropy + 1; @@ -720,7 +720,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) if (!do_drbg_init(dctx, td, &t)) goto err; - dctx->flags |= DRBG_FLAG_NOERR; + dctx->iflags |= DRBG_FLAG_NOERR; t.entlen = dctx->min_entropy - 1; @@ -756,7 +756,7 @@ 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)) + if (!(dctx->iflags & DRBG_FLAG_NOERR)) FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_FUNCTION_ERROR); FIPS_drbg_uninstantiate(dctx); return 0; @@ -767,6 +767,7 @@ 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) @@ -780,6 +781,24 @@ int fips_drbg_kat(DRBG_CTX *dctx, int nid, unsigned int flags) return 0; } +int FIPS_drbg_test(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); + return rv; + } + int FIPS_selftest_drbg(void) { DRBG_CTX *dctx; diff --git a/fips/rand/fips_rand.h b/fips/rand/fips_rand.h index d81ffccd3c..dc33cf136c 100644 --- a/fips/rand/fips_rand.h +++ b/fips/rand/fips_rand.h @@ -74,7 +74,7 @@ int FIPS_x931_status(void); const RAND_METHOD *FIPS_x931_method(void); typedef struct drbg_ctx_st DRBG_CTX; - +/* DRBG external flags */ /* Flag for CTR mode only: use derivation function ctr_df */ #define DRBG_FLAG_CTR_USE_DF 0x1 /* PRNG is in test state */ @@ -115,6 +115,8 @@ int FIPS_drbg_get_strength(DRBG_CTX *dctx); void FIPS_drbg_set_check_interval(DRBG_CTX *dctx, int interval); void FIPS_drbg_set_reseed_interval(DRBG_CTX *dctx, int interval); +int FIPS_drbg_test(DRBG_CTX *dctx); + DRBG_CTX *FIPS_get_default_drbg(void); const RAND_METHOD *FIPS_drbg_method(void); diff --git a/fips/rand/fips_rand_lcl.h b/fips/rand/fips_rand_lcl.h index 32809d41ac..fc649c003b 100644 --- a/fips/rand/fips_rand_lcl.h +++ b/fips/rand/fips_rand_lcl.h @@ -122,12 +122,12 @@ struct drbg_ec_ctx_st BN_CTX *bctx; }; -/* DRBG flags */ +/* DRBG internal flags */ /* Functions shouldn't call err library */ -#define DRBG_FLAG_NOERR 0x4 +#define DRBG_FLAG_NOERR 0x1 /* Custom reseed checking */ -#define DRBG_CUSTOM_RESEED 0x8 +#define DRBG_CUSTOM_RESEED 0x2 /* DRBG status values */ /* not initialised */ @@ -156,8 +156,10 @@ struct drbg_ctx_st /* First types common to all implementations */ /* DRBG type: a NID for the underlying algorithm */ int type; - /* Various flags */ - unsigned int flags; + /* Various external flags */ + unsigned int xflags; + /* Various internal use only flags */ + unsigned int iflags; /* Used for periodic health checks */ int health_check_cnt, health_check_interval; -- 2.25.1