Implement continuous RNG test for SP800-90 DRBGs.
diff --git a/crypto/fips_err.h b/crypto/fips_err.h
index 4b75c2d..4ff3ec1 100644
--- a/crypto/fips_err.h
+++ b/crypto/fips_err.h
@@ -84,6 +84,7 @@
 {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 @@
 {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 af36f03..6dadc1e 100644
--- a/fips/fips.h
+++ b/fips/fips.h
@@ -194,6 +194,7 @@
 #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 @@
 #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 0e06273..94bc36a 100644
--- a/fips/rand/fips_drbg_lib.c
+++ b/fips/rand/fips_drbg_lib.c
@@ -263,7 +263,8 @@
 	}
 
 
-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 @@
 	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 7e64bb4..8f97ac0 100644
--- a/fips/rand/fips_rand_lcl.h
+++ b/fips/rand/fips_rand_lcl.h
@@ -167,6 +167,12 @@
 	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;
+
 	};