Reorganise DRBG API so the entropy and nonce callbacks can return a
pointer to a buffer instead of copying to a fixed length buffer. This
removes the entropy and nonce length restrictions.
diff --git a/fips/rand/fips_drbg_ctr.c b/fips/rand/fips_drbg_ctr.c
index 7e6d497..0a5270d 100644
--- a/fips/rand/fips_drbg_ctr.c
+++ b/fips/rand/fips_drbg_ctr.c
@@ -404,9 +404,9 @@
 		AES_set_encrypt_key(df_key, dctx->strength, &cctx->df_ks);
 
 		dctx->min_entropy = cctx->keylen;
-		dctx->max_entropy = DRBG_MAX_ENTROPY;
+		dctx->max_entropy = DRBG_MAX_LENGTH;
 		dctx->min_nonce = dctx->min_entropy / 2;
-		dctx->max_nonce = DRBG_MAX_NONCE;
+		dctx->max_nonce = DRBG_MAX_LENGTH;
 		dctx->max_pers = DRBG_MAX_LENGTH;
 		dctx->max_adin = DRBG_MAX_LENGTH;
 		}
diff --git a/fips/rand/fips_drbg_hash.c b/fips/rand/fips_drbg_hash.c
index f6135c0..b20d072 100644
--- a/fips/rand/fips_drbg_hash.c
+++ b/fips/rand/fips_drbg_hash.c
@@ -368,10 +368,10 @@
 
 
 	dctx->min_entropy = dctx->strength / 8;
-	dctx->max_entropy = DRBG_MAX_ENTROPY;
+	dctx->max_entropy = DRBG_MAX_LENGTH;
 
 	dctx->min_nonce = dctx->min_entropy / 2;
-	dctx->max_nonce = DRBG_MAX_NONCE;
+	dctx->max_nonce = DRBG_MAX_LENGTH;
 
 	dctx->max_pers = DRBG_MAX_LENGTH;
 	dctx->max_adin = DRBG_MAX_LENGTH;
