Standardize apps use of -rand, etc.

Standardized the -rand flag and added a new one:
    -rand file...
            Always reads the specified files
    -writerand file
            Always writes to the file on exit

For apps that use a config file, the RANDFILE config parameter reads
the file at startup (to seed the RNG) and write to it on exit if
the -writerand flag isn't used.

Ensured that every app that took -rand also took -writerand, and
made sure all of that agreed with all the documentation.

Fix error reporting in write_file and -rand

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/3862)
diff --git a/apps/app_rand.c b/apps/app_rand.c
index 21445ac..960d2fe 100644
--- a/apps/app_rand.c
+++ b/apps/app_rand.c
@@ -10,108 +10,82 @@
 #include "apps.h"
 #include <openssl/bio.h>
 #include <openssl/rand.h>
+#include <openssl/conf.h>
 
-static int seeded = 0;
-static int egdsocket = 0;
+static const char *save_rand_file;
 
-int app_RAND_load_file(const char *file, int dont_warn)
+void app_RAND_load_conf(CONF *c, const char *section)
 {
-    int consider_randfile = (file == NULL);
-    char buffer[200];
+    const char *randfile = NCONF_get_string(c, section, "RANDFILE");
 
-    if (file == NULL) {
-        file = RAND_file_name(buffer, sizeof buffer);
-#ifndef OPENSSL_NO_EGD
-    } else if (RAND_egd(file) > 0) {
-        /*
-         * we try if the given filename is an EGD socket. if it is, we don't
-         * write anything back to the file.
-         */
-        egdsocket = 1;
-        return 1;
-#endif
+    if (randfile == NULL) {
+        ERR_clear_error();
+        return;
     }
-
-    if (file == NULL || !RAND_load_file(file, -1)) {
-        if (RAND_status() == 0) {
-            if (!dont_warn) {
-                BIO_printf(bio_err, "unable to load 'random state'\n");
-                BIO_printf(bio_err,
-                           "This means that the random number generator has not been seeded\n");
-                BIO_printf(bio_err, "with much random data.\n");
-                if (consider_randfile) { /* explanation does not apply when a
-                                          * file is explicitly named */
-                    BIO_printf(bio_err,
-                               "Consider setting the RANDFILE environment variable to point at a file that\n");
-                    BIO_printf(bio_err,
-                               "'random' data can be kept in (the file will be overwritten).\n");
-                }
-            }
-            return 0;
-        }
+    if (RAND_load_file(randfile, -1) < 0) {
+        BIO_printf(bio_err, "Can't load %s into RNG\n", randfile);
+        ERR_print_errors(bio_err);
+        return;
     }
-    seeded = 1;
-    return 1;
+    if (save_rand_file == NULL)
+        save_rand_file = randfile;
 }
 
-long app_RAND_load_files(char *name)
+static int loadfiles(char *name)
 {
     char *p, *n;
-    int last;
-    long tot = 0;
-#ifndef OPENSSL_NO_EGD
-    int egd;
-#endif
+    int last, ret = 1;
 
-    for (;;) {
+    for ( ; ; ) {
         last = 0;
-        for (p = name; ((*p != '\0') && (*p != LIST_SEPARATOR_CHAR)); p++) ;
+        for (p = name; *p != '\0' && *p != LIST_SEPARATOR_CHAR; p++)
+            continue;
         if (*p == '\0')
             last = 1;
         *p = '\0';
+        if (RAND_load_file(name, -1) < 0) {
+            BIO_printf(bio_err, "Can't load %s into RNG\n", name);
+            ERR_print_errors(bio_err);
+            ret = 0;
+        }
         n = name;
-        name = p + 1;
-        if (*n == '\0')
-            break;
-
-#ifndef OPENSSL_NO_EGD
-        egd = RAND_egd(n);
-        if (egd > 0)
-            tot += egd;
-        else
-#endif
-            tot += RAND_load_file(n, -1);
         if (last)
             break;
+        name = p + 1;
+        if (*name == '\0')
+            break;
     }
-    if (tot > 512)
-        app_RAND_allow_write_file();
-    return (tot);
+    return ret;
 }
 
-int app_RAND_write_file(const char *file)
+void app_RAND_write(void)
 {
-    char buffer[200];
-
-    if (egdsocket || !seeded) {
-        /*
-         * If we didn't manage to read the seed file, don't write a
-         * file out -- it would suppress a crucial warning the next
-         * time we want to use it.
-         */
-        return 0;
+    if (save_rand_file == NULL)
+        return;
+    if (RAND_write_file(save_rand_file) == -1) {
+        BIO_printf(bio_err, "Cannot write random bytes:\n");
+        ERR_print_errors(bio_err);
     }
+}
 
-    if (file == NULL)
-        file = RAND_file_name(buffer, sizeof buffer);
-    if (file == NULL || !RAND_write_file(file)) {
-        BIO_printf(bio_err, "unable to write 'random state'\n");
-        return 0;
+
+/*
+ * See comments in opt_verify for explanation of this.
+ */
+enum r_range { OPT_R_ENUM };
+
+int opt_rand(int opt)
+{
+    switch ((enum r_range)opt) {
+    case OPT_R__FIRST:
+    case OPT_R__LAST:
+        break;
+    case OPT_R_RAND:
+        return loadfiles(opt_arg());
+        break;
+    case OPT_R_WRITERAND:
+        save_rand_file = opt_arg();
+        break;
     }
     return 1;
 }
-
-void app_RAND_allow_write_file(void)
-{
-    seeded = 1;
-}
diff --git a/apps/apps.h b/apps/apps.h
index 09c601b..aa3cd3f 100644
--- a/apps/apps.h
+++ b/apps/apps.h
@@ -40,16 +40,8 @@
  */
 #define _UC(c) ((unsigned char)(c))
 
-int app_RAND_load_file(const char *file, int dont_warn);
-int app_RAND_write_file(const char *file);
-/*
- * When `file' is NULL, use defaults. `bio_e' is for error messages.
- */
-void app_RAND_allow_write_file(void);
-long app_RAND_load_files(char *file); /* `file' is a list of files to read,
-                                       * separated by LIST_SEPARATOR_CHAR
-                                       * (see e_os.h).  The string is
-                                       * destroyed! */
+void app_RAND_load_conf(CONF *c, const char *section);
+void app_RAND_write(void);
 
 extern char *default_config_file;
 extern BIO *bio_in;
@@ -177,7 +169,7 @@
         case OPT_V_ALLOW_PROXY_CERTS
 
 /*
- * Common "extended"? options.
+ * Common "extended validation" options.
  */
 # define OPT_X_ENUM \
         OPT_X__FIRST=1000, \
@@ -300,6 +292,20 @@
   || o == OPT_S_NOTLS1_2 || o == OPT_S_NOTLS1_3)
 
 /*
+ * Random state options.
+ */
+# define OPT_R_ENUM \
+        OPT_R__FIRST=1500, OPT_R_RAND, OPT_R_WRITERAND, OPT_R__LAST
+
+# define OPT_R_OPTIONS \
+    {"rand", OPT_R_RAND, 's', "Load the file(s) into the random number generator"}, \
+    {"writerand", OPT_R_WRITERAND, '>', "Write random data to the specified file"}
+
+# define OPT_R_CASES \
+        OPT_R__FIRST: case OPT_R__LAST: break; \
+        case OPT_R_RAND: case OPT_R_WRITERAND
+
+/*
  * Option parsing.
  */
 extern const char OPT_HELP_STR[];
@@ -373,6 +379,7 @@
 char **opt_rest(void);
 int opt_num_rest(void);
 int opt_verify(int i, X509_VERIFY_PARAM *vpm);
+int opt_rand(int i);
 void opt_help(const OPTIONS * list);
 int opt_format_error(const char *s, unsigned long flags);
 
diff --git a/apps/ca.c b/apps/ca.c
index 91d962f..c1c2c49 100644
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -153,6 +153,7 @@
     OPT_GENCRL, OPT_MSIE_HACK, OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC,
     OPT_INFILES, OPT_SS_CERT, OPT_SPKAC, OPT_REVOKE, OPT_VALID,
     OPT_EXTENSIONS, OPT_EXTFILE, OPT_STATUS, OPT_UPDATEDB, OPT_CRLEXTS,
+    OPT_R_ENUM,
     /* Do not change the order here; see related case statements below */
     OPT_CRL_REASON, OPT_CRL_HOLD, OPT_CRL_COMPROMISE, OPT_CRL_CA_COMPROMISE
 } OPTION_CHOICE;
@@ -217,6 +218,7 @@
      "sets compromise time to val and the revocation reason to keyCompromise"},
     {"crl_CA_compromise", OPT_CRL_CA_COMPROMISE, 's',
      "sets compromise time to val and the revocation reason to CACompromise"},
+    OPT_R_OPTIONS,
 #ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 #endif
@@ -247,7 +249,7 @@
     char *outdir = NULL, *outfile = NULL, *rev_arg = NULL, *ser_status = NULL;
     const char *serialfile = NULL, *subj = NULL;
     char *prog, *startdate = NULL, *enddate = NULL;
-    char *dbfile = NULL, *f, *randfile = NULL;
+    char *dbfile = NULL, *f;
     char new_cert[CERT_MAX + 1];
     char tmp[10 + 1] = "\0";
     char *const *pp;
@@ -332,6 +334,10 @@
         case OPT_PASSIN:
             passinarg = opt_arg();
             break;
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
+            break;
         case OPT_KEY:
             key = opt_arg();
             break;
@@ -465,10 +471,7 @@
         }
     }
 
