LCOV - code coverage report
Current view: top level - lib/crypt_ops - crypto_rand.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 117 123 95.1 %
Date: 2021-11-24 03:28:48 Functions: 14 15 93.3 %

          Line data    Source code
       1             : /* Copyright (c) 2001, Matej Pfajfar.
       2             :  * Copyright (c) 2001-2004, Roger Dingledine.
       3             :  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       4             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       5             : /* See LICENSE for licensing information */
       6             : 
       7             : /**
       8             :  * \file crypto_rand.c
       9             :  *
      10             :  * \brief Functions for initialising and seeding (pseudo-)random
      11             :  * number generators, and working with randomness.
      12             :  **/
      13             : 
      14             : #define CRYPTO_RAND_PRIVATE
      15             : 
      16             : #include "lib/crypt_ops/crypto_rand.h"
      17             : 
      18             : #ifdef _WIN32
      19             : #include <windows.h>
      20             : #include <wincrypt.h>
      21             : #endif /* defined(_WIN32) */
      22             : 
      23             : #include "lib/container/smartlist.h"
      24             : #include "lib/crypt_ops/compat_openssl.h"
      25             : #include "lib/crypt_ops/crypto_util.h"
      26             : #include "lib/encoding/binascii.h"
      27             : #include "lib/intmath/weakrng.h"
      28             : #include "lib/log/log.h"
      29             : #include "lib/log/util_bug.h"
      30             : #include "lib/malloc/malloc.h"
      31             : #include "lib/sandbox/sandbox.h"
      32             : #include "lib/string/compat_string.h"
      33             : #include "lib/string/util_string.h"
      34             : #include "lib/testsupport/testsupport.h"
      35             : #include "lib/fs/files.h"
      36             : 
      37             : #include "lib/defs/digest_sizes.h"
      38             : #include "lib/crypt_ops/crypto_digest.h"
      39             : #include "lib/ctime/di_ops.h"
      40             : 
      41             : #ifdef ENABLE_NSS
      42             : #include "lib/crypt_ops/crypto_nss_mgt.h"
      43             : #endif
      44             : 
      45             : #ifdef ENABLE_OPENSSL
      46             : DISABLE_GCC_WARNING("-Wredundant-decls")
      47             : #include <openssl/rand.h>
      48             : #include <openssl/sha.h>
      49             : ENABLE_GCC_WARNING("-Wredundant-decls")
      50             : #endif /* defined(ENABLE_OPENSSL) */
      51             : 
      52             : #ifdef ENABLE_NSS
      53             : #include <pk11pub.h>
      54             : #include <secerr.h>
      55             : #include <prerror.h>
      56             : #endif
      57             : 
      58             : #if __GNUC__ && GCC_VERSION >= 402
      59             : #if GCC_VERSION >= 406
      60             : #pragma GCC diagnostic pop
      61             : #else
      62             : #pragma GCC diagnostic warning "-Wredundant-decls"
      63             : #endif
      64             : #endif /* __GNUC__ && GCC_VERSION >= 402 */
      65             : 
      66             : #ifdef HAVE_FCNTL_H
      67             : #include <fcntl.h>
      68             : #endif
      69             : #ifdef HAVE_SYS_FCNTL_H
      70             : #include <sys/fcntl.h>
      71             : #endif
      72             : #ifdef HAVE_SYS_STAT_H
      73             : #include <sys/stat.h>
      74             : #endif
      75             : #ifdef HAVE_UNISTD_H
      76             : #include <unistd.h>
      77             : #endif
      78             : #ifdef HAVE_SYS_SYSCALL_H
      79             : #include <sys/syscall.h>
      80             : #endif
      81             : #ifdef HAVE_SYS_RANDOM_H
      82             : #include <sys/random.h>
      83             : #endif
      84             : 
      85             : #include <string.h>
      86             : #include <errno.h>
      87             : 
      88             : /**
      89             :  * How many bytes of entropy we add at once.
      90             :  *
      91             :  * This is how much entropy OpenSSL likes to add right now, so maybe it will
      92             :  * work for us too.
      93             :  **/
      94             : #define ADD_ENTROPY 32
      95             : 
      96             : /**
      97             :  * Longest recognized DNS query.
      98             :  **/
      99             : #define MAX_DNS_LABEL_SIZE 63
     100             : 
     101             : /**
     102             :  * Largest strong entropy request permitted.
     103             :  **/
     104             : #define MAX_STRONGEST_RAND_SIZE 256
     105             : 
     106             : /**
     107             :  * Set the seed of the weak RNG to a random value.
     108             :  **/
     109             : void
     110           7 : crypto_seed_weak_rng(tor_weak_rng_t *rng)
     111             : {
     112           7 :   unsigned seed;
     113           7 :   crypto_rand((void*)&seed, sizeof(seed));
     114           7 :   tor_init_weak_random(rng, seed);
     115           7 : }
     116             : 
     117             : #ifdef TOR_UNIT_TESTS
     118             : int break_strongest_rng_syscall = 0;
     119             : int break_strongest_rng_fallback = 0;
     120             : #endif
     121             : 
     122             : /**
     123             :  * Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
     124             :  * via system calls, storing it into <b>out</b>. Return 0 on success, -1 on
     125             :  * failure.  A maximum request size of 256 bytes is imposed.
     126             :  **/
     127             : static int
     128        8549 : crypto_strongest_rand_syscall(uint8_t *out, size_t out_len)
     129             : {
     130        8549 :   tor_assert(out_len <= MAX_STRONGEST_RAND_SIZE);
     131             : 
     132             :   /* We only log at notice-level here because in the case that this function
     133             :    * fails the crypto_strongest_rand_raw() caller will log with a warning-level
     134             :    * message and let crypto_strongest_rand() error out and finally terminating
     135             :    * Tor with an assertion error.
     136             :    */
     137             : 
     138             : #ifdef TOR_UNIT_TESTS
     139        8549 :   if (break_strongest_rng_syscall)
     140             :     return -1;
     141             : #endif
     142             : 
     143             : #if defined(_WIN32)
     144             :   static int provider_set = 0;
     145             :   static HCRYPTPROV provider;
     146             : 
     147             :   if (!provider_set) {
     148             :     if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
     149             :                              CRYPT_VERIFYCONTEXT)) {
     150             :       log_notice(LD_CRYPTO, "Unable to set Windows CryptoAPI provider [1].");
     151             :       return -1;
     152             :     }
     153             :     provider_set = 1;
     154             :   }
     155             :   if (!CryptGenRandom(provider, out_len, out)) {
     156             :     log_notice(LD_CRYPTO, "Unable get entropy from the Windows CryptoAPI.");
     157             :     return -1;
     158             :   }
     159             : 
     160             :   return 0;
     161             : #elif defined(__linux__) && defined(SYS_getrandom)
     162        8448 :   static int getrandom_works = 1; /* Be optimistic about our chances... */
     163             : 
     164             :   /* getrandom() isn't as straightforward as getentropy(), and has
     165             :    * no glibc wrapper.
     166             :    *
     167             :    * As far as I can tell from getrandom(2) and the source code, the
     168             :    * requests we issue will always succeed (though it will block on the
     169             :    * call if /dev/urandom isn't seeded yet), since we are NOT specifying
     170             :    * GRND_NONBLOCK and the request is <= 256 bytes.
     171             :    *
     172             :    * The manpage is unclear on what happens if a signal interrupts the call
     173             :    * while the request is blocked due to lack of entropy....
     174             :    *
     175             :    * We optimistically assume that getrandom() is available and functional
     176             :    * because it is the way of the future, and 2 branch mispredicts pale in
     177             :    * comparison to the overheads involved with failing to open
     178             :    * /dev/srandom followed by opening and reading from /dev/urandom.
     179             :    */
     180        8448 :   if (PREDICT_LIKELY(getrandom_works)) {
     181             :     long ret;
     182             :     /* A flag of '0' here means to read from '/dev/urandom', and to
     183             :      * block if insufficient entropy is available to service the
     184             :      * request.
     185             :      */
     186             :     const unsigned int flags = 0;
     187        8448 :     do {
     188        8448 :       ret = syscall(SYS_getrandom, out, out_len, flags);
     189        8448 :     } while (ret == -1 && ((errno == EINTR) ||(errno == EAGAIN)));
     190             : 
     191        8448 :     if (PREDICT_UNLIKELY(ret == -1)) {
     192             :       /* LCOV_EXCL_START we can't actually make the syscall fail in testing. */
     193             :       tor_assert(errno != EAGAIN);
     194             :       tor_assert(errno != EINTR);
     195             : 
     196             :       /* Useful log message for errno. */
     197             :       if (errno == ENOSYS) {
     198             :         log_notice(LD_CRYPTO, "Can't get entropy from getrandom()."
     199             :                    " You are running a version of Tor built to support"
     200             :                    " getrandom(), but the kernel doesn't implement this"
     201             :                    " function--probably because it is too old?"
     202             :                    " Trying fallback method instead.");
     203             :       } else {
     204             :         log_notice(LD_CRYPTO, "Can't get entropy from getrandom(): %s."
     205             :                               " Trying fallback method instead.",
     206             :                    strerror(errno));
     207             :       }
     208             : 
     209             :       getrandom_works = 0; /* Don't bother trying again. */
     210             :       return -1;
     211             :       /* LCOV_EXCL_STOP */
     212             :     }
     213             : 
     214        8448 :     tor_assert(ret == (long)out_len);
     215             :     return 0;
     216             :   }
     217             : 
     218             :   return -1; /* getrandom() previously failed unexpectedly. */
     219             : #elif defined(HAVE_GETENTROPY)
     220             :   /* getentropy() is what Linux's getrandom() wants to be when it grows up.
     221             :    * the only gotcha is that requests are limited to 256 bytes.
     222             :    */
     223             :   return getentropy(out, out_len);
     224             : #else
     225             :   (void) out;
     226             : #endif /* defined(_WIN32) || ... */
     227             : 
     228             :   /* This platform doesn't have a supported syscall based random. */
     229             :   return -1;
     230             : }
     231             : 
     232             : /**
     233             :  * Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
     234             :  * via the per-platform fallback mechanism, storing it into <b>out</b>.
     235             :  * Return 0 on success, -1 on failure.  A maximum request size of 256 bytes
     236             :  * is imposed.
     237             :  **/
     238             : static int
     239         101 : crypto_strongest_rand_fallback(uint8_t *out, size_t out_len)
     240             : {
     241             : #ifdef TOR_UNIT_TESTS
     242         101 :   if (break_strongest_rng_fallback)
     243             :     return -1;
     244             : #endif
     245             : 
     246             : #ifdef _WIN32
     247             :   /* Windows exclusively uses crypto_strongest_rand_syscall(). */
     248             :   (void)out;
     249             :   (void)out_len;
     250             :   return -1;
     251             : #else /* !defined(_WIN32) */
     252             :   static const char *filenames[] = {
     253             :     "/dev/srandom", "/dev/urandom", "/dev/random", NULL
     254             :   };
     255             :   int fd, i;
     256             :   size_t n;
     257             : 
     258         200 :   for (i = 0; filenames[i]; ++i) {
     259         200 :     log_debug(LD_FS, "Considering %s as entropy source", filenames[i]);
     260         200 :     fd = open(sandbox_intern_string(filenames[i]), O_RDONLY, 0);
     261         200 :     if (fd<0) continue;
     262         100 :     log_info(LD_CRYPTO, "Reading entropy from \"%s\"", filenames[i]);
     263         100 :     n = read_all_from_fd(fd, (char*)out, out_len);
     264         100 :     close(fd);
     265         100 :     if (n != out_len) {
     266             :       /* LCOV_EXCL_START
     267             :        * We can't make /dev/foorandom actually fail. */
     268             :       log_notice(LD_CRYPTO,
     269             :                  "Error reading from entropy source %s (read only %lu bytes).",
     270             :                  filenames[i],
     271             :                  (unsigned long)n);
     272             :       return -1;
     273             :       /* LCOV_EXCL_STOP */
     274             :     }
     275             : 
     276             :     return 0;
     277             :   }
     278             : 
     279             :   return -1;
     280             : #endif /* defined(_WIN32) */
     281             : }
     282             : 
     283             : /**
     284             :  * Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
     285             :  * storing it into <b>out</b>. Return 0 on success, -1 on failure.  A maximum
     286             :  * request size of 256 bytes is imposed.
     287             :  **/
     288             : STATIC int
     289        8549 : crypto_strongest_rand_raw(uint8_t *out, size_t out_len)
     290             : {
     291        8549 :   static const size_t sanity_min_size = 16;
     292        8549 :   static const int max_attempts = 3;
     293        8549 :   tor_assert(out_len <= MAX_STRONGEST_RAND_SIZE);
     294             : 
     295             :   /* For buffers >= 16 bytes (128 bits), we sanity check the output by
     296             :    * zero filling the buffer and ensuring that it actually was at least
     297             :    * partially modified.
     298             :    *
     299             :    * Checking that any individual byte is non-zero seems like it would
     300             :    * fail too often (p = out_len * 1/256) for comfort, but this is an
     301             :    * "adjust according to taste" sort of check.
     302             :    */
     303        8549 :   memwipe(out, 0, out_len);
     304        8549 :   for (int i = 0; i < max_attempts; i++) {
     305             :     /* Try to use the syscall/OS favored mechanism to get strong entropy. */
     306        8549 :     if (crypto_strongest_rand_syscall(out, out_len) != 0) {
     307             :       /* Try to use the less-favored mechanism to get strong entropy. */
     308         101 :       if (crypto_strongest_rand_fallback(out, out_len) != 0) {
     309             :         /* Welp, we tried.  Hopefully the calling code terminates the process
     310             :          * since we're basically boned without good entropy.
     311             :          */
     312           1 :         log_warn(LD_CRYPTO,
     313             :                  "Cannot get strong entropy: no entropy source found.");
     314           1 :         return -1;
     315             :       }
     316             :     }
     317             : 
     318        8548 :     if ((out_len < sanity_min_size) || !safe_mem_is_zero((char*)out, out_len))
     319        8548 :       return 0;
     320             :   }
     321             : 
     322             :   /* LCOV_EXCL_START
     323             :    *
     324             :    * We tried max_attempts times to fill a buffer >= 128 bits long,
     325             :    * and each time it returned all '0's.  Either the system entropy
     326             :    * source is busted, or the user should go out and buy a ticket to
     327             :    * every lottery on the planet.
     328             :    */
     329             :   log_warn(LD_CRYPTO, "Strong OS entropy returned all zero buffer.");
     330             : 
     331             :   return -1;
     332             :   /* LCOV_EXCL_STOP */
     333             : }
     334             : 
     335             : /**
     336             :  * Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
     337             :  * storing it into <b>out</b>.
     338             :  **/
     339             : void
     340        2671 : crypto_strongest_rand(uint8_t *out, size_t out_len)
     341             : {
     342        2671 :   crypto_strongest_rand_(out, out_len);
     343        2671 : }
     344             : 
     345             : /**
     346             :  * Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
     347             :  * storing it into <b>out</b>. (Mockable version.)
     348             :  **/
     349        2670 : MOCK_IMPL(void,
     350             : crypto_strongest_rand_,(uint8_t *out, size_t out_len))
     351             : {
     352             : #define DLEN DIGEST512_LEN
     353             : 
     354             :   /* We're going to hash DLEN bytes from the system RNG together with some
     355             :    * bytes from the PRNGs from our crypto librar(y/ies), in order to yield
     356             :    * DLEN bytes.
     357             :    */
     358        2670 :   uint8_t inp[DLEN*3];
     359        2670 :   uint8_t tmp[DLEN];
     360        2670 :   tor_assert(out);
     361        2870 :   while (out_len) {
     362        2770 :     memset(inp, 0, sizeof(inp));
     363             : #ifdef ENABLE_OPENSSL
     364        2770 :     RAND_bytes(inp, DLEN);
     365             : #endif
     366             : #ifdef ENABLE_NSS
     367             :     PK11_GenerateRandom(inp+DLEN, DLEN);
     368             : #endif
     369        2770 :     if (crypto_strongest_rand_raw(inp+DLEN*2, DLEN) < 0) {
     370             :       // LCOV_EXCL_START
     371             :       log_err(LD_CRYPTO, "Failed to load strong entropy when generating an "
     372             :               "important key. Exiting.");
     373             :       /* Die with an assertion so we get a stack trace. */
     374             :       tor_assert(0);
     375             :       // LCOV_EXCL_STOP
     376             :     }
     377        2770 :     if (out_len >= DLEN) {
     378         200 :       crypto_digest512((char*)out, (char*)inp, sizeof(inp), DIGEST_SHA512);
     379         200 :       out += DLEN;
     380         200 :       out_len -= DLEN;
     381             :     } else {
     382        2570 :       crypto_digest512((char*)tmp, (char*)inp, sizeof(inp), DIGEST_SHA512);
     383        2570 :       memcpy(out, tmp, out_len);
     384             :       break;
     385             :     }
     386             :   }
     387        2670 :   memwipe(tmp, 0, sizeof(tmp));
     388        2670 :   memwipe(inp, 0, sizeof(inp));
     389             : #undef DLEN
     390        2670 : }
     391             : 
     392             : #ifdef ENABLE_OPENSSL
     393             : /**
     394             :  * Seed OpenSSL's random number generator with bytes from the operating
     395             :  * system.  Return 0 on success, -1 on failure.
     396             :  **/
     397             : static int
     398        5578 : crypto_seed_openssl_rng(void)
     399             : {
     400        5578 :   int rand_poll_ok = 0, load_entropy_ok = 0;
     401        5578 :   uint8_t buf[ADD_ENTROPY];
     402             : 
     403             :   /* OpenSSL has a RAND_poll function that knows about more kinds of
     404             :    * entropy than we do.  We'll try calling that, *and* calling our own entropy
     405             :    * functions.  If one succeeds, we'll accept the RNG as seeded. */
     406        5578 :   rand_poll_ok = RAND_poll();
     407        5578 :   if (rand_poll_ok == 0)
     408             :     log_warn(LD_CRYPTO, "RAND_poll() failed."); // LCOV_EXCL_LINE
     409             : 
     410        5578 :   load_entropy_ok = !crypto_strongest_rand_raw(buf, sizeof(buf));
     411        5578 :   if (load_entropy_ok) {
     412        5578 :     RAND_seed(buf, sizeof(buf));
     413             :   }
     414             : 
     415        5578 :   memwipe(buf, 0, sizeof(buf));
     416             : 
     417        5578 :   if ((rand_poll_ok || load_entropy_ok) && RAND_status() == 1)
     418             :     return 0;
     419             :   else
     420           0 :     return -1;
     421             : }
     422             : #endif /* defined(ENABLE_OPENSSL) */
     423             : 
     424             : #ifdef ENABLE_NSS
     425             : /**
     426             :  * Seed OpenSSL's random number generator with bytes from the operating
     427             :  * system.  Return 0 on success, -1 on failure.
     428             :  **/
     429             : static int
     430             : crypto_seed_nss_rng(void)
     431             : {
     432             :   uint8_t buf[ADD_ENTROPY];
     433             : 
     434             :   int load_entropy_ok = !crypto_strongest_rand_raw(buf, sizeof(buf));
     435             :   if (load_entropy_ok) {
     436             :     if (PK11_RandomUpdate(buf, sizeof(buf)) != SECSuccess) {
     437             :       load_entropy_ok = 0;
     438             :     }
     439             :   }
     440             : 
     441             :   memwipe(buf, 0, sizeof(buf));
     442             : 
     443             :   return load_entropy_ok ? 0 : -1;
     444             : }
     445             : #endif /* defined(ENABLE_NSS) */
     446             : 
     447             : /**
     448             :  * Seed the RNG for any and all crypto libraries that we're using with bytes
     449             :  * from the operating system.  Return 0 on success, -1 on failure.
     450             :  */
     451             : int
     452        5578 : crypto_seed_rng(void)
     453             : {
     454        5578 :   int seeded = 0;
     455             : #ifdef ENABLE_NSS
     456             :   if (crypto_seed_nss_rng() < 0)
     457             :     return -1;
     458             :   ++seeded;
     459             : #endif
     460             : #ifdef ENABLE_OPENSSL
     461        5578 :   if (crypto_seed_openssl_rng() < 0)
     462           0 :     return -1;
     463        5578 :   ++seeded;
     464             : #endif
     465             :   tor_assert(seeded);
     466             :   return 0;
     467             : }
     468             : 
     469             : /**
     470             :  * Write <b>n</b> bytes of strong random data to <b>to</b>. Supports mocking
     471             :  * for unit tests.
     472             :  *
     473             :  * This function is not allowed to fail; if it would fail to generate strong
     474             :  * entropy, it must terminate the process instead.
     475             :  **/
     476      402918 : MOCK_IMPL(void,
     477             : crypto_rand, (char *to, size_t n))
     478             : {
     479      402918 :   crypto_rand_unmocked(to, n);
     480      402918 : }
     481             : 
     482             : /**
     483             :  * Write <b>n</b> bytes of strong random data to <b>to</b>.  Most callers
     484             :  * will want crypto_rand instead.
     485             :  *
     486             :  * This function is not allowed to fail; if it would fail to generate strong
     487             :  * entropy, it must terminate the process instead.
     488             :  **/
     489             : void
     490      402920 : crypto_rand_unmocked(char *to, size_t n)
     491             : {
     492      402920 :   if (n == 0)
     493             :     return;
     494             : 
     495      402900 :   tor_assert(n < INT_MAX);
     496      402900 :   tor_assert(to);
     497             : 
     498             : #ifdef ENABLE_NSS
     499             :   SECStatus s = PK11_GenerateRandom((unsigned char*)to, (int)n);
     500             :   if (s != SECSuccess) {
     501             :     /* NSS rather sensibly might refuse to generate huge amounts of random
     502             :      * data at once.  Unfortunately, our unit test do this in a couple of
     503             :      * places.  To solve this issue, we use our XOF to stretch a shorter
     504             :      * output when a longer one is needed.
     505             :      *
     506             :      * Yes, this is secure. */
     507             : 
     508             :     /* This is longer than it needs to be; 1600 bits == 200 bytes is the
     509             :      * state-size of SHA3. */
     510             : #define BUFLEN 512
     511             :     tor_assert(PR_GetError() == SEC_ERROR_INVALID_ARGS && n > BUFLEN);
     512             :     unsigned char buf[BUFLEN];
     513             :     s = PK11_GenerateRandom(buf, BUFLEN);
     514             :     tor_assert(s == SECSuccess);
     515             :     crypto_xof_t *xof = crypto_xof_new();
     516             :     crypto_xof_add_bytes(xof, buf, BUFLEN);
     517             :     crypto_xof_squeeze_bytes(xof, (unsigned char *)to, n);
     518             :     crypto_xof_free(xof);
     519             :     memwipe(buf, 0, BUFLEN);
     520             : 
     521             : #undef BUFLEN
     522             :   }
     523             : #else /* !defined(ENABLE_NSS) */
     524      402900 :   int r = RAND_bytes((unsigned char*)to, (int)n);
     525             :   /* We consider a PRNG failure non-survivable. Let's assert so that we get a
     526             :    * stack trace about where it happened.
     527             :    */
     528      402900 :   tor_assert(r >= 0);
     529             : #endif /* defined(ENABLE_NSS) */
     530             : }
     531             : 
     532             : /**
     533             :  * Draw an unsigned 32-bit integer uniformly at random.
     534             :  */
     535             : uint32_t
     536           0 : crypto_rand_u32(void)
     537             : {
     538           0 :   uint32_t rand;
     539           0 :   crypto_rand((void*)&rand, sizeof(rand));
     540           0 :   return rand;
     541             : }
     542             : 
     543             : /**
     544             :  * Generate and return a new random hostname starting with <b>prefix</b>,
     545             :  * ending with <b>suffix</b>, and containing no fewer than
     546             :  * <b>min_rand_len</b> and no more than <b>max_rand_len</b> random base32
     547             :  * characters. Does not check for failure.
     548             :  *
     549             :  * Clip <b>max_rand_len</b> to MAX_DNS_LABEL_SIZE.
     550             :  **/
     551             : char *
     552         341 : crypto_random_hostname(int min_rand_len, int max_rand_len, const char *prefix,
     553             :                        const char *suffix)
     554             : {
     555         341 :   char *result, *rand_bytes;
     556         341 :   int randlen, rand_bytes_len;
     557         341 :   size_t resultlen, prefixlen;
     558             : 
     559         341 :   if (max_rand_len > MAX_DNS_LABEL_SIZE)
     560             :     max_rand_len = MAX_DNS_LABEL_SIZE;
     561         341 :   if (min_rand_len > max_rand_len)
     562             :     min_rand_len = max_rand_len;
     563             : 
     564         341 :   randlen = crypto_rand_int_range(min_rand_len, max_rand_len+1);
     565             : 
     566         341 :   prefixlen = strlen(prefix);
     567         341 :   resultlen = prefixlen + strlen(suffix) + randlen + 16;
     568             : 
     569         341 :   rand_bytes_len = ((randlen*5)+7)/8;
     570         341 :   if (rand_bytes_len % 5)
     571         254 :     rand_bytes_len += 5 - (rand_bytes_len%5);
     572         341 :   rand_bytes = tor_malloc(rand_bytes_len);
     573         341 :   crypto_rand(rand_bytes, rand_bytes_len);
     574             : 
     575         341 :   result = tor_malloc(resultlen);
     576         341 :   memcpy(result, prefix, prefixlen);
     577         341 :   base32_encode(result+prefixlen, resultlen-prefixlen,
     578             :                 rand_bytes, rand_bytes_len);
     579         341 :   tor_free(rand_bytes);
     580         341 :   strlcpy(result+prefixlen+randlen, suffix, resultlen-(prefixlen+randlen));
     581             : 
     582         341 :   return result;
     583             : }
     584             : 
     585             : /**
     586             :  * Return a randomly chosen element of <b>sl</b>; or NULL if <b>sl</b>
     587             :  * is empty.
     588             :  **/
     589             : void *
     590         312 : smartlist_choose(const smartlist_t *sl)
     591             : {
     592         312 :   int len = smartlist_len(sl);
     593         312 :   if (len)
     594         300 :     return smartlist_get(sl,crypto_rand_int(len));
     595             :   return NULL; /* no elements to choose from */
     596             : }
     597             : 
     598             : /**
     599             :  * Scramble the elements of <b>sl</b> into a random order.
     600             :  **/
     601             : void
     602          61 : smartlist_shuffle(smartlist_t *sl)
     603             : {
     604          61 :   int i;
     605             :   /* From the end of the list to the front, choose at random from the
     606             :      positions we haven't looked at yet, and swap that position into the
     607             :      current position.  Remember to give "no swap" the same probability as
     608             :      any other swap. */
     609         903 :   for (i = smartlist_len(sl)-1; i > 0; --i) {
     610         842 :     int j = crypto_rand_int(i+1);
     611         842 :     smartlist_swap(sl, i, j);
     612             :   }
     613          61 : }
     614             : 
     615             : /** Make sure that openssl is using its default PRNG. Return 1 if we had to
     616             :  * adjust it; 0 otherwise. */
     617             : int
     618       11090 : crypto_force_rand_ssleay(void)
     619             : {
     620             : #ifdef ENABLE_OPENSSL
     621       11090 :   RAND_METHOD *default_method;
     622       11090 :   default_method = RAND_OpenSSL();
     623       11090 :   if (RAND_get_rand_method() != default_method) {
     624           1 :     log_notice(LD_CRYPTO, "It appears that one of our engines has provided "
     625             :                "a replacement the OpenSSL RNG. Resetting it to the default "
     626             :                "implementation.");
     627           1 :     RAND_set_rand_method(default_method);
     628           1 :     return 1;
     629             :   }
     630             : #endif /* defined(ENABLE_OPENSSL) */
     631             :   return 0;
     632             : }

Generated by: LCOV version 1.14