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.
This commit is contained in:
Dr. Stephen Henson 2013-12-25 15:00:39 +00:00
parent 4b64e0cbdb
commit ef643cc7bd
3 changed files with 81 additions and 0 deletions

View File

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

View File

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

View File

@ -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);
}