Extensive reorganisation of PRNG handling in FIPS module: all calls
now use an internal RAND_METHOD. All dependencies to OpenSSL standard
PRNG are now removed: it is the applications resposibility to setup
the FIPS PRNG and initalise it.

Initial OpenSSL RAND_init_fips() function that will setup the DRBG
for the "FIPS capable OpenSSL".
diff --git a/CHANGES b/CHANGES
index 7709cc2..4307a99 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,14 @@
 
  Changes between 1.0.1 and 1.1.0  [xx XXX xxxx]
 
+  *) Extensive reorganisation of FIPS PRNG behaviour. Remove all dependencies
+     to OpenSSL RAND code and replace with a tiny FIPS RAND API which also
+     performs algorithm blocking for unapproved PRNG types. Also do not
+     set PRNG type in FIPS_mode_set(): leave this to the application.
+     Add default OpenSSL DRBG handling: sets up FIPS PRNG and seeds with
+     the standard OpenSSL PRNG.
+     [Steve Henson]
+
   *) Rename old X9.31 PRNG functions of the form FIPS_rand* to FIPS_x931*.
      This shouldn't present any incompatibility problems because applications
      shouldn't be using these directly and any that are will need to rethink
diff --git a/crypto/evp/e_des3.c b/crypto/evp/e_des3.c
index 785d76b..2f016f0 100644
--- a/crypto/evp/e_des3.c
+++ b/crypto/evp/e_des3.c
@@ -56,6 +56,8 @@
  * [including the GNU Public Licence.]
  */
 
+#define OPENSSL_FIPSAPI
+
 #include <stdio.h>
 #include "cryptlib.h"
 #ifndef OPENSSL_NO_DES
