LCOV - code coverage report
Current view: top level - src - random.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 39 41 95.1 %
Date: 2015-10-12 22:39:14 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2014 The Bitcoin Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #include "random.h"
       7             : 
       8             : #include "support/cleanse.h"
       9             : #ifdef WIN32
      10             : #include "compat.h" // for Windows API
      11             : #endif
      12             : #include "serialize.h"        // for begin_ptr(vec)
      13             : #include "util.h"             // for LogPrint()
      14             : #include "utilstrencodings.h" // for GetTime()
      15             : 
      16             : #include <limits>
      17             : 
      18             : #ifndef WIN32
      19             : #include <sys/time.h>
      20             : #endif
      21             : 
      22             : #include <openssl/err.h>
      23             : #include <openssl/rand.h>
      24             : 
      25             : static inline int64_t GetPerformanceCounter()
      26             : {
      27       22743 :     int64_t nCounter = 0;
      28             : #ifdef WIN32
      29             :     QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
      30             : #else
      31             :     timeval t;
      32       22743 :     gettimeofday(&t, NULL);
      33       22743 :     nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
      34             : #endif
      35             :     return nCounter;
      36             : }
      37             : 
      38       22743 : void RandAddSeed()
      39             : {
      40             :     // Seed with CPU performance counter
      41       22743 :     int64_t nCounter = GetPerformanceCounter();
      42       22743 :     RAND_add(&nCounter, sizeof(nCounter), 1.5);
      43       22743 :     memory_cleanse((void*)&nCounter, sizeof(nCounter));
      44       22743 : }
      45             : 
      46       22540 : void RandAddSeedPerfmon()
      47             : {
      48       22540 :     RandAddSeed();
      49             : 
      50             : #ifdef WIN32
      51             :     // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
      52             :     // Seed with the entire set of perfmon data
      53             : 
      54             :     // This can take up to 2 seconds, so only do it every 10 minutes
      55             :     static int64_t nLastPerfmon;
      56             :     if (GetTime() < nLastPerfmon + 10 * 60)
      57             :         return;
      58             :     nLastPerfmon = GetTime();
      59             : 
      60             :     std::vector<unsigned char> vData(250000, 0);
      61             :     long ret = 0;
      62             :     unsigned long nSize = 0;
      63             :     const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
      64             :     while (true) {
      65             :         nSize = vData.size();
      66             :         ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, begin_ptr(vData), &nSize);
      67             :         if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
      68             :             break;
      69             :         vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
      70             :     }
      71             :     RegCloseKey(HKEY_PERFORMANCE_DATA);
      72             :     if (ret == ERROR_SUCCESS) {
      73             :         RAND_add(begin_ptr(vData), nSize, nSize / 100.0);
      74             :         memory_cleanse(begin_ptr(vData), nSize);
      75             :         LogPrint("rand", "%s: %lu bytes\n", __func__, nSize);
      76             :     } else {
      77             :         static bool warned = false; // Warn only once
      78             :         if (!warned) {
      79             :             LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
      80             :             warned = true;
      81             :         }
      82             :     }
      83             : #endif
      84       22540 : }
      85             : 
      86      537940 : void GetRandBytes(unsigned char* buf, int num)
      87             : {
      88      537940 :     if (RAND_bytes(buf, num) != 1) {
      89           0 :         LogPrintf("%s: OpenSSL RAND_bytes() failed with error: %s\n", __func__, ERR_error_string(ERR_get_error(), NULL));
      90           0 :         assert(false);
      91             :     }
      92      537940 : }
      93             : 
      94      367913 : uint64_t GetRand(uint64_t nMax)
      95             : {
      96      367913 :     if (nMax == 0)
      97             :         return 0;
      98             : 
      99             :     // The range of the random source must be a multiple of the modulus
     100             :     // to give every possible output value an equal possibility
     101      367913 :     uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
     102      367913 :     uint64_t nRand = 0;
     103      367913 :     do {
     104      367913 :         GetRandBytes((unsigned char*)&nRand, sizeof(nRand));
     105      367913 :     } while (nRand >= nRange);
     106      367913 :     return (nRand % nMax);
     107             : }
     108             : 
     109      342008 : int GetRandInt(int nMax)
     110             : {
     111      342008 :     return GetRand(nMax);
     112             : }
     113             : 
     114      161612 : uint256 GetRandHash()
     115             : {
     116             :     uint256 hash;
     117      161612 :     GetRandBytes((unsigned char*)&hash, sizeof(hash));
     118      161612 :     return hash;
     119             : }
     120             : 
     121             : uint32_t insecure_rand_Rz = 11;
     122             : uint32_t insecure_rand_Rw = 11;
     123        2275 : void seed_insecure_rand(bool fDeterministic)
     124             : {
     125             :     // The seed values have some unlikely fixed points which we avoid.
     126        2275 :     if (fDeterministic) {
     127           1 :         insecure_rand_Rz = insecure_rand_Rw = 11;
     128             :     } else {
     129             :         uint32_t tmp;
     130        2274 :         do {
     131        2274 :             GetRandBytes((unsigned char*)&tmp, 4);
     132        2274 :         } while (tmp == 0 || tmp == 0x9068ffffU);
     133        2274 :         insecure_rand_Rz = tmp;
     134        2274 :         do {
     135        2274 :             GetRandBytes((unsigned char*)&tmp, 4);
     136        2274 :         } while (tmp == 0 || tmp == 0x464fffffU);
     137        2274 :         insecure_rand_Rw = tmp;
     138             :     }
     139        2884 : }

Generated by: LCOV version 1.11