Add periodic DRBG health checks as required by SP800-90.
diff --git a/fips/fips.h b/fips/fips.h index f9c3dde..155cbbc 100644 --- a/fips/fips.h +++ b/fips/fips.h
@@ -244,6 +244,7 @@ #define FIPS_F_FIPS_CIPHERINIT 109 #define FIPS_F_FIPS_DIGESTINIT 110 #define FIPS_F_FIPS_DRBG_BYTES 111 +#define FIPS_F_FIPS_DRBG_CHECK 146 #define FIPS_F_FIPS_DRBG_CPRNG_TEST 112 #define FIPS_F_FIPS_DRBG_GENERATE 113 #define FIPS_F_FIPS_DRBG_HEALTH_CHECK 114
diff --git a/fips/rand/fips_drbg_lib.c b/fips/rand/fips_drbg_lib.c index 10d549b..6d983aa 100644 --- a/fips/rand/fips_drbg_lib.c +++ b/fips/rand/fips_drbg_lib.c
@@ -71,6 +71,9 @@ dctx->flags = flags; dctx->type = type; + dctx->health_check_cnt = 0; + dctx->health_check_interval = DRBG_HEALTH_INTERVAL; + rv = fips_drbg_hash_init(dctx); if (rv == -2) @@ -277,6 +280,24 @@ return 0; } +static int fips_drbg_check(DRBG_CTX *dctx) + { + if (dctx->flags & 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)) + { + FIPSerr(FIPS_F_FIPS_DRBG_CHECK, FIPS_R_SELFTEST_FAILURE); + return 0; + } + dctx->health_check_cnt = 0; + } + return 1; + } int FIPS_drbg_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen, int strength, int prediction_resistance, @@ -284,6 +305,9 @@ { int r = 0; + if (!fips_drbg_check(dctx)) + return 0; + if (dctx->status != DRBG_STATUS_READY && dctx->status != DRBG_STATUS_RESEED) { @@ -408,6 +432,11 @@ return dctx->strength; } +void FIPS_drbg_set_check_interval(DRBG_CTX *dctx, int interval) + { + dctx->health_check_interval = interval; + } + static int drbg_stick = 0; void FIPS_drbg_stick(void)
diff --git a/fips/rand/fips_rand.h b/fips/rand/fips_rand.h index 6186c00..44a3c4f 100644 --- a/fips/rand/fips_rand.h +++ b/fips/rand/fips_rand.h
@@ -108,6 +108,7 @@ void FIPS_drbg_set_app_data(DRBG_CTX *ctx, void *app_data); size_t FIPS_drbg_get_blocklength(DRBG_CTX *dctx); int FIPS_drbg_get_strength(DRBG_CTX *dctx); +void FIPS_drbg_set_check_interval(DRBG_CTX *dctx, int interval); 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 94f58ea..eeed0ec 100644 --- a/fips/rand/fips_rand_lcl.h +++ b/fips/rand/fips_rand_lcl.h
@@ -105,6 +105,8 @@ */ #define DRBG_MAX_BLOCK EVP_MAX_MD_SIZE +#define DRBG_HEALTH_INTERVAL (1 << 24) + /* DRBG context structure */ struct drbg_ctx_st @@ -114,6 +116,8 @@ int type; /* Various flags */ unsigned int flags; + /* Used for periodic health checks */ + int health_check_cnt, health_check_interval; /* The following parameters are setup by mechanism drbg_init() call */ int strength;