-    randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
-    if (randfile == NULL)
-        ERR_clear_error();
-    app_RAND_load_file(randfile, 0);
+    app_RAND_load_conf(conf, BASE_SECTION);
 
     f = NCONF_get_string(conf, section, STRING_MASK);
     if (f == NULL)
@@ -1220,7 +1223,6 @@
 
     if (ret)
         ERR_print_errors(bio_err);
-    app_RAND_write_file(randfile);
     if (free_key)
         OPENSSL_free(key);
     BN_free(serial);
diff --git a/apps/cms.c b/apps/cms.c
index 25ee7e8..543d013 100644
--- a/apps/cms.c
+++ b/apps/cms.c
@@ -76,10 +76,11 @@
     OPT_RR_ALL, OPT_RR_FIRST, OPT_RCTFORM, OPT_CERTFILE, OPT_CAFILE,
     OPT_CAPATH, OPT_NOCAPATH, OPT_NOCAFILE,OPT_CONTENT, OPT_PRINT,
     OPT_SECRETKEY, OPT_SECRETKEYID, OPT_PWRI_PASSWORD, OPT_ECONTENT_TYPE,
-    OPT_RAND, OPT_PASSIN, OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP,
+    OPT_PASSIN, OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP,
     OPT_CERTSOUT, OPT_MD, OPT_INKEY, OPT_KEYFORM, OPT_KEYOPT, OPT_RR_FROM,
     OPT_RR_TO, OPT_AES128_WRAP, OPT_AES192_WRAP, OPT_AES256_WRAP,
     OPT_3DES_WRAP, OPT_ENGINE,
+    OPT_R_ENUM,
     OPT_V_ENUM,
     OPT_CIPHER
 } OPTION_CHOICE;
@@ -152,8 +153,6 @@
     {"secretkeyid", OPT_SECRETKEYID, 's'},
     {"pwri_password", OPT_PWRI_PASSWORD, 's'},
     {"econtent_type", OPT_ECONTENT_TYPE, 's'},
-    {"rand", OPT_RAND, 's',
-     "Load the file(s) into the random number generator"},
     {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
     {"to", OPT_TO, 's', "To address"},
     {"from", OPT_FROM, 's', "From address"},
@@ -169,6 +168,7 @@
     {"receipt_request_from", OPT_RR_FROM, 's'},
     {"receipt_request_to", OPT_RR_TO, 's'},
     {"", OPT_CIPHER, '-', "Any supported cipher"},
+    OPT_R_OPTIONS,
     OPT_V_OPTIONS,
     {"aes128-wrap", OPT_AES128_WRAP, '-', "Use AES128 to wrap key"},
     {"aes192-wrap", OPT_AES192_WRAP, '-', "Use AES192 to wrap key"},
@@ -202,16 +202,13 @@
     const char *CAfile = NULL, *CApath = NULL;
     char *certsoutfile = NULL;
     int noCAfile = 0, noCApath = 0;
-    char *infile = NULL, *outfile = NULL, *rctfile = NULL, *inrand = NULL;
-    char *passinarg = NULL, *passin = NULL, *signerfile = NULL, *recipfile =
-        NULL;
+    char *infile = NULL, *outfile = NULL, *rctfile = NULL;
+    char *passinarg = NULL, *passin = NULL, *signerfile = NULL, *recipfile = NULL;
     char *to = NULL, *from = NULL, *subject = NULL, *prog;
     cms_key_param *key_first = NULL, *key_param = NULL;
-    int flags = CMS_DETACHED, noout = 0, print = 0, keyidx = -1, vpmtouched =
-        0;
+    int flags = CMS_DETACHED, noout = 0, print = 0, keyidx = -1, vpmtouched = 0;
     int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
-    int need_rand = 0, operation = 0, ret = 1, rr_print = 0, rr_allorfirst =
-        -1;
+    int operation = 0, ret = 1, rr_print = 0, rr_allorfirst = -1;
     int verify_retcode = 0, rctformat = FORMAT_SMIME, keyform = FORMAT_PEM;
     size_t secret_keylen = 0, secret_keyidlen = 0;
     unsigned char *pwri_pass = NULL, *pwri_tmp = NULL;
@@ -449,10 +446,6 @@
                 goto opthelp;
             }
             break;
-        case OPT_RAND:
-            inrand = opt_arg();
-            need_rand = 1;
-            break;
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
             break;
@@ -568,6 +561,10 @@
                 goto end;
             vpmtouched++;
             break;
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
+            break;
         case OPT_3DES_WRAP:
 # ifndef OPENSSL_NO_DES
             wrap_cipher = EVP_des_ede3_wrap();
@@ -624,7 +621,6 @@
         }
         signerfile = NULL;
         keyfile = NULL;
-        need_rand = 1;
     } else if (operation == SMIME_DECRYPT) {
         if (recipfile == NULL && keyfile == NULL
             && secret_key == NULL && pwri_pass == NULL) {
@@ -638,7 +634,6 @@
             BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
             goto opthelp;
         }
-        need_rand = 1;
     } else if (!operation) {
         goto opthelp;
     }
@@ -648,13 +643,6 @@
         goto end;
     }
 
-    if (need_rand) {
-        app_RAND_load_file(NULL, (inrand != NULL));
-        if (inrand != NULL)
-            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
-                       app_RAND_load_files(inrand));
-    }
-
     ret = 2;
 
     if (!(operation & SMIME_SIGNERS))
@@ -1083,8 +1071,6 @@
  end:
     if (ret)
         ERR_print_errors(bio_err);
-    if (need_rand)
-        app_RAND_write_file(NULL);
     sk_X509_pop_free(encerts, X509_free);
     sk_X509_pop_free(other, X509_free);
     X509_VERIFY_PARAM_free(vpm);
diff --git a/apps/dgst.c b/apps/dgst.c
index 545c032..df50947 100644
--- a/apps/dgst.c
+++ b/apps/dgst.c
@@ -29,11 +29,12 @@
 
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
-    OPT_C, OPT_R, OPT_RAND, OPT_OUT, OPT_SIGN, OPT_PASSIN, OPT_VERIFY,
+    OPT_C, OPT_R, OPT_OUT, OPT_SIGN, OPT_PASSIN, OPT_VERIFY,
     OPT_PRVERIFY, OPT_SIGNATURE, OPT_KEYFORM, OPT_ENGINE, OPT_ENGINE_IMPL,
     OPT_HEX, OPT_BINARY, OPT_DEBUG, OPT_FIPS_FINGERPRINT,
     OPT_HMAC, OPT_MAC, OPT_SIGOPT, OPT_MACOPT,
