14#define CRYPTO_RAND_PRIVATE
24#include "lib/crypt_ops/compat_openssl.h"
46DISABLE_GCC_WARNING(
"-Wredundant-decls")
47#include <openssl/rand.h>
48#include <openssl/sha.h>
49ENABLE_GCC_WARNING(
"-Wredundant-decls")
53DISABLE_GCC_WARNING(
"-Wstrict-prototypes")
57ENABLE_GCC_WARNING(
"-Wstrict-prototypes")
60#if __GNUC__ && GCC_VERSION >= 402
62#pragma GCC diagnostic pop
64#pragma GCC diagnostic warning "-Wredundant-decls"
71#ifdef HAVE_SYS_FCNTL_H
80#ifdef HAVE_SYS_SYSCALL_H
81#include <sys/syscall.h>
83#ifdef HAVE_SYS_RANDOM_H
84#include <sys/random.h>
101#define MAX_DNS_LABEL_SIZE 63
106#define MAX_STRONGEST_RAND_SIZE 256
120int break_strongest_rng_syscall = 0;
121int break_strongest_rng_fallback = 0;
141 if (break_strongest_rng_syscall)
146 static int provider_set = 0;
147 static HCRYPTPROV provider;
150 if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
151 CRYPT_VERIFYCONTEXT)) {
152 log_notice(
LD_CRYPTO,
"Unable to set Windows CryptoAPI provider [1].");
157 if (!CryptGenRandom(provider, out_len, out)) {
158 log_notice(
LD_CRYPTO,
"Unable get entropy from the Windows CryptoAPI.");
163#elif defined(__linux__) && defined(SYS_getrandom)
164 static int getrandom_works = 1;
182 if (PREDICT_LIKELY(getrandom_works)) {
188 const unsigned int flags = 0;
190 ret = syscall(SYS_getrandom, out, out_len, flags);
191 }
while (ret == -1 && ((errno == EINTR) ||(errno == EAGAIN)));
193 if (PREDICT_UNLIKELY(ret == -1)) {
199 if (errno == ENOSYS) {
200 log_notice(
LD_CRYPTO,
"Can't get entropy from getrandom()."
201 " You are running a version of Tor built to support"
202 " getrandom(), but the kernel doesn't implement this"
203 " function--probably because it is too old?"
204 " Trying fallback method instead.");
206 log_notice(
LD_CRYPTO,
"Can't get entropy from getrandom(): %s."
207 " Trying fallback method instead.",
221#elif defined(HAVE_GETENTROPY)
225 return getentropy(out, out_len);
244 if (break_strongest_rng_fallback)
254 static const char *filenames[] = {
255 "/dev/srandom",
"/dev/urandom",
"/dev/random", NULL
260 for (i = 0; filenames[i]; ++i) {
261 log_debug(
LD_FS,
"Considering %s as entropy source", filenames[i]);
264 log_info(
LD_CRYPTO,
"Reading entropy from \"%s\"", filenames[i]);
271 "Error reading from entropy source %s (read only %lu bytes).",
293 static const size_t sanity_min_size = 16;
294 static const int max_attempts = 3;
306 for (
int i = 0; i < max_attempts; i++) {
315 "Cannot get strong entropy: no entropy source found.");
331 log_warn(
LD_CRYPTO,
"Strong OS entropy returned all zero buffer.");
354#define DLEN DIGEST512_LEN
364 memset(inp, 0,
sizeof(inp));
366 RAND_bytes(inp, DLEN);
369 PK11_GenerateRandom(inp+DLEN, DLEN);
373 log_err(
LD_CRYPTO,
"Failed to load strong entropy when generating an "
374 "important key. Exiting.");
379 if (out_len >= DLEN) {
385 memcpy(out, tmp, out_len);
400crypto_seed_openssl_rng(
void)
402 int rand_poll_ok = 0, load_entropy_ok = 0;
408 rand_poll_ok = RAND_poll();
409 if (rand_poll_ok == 0)
410 log_warn(
LD_CRYPTO,
"RAND_poll() failed.");
413 if (load_entropy_ok) {
414 RAND_seed(buf,
sizeof(buf));
419 if ((rand_poll_ok || load_entropy_ok) && RAND_status() == 1)
432crypto_seed_nss_rng(
void)
437 if (load_entropy_ok) {
438 if (PK11_RandomUpdate(buf,
sizeof(buf)) != SECSuccess) {
445 return load_entropy_ok ? 0 : -1;
458 if (crypto_seed_nss_rng() < 0)
463 if (crypto_seed_openssl_rng() < 0)
501 SECStatus s = PK11_GenerateRandom((
unsigned char*)to, (
int)n);
502 if (s != SECSuccess) {
513 tor_assert(PR_GetError() == SEC_ERROR_INVALID_ARGS && n > BUFLEN);
514 unsigned char buf[BUFLEN];
515 s = PK11_GenerateRandom(buf, BUFLEN);
526 int r = RAND_bytes((
unsigned char*)to, (
int)n);
557 char *result, *rand_bytes;
558 int randlen, rand_bytes_len;
559 size_t resultlen, prefixlen;
563 if (min_rand_len > max_rand_len)
564 min_rand_len = max_rand_len;
568 prefixlen = strlen(prefix);
569 resultlen = prefixlen + strlen(suffix) + randlen + 16;
573 rand_bytes_len = ((randlen*5)+7)/8;
574 if (rand_bytes_len % 5)
575 rand_bytes_len += 5 - (rand_bytes_len%5);
576 rand_bytes = tor_malloc(rand_bytes_len);
579 result = tor_malloc(resultlen);
580 memcpy(result, prefix, prefixlen);
582 rand_bytes, rand_bytes_len);
584 strlcpy(result+prefixlen+randlen, suffix, resultlen-(prefixlen+randlen));
596 int len = smartlist_len(sl);
613 for (i = smartlist_len(sl)-1; i > 0; --i) {
625 RAND_METHOD *default_method;
626 default_method = RAND_OpenSSL();
627 if (RAND_get_rand_method() != default_method) {
628 log_notice(
LD_CRYPTO,
"It appears that one of our engines has provided "
629 "a replacement the OpenSSL RNG. Resetting it to the default "
631 RAND_set_rand_method(default_method);
void base32_encode(char *dest, size_t destlen, const char *src, size_t srclen)
Header for compat_string.c.
void crypto_xof_squeeze_bytes(crypto_xof_t *xof, uint8_t *out, size_t len)
crypto_xof_t * crypto_xof_new(void)
void crypto_xof_add_bytes(crypto_xof_t *xof, const uint8_t *data, size_t len)
Headers for crypto_digest.c.
int crypto_digest512(char *digest, const char *m, size_t len, digest_algorithm_t algorithm)
#define crypto_xof_free(xof)
Headers for crypto_nss_mgt.c.
int crypto_seed_rng(void)
void * smartlist_choose(const smartlist_t *sl)
#define MAX_DNS_LABEL_SIZE
static int crypto_strongest_rand_fallback(uint8_t *out, size_t out_len)
char * crypto_random_hostname(int min_rand_len, int max_rand_len, const char *prefix, const char *suffix)
static int crypto_strongest_rand_syscall(uint8_t *out, size_t out_len)
STATIC int crypto_strongest_rand_raw(uint8_t *out, size_t out_len)
void crypto_strongest_rand_(uint8_t *out, size_t out_len)
void crypto_rand(char *to, size_t n)
uint32_t crypto_rand_u32(void)
void crypto_rand_unmocked(char *to, size_t n)
void crypto_seed_weak_rng(tor_weak_rng_t *rng)
void smartlist_shuffle(smartlist_t *sl)
int crypto_force_rand_ssleay(void)
#define MAX_STRONGEST_RAND_SIZE
void crypto_strongest_rand(uint8_t *out, size_t out_len)
Common functions for using (pseudo-)random number generators.
int crypto_rand_int_range(unsigned int min, unsigned int max)
int crypto_rand_int(unsigned int max)
void memwipe(void *mem, uint8_t byte, size_t sz)
Common functions for cryptographic routines.
int safe_mem_is_zero(const void *mem, size_t sz)
Definitions for common sizes of cryptographic digests.
Wrappers for reading and writing data to files on disk.
ssize_t read_all_from_fd(int fd, char *buf, size_t count)
Headers for util_malloc.c.
Header file for sandbox.c.
#define sandbox_intern_string(s)
static void smartlist_swap(smartlist_t *sl, int idx1, int idx2)
Macros to implement mocking and selective exposure for the test code.
#define MOCK_IMPL(rv, funcname, arglist)
Macros to manage assertions, fatal and non-fatal.
Header for util_string.c.
void tor_init_weak_random(tor_weak_rng_t *rng, unsigned seed)