diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2013-12-25 15:00:39 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2014-01-11 14:19:25 +0000 |
commit | ef643cc7bdb24fbff4740192a7fc1fc768fb7693 (patch) | |
tree | 5b23135247501a337e1a66c3a7089e0e95c3a44c /crypto/rand/md_rand.c | |
parent | 4b64e0cbdb563e13a6f7cd8631b31532c04f1234 (diff) |
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.
Diffstat (limited to 'crypto/rand/md_rand.c')
-rw-r--r-- | crypto/rand/md_rand.c | 79 |
1 files changed, 79 insertions, 0 deletions
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 |