From ef643cc7bdb24fbff4740192a7fc1fc768fb7693 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Wed, 25 Dec 2013 15:00:39 +0000 Subject: [PATCH] Use rdrand as additional entropy source. If available rdrand is used as an additional entropy source for the PRNG and for additional input in FIPS mode. --- crypto/rand/md_rand.c | 79 ++++++++++++++++++++++++++++++++++++++++++ crypto/rand/rand_lcl.h | 1 + crypto/rand/rand_lib.c | 1 + 3 files changed, 81 insertions(+) diff --git a/crypto/rand/md_rand.c b/crypto/rand/md_rand.c index 2d6a55f6ed..7158d30d8f 100644 --- a/crypto/rand/md_rand.c +++ b/crypto/rand/md_rand.c @@ -167,6 +167,8 @@ int rand_predictable=0; const char RAND_version[]="RAND" OPENSSL_VERSION_PTEXT; +static void rand_hw_seed(EVP_MD_CTX *ctx); + static void ssleay_rand_cleanup(void); static int ssleay_rand_seed(const void *buf, int num); static int ssleay_rand_add(const void *buf, int num, double add_entropy); @@ -531,6 +533,7 @@ static int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo) sizeof tv)) goto err; curr_time = 0; + rand_hw_seed(&m); } if (!MD_Update(&m,local_md,MD_DIGEST_LENGTH)) goto err; @@ -663,3 +666,79 @@ static int ssleay_rand_status(void) return ret; } + +/* rand_hw_seed: get seed data from any available hardware RNG. + * only currently supports rdrand. + */ + +/* Adapted from eng_rdrand.c */ + +#if (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined (_M_X64)) && defined(OPENSSL_CPUID_OBJ) + +#define RDRAND_CALLS 4 + +size_t OPENSSL_ia32_rdrand(void); +extern unsigned int OPENSSL_ia32cap_P[]; + +static void rand_hw_seed(EVP_MD_CTX *ctx) + { + int i; + if (!(OPENSSL_ia32cap_P[1] & (1<<(62-32)))) + return; + for (i = 0; i < RDRAND_CALLS; i++) + { + size_t rnd; + rnd = OPENSSL_ia32_rdrand(); + if (rnd == 0) + return; + MD_Update(ctx, (unsigned char *)rnd, sizeof(size_t)); + } + } + +/* XOR an existing buffer with random data */ + +void rand_hw_xor(unsigned char *buf, size_t num) + { + size_t rnd; + if (!(OPENSSL_ia32cap_P[1] & (1<<(62-32)))) + return; + while (num >= sizeof(size_t)) + { + rnd = OPENSSL_ia32_rdrand(); + if (rnd == 0) + return; + *((size_t *)buf) ^= rnd; + buf += sizeof(size_t); + num -= sizeof(size_t); + } + if (num) + { + rnd = OPENSSL_ia32_rdrand(); + if (rnd == 0) + return; + while(num) + { + *buf ^= rnd & 0xff; + rnd >>= 8; + buf++; + num--; + } + } + } + + +#else + +static void rand_hw_seed(EVP_MD_CTX *ctx) + { + return; + } + +void rand_hw_xor(unsigned char *buf, size_t num) + { + return; + } + +#endif diff --git a/crypto/rand/rand_lcl.h b/crypto/rand/rand_lcl.h index 618a8ec899..6696b8057b 100644 --- a/crypto/rand/rand_lcl.h +++ b/crypto/rand/rand_lcl.h @@ -154,5 +154,6 @@ #define MD(a,b,c) EVP_Digest(a,b,c,NULL,EVP_md2(), NULL) #endif +void rand_hw_xor(unsigned char *buf, size_t num); #endif diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index e8957dbb30..4aa6486c81 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -227,6 +227,7 @@ static size_t drbg_get_adin(DRBG_CTX *ctx, unsigned char **pout) static unsigned char buf[16]; static unsigned long counter; FIPS_get_timevec(buf, &counter); + rand_hw_xor(buf, sizeof(buf)); *pout = buf; return sizeof(buf); } -- 2.25.1