-    OPT_DIGEST
+    OPT_DIGEST,
+    OPT_R_ENUM,
 } OPTION_CHOICE;
 
 const OPTIONS dgst_options[] = {
@@ -43,8 +44,6 @@
     {"help", OPT_HELP, '-', "Display this summary"},
     {"c", OPT_C, '-', "Print the digest with separating colons"},
     {"r", OPT_R, '-', "Print the digest in coreutils format"},
-    {"rand", OPT_RAND, 's',
-     "Use file(s) containing random data to seed RNG or an EGD sock"},
     {"out", OPT_OUT, '>', "Output to filename rather than stdout"},
     {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
     {"sign", OPT_SIGN, 's', "Sign digest using private key"},
@@ -65,6 +64,7 @@
     {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
     {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form or key"},
     {"", OPT_DIGEST, '-', "Any supported digest"},
+    OPT_R_OPTIONS,
 #ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
     {"engine_impl", OPT_ENGINE_IMPL, '-',
@@ -84,7 +84,7 @@
     char *passinarg = NULL, *passin = NULL;
     const EVP_MD *md = NULL, *m;
     const char *outfile = NULL, *keyfile = NULL, *prog = NULL;
-    const char *sigfile = NULL, *randfile = NULL;
+    const char *sigfile = NULL;
     OPTION_CHOICE o;
     int separator = 0, debug = 0, keyform = FORMAT_PEM, siglen = 0;
     int i, ret = 1, out_bin = -1, want_pub = 0, do_verify = 0;
@@ -113,8 +113,9 @@
         case OPT_R:
             separator = 2;
             break;
-        case OPT_RAND:
-            randfile = opt_arg();
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
             break;
         case OPT_OUT:
             outfile = opt_arg();
@@ -223,9 +224,6 @@
             out_bin = 0;
     }
 
-    if (randfile != NULL)
-        app_RAND_load_file(randfile, 0);
-
     out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT);
     if (out == NULL)
         goto end;
diff --git a/apps/dhparam.c b/apps/dhparam.c
index fc3a51e..28ae6c3 100644
--- a/apps/dhparam.c
+++ b/apps/dhparam.c
@@ -36,7 +36,8 @@
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT,
     OPT_ENGINE, OPT_CHECK, OPT_TEXT, OPT_NOOUT,
-    OPT_RAND, OPT_DSAPARAM, OPT_C, OPT_2, OPT_5
+    OPT_DSAPARAM, OPT_C, OPT_2, OPT_5,
+    OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS dhparam_options[] = {
@@ -50,8 +51,7 @@
     {"check", OPT_CHECK, '-', "Check the DH parameters"},
     {"text", OPT_TEXT, '-', "Print a text form of the DH parameters"},
     {"noout", OPT_NOOUT, '-', "Don't output any DH parameters"},
-    {"rand", OPT_RAND, 's',
-     "Load the file(s) into the random number generator"},
+    OPT_R_OPTIONS,
     {"C", OPT_C, '-', "Print C code"},
     {"2", OPT_2, '-', "Generate parameters using 2 as the generator value"},
     {"5", OPT_5, '-', "Generate parameters using 5 as the generator value"},
@@ -69,7 +69,7 @@
 {
     BIO *in = NULL, *out = NULL;
     DH *dh = NULL;
-    char *infile = NULL, *outfile = NULL, *prog, *inrand = NULL;
+    char *infile = NULL, *outfile = NULL, *prog;
     ENGINE *e = NULL;
 #ifndef OPENSSL_NO_DSA
     int dsaparam = 0;
@@ -130,8 +130,9 @@
         case OPT_NOOUT:
             noout = 1;
             break;
-        case OPT_RAND:
-            inrand = opt_arg();
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
             break;
         }
     }
@@ -165,13 +166,6 @@
         }
 
         BN_GENCB_set(cb, dh_cb, bio_err);
-        if (!app_RAND_load_file(NULL, 1) && inrand == NULL) {
-            BIO_printf(bio_err,
-                       "warning, not much extra random data, consider using the -rand option\n");
-        }
-        if (inrand != NULL)
-            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
-                       app_RAND_load_files(inrand));
 
 # ifndef OPENSSL_NO_DSA
         if (dsaparam) {
@@ -211,7 +205,6 @@
         }
 
         BN_GENCB_free(cb);
-        app_RAND_write_file(NULL);
     } else {
 
         in = bio_open_default(infile, 'r', informat);
diff --git a/apps/dsaparam.c b/apps/dsaparam.c
index cf0a10b..39185e3 100644
--- a/apps/dsaparam.c
+++ b/apps/dsaparam.c
@@ -29,7 +29,7 @@
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_C,
-    OPT_NOOUT, OPT_GENKEY, OPT_RAND, OPT_ENGINE
+    OPT_NOOUT, OPT_GENKEY, OPT_ENGINE, OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS dsaparam_options[] = {
@@ -42,7 +42,7 @@
     {"C", OPT_C, '-', "Output C code"},
     {"noout", OPT_NOOUT, '-', "No output"},
     {"genkey", OPT_GENKEY, '-', "Generate a DSA key"},
-    {"rand", OPT_RAND, 's', "Files to use for random number input"},
+    OPT_R_OPTIONS,
 # ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
 # endif
@@ -55,10 +55,10 @@
     DSA *dsa = NULL;
     BIO *in = NULL, *out = NULL;
     BN_GENCB *cb = NULL;
-    int numbits = -1, num = 0, genkey = 0, need_rand = 0;
+    int numbits = -1, num = 0, genkey = 0;
     int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0;
     int ret = 1, i, text = 0, private = 0;
-    char *infile = NULL, *outfile = NULL, *prog, *inrand = NULL;
+    char *infile = NULL, *outfile = NULL, *prog;
     OPTION_CHOICE o;
 
     prog = opt_init(argc, argv, dsaparam_options);
@@ -97,11 +97,11 @@
             C = 1;
             break;
         case OPT_GENKEY:
-            genkey = need_rand = 1;
+            genkey = 1;
             break;
-        case OPT_RAND:
-            inrand = opt_arg();
-            need_rand = 1;
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
             break;
         case OPT_NOOUT:
             noout = 1;
@@ -116,7 +116,6 @@
             goto end;
         /* generate a key */
         numbits = num;
-        need_rand = 1;
     }
     private = genkey ? 1 : 0;
 
@@ -127,13 +126,6 @@
     if (out == NULL)
         goto end;
 
-    if (need_rand) {
-        app_RAND_load_file(NULL, (inrand != NULL));
-        if (inrand != NULL)
-            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
-                       app_RAND_load_files(inrand));
-    }
-
     if (numbits > 0) {
         cb = BN_GENCB_new();
         if (cb == NULL) {
@@ -141,7 +133,6 @@
             goto end;
         }
         BN_GENCB_set(cb, dsa_cb, bio_err);
-        assert(need_rand);
         dsa = DSA_new();
         if (dsa == NULL) {
             BIO_printf(bio_err, "Error allocating DSA object\n");
@@ -217,7 +208,6 @@
     if (genkey) {
         DSA *dsakey;
 
-        assert(need_rand);
         if ((dsakey = DSAparams_dup(dsa)) == NULL)
             goto end;
         if (!DSA_generate_key(dsakey)) {
@@ -233,8 +223,6 @@
                                             NULL);
         DSA_free(dsakey);
     }
-    if (need_rand)
-        app_RAND_write_file(NULL);
     ret = 0;
  end:
     BN_GENCB_free(cb);
diff --git a/apps/ecparam.c b/apps/ecparam.c
index 3661a88..6521ccb 100644
--- a/apps/ecparam.c
+++ b/apps/ecparam.c
@@ -29,7 +29,8 @@
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_C,
     OPT_CHECK, OPT_LIST_CURVES, OPT_NO_SEED, OPT_NOOUT, OPT_NAME,
-    OPT_CONV_FORM, OPT_PARAM_ENC, OPT_GENKEY, OPT_RAND, OPT_ENGINE
+    OPT_CONV_FORM, OPT_PARAM_ENC, OPT_GENKEY, OPT_ENGINE,
+    OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS ecparam_options[] = {
@@ -52,7 +53,7 @@
     {"param_enc", OPT_PARAM_ENC, 's',
      "Specifies the way the ec parameters are encoded"},
     {"genkey", OPT_GENKEY, '-', "Generate ec key"},
-    {"rand", OPT_RAND, 's', "Files to use for random number input"},
+    OPT_R_OPTIONS,
 # ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 # endif
@@ -80,7 +81,7 @@
     BIO *in = NULL, *out = NULL;
     EC_GROUP *group = NULL;
     point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
-    char *curve_name = NULL, *inrand = NULL;
+    char *curve_name = NULL;
     char *infile = NULL, *outfile = NULL, *prog;
     unsigned char *buffer = NULL;
     OPTION_CHOICE o;
@@ -88,7 +89,7 @@
     int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0;
     int ret = 1, private = 0;
     int list_curves = 0, no_seed = 0, check = 0, new_form = 0;
-    int text = 0, i, need_rand = 0, genkey = 0;
+    int text = 0, i, genkey = 0;
 
     prog = opt_init(argc, argv, ecparam_options);
     while ((o = opt_next()) != OPT_EOF) {
@@ -149,11 +150,11 @@
             new_asn1_flag = 1;
             break;
         case OPT_GENKEY:
-            genkey = need_rand = 1;
+            genkey = 1;
             break;
-        case OPT_RAND:
-            inrand = opt_arg();
-            need_rand = 1;
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
             break;
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
@@ -395,21 +396,12 @@
         }
     }
 
-    if (need_rand) {
-        app_RAND_load_file(NULL, (inrand != NULL));
-        if (inrand != NULL)
-            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
-                       app_RAND_load_files(inrand));
-    }
-
     if (genkey) {
         EC_KEY *eckey = EC_KEY_new();
 
         if (eckey == NULL)
             goto end;
 
-        assert(need_rand);
-
         if (EC_KEY_set_group(eckey, group) == 0) {
             BIO_printf(bio_err, "unable to set group when generating key\n");
             EC_KEY_free(eckey);
@@ -432,9 +424,6 @@
         EC_KEY_free(eckey);
     }
 
-    if (need_rand)
-        app_RAND_write_file(NULL);
-
     ret = 0;
  end:
     BN_free(ec_p);
diff --git a/apps/enc.c b/apps/enc.c
index cc6fa0a..db5d3a2 100644
--- a/apps/enc.c
+++ b/apps/enc.c
@@ -43,7 +43,8 @@
     OPT_E, OPT_IN, OPT_OUT, OPT_PASS, OPT_ENGINE, OPT_D, OPT_P, OPT_V,
     OPT_NOPAD, OPT_SALT, OPT_NOSALT, OPT_DEBUG, OPT_UPPER_P, OPT_UPPER_A,
     OPT_A, OPT_Z, OPT_BUFSIZE, OPT_K, OPT_KFILE, OPT_UPPER_K, OPT_NONE,
-    OPT_UPPER_S, OPT_IV, OPT_MD, OPT_CIPHER
+    OPT_UPPER_S, OPT_IV, OPT_MD, OPT_CIPHER,
+    OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS enc_options[] = {
@@ -74,6 +75,7 @@
     {"md", OPT_MD, 's', "Use specified digest to create a key from the passphrase"},
     {"none", OPT_NONE, '-', "Don't encrypt"},
     {"", OPT_CIPHER, '-', "Any supported cipher"},
+    OPT_R_OPTIONS,
 #ifdef ZLIB
     {"z", OPT_Z, '-', "Use zlib as the 'encryption'"},
 #endif
@@ -255,6 +257,10 @@
         case OPT_NONE:
             cipher = NULL;
             break;
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
+            break;
         }
     }
 
diff --git a/apps/gendsa.c b/apps/gendsa.c
index c9563a7..fa68323 100644
--- a/apps/gendsa.c
+++ b/apps/gendsa.c
@@ -26,7 +26,8 @@
 
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
-    OPT_OUT, OPT_PASSOUT, OPT_ENGINE, OPT_RAND, OPT_CIPHER
+    OPT_OUT, OPT_PASSOUT, OPT_ENGINE, OPT_CIPHER,
+    OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS gendsa_options[] = {
@@ -35,8 +36,7 @@
     {"help", OPT_HELP, '-', "Display this summary"},
     {"out", OPT_OUT, '>', "Output the key to the specified file"},
     {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
-    {"rand", OPT_RAND, 's',
-     "Load the file(s) into the random number generator"},
+    OPT_R_OPTIONS,
     {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"},
 # ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
@@ -50,7 +50,7 @@
     BIO *out = NULL, *in = NULL;
     DSA *dsa = NULL;
     const EVP_CIPHER *enc = NULL;
-    char *inrand = NULL, *dsaparams = NULL;
+    char *dsaparams = NULL;
     char *outfile = NULL, *passoutarg = NULL, *passout = NULL, *prog;
     OPTION_CHOICE o;
     int ret = 1, private = 0;
@@ -77,8 +77,9 @@
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
             break;
-        case OPT_RAND:
-            inrand = opt_arg();
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
             break;
         case OPT_CIPHER:
             if (!opt_cipher(opt_unknown(), &enc))
@@ -114,21 +115,11 @@
     if (out == NULL)
         goto end2;
 
-    if (!app_RAND_load_file(NULL, 1) && inrand == NULL) {
-        BIO_printf(bio_err,
-                   "warning, not much extra random data, consider using the -rand option\n");
-    }
-    if (inrand != NULL)
-        BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
-                   app_RAND_load_files(inrand));
-
     DSA_get0_pqg(dsa, &p, NULL, NULL);
     BIO_printf(bio_err, "Generating DSA key, %d bits\n", BN_num_bits(p));
     if (!DSA_generate_key(dsa))
         goto end;
 
-    app_RAND_write_file(NULL);
-
     assert(private);
     if (!PEM_write_bio_DSAPrivateKey(out, dsa, enc, NULL, 0, NULL, passout))
         goto end;
diff --git a/apps/genrsa.c b/apps/genrsa.c
index 033e692..2bc70a9 100644
--- a/apps/genrsa.c
+++ b/apps/genrsa.c
@@ -33,7 +33,8 @@
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_3, OPT_F4, OPT_ENGINE,
-    OPT_OUT, OPT_RAND, OPT_PASSOUT, OPT_CIPHER
+    OPT_OUT, OPT_PASSOUT, OPT_CIPHER,
+    OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS genrsa_options[] = {
@@ -42,8 +43,7 @@
     {"F4", OPT_F4, '-', "Use F4 (0x10001) for the E value"},
     {"f4", OPT_F4, '-', "Use F4 (0x10001) for the E value"},
     {"out", OPT_OUT, 's', "Output the key to specified file"},
-    {"rand", OPT_RAND, 's',
-     "Load the file(s) into the random number generator"},
+    OPT_R_OPTIONS,
     {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
     {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"},
 # ifndef OPENSSL_NO_ENGINE
@@ -65,7 +65,7 @@
     int ret = 1, num = DEFBITS, private = 0;
     unsigned long f4 = RSA_F4;
     char *outfile = NULL, *passoutarg = NULL, *passout = NULL;
-    char *inrand = NULL, *prog, *hexe, *dece;
+    char *prog, *hexe, *dece;
     OPTION_CHOICE o;
 
     if (bn == NULL || cb == NULL)
@@ -96,8 +96,9 @@
         case OPT_ENGINE:
             eng = setup_engine(opt_arg(), 0);
             break;
-        case OPT_RAND:
-            inrand = opt_arg();
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
             break;
         case OPT_PASSOUT:
             passoutarg = opt_arg();
@@ -124,15 +125,6 @@
     if (out == NULL)
         goto end;
 
-    if (!app_RAND_load_file(NULL, 1) && inrand == NULL
-        && !RAND_status()) {
-        BIO_printf(bio_err,
-                   "warning, not much extra random data, consider using the -rand option\n");
-    }
-    if (inrand != NULL)
-        BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
-                   app_RAND_load_files(inrand));
-
     BIO_printf(bio_err, "Generating RSA private key, %d bit long modulus\n",
                num);
     rsa = eng ? RSA_new_method(eng) : RSA_new();
@@ -142,8 +134,6 @@
     if (!BN_set_word(bn, f4) || !RSA_generate_key_ex(rsa, num, bn, cb))
         goto end;
 
-    app_RAND_write_file(NULL);
-
     RSA_get0_key(rsa, NULL, &e, NULL);
     hexe = BN_bn2hex(e);
     dece = BN_bn2dec(e);
diff --git a/apps/openssl.c b/apps/openssl.c
index e23c390..866c00e 100644
--- a/apps/openssl.c
+++ b/apps/openssl.c
@@ -240,6 +240,7 @@
     OPENSSL_free(default_config_file);
     lh_FUNCTION_free(prog);
     OPENSSL_free(arg.argv);
+    app_RAND_write();
 
     BIO_free(bio_in);
     BIO_free_all(bio_out);
diff --git a/apps/passwd.c b/apps/passwd.c
index 7ce40e0..eb5a622 100644
--- a/apps/passwd.c
+++ b/apps/passwd.c
@@ -65,7 +65,8 @@
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_IN,
     OPT_NOVERIFY, OPT_QUIET, OPT_TABLE, OPT_REVERSE, OPT_APR1,
-    OPT_1, OPT_5, OPT_6, OPT_CRYPT, OPT_AIXMD5, OPT_SALT, OPT_STDIN
+    OPT_1, OPT_5, OPT_6, OPT_CRYPT, OPT_AIXMD5, OPT_SALT, OPT_STDIN,
+    OPT_R_ENUM,
 } OPTION_CHOICE;
 
 const OPTIONS passwd_options[] = {
@@ -90,6 +91,7 @@
 # ifndef OPENSSL_NO_DES
     {"crypt", OPT_CRYPT, '-', "Standard Unix password algorithm (default)"},
 # endif
+    OPT_R_OPTIONS,
     {NULL}
 };
 
@@ -182,6 +184,10 @@
             in_stdin = 1;
             pw_source_defined = 1;
             break;
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/pkcs12.c b/apps/pkcs12.c
index 2ec8fdc..28ae2d5 100644
--- a/apps/pkcs12.c
+++ b/apps/pkcs12.c
@@ -53,9 +53,10 @@
     OPT_CACERTS, OPT_NOOUT, OPT_INFO, OPT_CHAIN, OPT_TWOPASS, OPT_NOMACVER,
     OPT_DESCERT, OPT_EXPORT, OPT_NOITER, OPT_MACITER, OPT_NOMACITER,
     OPT_NOMAC, OPT_LMK, OPT_NODES, OPT_MACALG, OPT_CERTPBE, OPT_KEYPBE,
-    OPT_RAND, OPT_INKEY, OPT_CERTFILE, OPT_NAME, OPT_CSP, OPT_CANAME,
+    OPT_INKEY, OPT_CERTFILE, OPT_NAME, OPT_CSP, OPT_CANAME,
     OPT_IN, OPT_OUT, OPT_PASSIN, OPT_PASSOUT, OPT_PASSWORD, OPT_CAPATH,
-    OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_ENGINE
+    OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_ENGINE,
+    OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS pkcs12_options[] = {
@@ -91,8 +92,7 @@
     {"macalg", OPT_MACALG, 's',
      "Digest algorithm used in MAC (default SHA1)"},
     {"keypbe", OPT_KEYPBE, 's', "Private key PBE algorithm (default 3DES)"},
-    {"rand", OPT_RAND, 's',
-     "Load the file(s) into the random number generator"},
+    OPT_R_OPTIONS,
     {"inkey", OPT_INKEY, 's', "Private key if not infile"},
     {"certfile", OPT_CERTFILE, '<', "Load certs from file"},
     {"name", OPT_NAME, 's', "Use name as friendly name"},
@@ -133,7 +133,7 @@
     int ret = 1, macver = 1, add_lmk = 0, private = 0;
     int noprompt = 0;
     char *passinarg = NULL, *passoutarg = NULL, *passarg = NULL;
-    char *passin = NULL, *passout = NULL, *inrand = NULL, *macalg = NULL;
+    char *passin = NULL, *passout = NULL, *macalg = NULL;
     char *cpass = NULL, *mpass = NULL, *badpass = NULL;
     const char *CApath = NULL, *CAfile = NULL, *prog;
     int noCApath = 0, noCAfile = 0;
@@ -225,8 +225,9 @@
             if (!set_pbe(&key_pbe, opt_arg()))
                 goto opthelp;
             break;
-        case OPT_RAND:
-            inrand = opt_arg();
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
             break;
         case OPT_INKEY:
             keyname = opt_arg();
@@ -314,13 +315,6 @@
         mpass = macpass;
     }
 
-    if (export_cert || inrand != NULL) {
-        app_RAND_load_file(NULL, (inrand != NULL));
-        if (inrand != NULL)
-            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
-                       app_RAND_load_files(inrand));
-    }
-
     if (twopass) {
         /* To avoid bit rot */
         if (1) {
@@ -576,8 +570,6 @@
     ret = 0;
  end:
     PKCS12_free(p12);
-    if (export_cert || inrand)
-        app_RAND_write_file(NULL);
     release_engine(e);
     BIO_free(in);
     BIO_free_all(out);
diff --git a/apps/pkcs8.c b/apps/pkcs8.c
index ad41f7b..ea0e856 100644
--- a/apps/pkcs8.c
+++ b/apps/pkcs8.c
@@ -24,7 +24,8 @@
     OPT_SCRYPT, OPT_SCRYPT_N, OPT_SCRYPT_R, OPT_SCRYPT_P,
 #endif
     OPT_V2, OPT_V1, OPT_V2PRF, OPT_ITER, OPT_PASSIN, OPT_PASSOUT,
-    OPT_TRADITIONAL
+    OPT_TRADITIONAL,
+    OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS pkcs8_options[] = {
@@ -36,6 +37,7 @@
     {"topk8", OPT_TOPK8, '-', "Output PKCS8 file"},
     {"noiter", OPT_NOITER, '-', "Use 1 as iteration count"},
     {"nocrypt", OPT_NOCRYPT, '-', "Use or expect unencrypted private key"},
+    OPT_R_OPTIONS,
     {"v2", OPT_V2, 's', "Use PKCS#5 v2.0 and cipher"},
     {"v1", OPT_V1, 's', "Use PKCS#5 v1.5 and cipher"},
     {"v2prf", OPT_V2PRF, 's', "Set the PRF algorithm to use with PKCS#5 v2.0"},
@@ -112,6 +114,10 @@
         case OPT_NOCRYPT:
             nocrypt = 1;
             break;
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
+            break;
         case OPT_TRADITIONAL:
             traditional = 1;
             break;
@@ -248,7 +254,6 @@
                 BIO_printf(bio_err, "Password required\n");
                 goto end;
             }
-            app_RAND_load_file(NULL, 0);
             p8 = PKCS8_set0_pbe(p8pass, strlen(p8pass), p8inf, pbe);
             if (p8 == NULL) {
                 X509_ALGOR_free(pbe);
@@ -256,7 +261,6 @@
                 ERR_print_errors(bio_err);
                 goto end;
             }
-            app_RAND_write_file(NULL);
             assert(private);
             if (outformat == FORMAT_PEM)
                 PEM_write_bio_PKCS8(out, p8);
diff --git a/apps/pkeyutl.c b/apps/pkeyutl.c
index 90e9ae3..990375b 100644
--- a/apps/pkeyutl.c
+++ b/apps/pkeyutl.c
@@ -36,7 +36,8 @@
     OPT_PUBIN, OPT_CERTIN, OPT_ASN1PARSE, OPT_HEXDUMP, OPT_SIGN,
     OPT_VERIFY, OPT_VERIFYRECOVER, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT,
     OPT_DERIVE, OPT_SIGFILE, OPT_INKEY, OPT_PEERKEY, OPT_PASSIN,
-    OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_KDF, OPT_KDFLEN
+    OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_KDF, OPT_KDFLEN,
+    OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS pkeyutl_options[] = {
@@ -64,6 +65,7 @@
     {"peerform", OPT_PEERFORM, 'E', "Peer key format - default PEM"},
     {"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"},
     {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"},
+    OPT_R_OPTIONS,
 #ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
     {"engine_impl", OPT_ENGINE_IMPL, '-',
@@ -134,6 +136,10 @@
             if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyform))
                 goto opthelp;
             break;
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
+            break;
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
             break;
@@ -238,9 +244,6 @@
         goto end;
     }
 
-/* FIXME: seed PRNG only if needed */
-    app_RAND_load_file(NULL, 0);
-
     if (pkey_op != EVP_PKEY_OP_DERIVE) {
         in = bio_open_default(infile, 'r', FORMAT_BINARY);
         if (in == NULL)
diff --git a/apps/rand.c b/apps/rand.c
index 33dbf57..3455006 100644
--- a/apps/rand.c
+++ b/apps/rand.c
@@ -19,7 +19,8 @@
 
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
-    OPT_OUT, OPT_ENGINE, OPT_RAND, OPT_BASE64, OPT_HEX
+    OPT_OUT, OPT_ENGINE, OPT_BASE64, OPT_HEX,
+    OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS rand_options[] = {
@@ -27,8 +28,7 @@
     {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
     {"help", OPT_HELP, '-', "Display this summary"},
     {"out", OPT_OUT, '>', "Output file"},
-    {"rand", OPT_RAND, 's',
-     "Load the file(s) into the random number generator"},
+    OPT_R_OPTIONS,
     {"base64", OPT_BASE64, '-', "Base64 encode output"},
     {"hex", OPT_HEX, '-', "Hex encode output"},
 #ifndef OPENSSL_NO_ENGINE
@@ -41,7 +41,7 @@
 {
     ENGINE *e = NULL;
     BIO *out = NULL;
-    char *inrand = NULL, *outfile = NULL, *prog;
+    char *outfile = NULL, *prog;
     OPTION_CHOICE o;
     int format = FORMAT_BINARY, i, num = -1, r, ret = 1;
 
@@ -63,8 +63,9 @@
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
             break;
-        case OPT_RAND:
-            inrand = opt_arg();
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
             break;
         case OPT_BASE64:
             format = FORMAT_BASE64;
@@ -80,11 +81,6 @@
     if (argc != 1 || !opt_int(argv[0], &num) || num < 0)
         goto opthelp;
 
-    app_RAND_load_file(NULL, (inrand != NULL));
-    if (inrand != NULL)
-        BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
-                   app_RAND_load_files(inrand));
-
     out = bio_open_default(outfile, 'w', format);
     if (out == NULL)
         goto end;
@@ -118,7 +114,7 @@
     }
     if (format == FORMAT_TEXT)
         BIO_puts(out, "\n");
-    if (BIO_flush(out) <= 0 || !app_RAND_write_file(NULL))
+    if (BIO_flush(out) <= 0)
         goto end;
 
     ret = 0;
diff --git a/apps/req.c b/apps/req.c
index d72a172..f43dae5 100644
--- a/apps/req.c
+++ b/apps/req.c
@@ -76,12 +76,13 @@
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_KEYGEN_ENGINE, OPT_KEY,
     OPT_PUBKEY, OPT_NEW, OPT_CONFIG, OPT_KEYFORM, OPT_IN, OPT_OUT,
-    OPT_KEYOUT, OPT_PASSIN, OPT_PASSOUT, OPT_RAND, OPT_NEWKEY,
+    OPT_KEYOUT, OPT_PASSIN, OPT_PASSOUT, OPT_NEWKEY,
     OPT_PKEYOPT, OPT_SIGOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS,
     OPT_VERIFY, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8,
     OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT, OPT_X509,
     OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL, OPT_EXTENSIONS,
-    OPT_REQEXTS, OPT_PRECERT, OPT_MD
+    OPT_REQEXTS, OPT_PRECERT, OPT_MD,
+    OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS req_options[] = {
@@ -98,8 +99,7 @@
     {"keyout", OPT_KEYOUT, '>', "File to send the key to"},
     {"passin", OPT_PASSIN, 's', "Private key password source"},
     {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
-    {"rand", OPT_RAND, 's',
-     "Load the file(s) into the random number generator"},
+    OPT_R_OPTIONS,
     {"newkey", OPT_NEWKEY, 's', "Specify as type:bits"},
     {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"},
     {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
@@ -151,7 +151,7 @@
     const EVP_CIPHER *cipher = NULL;
     const EVP_MD *md_alg = NULL, *digest = NULL;
     char *extensions = NULL, *infile = NULL;
-    char *outfile = NULL, *keyfile = NULL, *inrand = NULL;
+    char *outfile = NULL, *keyfile = NULL;
     char *keyalgstr = NULL, *p, *prog, *passargin = NULL, *passargout = NULL;
     char *passin = NULL, *passout = NULL;
     char *nofree_passin = NULL, *nofree_passout = NULL;
@@ -234,8 +234,9 @@
         case OPT_PASSOUT:
             passargout = opt_arg();
             break;
-        case OPT_RAND:
-            inrand = opt_arg();
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
             break;
         case OPT_NEWKEY:
             keyalg = opt_arg();
@@ -454,20 +455,12 @@
             /* load_key() has already printed an appropriate message */
             goto end;
         } else {
-            char *randfile = NCONF_get_string(req_conf, SECTION, "RANDFILE");
-            if (randfile == NULL)
-                ERR_clear_error();
-            app_RAND_load_file(randfile, 0);
+            app_RAND_load_conf(req_conf, SECTION);
         }
     }
 
     if (newreq && (pkey == NULL)) {
-        char *randfile = NCONF_get_string(req_conf, SECTION, "RANDFILE");
-        if (randfile == NULL)
-            ERR_clear_error();
-        app_RAND_load_file(randfile, 0);
-        if (inrand != NULL)
-            app_RAND_load_files(inrand);
+        app_RAND_load_conf(req_conf, SECTION);
 
         if (!NCONF_get_number(req_conf, SECTION, BITS, &newkey)) {
             newkey = DEFAULT_KEY_LENGTH;
@@ -525,8 +518,6 @@
         EVP_PKEY_CTX_free(genctx);
         genctx = NULL;
 
-        app_RAND_write_file(randfile);
-
         if (keyout == NULL) {
             keyout = NCONF_get_string(req_conf, SECTION, KEYFILE);
             if (keyout == NULL)
diff --git a/apps/rsautl.c b/apps/rsautl.c
index c8a2650..ca9cb79 100644
--- a/apps/rsautl.c
+++ b/apps/rsautl.c
@@ -32,7 +32,8 @@
     OPT_ENGINE, OPT_IN, OPT_OUT, OPT_ASN1PARSE, OPT_HEXDUMP,
     OPT_RAW, OPT_OAEP, OPT_SSL, OPT_PKCS, OPT_X931,
     OPT_SIGN, OPT_VERIFY, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT,
-    OPT_PUBIN, OPT_CERTIN, OPT_INKEY, OPT_PASSIN, OPT_KEYFORM
+    OPT_PUBIN, OPT_CERTIN, OPT_INKEY, OPT_PASSIN, OPT_KEYFORM,
+    OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS rsautl_options[] = {
@@ -57,6 +58,7 @@
     {"encrypt", OPT_ENCRYPT, '-', "Encrypt with public key"},
     {"decrypt", OPT_DECRYPT, '-', "Decrypt with private key"},
     {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
+    OPT_R_OPTIONS,
 # ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 # endif
@@ -153,6 +155,10 @@
         case OPT_PASSIN:
             passinarg = opt_arg();
             break;
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
@@ -169,9 +175,6 @@
         goto end;
     }
 
-/* FIXME: seed PRNG only if needed */
-    app_RAND_load_file(NULL, 0);
-
     switch (key_type) {
     case KEY_PRIVKEY:
         pkey = load_key(keyfile, keyformat, 0, passin, e, "Private Key");
diff --git a/apps/s_client.c b/apps/s_client.c
index 114071c..45464a4 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -572,7 +572,7 @@
     OPT_CERT, OPT_CRL, OPT_CRL_DOWNLOAD, OPT_SESS_OUT, OPT_SESS_IN,
     OPT_CERTFORM, OPT_CRLFORM, OPT_VERIFY_RET_ERROR, OPT_VERIFY_QUIET,
     OPT_BRIEF, OPT_PREXIT, OPT_CRLF, OPT_QUIET, OPT_NBIO,
-    OPT_SSL_CLIENT_ENGINE, OPT_RAND, OPT_IGN_EOF, OPT_NO_IGN_EOF,
+    OPT_SSL_CLIENT_ENGINE, OPT_IGN_EOF, OPT_NO_IGN_EOF,
     OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_STATUS, OPT_WDEBUG,
     OPT_MSG, OPT_MSGFILE, OPT_ENGINE, OPT_TRACE, OPT_SECURITY_DEBUG,
     OPT_SECURITY_DEBUG_VERBOSE, OPT_SHOWCERTS, OPT_NBIO_TEST, OPT_STATE,
@@ -598,7 +598,8 @@
 #ifndef OPENSSL_NO_CT
     OPT_CT, OPT_NOCT, OPT_CTLOG_FILE,
 #endif
-    OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME
+    OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME,
+    OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS s_client_options[] = {
@@ -654,8 +655,7 @@
      "Use the appropriate STARTTLS command before starting TLS"},
     {"xmpphost", OPT_XMPPHOST, 's',
      "Host to use with \"-starttls xmpp[-server]\""},
-    {"rand", OPT_RAND, 's',
-     "Load the file(s) into the random number generator"},
+    OPT_R_OPTIONS,
     {"sess_out", OPT_SESS_OUT, '>', "File to write SSL session to"},
     {"sess_in", OPT_SESS_IN, '<', "File to read SSL session from"},
     {"use_srtp", OPT_USE_SRTP, 's',
@@ -881,7 +881,6 @@
     char *cert_file = NULL, *key_file = NULL, *chain_file = NULL;
     char *chCApath = NULL, *chCAfile = NULL, *host = NULL;
     char *port = OPENSSL_strdup(PORT);
-    char *inrand = NULL;
     char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL;
     char *ReqCAfile = NULL;
     char *sess_in = NULL, *crl_file = NULL, *p;
@@ -905,7 +904,6 @@
 #endif
     int read_buf_len = 0;
     int fallback_scsv = 0;
-    long randamt = 0;
     OPTION_CHOICE o;
 #ifndef OPENSSL_NO_DTLS
     int enable_timeouts = 0;
@@ -1152,8 +1150,9 @@
             }
 #endif
             break;
-        case OPT_RAND:
-            inrand = opt_arg();
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
             break;
         case OPT_IGN_EOF:
             c_ign_eof = 1;
@@ -1604,16 +1603,6 @@
     if (!load_excert(&exc))
         goto end;
 
-    if (!app_RAND_load_file(NULL, 1) && inrand == NULL
-        && !RAND_status()) {
-        BIO_printf(bio_err,
-                   "warning, not much extra random data, consider using the -rand option\n");
-    }
-    if (inrand != NULL) {
-        randamt = app_RAND_load_files(inrand);
-        BIO_printf(bio_err, "%ld semi-random bytes loaded\n", randamt);
-    }
-
     if (bio_c_out == NULL) {
         if (c_quiet && !c_debug) {
             bio_c_out = BIO_new(BIO_s_null());
diff --git a/apps/s_server.c b/apps/s_server.c
index 8df767c..961c738 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -745,10 +745,11 @@
     OPT_MAX_SEND_FRAG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_READ_BUF,
     OPT_SSL3, OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1,
     OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_LISTEN,
-    OPT_ID_PREFIX, OPT_RAND, OPT_SERVERNAME, OPT_SERVERNAME_FATAL,
+    OPT_ID_PREFIX, OPT_SERVERNAME, OPT_SERVERNAME_FATAL,
     OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN,
     OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN,
     OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_EARLY_DATA,
+    OPT_R_ENUM,
     OPT_S_ENUM,
     OPT_V_ENUM,
     OPT_X_ENUM
@@ -825,8 +826,7 @@
     {"HTTP", OPT_HTTP, '-', "Like -WWW but ./path includes HTTP headers"},
     {"id_prefix", OPT_ID_PREFIX, 's',
      "Generate SSL/TLS session IDs prefixed by arg"},
-    {"rand", OPT_RAND, 's',
-     "Load the file(s) into the random number generator"},
+    OPT_R_OPTIONS,
     {"keymatexport", OPT_KEYMATEXPORT, 's',
      "Export keying material using label"},
     {"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p',
@@ -974,7 +974,7 @@
     X509 *s_cert = NULL, *s_dcert = NULL;
     X509_VERIFY_PARAM *vpm = NULL;
     const char *CApath = NULL, *CAfile = NULL, *chCApath = NULL, *chCAfile = NULL;
-    char *dpassarg = NULL, *dpass = NULL, *inrand = NULL;
+    char *dpassarg = NULL, *dpass = NULL;
     char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL;
     char *crl_file = NULL, *prog;
 #ifdef AF_UNIX
@@ -1494,8 +1494,9 @@
         case OPT_ENGINE:
             engine = setup_engine(opt_arg(), 1);
             break;
-        case OPT_RAND:
-            inrand = opt_arg();
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
             break;
         case OPT_SERVERNAME:
             tlsextcbp.servername = opt_arg();
@@ -1708,15 +1709,6 @@
 
     }
 
-    if (!app_RAND_load_file(NULL, 1) && inrand == NULL
-        && !RAND_status()) {
-        BIO_printf(bio_err,
-                   "warning, not much extra random data, consider using the -rand option\n");
-    }
-    if (inrand != NULL)
-        BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
-                   app_RAND_load_files(inrand));
-
     if (bio_s_out == NULL) {
         if (s_quiet && !s_debug) {
             bio_s_out = BIO_new(BIO_s_null());
diff --git a/apps/smime.c b/apps/smime.c
index babe4ef..8617ba4 100644
--- a/apps/smime.c
+++ b/apps/smime.c
@@ -37,9 +37,10 @@
     OPT_PK7OUT, OPT_TEXT, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCHAIN,
     OPT_NOCERTS, OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP,
     OPT_BINARY, OPT_NOSIGS, OPT_STREAM, OPT_INDEF, OPT_NOINDEF,
-    OPT_CRLFEOL, OPT_RAND, OPT_ENGINE, OPT_PASSIN,
+    OPT_CRLFEOL, OPT_ENGINE, OPT_PASSIN,
     OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP, OPT_MD,
     OPT_CIPHER, OPT_INKEY, OPT_KEYFORM, OPT_CERTFILE, OPT_CAFILE,
+    OPT_R_ENUM,
     OPT_V_ENUM,
     OPT_CAPATH, OPT_NOCAFILE, OPT_NOCAPATH, OPT_IN, OPT_INFORM, OPT_OUT,
     OPT_OUTFORM, OPT_CONTENT
@@ -96,8 +97,7 @@
     {"indef", OPT_INDEF, '-', "Same as -stream" },
     {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"},
     {"crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination instead of CR only"},
-    {"rand", OPT_RAND, 's',
-     "Load the file(s) into the random number generator"},
+    OPT_R_OPTIONS,
     {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
     {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"},
     {"", OPT_CIPHER, '-', "Any supported cipher"},
@@ -121,15 +121,12 @@
     const EVP_CIPHER *cipher = NULL;
     const EVP_MD *sign_md = NULL;
     const char *CAfile = NULL, *CApath = NULL, *prog = NULL;
-    char *certfile = NULL, *keyfile = NULL, *contfile = NULL, *inrand = NULL;
-    char *infile = NULL, *outfile = NULL, *signerfile = NULL, *recipfile =
-        NULL;
-    char *passinarg = NULL, *passin = NULL, *to = NULL, *from =
-        NULL, *subject = NULL;
+    char *certfile = NULL, *keyfile = NULL, *contfile = NULL;
+    char *infile = NULL, *outfile = NULL, *signerfile = NULL, *recipfile = NULL;
+    char *passinarg = NULL, *passin = NULL, *to = NULL, *from = NULL, *subject = NULL;
     OPTION_CHOICE o;
     int noCApath = 0, noCAfile = 0;
-    int flags = PKCS7_DETACHED, operation = 0, ret = 0, need_rand = 0, indef =
-        0;
+    int flags = PKCS7_DETACHED, operation = 0, ret = 0, indef = 0;
     int informat = FORMAT_SMIME, outformat = FORMAT_SMIME, keyform =
         FORMAT_PEM;
     int vpmtouched = 0, rv = 0;
@@ -224,9 +221,9 @@
             flags |= PKCS7_CRLFEOL;
             mime_eol = "\r\n";
             break;
-        case OPT_RAND:
-            inrand = opt_arg();
-            need_rand = 1;
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
             break;
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
@@ -351,7 +348,6 @@
         }
         signerfile = NULL;
         keyfile = NULL;
-        need_rand = 1;
     } else if (operation == SMIME_DECRYPT) {
         if (recipfile == NULL && keyfile == NULL) {
             BIO_printf(bio_err,
@@ -363,7 +359,6 @@
             BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
             goto opthelp;
         }
-        need_rand = 1;
     } else if (!operation) {
         goto opthelp;
     }
@@ -373,13 +368,6 @@
         goto end;
     }
 
-    if (need_rand) {
-        app_RAND_load_file(NULL, (inrand != NULL));
-        if (inrand != NULL)
-            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
-                       app_RAND_load_files(inrand));
-    }
-
     ret = 2;
 
     if (!(operation & SMIME_SIGNERS))
@@ -603,8 +591,6 @@
     }
     ret = 0;
  end:
-    if (need_rand)
-        app_RAND_write_file(NULL);
     if (ret)
         ERR_print_errors(bio_err);
     sk_X509_pop_free(encerts, X509_free);
diff --git a/apps/speed.c b/apps/speed.c
index bd32786..a086060 100644
--- a/apps/speed.c
+++ b/apps/speed.c
@@ -342,7 +342,7 @@
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_ELAPSED, OPT_EVP, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI,
-    OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS
+    OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM,
 } OPTION_CHOICE;
 
 const OPTIONS speed_options[] = {
@@ -365,6 +365,7 @@
     {"async_jobs", OPT_ASYNCJOBS, 'p',
      "Enable async mode and start pnum jobs"},
 #endif
+    OPT_R_OPTIONS,
 #ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 #endif
@@ -1410,6 +1411,10 @@
             goto end;
 #endif
             break;
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/srp.c b/apps/srp.c
index c31830e..f67c7ff 100644
--- a/apps/srp.c
+++ b/apps/srp.c
@@ -26,7 +26,6 @@
 # define BASE_SECTION    "srp"
 # define CONFIG_FILE "openssl.cnf"
 
-# define ENV_RANDFILE            "RANDFILE"
 
 # define ENV_DATABASE            "srpvfile"
 # define ENV_DEFAULT_SRP         "default_srp"
@@ -189,7 +188,7 @@
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_VERBOSE, OPT_CONFIG, OPT_NAME, OPT_SRPVFILE, OPT_ADD,
     OPT_DELETE, OPT_MODIFY, OPT_LIST, OPT_GN, OPT_USERINFO,
-    OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE
+    OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE, OPT_R_ENUM,
 } OPTION_CHOICE;
 
 const OPTIONS srp_options[] = {
@@ -207,6 +206,7 @@
     {"userinfo", OPT_USERINFO, 's', "Additional info to be set for user"},
     {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
     {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+    OPT_R_OPTIONS,
 # ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 # endif
@@ -222,7 +222,7 @@
     int doupdatedb = 0, mode = OPT_ERR;
     char *user = NULL, *passinarg = NULL, *passoutarg = NULL;
     char *passin = NULL, *passout = NULL, *gN = NULL, *userinfo = NULL;
-    char *randfile = NULL, *section = NULL;
+    char *section = NULL;
     char **gNrow = NULL, *configfile = NULL;
     char *srpvfile = NULL, **pp, *prog;
     OPTION_CHOICE o;
@@ -278,6 +278,10 @@
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
             break;
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
@@ -335,8 +339,7 @@
                 goto end;
         }
 
-        if (randfile == NULL)
-            randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
+        app_RAND_load_conf(conf, BASE_SECTION);
 
         if (verbose)
             BIO_printf(bio_err,
@@ -347,10 +350,6 @@
         if (srpvfile == NULL)
             goto end;
     }
-    if (randfile == NULL)
-        ERR_clear_error();
-    else
-        app_RAND_load_file(randfile, 0);
 
     if (verbose)
         BIO_printf(bio_err, "Trying to read SRP verifier file \"%s\"\n",
@@ -604,8 +603,6 @@
     OPENSSL_free(passout);
     if (ret)
         ERR_print_errors(bio_err);
-    if (randfile != NULL)
-        app_RAND_write_file(randfile);
     NCONF_free(conf);
     free_index(db);
     release_engine(e);
diff --git a/apps/ts.c b/apps/ts.c
index 636c777..5e7729e 100644
--- a/apps/ts.c
+++ b/apps/ts.c
@@ -79,11 +79,11 @@
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_ENGINE, OPT_CONFIG, OPT_SECTION, OPT_QUERY, OPT_DATA,
-    OPT_DIGEST, OPT_RAND, OPT_TSPOLICY, OPT_NO_NONCE, OPT_CERT,
+    OPT_DIGEST, OPT_TSPOLICY, OPT_NO_NONCE, OPT_CERT,
     OPT_IN, OPT_TOKEN_IN, OPT_OUT, OPT_TOKEN_OUT, OPT_TEXT,
     OPT_REPLY, OPT_QUERYFILE, OPT_PASSIN, OPT_INKEY, OPT_SIGNER,
     OPT_CHAIN, OPT_VERIFY, OPT_CAPATH, OPT_CAFILE, OPT_UNTRUSTED,
-    OPT_MD, OPT_V_ENUM
+    OPT_MD, OPT_V_ENUM, OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS ts_options[] = {
@@ -93,8 +93,7 @@
     {"query", OPT_QUERY, '-', "Generate a TS query"},
     {"data", OPT_DATA, '<', "File to hash"},
     {"digest", OPT_DIGEST, 's', "Digest (as a hex string)"},
-    {"rand", OPT_RAND, 's',
-     "Load the file(s) into the random number generator"},
+    OPT_R_OPTIONS,
     {"tspolicy", OPT_TSPOLICY, 's', "Policy OID to use"},
     {"no_nonce", OPT_NO_NONCE, '-', "Do not include a nonce"},
     {"cert", OPT_CERT, '-', "Put cert request into query"},
@@ -158,7 +157,7 @@
     const char *section = NULL;
     char **helpp;
     char *password = NULL;
-    char *data = NULL, *digest = NULL, *rnd = NULL, *policy = NULL;
+    char *data = NULL, *digest = NULL, *policy = NULL;
     char *in = NULL, *out = NULL, *queryfile = NULL, *passin = NULL;
     char *inkey = NULL, *signer = NULL, *chain = NULL, *CApath = NULL;
     const EVP_MD *md = NULL;
@@ -207,8 +206,9 @@
         case OPT_DIGEST:
             digest = opt_arg();
             break;
-        case OPT_RAND:
-            rnd = opt_arg();
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
             break;
         case OPT_TSPOLICY:
             policy = opt_arg();
@@ -275,16 +275,6 @@
     if (mode == OPT_ERR || opt_num_rest() != 0)
         goto opthelp;
 
-    /* Seed the random number generator if it is going to be used. */
-    if (mode == OPT_QUERY && !no_nonce) {
-        if (!app_RAND_load_file(NULL, 1) && rnd == NULL)
-            BIO_printf(bio_err, "warning, not much extra random "
-                       "data, consider using the -rand option\n");
-        if (rnd != NULL)
-            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
-                       app_RAND_load_files(rnd));
-    }
-
     if (mode == OPT_REPLY && passin &&
         !app_passwd(passin, NULL, &password, NULL)) {
         BIO_printf(bio_err, "Error getting password.\n");
@@ -328,7 +318,6 @@
 
  end:
     X509_VERIFY_PARAM_free(vpm);
-    app_RAND_write_file(NULL);
     NCONF_free(conf);
     OPENSSL_free(password);
     return (ret);
diff --git a/apps/x509.c b/apps/x509.c
index 6a24da2..7928ccb 100644
--- a/apps/x509.c
+++ b/apps/x509.c
@@ -58,7 +58,8 @@
     OPT_CLRREJECT, OPT_ALIAS, OPT_CACREATESERIAL, OPT_CLREXT, OPT_OCSPID,
     OPT_SUBJECT_HASH_OLD,
     OPT_ISSUER_HASH_OLD,
-    OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES
+    OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES,
+    OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS x509_options[] = {
@@ -118,6 +119,7 @@
     {"text", OPT_TEXT, '-', "Print the certificate in text form"},
     {"C", OPT_C, '-', "Print out C code forms"},
     {"extfile", OPT_EXTFILE, '<', "File with X509V3 extensions to add"},
+    OPT_R_OPTIONS,
     {"extensions", OPT_EXTENSIONS, 's', "Section from config file to use"},
     {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
     {"certopt", OPT_CERTOPT, 's', "Various certificate text options"},
@@ -166,7 +168,7 @@
     char *prog;
     int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0, pprint = 0;
     int C = 0, CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM;
-    int fingerprint = 0, reqfile = 0, need_rand = 0, checkend = 0;
+    int fingerprint = 0, reqfile = 0, checkend = 0;
     int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM;
     int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0;
     int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0;
@@ -227,7 +229,7 @@
             outfile = opt_arg();
             break;
         case OPT_REQ:
-            reqfile = need_rand = 1;
+            reqfile = 1;
             break;
 
         case OPT_SIGOPT:
@@ -247,18 +249,20 @@
         case OPT_EXTFILE:
             extfile = opt_arg();
             break;
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
+            break;
         case OPT_EXTENSIONS:
             extsect = opt_arg();
             break;
         case OPT_SIGNKEY:
             keyfile = opt_arg();
             sign_flag = ++num;
-            need_rand = 1;
             break;
         case OPT_CA:
             CAfile = opt_arg();
             CA_flag = ++num;
-            need_rand = 1;
             break;
         case OPT_CAKEY:
             CAkeyfile = opt_arg();
@@ -460,9 +464,6 @@
     if (out == NULL)
         goto end;
 
-    if (need_rand)
-        app_RAND_load_file(NULL, 0);
-
     if (!app_passwd(passinarg, NULL, &passin, NULL)) {
         BIO_printf(bio_err, "Error getting password\n");
         goto end;
@@ -793,7 +794,6 @@
                         goto end;
                 }
 
-                assert(need_rand);
                 if (!sign(x, Upkey, days, clrext, digest, extconf, extsect, preserve_dates))
                     goto end;
             } else if (CA_flag == i) {
@@ -805,7 +805,6 @@
                         goto end;
                 }
 
-                assert(need_rand);
                 if (!x509_certify(ctx, CAfile, digest, x, xca,
                                   CApkey, sigopts,
                                   CAserial, CA_createserial, days, clrext,
@@ -882,8 +881,6 @@
     }
     ret = 0;
  end:
-    if (need_rand)
-        app_RAND_write_file(NULL);
     NCONF_free(extconf);
     BIO_free_all(out);
     X509_STORE_free(ctx);