diff --git a/crypto/fips_err.h b/crypto/fips_err.h
index 589263c..d63e869 100644
--- a/crypto/fips_err.h
+++ b/crypto/fips_err.h
@@ -96,6 +96,12 @@
 {ERR_FUNC(FIPS_F_FIPS_DSA_CHECK),	"FIPS_DSA_CHECK"},
 {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"},
+{ERR_FUNC(FIPS_F_FIPS_RAND_BYTES),	"FIPS_rand_bytes"},
+{ERR_FUNC(FIPS_F_FIPS_RAND_PSEUDO_BYTES),	"FIPS_rand_pseudo_bytes"},
+{ERR_FUNC(FIPS_F_FIPS_RAND_SEED),	"FIPS_rand_seed"},
+{ERR_FUNC(FIPS_F_FIPS_RAND_SET_METHOD),	"FIPS_rand_set_method"},
+{ERR_FUNC(FIPS_F_FIPS_RAND_STATUS),	"FIPS_rand_status"},
 {ERR_FUNC(FIPS_F_FIPS_SELFTEST_AES),	"FIPS_selftest_aes"},
 {ERR_FUNC(FIPS_F_FIPS_SELFTEST_AES_GCM),	"FIPS_selftest_aes_gcm"},
 {ERR_FUNC(FIPS_F_FIPS_SELFTEST_CMAC),	"FIPS_selftest_cmac"},
@@ -105,6 +111,7 @@
 {ERR_FUNC(FIPS_F_FIPS_SELFTEST_HMAC),	"FIPS_selftest_hmac"},
 {ERR_FUNC(FIPS_F_FIPS_SELFTEST_RNG),	"FIPS_selftest_rng"},
 {ERR_FUNC(FIPS_F_FIPS_SELFTEST_SHA1),	"FIPS_selftest_sha1"},
+{ERR_FUNC(FIPS_F_FIPS_SELFTEST_X931),	"FIPS_selftest_x931"},
 {ERR_FUNC(FIPS_F_HASH_FINAL),	"HASH_FINAL"},
 {ERR_FUNC(FIPS_F_RSA_BUILTIN_KEYGEN),	"RSA_BUILTIN_KEYGEN"},
 {ERR_FUNC(FIPS_F_RSA_EAY_PRIVATE_DECRYPT),	"RSA_EAY_PRIVATE_DECRYPT"},
diff --git a/crypto/o_init.c b/crypto/o_init.c
index bb6d9cf..b7f8d10 100644
--- a/crypto/o_init.c
+++ b/crypto/o_init.c
@@ -56,6 +56,7 @@
 #include <openssl/err.h>
 #ifdef OPENSSL_FIPS
 #include <openssl/fips.h>
+#include <openssl/rand.h>
 #endif
 
 #if defined(__GNUC__) && __GNUC__>=2
@@ -123,6 +124,7 @@
 	FIPS_set_locking_callbacks(CRYPTO_lock, CRYPTO_add_lock);
 	FIPS_set_error_callbacks(ERR_put_error, ERR_add_error_vdata);
 	FIPS_set_malloc_callbacks(CRYPTO_malloc, CRYPTO_free);
+	RAND_init_fips();
 #endif
 #if 0
 	fprintf(stderr, "Called OPENSSL_init\n");
diff --git a/crypto/rand/rand.h b/crypto/rand/rand.h
index 8db2a5f..d446c38 100644
--- a/crypto/rand/rand.h
+++ b/crypto/rand/rand.h
@@ -94,7 +94,7 @@
 
 int RAND_set_rand_method(const RAND_METHOD *meth);
 const RAND_METHOD *RAND_get_rand_method(void);
-#if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_FIPS)
+#ifndef OPENSSL_NO_ENGINE
 int RAND_set_rand_engine(ENGINE *engine);
 #endif
 RAND_METHOD *RAND_SSLeay(void);
@@ -119,6 +119,10 @@
 
 #endif
 
+#ifdef OPENSSL_FIPS
+int RAND_init_fips(void);
+#endif
+
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
  * made after this point may be overwritten when the script is next run.
@@ -132,6 +136,7 @@
 #define RAND_F_FIPS_RAND_SET_DT				 103
 #define RAND_F_FIPS_SET_PRNG_SEED			 104
 #define RAND_F_FIPS_SET_TEST_MODE			 105
+#define RAND_F_FIPS_X931_SET_DT				 106
 #define RAND_F_RAND_GET_RAND_METHOD			 101
 #define RAND_F_SSLEAY_RAND_BYTES			 100
 
diff --git a/crypto/rand/rand_err.c b/crypto/rand/rand_err.c
index 1997752..a435b0b 100644
--- a/crypto/rand/rand_err.c
+++ b/crypto/rand/rand_err.c
@@ -74,6 +74,7 @@
 {ERR_FUNC(RAND_F_FIPS_RAND_SET_DT),	"FIPS_RAND_SET_DT"},
 {ERR_FUNC(RAND_F_FIPS_SET_PRNG_SEED),	"FIPS_SET_PRNG_SEED"},
 {ERR_FUNC(RAND_F_FIPS_SET_TEST_MODE),	"FIPS_SET_TEST_MODE"},
+{ERR_FUNC(RAND_F_FIPS_X931_SET_DT),	"FIPS_x931_set_dt"},
 {ERR_FUNC(RAND_F_RAND_GET_RAND_METHOD),	"RAND_get_rand_method"},
 {ERR_FUNC(RAND_F_SSLEAY_RAND_BYTES),	"SSLEAY_RAND_BYTES"},
 {0,NULL}
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c
index 3cf9ed5..ef10dd5 100644
--- a/crypto/rand/rand_lib.c
+++ b/crypto/rand/rand_lib.c
@@ -61,11 +61,6 @@
 #include "cryptlib.h"
 #include <openssl/rand.h>
 
-#ifdef OPENSSL_FIPSCANISTER
-#define OPENSSL_NO_ENGINE
-#include <openssl/fips.h>
-#endif
-
 #ifndef OPENSSL_NO_ENGINE
 #include <openssl/engine.h>
 #endif
@@ -180,3 +175,70 @@
 		return meth->status();
 	return 0;
 	}
