diff --git a/crypto/fips_err.h b/crypto/fips_err.h index 8c7a68c5f859a54737b20a4a9df68ac6fb4f25ed..0c2aa44f38dabe4034baf2e7300fb1180714497a 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 f9c3dde32dcffd7a60cab709c8d3c53e78e54fb1..155cbbc4db4171d12b184a7599fd3599354bc43e 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 10d549b5c2227881483f5510db9a4cb10a50e4be..6d983aaf4bdede5653a19ec2840f3d483a2eebe4 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 6186c003884455222bc42abb1eccc1e368e34f42..44a3c4f853dbe0a1959daf57cf5843094712c03d 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 94f58ea4cd7da02e1ebafa1f2f5f96d1426d00f1..eeed0eca2385254b52e9bf3121c6c3cb22479055 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;