Commit 3ee1eac2 authored by Rich Salz's avatar Rich Salz
Browse files

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: default avatarPaul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/3862)
parent e90fc053
Loading
Loading
Loading
Loading
+52 −78
Original line number Diff line number Diff line
@@ -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");
    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;
    }
            }
            return 0;
        }
    }
    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 ( ; ; ) {
        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 (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 (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.
 * See comments in opt_verify for explanation of this.
 */
        return 0;
    }
enum r_range { OPT_R_ENUM };

    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;
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;
}
+18 −11
Original line number Diff line number Diff line
@@ -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 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
        case OPT_V_ALLOW_PROXY_CERTS

/*
 * Common "extended"? options.
 * Common "extended validation" options.
 */
# define OPT_X_ENUM \
        OPT_X__FIRST=1000, \
@@ -299,6 +291,20 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
 (o == OPT_S_NOSSL3 || o == OPT_S_NOTLS1 || o == OPT_S_NOTLS1_1 \
  || 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.
 */
@@ -373,6 +379,7 @@ char *opt_reset(void);
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);

+8 −6
Original line number Diff line number Diff line
@@ -153,6 +153,7 @@ typedef enum OPTION_choice {
    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 @@ const OPTIONS ca_options[] = {
     "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 @@ int ca_main(int argc, char **argv)
    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 @@ opthelp:
        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 @@ end_of_options:
        }
    }

    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 @@ end_of_options:

    if (ret)
        ERR_print_errors(bio_err);
    app_RAND_write_file(randfile);
    if (free_key)
        OPENSSL_free(key);
    BN_free(serial);
+11 −25
Original line number Diff line number Diff line
@@ -76,10 +76,11 @@ typedef enum OPTION_choice {
    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 @@ const OPTIONS cms_options[] = {
    {"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 @@ const OPTIONS cms_options[] = {
    {"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 @@ int cms_main(int argc, char **argv)
    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 @@ int cms_main(int argc, char **argv)
                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 @@ int cms_main(int argc, char **argv)
                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 @@ int cms_main(int argc, char **argv)
        }
        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 @@ int cms_main(int argc, char **argv)
            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 @@ int cms_main(int argc, char **argv)
        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 @@ int cms_main(int argc, char **argv)
 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);
+8 −10
Original line number Diff line number Diff line
@@ -29,11 +29,12 @@ int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,

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 @@ const OPTIONS dgst_options[] = {
    {"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 @@ const OPTIONS dgst_options[] = {
    {"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 @@ int dgst_main(int argc, char **argv)
    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 @@ int dgst_main(int argc, char **argv)
        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 @@ int dgst_main(int argc, char **argv)
            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;
Loading