/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
static const RAND_METHOD *default_RAND_meth;
static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT;
RAND_BYTES_BUFFER rand_bytes;
+int rand_fork_count;
#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.
+ * because we are not sure about the amount of randomness it provides.
+ * 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!"
unsigned char c;
int i;
- for (i = 0; i < 10; i++) {
- c = (unsigned char)(OPENSSL_rdtsc() & 0xFF);
- cb(arg, &c, 1, 0.5);
+ if ((OPENSSL_ia32cap_P[0] & (1 << 4)) != 0) {
+ for (i = 0; i < TSC_READ_COUNT; i++) {
+ c = (unsigned char)(OPENSSL_rdtsc() & 0xFF);
+ cb(arg, &c, 1, 0.5);
+ }
}
}
#endif
#ifdef OPENSSL_RAND_SEED_RDCPU
-size_t OPENSSL_ia32_rdseed(void);
-size_t OPENSSL_ia32_rdrand(void);
+size_t OPENSSL_ia32_rdseed_bytes(char *buf, size_t len);
+size_t OPENSSL_ia32_rdrand_bytes(char *buf, size_t len);
extern unsigned int OPENSSL_ia32cap_P[];
int rand_read_cpu(RAND_poll_fn cb, void *arg)
{
- size_t i, s;
+ char buff[RANDOMNESS_NEEDED];
/* 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;
- cb(arg, &s, (int)sizeof(s), sizeof(s));
- }
- if (i >= RANDOMNESS_NEEDED)
+ if ((OPENSSL_ia32cap_P[2] & (1 << 18)) != 0) {
+ if (OPENSSL_ia32_rdseed_bytes(buff, sizeof(buff)) == sizeof(buff)) {
+ cb(arg, buff, (int)sizeof(buff), sizeof(buff));
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;
- cb(arg, &s, (int)sizeof(s), sizeof(s));
- }
- if (i >= RANDOMNESS_NEEDED)
+ if (OPENSSL_ia32_rdrand_bytes(buff, sizeof(buff)) == sizeof(buff)) {
+ cb(arg, buff, (int)sizeof(buff), sizeof(buff));
return 1;
+ }
}
return 0;
min_len = drbg->size;
}
- if (rand_drbg.filled) {
+ if (drbg->filled) {
/* Re-use what we have. */
*pout = drbg->randomness;
return drbg->size;
}
+ drbg->randomness = drbg->secure ? OPENSSL_secure_malloc(drbg->size)
+ : OPENSSL_malloc(drbg->size);
+
/* If we don't have enough, try to get more. */
CRYPTO_THREAD_write_lock(rand_bytes.lock);
for (i = RAND_POLL_RETRIES; rand_bytes.curr < min_len && --i >= 0; ) {
min_len = rand_bytes.curr;
if (min_len != 0) {
memcpy(drbg->randomness, rand_bytes.buff, min_len);
- rand_drbg.filled = 1;
+ drbg->filled = 1;
/* Update amount left and shift it down. */
rand_bytes.curr -= min_len;
if (rand_bytes.curr != 0)
memmove(rand_bytes.buff, &rand_bytes.buff[min_len], rand_bytes.curr);
}
CRYPTO_THREAD_unlock(rand_bytes.lock);
+ *pout = drbg->randomness;
return min_len;
}
min_len = drbg->size;
}
+ drbg->randomness = drbg->secure ? OPENSSL_secure_malloc(drbg->size)
+ : OPENSSL_malloc(drbg->size);
+
/* Get random from parent, include our state as additional input. */
st = RAND_DRBG_generate(drbg->parent, drbg->randomness, min_len, 0,
(unsigned char *)drbg, sizeof(*drbg));
if (st == 0)
return 0;
drbg->filled = 1;
+ *pout = drbg->randomness;
return min_len;
}
void drbg_release_entropy(RAND_DRBG *drbg, unsigned char *out)
{
drbg->filled = 0;
- OPENSSL_cleanse(drbg->randomness, drbg->size);
+ if (drbg->secure)
+ OPENSSL_secure_clear_free(drbg->randomness, drbg->size);
+ else
+ OPENSSL_clear_free(drbg->randomness, drbg->size);
+ drbg->randomness = NULL;
}
drbg->lock = CRYPTO_THREAD_lock_new();
ret &= drbg->lock != NULL;
drbg->size = RANDOMNESS_NEEDED;
- drbg->randomness = OPENSSL_malloc(drbg->size);
- ret &= drbg->randomness != NULL;
+ drbg->secure = CRYPTO_secure_malloc_initialized();
+ drbg->randomness = NULL;
/* If you change these parameters, see RANDOMNESS_NEEDED */
ret &= RAND_DRBG_set(drbg,
NID_aes_128_ctr, RAND_DRBG_FLAG_CTR_USE_DF) == 1;
static void free_drbg(RAND_DRBG *drbg)
{
CRYPTO_THREAD_lock_free(drbg->lock);
- OPENSSL_clear_free(drbg->randomness, drbg->size);
RAND_DRBG_uninstantiate(drbg);
}
+void rand_fork()
+{
+ rand_fork_count++;
+}
+
DEFINE_RUN_ONCE_STATIC(do_rand_init)
{
int ret = 1;
ret &= rand_bytes.lock != NULL;
rand_bytes.curr = 0;
rand_bytes.size = MAX_RANDOMNESS_HELD;
- /* TODO: Should this be secure malloc? */
- rand_bytes.buff = malloc(rand_bytes.size);
-
+ rand_bytes.secure = CRYPTO_secure_malloc_initialized();
+ rand_bytes.buff = rand_bytes.secure
+ ? OPENSSL_secure_malloc(rand_bytes.size)
+ : OPENSSL_malloc(rand_bytes.size);
ret &= rand_bytes.buff != NULL;
ret &= setup_drbg(&rand_drbg);
ret &= setup_drbg(&priv_drbg);
return ret;
}
-
void rand_cleanup_int(void)
{
const RAND_METHOD *meth = default_RAND_meth;
#endif
CRYPTO_THREAD_lock_free(rand_meth_lock);
CRYPTO_THREAD_lock_free(rand_bytes.lock);
- OPENSSL_clear_free(rand_bytes.buff, rand_bytes.size);
+ if (rand_bytes.secure)
+ OPENSSL_secure_clear_free(rand_bytes.buff, rand_bytes.size);
+ else
+ OPENSSL_clear_free(rand_bytes.buff, rand_bytes.size);
free_drbg(&rand_drbg);
free_drbg(&priv_drbg);
}