+
+#ifdef OPENSSL_FIPS
+
+#include <openssl/fips.h>
+#include <openssl/fips_rand.h>
+
+/* FIPS DRBG initialisation code. This sets up the DRBG for use by the
+ * rest of OpenSSL. 
+ */
+
+/* Entropy gatherer: use standard OpenSSL PRNG to seed (this will gather
+ * entropy internally through RAND_poll().
+ */
+
+static size_t drbg_get_entropy(DRBG_CTX *ctx, unsigned char **pout,
+                                int entropy, size_t min_len, size_t max_len)
+        {
+	*pout = OPENSSL_malloc(min_len);
+	if (!*pout)
+		return 0;
+	if (RAND_SSLeay()->bytes(*pout, min_len) <= 0)
+		{
+		OPENSSL_free(*pout);
+		*pout = NULL;
+		return 0;
+		}
+        return min_len;
+        }
+
+static void drbg_free_entropy(DRBG_CTX *ctx, unsigned char *out, size_t olen)
+	{
+	OPENSSL_cleanse(out, olen);
+	OPENSSL_free(out);
+	}
+
+/* RAND_add() and RAND_seed() pass through to OpenSSL PRNG so it is 
+ * correctly seeded by RAND_poll().
+ */
+
+static int drbg_rand_add(DRBG_CTX *ctx, const void *in, int inlen,
+				double entropy)
+	{
+	return RAND_SSLeay()->add(in, inlen, entropy);
+	}
+
+static int drbg_rand_seed(DRBG_CTX *ctx, const void *in, int inlen)
+	{
+	return RAND_SSLeay()->seed(in, inlen);
+	}
+
+int RAND_init_fips(void)
+	{
+	DRBG_CTX *dctx;
+	unsigned char pers[16] = {0,0,0};
+	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);
+	FIPS_drbg_set_rand_callbacks(dctx, 0, 0,
+					drbg_rand_seed, drbg_rand_add);
+        FIPS_drbg_instantiate(dctx, pers, sizeof(pers));
+        FIPS_rand_set_method(FIPS_drbg_method());
+	return 1;
+	}
+
+#endif
diff --git a/fips/fips.c b/fips/fips.c
index 42f4003..7ca2492 100644
--- a/fips/fips.c
+++ b/fips/fips.c
@@ -73,7 +73,6 @@
 static int fips_selftest_fail;
 static int fips_mode;
 static int fips_started = 0;
-static const void *fips_rand_check;
 
 static int fips_is_owning_thread(void);
 static int fips_set_owning_thread(void);
@@ -97,18 +96,6 @@
 		}
 	}
 
-static void fips_set_rand_check(const void *rand_check)
-	{
-	int owning_thread = fips_is_owning_thread();
-
-	if (fips_started)
-		{
-		if (!owning_thread) fips_w_lock();
-		fips_rand_check = rand_check;
-		if (!owning_thread) fips_w_unlock();
-		}
-	}
-
 int FIPS_mode(void)
 	{
 	int ret = 0;
@@ -123,20 +110,6 @@
 	return ret;
 	}
 
-const void *FIPS_rand_check(void)
-	{
-	const void *ret = 0;
-	int owning_thread = fips_is_owning_thread();
-
-	if (fips_started)
-		{
-		if (!owning_thread) fips_r_lock();
-		ret = fips_rand_check;
-		if (!owning_thread) fips_r_unlock();
-		}
-	return ret;
-	}
-
 int FIPS_selftest_failed(void)
     {
     int ret = 0;
@@ -329,28 +302,7 @@
 	    ret = 0;
 	    goto end;
 	    }
-#if 0
-	/* automagically seed PRNG if not already seeded */
-	if(!FIPS_rand_status())
-	    {
-	    unsigned char buf[48];
-	    if(RAND_bytes(buf,sizeof buf) <= 0)
-		{
-		fips_selftest_fail = 1;
-		ret = 0;
-		goto end;
-		}
-	    FIPS_rand_set_key(buf,32);
-	    FIPS_rand_seed(buf+32,16);
-	    }
 
