From b8b6a13a569fc6a5ad097502cdc87a121a27f3c6 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Thu, 21 Apr 2011 14:17:15 +0000 Subject: [PATCH] Add continuous RNG test to entropy source. Entropy callbacks now need to specify a "block length". --- crypto/fips_err.h | 2 ++ crypto/rand/rand_lib.c | 2 +- fips/fips.h | 2 ++ fips/fips_test_suite.c | 6 ++++- fips/fips_utl.h | 16 ++++++++++-- fips/rand/fips_drbg_lib.c | 48 +++++++++++++++++++++++++++++++--- fips/rand/fips_drbg_selftest.c | 8 +++--- fips/rand/fips_drbgvs.c | 2 +- fips/rand/fips_rand.h | 1 + fips/rand/fips_rand_lcl.h | 3 +++ 10 files changed, 77 insertions(+), 13 deletions(-) diff --git a/crypto/fips_err.h b/crypto/fips_err.h index 0c2aa44f3..f4f834124 100644 --- a/crypto/fips_err.h +++ b/crypto/fips_err.h @@ -91,6 +91,7 @@ static ERR_STRING_DATA FIPS_str_functs[]= {ERR_FUNC(FIPS_F_FIPS_DRBG_NEW), "FIPS_drbg_new"}, {ERR_FUNC(FIPS_F_FIPS_DRBG_RESEED), "FIPS_drbg_reseed"}, {ERR_FUNC(FIPS_F_FIPS_DRBG_SINGLE_KAT), "FIPS_DRBG_SINGLE_KAT"}, +{ERR_FUNC(FIPS_F_FIPS_GET_ENTROPY), "FIPS_GET_ENTROPY"}, {ERR_FUNC(FIPS_F_FIPS_MODE_SET), "FIPS_mode_set"}, {ERR_FUNC(FIPS_F_FIPS_PKEY_SIGNATURE_TEST), "fips_pkey_signature_test"}, {ERR_FUNC(FIPS_F_FIPS_RAND_ADD), "FIPS_rand_add"}, @@ -128,6 +129,7 @@ static ERR_STRING_DATA FIPS_str_reasons[]= {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_ENTROPY_SOURCE_STUCK) ,"entropy source stuck"}, {ERR_REASON(FIPS_R_ERROR_INITIALISING_DRBG),"error initialising drbg"}, {ERR_REASON(FIPS_R_ERROR_INSTANTIATING_DRBG),"error instantiating drbg"}, {ERR_REASON(FIPS_R_ERROR_RETRIEVING_ADDITIONAL_INPUT),"error retrieving additional input"}, diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index c653d38c8..0e8201316 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -253,7 +253,7 @@ int RAND_init_fips(void) dctx = FIPS_get_default_drbg(); FIPS_drbg_init(dctx, NID_aes_256_ctr, DRBG_FLAG_CTR_USE_DF); FIPS_drbg_set_callbacks(dctx, - drbg_get_entropy, drbg_free_entropy, + drbg_get_entropy, drbg_free_entropy, 20, drbg_get_entropy, drbg_free_entropy); FIPS_drbg_set_rand_callbacks(dctx, drbg_get_adin, 0, drbg_rand_seed, drbg_rand_add); diff --git a/fips/fips.h b/fips/fips.h index 155cbbc4d..e84f477cc 100644 --- a/fips/fips.h +++ b/fips/fips.h @@ -253,6 +253,7 @@ void ERR_load_FIPS_strings(void); #define FIPS_F_FIPS_DRBG_NEW 117 #define FIPS_F_FIPS_DRBG_RESEED 118 #define FIPS_F_FIPS_DRBG_SINGLE_KAT 119 +#define FIPS_F_FIPS_GET_ENTROPY 147 #define FIPS_F_FIPS_MODE_SET 120 #define FIPS_F_FIPS_PKEY_SIGNATURE_TEST 121 #define FIPS_F_FIPS_RAND_ADD 122 @@ -287,6 +288,7 @@ void ERR_load_FIPS_strings(void); #define FIPS_R_DRBG_STUCK 103 #define FIPS_R_ENTROPY_ERROR_UNDETECTED 104 #define FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED 105 +#define FIPS_R_ENTROPY_SOURCE_STUCK 142 #define FIPS_R_ERROR_INITIALISING_DRBG 106 #define FIPS_R_ERROR_INSTANTIATING_DRBG 107 #define FIPS_R_ERROR_RETRIEVING_ADDITIONAL_INPUT 108 diff --git a/fips/fips_test_suite.c b/fips/fips_test_suite.c index 64452bae3..8192eb2cc 100644 --- a/fips/fips_test_suite.c +++ b/fips/fips_test_suite.c @@ -847,7 +847,6 @@ int main(int argc,char **argv) int do_drbg_stick = 0; int no_exit = 0; - fips_algtest_init_nofips(); FIPS_post_set_callback(post_cb); @@ -910,6 +909,8 @@ int main(int argc,char **argv) do_rng_stick = 1; no_exit = 1; printf("RNG test with stuck continuous test...\n"); + } else if (!strcmp(argv[1], "drbgentstick")) { + do_entropy_stick(); } else if (!strcmp(argv[1], "drbgstick")) { do_drbg_stick = 1; no_exit = 1; @@ -919,6 +920,7 @@ int main(int argc,char **argv) exit(1); } if (!no_exit) { + fips_algtest_init_nofips(); if (!FIPS_mode_set(1)) { printf("Power-up self test failed\n"); exit(1); @@ -928,6 +930,8 @@ int main(int argc,char **argv) } } + fips_algtest_init_nofips(); + /* Non-Approved cryptographic operation */ printf("1. Non-Approved cryptographic operation test...\n"); diff --git a/fips/fips_utl.h b/fips/fips_utl.h index 7869a181a..edd249b84 100644 --- a/fips/fips_utl.h +++ b/fips/fips_utl.h @@ -67,6 +67,7 @@ int bin2bint(const unsigned char *in,int len,char *out); void PrintValue(char *tag, unsigned char *val, int len); void OutputValue(char *tag, unsigned char *val, int len, FILE *rfp,int bitmode); void fips_algtest_init(void); +void do_entropy_stick(void); static int no_err; @@ -109,18 +110,29 @@ static size_t dummy_cb(DRBG_CTX *ctx, unsigned char **pout, return min_len; } +static int entropy_stick = 0; + static void fips_algtest_init_nofips(void) { DRBG_CTX *ctx; + size_t i; FIPS_set_error_callbacks(put_err_cb, add_err_cb); - OPENSSL_cleanse(dummy_entropy, 1024); + for (i = 0; i < sizeof(dummy_entropy); i++) + dummy_entropy[i] = i & 0xff; + if (entropy_stick) + memcpy(dummy_entropy + 32, dummy_entropy + 16, 16); ctx = FIPS_get_default_drbg(); FIPS_drbg_init(ctx, NID_aes_256_ctr, DRBG_FLAG_CTR_USE_DF); - FIPS_drbg_set_callbacks(ctx, dummy_cb, 0, dummy_cb, 0); + FIPS_drbg_set_callbacks(ctx, dummy_cb, 0, 16, dummy_cb, 0); FIPS_drbg_instantiate(ctx, dummy_entropy, 10); FIPS_rand_set_method(FIPS_drbg_method()); } +void do_entropy_stick(void) + { + entropy_stick = 1; + } + void fips_algtest_init(void) { fips_algtest_init_nofips(); diff --git a/fips/rand/fips_drbg_lib.c b/fips/rand/fips_drbg_lib.c index 6d983aaf4..46e42e294 100644 --- a/fips/rand/fips_drbg_lib.c +++ b/fips/rand/fips_drbg_lib.c @@ -71,6 +71,7 @@ int FIPS_drbg_init(DRBG_CTX *dctx, int type, unsigned int flags) dctx->flags = flags; dctx->type = type; + dctx->entropy_blocklen = 0; dctx->health_check_cnt = 0; dctx->health_check_interval = DRBG_HEALTH_INTERVAL; @@ -131,6 +132,43 @@ void FIPS_drbg_free(DRBG_CTX *dctx) OPENSSL_free(dctx); } +static size_t fips_get_entropy(DRBG_CTX *dctx, unsigned char **pout, + int entropy, size_t min_len, size_t max_len) + { + unsigned char *tout, *p; + size_t bl = dctx->entropy_blocklen, rv; + if (dctx->flags & 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); + *pout = tout + bl; + if (rv < (min_len + bl) || (rv % bl)) + return 0; + /* Compare consecutive blocks for continuous PRNG test */ + for (p = tout; p < tout + rv; p += bl) + { + if (!memcmp(p, p + bl, bl)) + { + FIPSerr(FIPS_F_FIPS_GET_ENTROPY, FIPS_R_ENTROPY_SOURCE_STUCK); + return 0; + } + } + return rv - bl; + } + +static void fips_cleanup_entropy(DRBG_CTX *dctx, + unsigned char *out, size_t olen) + { + size_t bl; + if (dctx->flags & DRBG_FLAG_TEST) + bl = 0; + else + bl = dctx->entropy_blocklen; + /* Call cleanup with original arguments */ + dctx->cleanup_entropy(dctx, out - bl, olen + bl); + } + + int FIPS_drbg_instantiate(DRBG_CTX *dctx, const unsigned char *pers, size_t perslen) { @@ -167,7 +205,7 @@ int FIPS_drbg_instantiate(DRBG_CTX *dctx, dctx->status = DRBG_STATUS_ERROR; - entlen = dctx->get_entropy(dctx, &entropy, dctx->strength, + entlen = fips_get_entropy(dctx, &entropy, dctx->strength, dctx->min_entropy, dctx->max_entropy); if (entlen < dctx->min_entropy || entlen > dctx->max_entropy) @@ -206,7 +244,7 @@ int FIPS_drbg_instantiate(DRBG_CTX *dctx, end: if (entropy && dctx->cleanup_entropy) - dctx->cleanup_entropy(dctx, entropy, entlen); + fips_cleanup_entropy(dctx, entropy, entlen); if (nonce && dctx->cleanup_nonce) dctx->cleanup_nonce(dctx, nonce, noncelen); @@ -252,7 +290,7 @@ int FIPS_drbg_reseed(DRBG_CTX *dctx, dctx->status = DRBG_STATUS_ERROR; - entlen = dctx->get_entropy(dctx, &entropy, dctx->strength, + entlen = fips_get_entropy(dctx, &entropy, dctx->strength, dctx->min_entropy, dctx->max_entropy); if (entlen < dctx->min_entropy || entlen > dctx->max_entropy) @@ -269,7 +307,7 @@ int FIPS_drbg_reseed(DRBG_CTX *dctx, end: if (entropy && dctx->cleanup_entropy) - dctx->cleanup_entropy(dctx, entropy, entlen); + fips_cleanup_entropy(dctx, entropy, entlen); if (dctx->status == DRBG_STATUS_READY) return 1; @@ -383,12 +421,14 @@ int FIPS_drbg_set_callbacks(DRBG_CTX *dctx, size_t (*get_entropy)(DRBG_CTX *ctx, unsigned char **pout, int entropy, size_t min_len, size_t max_len), void (*cleanup_entropy)(DRBG_CTX *ctx, unsigned char *out, size_t olen), + size_t entropy_blocklen, size_t (*get_nonce)(DRBG_CTX *ctx, unsigned char **pout, int entropy, size_t min_len, size_t max_len), void (*cleanup_nonce)(DRBG_CTX *ctx, unsigned char *out, size_t olen)) { if (dctx->status != DRBG_STATUS_UNINITIALISED) return 0; + dctx->entropy_blocklen = entropy_blocklen; dctx->get_entropy = get_entropy; dctx->cleanup_entropy = cleanup_entropy; dctx->get_nonce = get_nonce; diff --git a/fips/rand/fips_drbg_selftest.c b/fips/rand/fips_drbg_selftest.c index cbf0590c6..881bce041 100644 --- a/fips/rand/fips_drbg_selftest.c +++ b/fips/rand/fips_drbg_selftest.c @@ -759,7 +759,7 @@ static int fips_drbg_single_kat(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) unsigned char randout[1024]; if (!FIPS_drbg_init(dctx, td->nid, td->flags)) return 0; - if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, test_nonce, 0)) + if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0)) return 0; FIPS_drbg_set_app_data(dctx, &t); @@ -825,7 +825,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) if (!FIPS_drbg_init(dctx, td->nid, td->flags)) goto err; - if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, test_nonce, 0)) + if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0)) goto err; FIPS_drbg_set_app_data(dctx, &t); @@ -874,7 +874,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) /* Instantiate with valid data. NB: errors now reported again */ if (!FIPS_drbg_init(dctx, td->nid, td->flags)) goto err; - if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, test_nonce, 0)) + if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0)) goto err; FIPS_drbg_set_app_data(dctx, &t); @@ -936,7 +936,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td) if (!FIPS_drbg_init(dctx, td->nid, td->flags)) goto err; - if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, test_nonce, 0)) + if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0)) goto err; FIPS_drbg_set_app_data(dctx, &t); diff --git a/fips/rand/fips_drbgvs.c b/fips/rand/fips_drbgvs.c index 890732e13..70a116822 100644 --- a/fips/rand/fips_drbgvs.c +++ b/fips/rand/fips_drbgvs.c @@ -248,7 +248,7 @@ int main(int argc,char **argv) dctx = FIPS_drbg_new(nid, df | DRBG_FLAG_TEST); if (!dctx) exit (1); - FIPS_drbg_set_callbacks(dctx, test_entropy, 0, + FIPS_drbg_set_callbacks(dctx, test_entropy, 0, 0, test_nonce, 0); FIPS_drbg_set_app_data(dctx, &t); randoutlen = (int)FIPS_drbg_get_blocklength(dctx); diff --git a/fips/rand/fips_rand.h b/fips/rand/fips_rand.h index 44a3c4f85..8d886e81d 100644 --- a/fips/rand/fips_rand.h +++ b/fips/rand/fips_rand.h @@ -93,6 +93,7 @@ int FIPS_drbg_set_callbacks(DRBG_CTX *dctx, size_t (*get_entropy)(DRBG_CTX *ctx, unsigned char **pout, int entropy, size_t min_len, size_t max_len), void (*cleanup_entropy)(DRBG_CTX *ctx, unsigned char *out, size_t olen), + size_t entropy_blocklen, size_t (*get_nonce)(DRBG_CTX *ctx, unsigned char **pout, int entropy, size_t min_len, size_t max_len), void (*cleanup_nonce)(DRBG_CTX *ctx, unsigned char *out, size_t olen)); diff --git a/fips/rand/fips_rand_lcl.h b/fips/rand/fips_rand_lcl.h index eeed0eca2..1f5b288f1 100644 --- a/fips/rand/fips_rand_lcl.h +++ b/fips/rand/fips_rand_lcl.h @@ -157,6 +157,9 @@ struct drbg_ctx_st /* uninstantiate */ int (*uninstantiate)(DRBG_CTX *ctx); + /* Entropy source block length */ + size_t entropy_blocklen; + /* entropy gathering function */ size_t (*get_entropy)(DRBG_CTX *ctx, unsigned char **pout, int entropy, size_t min_len, size_t max_len);