From 14264b19deb526432a5749e083ef38af9e1ce516 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Wed, 20 Apr 2011 17:06:38 +0000 Subject: [PATCH] Add periodic DRBG health checks as required by SP800-90. --- crypto/fips_err.h | 1 + fips/fips.h | 1 + fips/rand/fips_drbg_lib.c | 29 +++++++++++++++++++++++++++++ fips/rand/fips_rand.h | 1 + fips/rand/fips_rand_lcl.h | 4 ++++ 5 files changed, 36 insertions(+) diff --git a/crypto/fips_err.h b/crypto/fips_err.h index 8c7a68c5f8..0c2aa44f38 100644 --- a/crypto/fips_err.h +++ b/crypto/fips_err.h @@ -82,6 +82,7 @@ static ERR_STRING_DATA FIPS_str_functs[]= {ERR_FUNC(FIPS_F_FIPS_CIPHERINIT), "FIPS_CIPHERINIT"}, {ERR_FUNC(FIPS_F_FIPS_DIGESTINIT), "FIPS_DIGESTINIT"}, {ERR_FUNC(FIPS_F_FIPS_DRBG_BYTES), "FIPS_DRBG_BYTES"}, +{ERR_FUNC(FIPS_F_FIPS_DRBG_CHECK), "FIPS_DRBG_CHECK"}, {ERR_FUNC(FIPS_F_FIPS_DRBG_CPRNG_TEST), "FIPS_DRBG_CPRNG_TEST"}, {ERR_FUNC(FIPS_F_FIPS_DRBG_GENERATE), "FIPS_drbg_generate"}, {ERR_FUNC(FIPS_F_FIPS_DRBG_HEALTH_CHECK), "FIPS_DRBG_HEALTH_CHECK"}, diff --git a/fips/fips.h b/fips/fips.h index f9c3dde32d..155cbbc4db 100644 --- a/fips/fips.h +++ b/fips/fips.h @@ -244,6 +244,7 @@ void ERR_load_FIPS_strings(void); #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 10d549b5c2..6d983aaf4b 100644 --- a/fips/rand/fips_drbg_lib.c +++ b/fips/rand/fips_drbg_lib.c @@ -71,6 +71,9 @@ int FIPS_drbg_init(DRBG_CTX *dctx, int type, unsigned int flags) 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 @@ int FIPS_drbg_reseed(DRBG_CTX *dctx, 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 FIPS_drbg_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen, { 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 @@ int FIPS_drbg_get_strength(DRBG_CTX *dctx) 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 6186c00388..44a3c4f853 100644 --- a/fips/rand/fips_rand.h +++ b/fips/rand/fips_rand.h @@ -108,6 +108,7 @@ void *FIPS_drbg_get_app_data(DRBG_CTX *ctx); 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 94f58ea4cd..eeed0eca23 100644 --- a/fips/rand/fips_rand_lcl.h +++ b/fips/rand/fips_rand_lcl.h @@ -105,6 +105,8 @@ struct drbg_ctr_ctx_st */ #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 @@ struct drbg_ctx_st 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; -- GitLab