From e5cadaf8db8cd0b43edaeaf7223aeffb4450a9ab Mon Sep 17 00:00:00 2001
From: "Dr. Stephen Henson" <steve@openssl.org>
Date: Fri, 1 Apr 2011 17:49:45 +0000
Subject: [PATCH] Only zeroise sensitive parts of DRBG context, so the type and
 flags are undisturbed.

Allow setting of "rand" callbacks for DRBG.
---
 fips/rand/fips_drbg_lib.c      | 21 +++++++++++++++++++--
 fips/rand/fips_drbg_selftest.c |  6 +++---
 fips/rand/fips_rand.h          |  7 +++++++
 3 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/fips/rand/fips_drbg_lib.c b/fips/rand/fips_drbg_lib.c
index 61caca79e6..5564538540 100644
--- a/fips/rand/fips_drbg_lib.c
+++ b/fips/rand/fips_drbg_lib.c
@@ -114,7 +114,7 @@ void FIPS_drbg_free(DRBG_CTX *dctx)
 	{
 	if (dctx->uninstantiate)
 		dctx->uninstantiate(dctx);
-	OPENSSL_cleanse(dctx, sizeof(DRBG_CTX));
+	OPENSSL_cleanse(&dctx->d, sizeof(dctx->d));
 	OPENSSL_free(dctx);
 	}
 
@@ -403,7 +403,8 @@ int FIPS_drbg_uninstantiate(DRBG_CTX *dctx)
 	/* Although we'd like to cleanse here we can't because we have to
 	 * test the uninstantiate really zeroes the data.
 	 */
-	memset(dctx, 0, sizeof(DRBG_CTX));
+	memset(&dctx->d, 0, sizeof(dctx->d));
+	dctx->status = DRBG_STATUS_UNINITIALISED;
 	/* If method has problems uninstantiating, return error */
 	return rv;
 	}
@@ -425,6 +426,22 @@ int FIPS_drbg_set_callbacks(DRBG_CTX *dctx,
 	return 1;
 	}
 
+int FIPS_drbg_set_rand_callbacks(DRBG_CTX *dctx,
+	size_t (*get_adin)(DRBG_CTX *ctx, unsigned char **pout),
+	void (*cleanup_adin)(DRBG_CTX *ctx, unsigned char *out, size_t olen),
+	int (*rand_seed_cb)(DRBG_CTX *ctx, const void *buf, int num),
+	int (*rand_add_cb)(DRBG_CTX *ctx,
+				const void *buf, int num, double entropy))
+	{
+	if (dctx->status != DRBG_STATUS_UNINITIALISED)
+		return 0;
+	dctx->get_adin = get_adin;
+	dctx->cleanup_adin = cleanup_adin;
+	dctx->rand_seed_cb = rand_seed_cb;
+	dctx->rand_add_cb = rand_add_cb;
+	return 1;
+	}
+
 void *FIPS_drbg_get_app_data(DRBG_CTX *dctx)
 	{
 	return dctx->app_data;
diff --git a/fips/rand/fips_drbg_selftest.c b/fips/rand/fips_drbg_selftest.c
index c46fe58521..d1f9dd118b 100644
--- a/fips/rand/fips_drbg_selftest.c
+++ b/fips/rand/fips_drbg_selftest.c
@@ -954,11 +954,11 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td)
 		}
 
 	FIPS_drbg_uninstantiate(dctx);
-	p = (unsigned char *)dctx;
+	p = (unsigned char *)&dctx->d;
 	/* Standard says we have to check uninstantiate really zeroes
 	 * the data...
 	 */
-	for (i = 0; i < sizeof(DRBG_CTX); i++)
+	for (i = 0; i < sizeof(dctx->d); i++)
 		{
 		if (*p != 0)
 			{
@@ -980,7 +980,7 @@ static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td)
 	return 0;
 
 	}
-		
+
 
 int fips_drbg_kat(DRBG_CTX *dctx, int nid, unsigned int flags)
 	{
diff --git a/fips/rand/fips_rand.h b/fips/rand/fips_rand.h
index 1d32c0f5df..18ca8acbfc 100644
--- a/fips/rand/fips_rand.h
+++ b/fips/rand/fips_rand.h
@@ -97,6 +97,13 @@ int FIPS_drbg_set_callbacks(DRBG_CTX *dctx,
 				int entropy, size_t min_len, size_t max_len),
 	void (*cleanup_nonce)(DRBG_CTX *ctx, unsigned char *out, size_t olen));
 
+int FIPS_drbg_set_rand_callbacks(DRBG_CTX *dctx,
+	size_t (*get_adin)(DRBG_CTX *ctx, unsigned char **pout),
+	void (*cleanup_adin)(DRBG_CTX *ctx, unsigned char *out, size_t olen),
+	int (*rand_seed_cb)(DRBG_CTX *ctx, const void *buf, int num),
+	int (*rand_add_cb)(DRBG_CTX *ctx,
+				const void *buf, int num, double entropy));
+
 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);
-- 
2.40.0