-	/* now switch into FIPS mode */
-	fips_set_rand_check(FIPS_rand_method());
-	RAND_set_rand_method(FIPS_rand_method());
-#else
-	fips_set_rand_check(FIPS_drbg_method());
-	RAND_set_rand_method(FIPS_drbg_method());
-#endif
 	if(FIPS_selftest())
 	    fips_set_mode(1);
 	else
diff --git a/fips/fips.h b/fips/fips.h
index e4c3266..53bc12f 100644
--- a/fips/fips.h
+++ b/fips/fips.h
@@ -177,6 +177,12 @@
 #define ecdsa_check fips_ecdsa_check
 #define ecdh_check fips_ecdh_check
 
+#define RAND_bytes FIPS_rand_bytes
+#define RAND_pseudo_bytes FIPS_rand_pseudo_bytes
+#define RAND_add FIPS_rand_add
+#define RAND_seed FIPS_rand_seed
+#define RAND_status FIPS_rand_status
+
 #endif
 
 /* BEGIN ERROR CODES */
@@ -214,6 +220,12 @@
 #define FIPS_F_FIPS_DSA_CHECK				 107
 #define FIPS_F_FIPS_MODE_SET				 108
 #define FIPS_F_FIPS_PKEY_SIGNATURE_TEST			 109
+#define FIPS_F_FIPS_RAND_ADD				 143
+#define FIPS_F_FIPS_RAND_BYTES				 144
+#define FIPS_F_FIPS_RAND_PSEUDO_BYTES			 145
+#define FIPS_F_FIPS_RAND_SEED				 148
+#define FIPS_F_FIPS_RAND_SET_METHOD			 146
+#define FIPS_F_FIPS_RAND_STATUS				 147
 #define FIPS_F_FIPS_SELFTEST_AES			 110
 #define FIPS_F_FIPS_SELFTEST_AES_GCM			 130
 #define FIPS_F_FIPS_SELFTEST_CMAC			 139
@@ -223,6 +235,7 @@
 #define FIPS_F_FIPS_SELFTEST_HMAC			 113
 #define FIPS_F_FIPS_SELFTEST_RNG			 114
 #define FIPS_F_FIPS_SELFTEST_SHA1			 115
+#define FIPS_F_FIPS_SELFTEST_X931			 149
 #define FIPS_F_HASH_FINAL				 123
 #define FIPS_F_RSA_BUILTIN_KEYGEN			 116
 #define FIPS_F_RSA_EAY_PRIVATE_DECRYPT			 117
diff --git a/fips/fips_test_suite.c b/fips/fips_test_suite.c
index c82dffe..2cfd5ef 100644
--- a/fips/fips_test_suite.c
+++ b/fips/fips_test_suite.c
@@ -678,9 +678,6 @@
 
     printf("\tFIPS-mode test application\n\n");
 