diff --git a/fips/rand/fips_drbg_lib.c b/fips/rand/fips_drbg_lib.c
index a848ef2..761b0fc 100644
--- a/fips/rand/fips_drbg_lib.c
+++ b/fips/rand/fips_drbg_lib.c
@@ -121,7 +121,8 @@
 int FIPS_drbg_instantiate(DRBG_CTX *dctx,
 				const unsigned char *pers, size_t perslen)
 	{
-	size_t entlen, noncelen;
+	size_t entlen = 0, noncelen = 0;
+	unsigned char *nonce = NULL, *entropy = NULL;
 
 #if 0
 	/* Put here so error script picks them up */
@@ -153,7 +154,7 @@
 
 	dctx->status = DRBG_STATUS_ERROR;
 
-	entlen = dctx->get_entropy(dctx, dctx->entropy, dctx->strength,
+	entlen = dctx->get_entropy(dctx, &entropy, dctx->strength,
 				dctx->min_entropy, dctx->max_entropy);
 
 	if (entlen < dctx->min_entropy || entlen > dctx->max_entropy)
@@ -164,8 +165,7 @@
 
 	if (dctx->max_nonce > 0)
 		{
-
-		noncelen = dctx->get_nonce(dctx, dctx->nonce,
+		noncelen = dctx->get_nonce(dctx, &nonce,
 					dctx->strength / 2,
 					dctx->min_nonce, dctx->max_nonce);
 
@@ -176,12 +176,10 @@
 			}
 
 		}
-	else
-		noncelen = 0;
 
 	if (!dctx->instantiate(dctx, 
-				dctx->entropy, entlen,
-				dctx->nonce, noncelen,
+				entropy, entlen,
+				nonce, noncelen,
 				pers, perslen))
 		{
 		r = FIPS_R_ERROR_INSTANTIATING_DRBG;
@@ -194,8 +192,11 @@
 
 	end:
 
-	OPENSSL_cleanse(dctx->entropy, sizeof(dctx->entropy));
-	OPENSSL_cleanse(dctx->nonce, sizeof(dctx->nonce));
+	if (entropy && dctx->cleanup_entropy)
+		dctx->cleanup_entropy(dctx, entropy, entlen);
+
+	if (nonce && dctx->cleanup_nonce)
+		dctx->cleanup_nonce(dctx, nonce, noncelen);
 
 	if (dctx->status == DRBG_STATUS_READY)
 		return 1;
@@ -210,6 +211,7 @@
 int FIPS_drbg_reseed(DRBG_CTX *dctx,
 			const unsigned char *adin, size_t adinlen)
 	{
+	unsigned char *entropy = NULL;
 	size_t entlen;
 	int r = 0;
 
@@ -237,7 +239,7 @@
 
 	dctx->status = DRBG_STATUS_ERROR;
 
-	entlen = dctx->get_entropy(dctx, dctx->entropy, dctx->strength,
+	entlen = dctx->get_entropy(dctx, &entropy, dctx->strength,
 				dctx->min_entropy, dctx->max_entropy);
 
 	if (entlen < dctx->min_entropy || entlen > dctx->max_entropy)
@@ -246,13 +248,15 @@
 		goto end;
 		}
 
-	if (!dctx->reseed(dctx, dctx->entropy, entlen, adin, adinlen))
+	if (!dctx->reseed(dctx, entropy, entlen, adin, adinlen))
 		goto end;
 
 	dctx->status = DRBG_STATUS_READY;
 	dctx->reseed_counter = 1;
 	end:
-	OPENSSL_cleanse(dctx->entropy, sizeof(dctx->entropy));
+
+	if (entropy && dctx->cleanup_entropy)
+		dctx->cleanup_entropy(dctx, entropy, entlen);
 
 	if (dctx->status == DRBG_STATUS_READY)
 		return 1;
@@ -401,15 +405,19 @@
 	}
 
 int FIPS_drbg_set_callbacks(DRBG_CTX *dctx,
-	size_t (*get_entropy)(DRBG_CTX *ctx, unsigned char *out,
+	size_t (*get_entropy)(DRBG_CTX *ctx, unsigned char **pout,
 				int entropy, size_t min_len, size_t max_len),
-	size_t (*get_nonce)(DRBG_CTX *ctx, unsigned char *out,
-				int entropy, size_t min_len, size_t max_len))
+	void (*cleanup_entropy)(DRBG_CTX *ctx, unsigned char *out, size_t olen),
+	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->get_entropy = get_entropy;
+	dctx->cleanup_entropy = cleanup_entropy;
 	dctx->get_nonce = get_nonce;
+	dctx->cleanup_nonce = cleanup_nonce;
 	return 1;
 	}
 
diff --git a/fips/rand/fips_drbg_selftest.c b/fips/rand/fips_drbg_selftest.c
index 31b7a0b..a3732c1 100644
--- a/fips/rand/fips_drbg_selftest.c
+++ b/fips/rand/fips_drbg_selftest.c
@@ -732,20 +732,20 @@
 	int noncecnt;
 	} TEST_ENT;
 
-static size_t test_entropy(DRBG_CTX *dctx, unsigned char *out,
+static size_t test_entropy(DRBG_CTX *dctx, unsigned char **pout,
                                 int entropy, size_t min_len, size_t max_len)
 	{
 	TEST_ENT *t = FIPS_drbg_get_app_data(dctx);
-	memcpy(out, t->ent, t->entlen);
+	*pout = (unsigned char *)t->ent;
 	t->entcnt++;
 	return t->entlen;
 	}
 
-static size_t test_nonce(DRBG_CTX *dctx, unsigned char *out,
+static size_t test_nonce(DRBG_CTX *dctx, unsigned char **pout,
                                 int entropy, size_t min_len, size_t max_len)
 	{
 	TEST_ENT *t = FIPS_drbg_get_app_data(dctx);
-	memcpy(out, t->nonce, t->noncelen);
+	*pout = (unsigned char *)t->nonce;
 	t->noncecnt++;
 	return t->noncelen;
 	}
@@ -762,7 +762,7 @@
 	unsigned char randout[1024];
 	if (!FIPS_drbg_init(dctx, td->nid, td->flags))
 		return 0;
-	if (!FIPS_drbg_set_callbacks(dctx, test_entropy, test_nonce))
+	if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, test_nonce, 0))
 		return 0;
 
 	FIPS_drbg_set_app_data(dctx, &t);
@@ -818,7 +818,7 @@
 	if (!FIPS_drbg_init(dctx, td->nid, td->flags))
 		goto err;
 
-	if (!FIPS_drbg_set_callbacks(dctx, test_entropy, test_nonce))
+	if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, test_nonce, 0))
 		goto err;
 
 	FIPS_drbg_set_app_data(dctx, &t);
