From 1e803100de9e88fff6fc586a54e12dda5861557b Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Thu, 17 Mar 2011 18:53:33 +0000 Subject: [PATCH] Implement continuous RNG test for SP800-90 DRBGs. --- crypto/fips_err.h | 2 ++ fips/fips.h | 2 ++ fips/rand/fips_drbg_lib.c | 68 +++++++++++++++++++++++++++++++++++++-- fips/rand/fips_rand_lcl.h | 6 ++++ 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/crypto/fips_err.h b/crypto/fips_err.h index 4b75c2dc0b..4ff3ec1279 100644 --- a/crypto/fips_err.h +++ b/crypto/fips_err.h @@ -84,6 +84,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_GENERATE), "FIPS_drbg_generate"}, +{ERR_FUNC(FIPS_F_FIPS_DRBG_GENERATE_INTERNAL), "FIPS_DRBG_GENERATE_INTERNAL"}, {ERR_FUNC(FIPS_F_FIPS_DRBG_HEALTH_CHECK), "FIPS_DRBG_HEALTH_CHECK"}, {ERR_FUNC(FIPS_F_FIPS_DRBG_INIT), "FIPS_drbg_init"}, {ERR_FUNC(FIPS_F_FIPS_DRBG_INSTANTIATE), "FIPS_drbg_instantiate"}, @@ -118,6 +119,7 @@ static ERR_STRING_DATA FIPS_str_reasons[]= {ERR_REASON(FIPS_R_CANNOT_READ_EXE) ,"cannot read exe"}, {ERR_REASON(FIPS_R_CANNOT_READ_EXE_DIGEST),"cannot read exe digest"}, {ERR_REASON(FIPS_R_CONTRADICTING_EVIDENCE),"contradicting evidence"}, +{ERR_REASON(FIPS_R_DRBG_STUCK) ,"drbg stuck"}, {ERR_REASON(FIPS_R_ENTROPY_ERROR_UNDETECTED),"entropy error undetected"}, {ERR_REASON(FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED),"entropy not requested for reseed"}, {ERR_REASON(FIPS_R_ERROR_INITIALISING_DRBG),"error initialising drbg"}, diff --git a/fips/fips.h b/fips/fips.h index af36f03236..6dadc1ee18 100644 --- a/fips/fips.h +++ b/fips/fips.h @@ -194,6 +194,7 @@ void ERR_load_FIPS_strings(void); #define FIPS_F_FIPS_CIPHERINIT 128 #define FIPS_F_FIPS_DIGESTINIT 127 #define FIPS_F_FIPS_DRBG_GENERATE 132 +#define FIPS_F_FIPS_DRBG_GENERATE_INTERNAL 138 #define FIPS_F_FIPS_DRBG_HEALTH_CHECK 137 #define FIPS_F_FIPS_DRBG_INIT 136 #define FIPS_F_FIPS_DRBG_INSTANTIATE 133 @@ -225,6 +226,7 @@ void ERR_load_FIPS_strings(void); #define FIPS_R_CANNOT_READ_EXE 103 #define FIPS_R_CANNOT_READ_EXE_DIGEST 104 #define FIPS_R_CONTRADICTING_EVIDENCE 114 +#define FIPS_R_DRBG_STUCK 142 #define FIPS_R_ENTROPY_ERROR_UNDETECTED 133 #define FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED 134 #define FIPS_R_ERROR_INITIALISING_DRBG 120 diff --git a/fips/rand/fips_drbg_lib.c b/fips/rand/fips_drbg_lib.c index 0e06273cef..94bc36a31f 100644 --- a/fips/rand/fips_drbg_lib.c +++ b/fips/rand/fips_drbg_lib.c @@ -263,7 +263,8 @@ int FIPS_drbg_reseed(DRBG_CTX *dctx, } -int FIPS_drbg_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen, +static int fips_drbg_generate_internal(DRBG_CTX *dctx, + unsigned char *out, size_t outlen, int strength, int prediction_resistance, const unsigned char *adin, size_t adinlen) { @@ -313,13 +314,76 @@ int FIPS_drbg_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen, if (r) { if (!(dctx->flags & DRBG_FLAG_NOERR)) - FIPSerr(FIPS_F_FIPS_DRBG_GENERATE, r); + FIPSerr(FIPS_F_FIPS_DRBG_GENERATE_INTERNAL, r); return 0; } return 1; } +/* external generate function: incorporates continuous RNG test if not + * in test mode. + */ + +int FIPS_drbg_generate(DRBG_CTX *dctx, + unsigned char *out, size_t outlen, + int strength, int prediction_resistance, + const unsigned char *adin, size_t adinlen) + { + unsigned char tmp[16], *pout; + size_t poutlen; + /* If test mode don't run continuous RNG test */ + if (dctx->flags & DRBG_FLAG_TEST) + { + return fips_drbg_generate_internal(dctx, out, outlen, + strength, + prediction_resistance, + adin, adinlen); + } + /* If this is the first call generate block and save buffer */ + if (!dctx->lb_valid) + { + if (!fips_drbg_generate_internal(dctx, dctx->lb, 16, + strength, prediction_resistance, + adin, adinlen)) + return 0; + dctx->lb_valid = 1; + } + + /* If request less that 16 bytes request 16 in temp buffer */ + + if (outlen < 16) + { + pout = tmp; + poutlen = 16; + } + else + { + pout = out; + poutlen = outlen; + } + + /* Generate data */ + if (!fips_drbg_generate_internal(dctx, pout, poutlen, + strength, prediction_resistance, + adin, adinlen)) + return 0; + /* Compare to last block for continuous PRNG test */ + if (!memcmp(pout, dctx->lb, 16)) + { + FIPSerr(FIPS_F_FIPS_DRBG_GENERATE, FIPS_R_DRBG_STUCK); + return 0; + } + /* Update last block */ + memcpy(dctx->lb, pout, 16); + /* Copy to output buffer if needed */ + if (outlen < 16) + memcpy(out, pout, outlen); + + return 1; + + } + int FIPS_drbg_uninstantiate(DRBG_CTX *dctx) { int rv; diff --git a/fips/rand/fips_rand_lcl.h b/fips/rand/fips_rand_lcl.h index 7e64bb491f..8f97ac00be 100644 --- a/fips/rand/fips_rand_lcl.h +++ b/fips/rand/fips_rand_lcl.h @@ -167,6 +167,12 @@ struct drbg_ctx_st size_t (*get_nonce)(DRBG_CTX *ctx, unsigned char *out, int entropy, size_t min_len, size_t max_len); + /* Continuous random number test temporary area */ + /* Last block */ + unsigned char lb[16]; + /* set if lb is valid */ + int lb_valid; + };