Commit 8389ec4b authored by Rich Salz's avatar Rich Salz
Browse files

Add --with-rand-seed



Add a new config param to specify how the CSPRNG should be seeded.
Illegal values or nonsensical combinations (e.g., anything other
than "os" on VMS or HP VOS etc) result in build failures.
Add RDSEED support.
Add RDTSC but leave it disabled for now pending more investigation.

Refactor and reorganization all seeding files (rand_unix/win/vms) so
that they are simpler.

Only require 128 bits of seeding material.

Many document improvements, including why to not use RAND_add() and the
limitations around using load_file/write_file.
Document RAND_poll().

Cleanup Windows RAND_poll and return correct status

More completely initialize the default DRBG.

Reviewed-by: default avatarPaul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/3965)
parent 0d7903f8
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -561,6 +561,9 @@ $config{build_type} = "release";

my %unsupported_options = ();
my %deprecated_options = ();
# If you change this, update apps/version.c
my @known_seed_sources = qw(getrandom devrandom os egd none rdcpu librandom);
my @seed_sources = ();
while (@argvcopy)
	{
	$_ = shift @argvcopy;
@@ -729,6 +732,15 @@ while (@argvcopy)
			{
			$withargs{fuzzer_include}=$1;
			}
		elsif (/^--with-rand-seed=(.*)$/)
			{
			foreach my $x (split(m|,|, $1))
			    {
			    die "Unknown --with-rand-seed choice $x\n"
				if ! grep { $x eq $_ } @known_seed_sources;
			    push @seed_sources, $x;
			    }
                        }
		elsif (/^--cross-compile-prefix=(.*)$/)
			{
			$config{cross_compile_prefix}=$1;
@@ -812,6 +824,17 @@ if ($libs =~ /(^|\s)-Wl,-rpath,/
	"***** any of asan, msan or ubsan\n";
}

if (scalar(@seed_sources) == 0) {
    print "Using implicit seed configuration\n";
    push @seed_sources, 'os';
}
die "Cannot seed with none and anything else"
    if scalar(grep { $_ eq 'none' } @seed_sources) > 0
        && scalar(@seed_sources) > 1;
push @{$config{openssl_other_defines}},
     map { (my $x = $_) =~ tr|[\-a-z]|[_A-Z]|; "OPENSSL_RAND_SEED_$x" }
	@seed_sources;

my @tocheckfor = (keys %disabled);
while (@tocheckfor) {
    my %new_tocheckfor = ();
+35 −3
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@

typedef enum OPTION_choice {
    OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
    OPT_B, OPT_D, OPT_E, OPT_F, OPT_O, OPT_P, OPT_V, OPT_A
    OPT_B, OPT_D, OPT_E, OPT_F, OPT_O, OPT_P, OPT_V, OPT_A, OPT_R
} OPTION_CHOICE;

const OPTIONS version_options[] = {
@@ -44,13 +44,14 @@ const OPTIONS version_options[] = {
    {"f", OPT_F, '-', "Show compiler flags used"},
    {"o", OPT_O, '-', "Show some internal datatype options"},
    {"p", OPT_P, '-', "Show target build platform"},
    {"r", OPT_R, '-', "Show random seeding options"},
    {"v", OPT_V, '-', "Show library version"},
    {NULL}
};

int version_main(int argc, char **argv)
{
    int ret = 1, dirty = 0;
    int ret = 1, dirty = 0, seed = 0;
    int cflags = 0, version = 0, date = 0, options = 0, platform = 0, dir = 0;
    int engdir = 0;
    char *prog;
@@ -85,11 +86,14 @@ int version_main(int argc, char **argv)
        case OPT_P:
            dirty = platform = 1;
            break;
        case OPT_R:
            dirty = seed = 1;
            break;
        case OPT_V:
            dirty = version = 1;
            break;
        case OPT_A:
            cflags = version = date = platform = dir = engdir = 1;
            seed = cflags = version = date = platform = dir = engdir = 1;
            break;
        }
    }
@@ -133,6 +137,34 @@ int version_main(int argc, char **argv)
        printf("%s\n", OpenSSL_version(OPENSSL_DIR));
    if (engdir)
        printf("%s\n", OpenSSL_version(OPENSSL_ENGINES_DIR));
    if (seed) {
        printf("Seeding source:");
#ifdef OPENSSL_RAND_SEED_RTDSC
        printf(" rtdsc");
#endif
#ifdef OPENSSL_RAND_SEED_RDCPU
        printf(" rdrand-hardware");
#endif
#ifdef OPENSSL_RAND_SEED_LIBRANDOM
        printf(" C-library-random");
#endif
#ifdef OPENSSL_RAND_SEED_GETRANDOM
        printf(" getrandom-syscall");
#endif
#ifdef OPENSSL_RAND_SEED_DEVRANDOM
        printf(" random-device");
#endif
#ifdef OPENSSL_RAND_SEED_EGD
        printf(" EGD");
#endif
#ifdef OPENSSL_RAND_SEED_NONE
        printf(" none");
#endif
#ifdef OPENSSL_RAND_SEED_OS
        printf(" os-specific");
#endif
        printf("\n");
    }
    ret = 0;
 end:
    return (ret);
+5 −1
Original line number Diff line number Diff line
@@ -29,8 +29,12 @@ static CRYPTO_ONCE ossl_drbg_init = CRYPTO_ONCE_STATIC_INIT;

DEFINE_RUN_ONCE_STATIC(do_ossl_drbg_init)
{
    int st = 1;

    ossl_drbg.lock = CRYPTO_THREAD_lock_new();
    return ossl_drbg.lock != NULL;
    st &= ossl_drbg.lock != NULL;
    st &= RAND_DRBG_set(&ossl_drbg, NID_aes_128_ctr, 0) == 1;
    return st;
}

void rand_drbg_cleanup(void)
+19 −9
Original line number Diff line number Diff line
@@ -17,8 +17,8 @@
# include <openssl/ec.h>
# include "internal/rand.h"

/* we require 256 bits of randomness */
# define RANDOMNESS_NEEDED (256 / 8)
/* Amount of randomness (in bytes) we want for initial seeding. */
# define RANDOMNESS_NEEDED              (128 / 8)

/* Maximum count allowed in reseeding */
#define MAX_RESEED (1 << 24)
@@ -32,6 +32,9 @@
/* A default maximum length: larger than any reasonable value used in pratice */
# define DRBG_MAX_LENGTH                0x7ffffff0

/*
 * The context for DRBG AES-CTR
 */
typedef struct drbg_ctr_ctx_st {
    AES_KEY ks;
    size_t keylen;
@@ -46,6 +49,10 @@ typedef struct drbg_ctr_ctx_st {
    unsigned char KX[48];
} DRBG_CTR_CTX;


/*
 * The context for all DRBG's
 */
struct drbg_ctx_st {
    CRYPTO_RWLOCK *lock;
    DRBG_CTX *parent;
@@ -84,9 +91,12 @@ struct drbg_ctx_st {
extern RAND_METHOD openssl_rand_meth;
void rand_drbg_cleanup(void);

/* Hardware-based seeding functions. */
void rand_rdtsc(void);
int rand_rdcpu(void);

/* DRBG functions implementing AES-CTR */
int ctr_init(DRBG_CTX *dctx);
int drbg_hash_init(DRBG_CTX *dctx);
int drbg_hmac_init(DRBG_CTX *dctx);
int ctr_uninstantiate(DRBG_CTX *dctx);
int ctr_instantiate(DRBG_CTX *dctx,
                    const unsigned char *ent, size_t entlen,
+64 −0
Original line number Diff line number Diff line
@@ -25,6 +25,70 @@ static CRYPTO_RWLOCK *rand_meth_lock;
static const RAND_METHOD *default_RAND_meth;
static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT;

#ifdef OPENSSL_RAND_SEED_RDTSC
/*
 * IMPORTANT NOTE:  It is not currently possible to use this code
 * because we are not sure about the amount of randomness.  Some
 * SP900 tests have been run, but there is internal skepticism.
 * So for now this code is not used.
 */
# error "RDTSC enabled?  Should not be possible!"

/*
 * Since we get some randomness from the low-order bits of the
 * high-speec clock, it can help.  But don't return a status since
 * it's not sufficient to indicate whether or not the seeding was
 * done.
 */
void rand_rdtsc(void)
{
    unsigned char c;
    int i;

    for (i = 0; i < 10; i++) {
        c = (unsigned char)(OPENSSL_rdtsc() & 0xFF);
        RAND_add(&c, 1, 0.5);
    }
}
#endif

#ifdef OPENSSL_RAND_SEED_RDCPU
size_t OPENSSL_ia32_rdseed(void);
size_t OPENSSL_ia32_rdrand(void);

extern unsigned int OPENSSL_ia32cap_P[];

int rand_rdcpu(void)
{
    size_t i, s;

    /* If RDSEED is available, use that. */
    if ((OPENSSL_ia32cap_P[1] & (1 << 18)) != 0) {
        for (i = 0; i < RANDOMNESS_NEEDED; i += sizeof(s)) {
            s = OPENSSL_ia32_rdseed();
            if (s == 0)
                break;
            RAND_add(&s, (int)sizeof(s), sizeof(s));
        }
        if (i >= RANDOMNESS_NEEDED)
            return 1;
    }

    /* Second choice is RDRAND. */
    if ((OPENSSL_ia32cap_P[1] & (1 << (62 - 32))) != 0) {
        for (i = 0; i < RANDOMNESS_NEEDED; i += sizeof(s)) {
            s = OPENSSL_ia32_rdrand();
            if (s == 0)
                break;
            RAND_add(&s, (int)sizeof(s), sizeof(s));
        }
        if (i >= RANDOMNESS_NEEDED)
            return 1;
    }

    return 0;
}
#endif

DEFINE_RUN_ONCE_STATIC(do_rand_init)
{
Loading