@@ -860,7 +860,7 @@
 	/* 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, test_nonce))
+	if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 0, test_nonce, 0))
 		goto err;
 	FIPS_drbg_set_app_data(dctx, &t);
 
@@ -914,7 +914,7 @@
 
 	if (!FIPS_drbg_init(dctx, td->nid, td->flags))
 		goto err;
-	if (!FIPS_drbg_set_callbacks(dctx, test_entropy, test_nonce))
+	if (!FIPS_drbg_set_callbacks(dctx, test_entropy, 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 d3b47a0..890732e 100644
--- a/fips/rand/fips_drbgvs.c
+++ b/fips/rand/fips_drbgvs.c
@@ -135,19 +135,19 @@
 	size_t noncelen;
 	} TEST_ENT;
 
-static size_t test_entropy(DRBG_CTX *dctx, unsigned char *out,
+static size_t test_entropy(DRBG_CTX *dctx, unsigned char **pout,
                                 int entropy, size_t min_len, size_t max_len)
 	{
 	TEST_ENT *t = FIPS_drbg_get_app_data(dctx);
-	memcpy(out, t->ent, t->entlen);
+	*pout = (unsigned char *)t->ent;
 	return t->entlen;
 	}
 
-static size_t test_nonce(DRBG_CTX *dctx, unsigned char *out,
+static size_t test_nonce(DRBG_CTX *dctx, unsigned char **pout,
                                 int entropy, size_t min_len, size_t max_len)
 	{
 	TEST_ENT *t = FIPS_drbg_get_app_data(dctx);
-	memcpy(out, t->nonce, t->noncelen);
+	*pout = (unsigned char *)t->nonce;
 	return t->noncelen;
 	}
 
@@ -248,7 +248,8 @@
 			dctx = FIPS_drbg_new(nid, df | DRBG_FLAG_TEST);
 			if (!dctx)
 				exit (1);
-			FIPS_drbg_set_callbacks(dctx, test_entropy, test_nonce);
+			FIPS_drbg_set_callbacks(dctx, test_entropy, 0,
+							test_nonce, 0);
 			FIPS_drbg_set_app_data(dctx, &t);
 			randoutlen = (int)FIPS_drbg_get_blocklength(dctx);
 			r = FIPS_drbg_instantiate(dctx, pers, perslen);
diff --git a/fips/rand/fips_rand.h b/fips/rand/fips_rand.h
index b332549..f1e8136 100644
--- a/fips/rand/fips_rand.h
+++ b/fips/rand/fips_rand.h
@@ -90,10 +90,12 @@
 void FIPS_drbg_free(DRBG_CTX *dctx);
 
 int FIPS_drbg_set_callbacks(DRBG_CTX *dctx,
-	size_t (*get_entropy)(DRBG_CTX *ctx, unsigned char *out,
+	size_t (*get_entropy)(DRBG_CTX *ctx, unsigned char **pout,
 				int entropy, size_t min_len, size_t max_len),
-	size_t (*get_nonce)(DRBG_CTX *ctx, unsigned char *out,
-				int entropy, size_t min_len, size_t max_len));
+	void (*cleanup_entropy)(DRBG_CTX *ctx, unsigned char *out, size_t olen),
+	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));
 
 void *FIPS_drbg_get_app_data(DRBG_CTX *ctx);
 void FIPS_drbg_set_app_data(DRBG_CTX *ctx, void *app_data);
diff --git a/fips/rand/fips_rand_lcl.h b/fips/rand/fips_rand_lcl.h
index 4ec4ef8..b396226 100644
--- a/fips/rand/fips_rand_lcl.h
+++ b/fips/rand/fips_rand_lcl.h
@@ -153,17 +153,19 @@
 	/* uninstantiate */
 	int (*uninstantiate)(DRBG_CTX *ctx);
 
-	unsigned char entropy[DRBG_MAX_ENTROPY];
-
 	/* entropy gathering function */
-	size_t (*get_entropy)(DRBG_CTX *ctx, unsigned char *out,
+	size_t (*get_entropy)(DRBG_CTX *ctx, unsigned char **pout,
 				int entropy, size_t min_len, size_t max_len);
+	/* Indicates we have finished with entropy buffer */
+	void (*cleanup_entropy)(DRBG_CTX *ctx, unsigned char *out, size_t olen);
 
 	unsigned char nonce[DRBG_MAX_NONCE];
 
 	/* nonce gathering function */
-	size_t (*get_nonce)(DRBG_CTX *ctx, unsigned char *out,
+	size_t (*get_nonce)(DRBG_CTX *ctx, unsigned char **pout,
 				int entropy, size_t min_len, size_t max_len);
+	/* Indicates we have finished with nonce buffer */
+	void (*cleanup_nonce)(DRBG_CTX *ctx, unsigned char *out, size_t olen);
 
 	/* Continuous random number test temporary area */
 	/* Last block */