-    /* Load entropy from external file, if any */
-    RAND_load_file(".rnd", 1024);
-
     if (argv[1]) {
         /* Corrupted KAT tests */
         if (!strcmp(argv[1], "aes")) {
diff --git a/fips/fips_utl.h b/fips/fips_utl.h
index 4810566..91cbea2 100644
--- a/fips/fips_utl.h
+++ b/fips/fips_utl.h
@@ -118,6 +118,7 @@
 	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_instantiate(ctx, dummy_entropy, 10);
+	FIPS_rand_set_method(FIPS_drbg_method());
 	}
 
 void fips_algtest_init(void)
diff --git a/fips/rand/Makefile b/fips/rand/Makefile
index 8147951..bcf68dc 100644
--- a/fips/rand/Makefile
+++ b/fips/rand/Makefile
@@ -24,10 +24,10 @@
 LIB=$(TOP)/libcrypto.a
 LIBSRC=	fips_rand.c fips_rand_selftest.c \
 	fips_drbg_lib.c fips_drbg_hash.c fips_drbg_ctr.c fips_drbg_selftest.c \
-	fips_drbg_rand.c
+	fips_drbg_rand.c fips_rand_lib.c
 LIBOBJ=	fips_rand.o fips_rand_selftest.o \
 	fips_drbg_lib.o fips_drbg_hash.o fips_drbg_ctr.o fips_drbg_selftest.o \
-	fips_drbg_rand.o
+	fips_drbg_rand.o fips_rand_lib.o
 
 SRC= $(LIBSRC)
 
diff --git a/fips/rand/fips_drbg_rand.c b/fips/rand/fips_drbg_rand.c
index 1863026..8872ba2 100644
--- a/fips/rand/fips_drbg_rand.c
+++ b/fips/rand/fips_drbg_rand.c
@@ -145,28 +145,18 @@
 static int fips_drbg_seed(const void *seed, int seedlen)
 	{
 	DRBG_CTX *dctx = &ossl_dctx;
-	int rv = 1;
 	if (dctx->rand_seed_cb)
-		{
-		CRYPTO_w_lock(CRYPTO_LOCK_RAND);
-		rv = dctx->rand_seed_cb(dctx, seed, seedlen);
-		CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
-		}
-	return rv;
+		return dctx->rand_seed_cb(dctx, seed, seedlen);
+	return 1;
 	}
 
 static int fips_drbg_add(const void *seed, int seedlen,
 					double add_entropy)
 	{
 	DRBG_CTX *dctx = &ossl_dctx;
-	int rv = 1;
 	if (dctx->rand_add_cb)
-		{
-		CRYPTO_w_lock(CRYPTO_LOCK_RAND);
-		rv = dctx->rand_add_cb(dctx, seed, seedlen, add_entropy);
-		CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
-		}
-	return rv;
+		return dctx->rand_add_cb(dctx, seed, seedlen, add_entropy);
+	return 1;
 	}
 
 static const RAND_METHOD rand_drbg_meth =
diff --git a/fips/rand/fips_rand.c b/fips/rand/fips_rand.c
index d56b940..a8ebdb8 100644
--- a/fips/rand/fips_rand.c
+++ b/fips/rand/fips_rand.c
@@ -214,7 +214,7 @@
 	{
 	if (!sctx.test_mode)
 		{
-		RANDerr(RAND_F_FIPS_RAND_SET_DT,RAND_R_NOT_IN_TEST_MODE);
+		RANDerr(RAND_F_FIPS_X931_SET_DT,RAND_R_NOT_IN_TEST_MODE);
 		return 0;
 		}
 	memcpy(sctx.DT, dt, AES_BLOCK_LENGTH);
diff --git a/fips/rand/fips_rand.h b/fips/rand/fips_rand.h
index a691e14..1a57edd 100644
--- a/fips/rand/fips_rand.h
+++ b/fips/rand/fips_rand.h
@@ -112,6 +112,7 @@
 DRBG_CTX *FIPS_get_default_drbg(void);
 const RAND_METHOD *FIPS_drbg_method(void);
 
+int FIPS_rand_set_method(const RAND_METHOD *meth);
 
 #ifdef  __cplusplus
 }
diff --git a/fips/rand/fips_rand_lib.c b/fips/rand/fips_rand_lib.c
new file mode 100644
index 0000000..2d198f9
--- /dev/null
+++ b/fips/rand/fips_rand_lib.c
@@ -0,0 +1,140 @@
+/* ====================================================================
+ * Copyright (c) 2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define OPENSSL_FIPSAPI
+
+#include <openssl/crypto.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/fips.h>
+#include <openssl/fips_rand.h>
+#include "e_os.h"
+
+/* FIPS API for PRNG use. Similar to RAND functionality but without
+ * ENGINE and additional checking for non-FIPS rand methods.
+ */
+
+static const RAND_METHOD *fips_rand_meth = NULL;
+static int fips_approved_rand_meth = 0;
+
+int FIPS_rand_set_method(const RAND_METHOD *meth)
+	{
+	if (meth == FIPS_drbg_method())
+		fips_approved_rand_meth = 1;
+	else if (meth == FIPS_x931_method())
+		fips_approved_rand_meth = 2;
+	else
+		fips_approved_rand_meth = 0;
+
+	if (!fips_approved_rand_meth && FIPS_mode())
+		{
+		FIPSerr(FIPS_F_FIPS_RAND_SET_METHOD, FIPS_R_NON_FIPS_METHOD);
+		return 0;
+		}
+	fips_rand_meth = meth;
+	return 1;
+	}
+
+void FIPS_rand_seed(const void *buf, int num)
+	{
+	if (!fips_approved_rand_meth && FIPS_mode())
+		{
+		FIPSerr(FIPS_F_FIPS_RAND_SEED, FIPS_R_NON_FIPS_METHOD);
+		return;
+		}
+	if (fips_rand_meth && fips_rand_meth->seed)
+		fips_rand_meth->seed(buf,num);
+	}
+
+void FIPS_rand_add(const void *buf, int num, double entropy)
+	{
+	if (!fips_approved_rand_meth && FIPS_mode())
+		{
+		FIPSerr(FIPS_F_FIPS_RAND_ADD, FIPS_R_NON_FIPS_METHOD);
+		return;
+		}
+	if (fips_rand_meth && fips_rand_meth->add)
+		fips_rand_meth->add(buf,num,entropy);
+	}
+
+int FIPS_rand_bytes(unsigned char *buf, int num)
+	{
+	if (!fips_approved_rand_meth && FIPS_mode())
+		{
+		FIPSerr(FIPS_F_FIPS_RAND_BYTES, FIPS_R_NON_FIPS_METHOD);
+		return 0;
+		}
+	if (fips_rand_meth && fips_rand_meth->bytes)
+		return fips_rand_meth->bytes(buf,num);
+	return 0;
+	}
+
+int FIPS_rand_pseudo_bytes(unsigned char *buf, int num)
+	{
+	if (!fips_approved_rand_meth && FIPS_mode())
+		{
+		FIPSerr(FIPS_F_FIPS_RAND_PSEUDO_BYTES, FIPS_R_NON_FIPS_METHOD);
+		return 0;
+		}
+	if (fips_rand_meth && fips_rand_meth->pseudorand)
+		return fips_rand_meth->pseudorand(buf,num);
+	return -1;
+	}
+
+int FIPS_rand_status(void)
+	{
+	if (!fips_approved_rand_meth && FIPS_mode())
+		{
+		FIPSerr(FIPS_F_FIPS_RAND_STATUS, FIPS_R_NON_FIPS_METHOD);
+		return 0;
+		}
+	if (fips_rand_meth && fips_rand_meth->status)
+		return fips_rand_meth->status();
+	return 0;
+	}
diff --git a/fips/rand/fips_rand_selftest.c b/fips/rand/fips_rand_selftest.c
index ee5f320..afab1fa 100644
--- a/fips/rand/fips_rand_selftest.c
+++ b/fips/rand/fips_rand_selftest.c
@@ -356,14 +356,14 @@
 	FIPS_x931_reset();
 	if (!FIPS_x931_test_mode())
 		{
-		FIPSerr(FIPS_F_FIPS_SELFTEST_RNG,FIPS_R_SELFTEST_FAILED);
+		FIPSerr(FIPS_F_FIPS_SELFTEST_X931,FIPS_R_SELFTEST_FAILED);
 		return 0;
 		}
 	if (!fips_x931_test(aes_128_key,aes_128_tv)
 		|| !fips_x931_test(aes_192_key, aes_192_tv)
 		|| !fips_x931_test(aes_256_key, aes_256_tv))
 		{
-		FIPSerr(FIPS_F_FIPS_SELFTEST_RNG,FIPS_R_SELFTEST_FAILED);
+		FIPSerr(FIPS_F_FIPS_SELFTEST_X931,FIPS_R_SELFTEST_FAILED);
 		return 0;
 		}
 	FIPS_x931_reset();