LCOV - code coverage report
Current view: top level - lunchbox - rng.cpp (source / functions) Hit Total Coverage
Test: Lunchbox Lines: 22 26 84.6 %
Date: 2018-10-03 05:33:11 Functions: 7 7 100.0 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2010-2015, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *                          Daniel Nachbaur <danielnachbaur@gmail.com>
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or modify it under
       6             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       7             :  * by the Free Software Foundation.
       8             :  *
       9             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      10             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      11             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      12             :  * details.
      13             :  *
      14             :  * You should have received a copy of the GNU Lesser General Public License
      15             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      16             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      17             :  */
      18             : 
      19             : #include "rng.h"
      20             : 
      21             : #pragma warning(push)
      22             : #pragma warning(disable : 4985) // inconsistent decl of ceil
      23             : 
      24             : #ifdef _WIN32
      25             : #ifndef NOMINMAX
      26             : #define NOMINMAX
      27             : #endif
      28             : #include <wincrypt.h>
      29             : #include <wtypes.h>
      30             : #pragma comment(lib, "advapi32.lib")
      31             : #else
      32             : #include <unistd.h>
      33             : #endif
      34             : 
      35             : #include <cstdlib>
      36             : #include <fcntl.h>
      37             : #include <limits>
      38             : #include <stdio.h>
      39             : #pragma warning(pop)
      40             : 
      41             : namespace lunchbox
      42             : {
      43             : namespace
      44             : {
      45             : #ifdef __linux__
      46             : 
      47             : static int _fd = -1;
      48             : 
      49           2 : void _exit()
      50             : {
      51           2 :     if (_fd >= 0)
      52             :     {
      53           2 :         ::close(_fd);
      54           2 :         _fd = -1;
      55             :     }
      56           2 : }
      57             : 
      58           2 : int _init()
      59             : {
      60           2 :     const int fd = ::open("/dev/urandom", O_RDONLY);
      61           2 :     if (fd >= 0)
      62           2 :         ::atexit(_exit);
      63             :     else
      64             :     {
      65           0 :         LBERROR << "Failed to open /dev/urandom: " << sysError << std::endl;
      66           0 :         return -1;
      67             :     }
      68           2 :     _fd = fd;
      69           2 :     return fd;
      70             : }
      71             : 
      72             : #elif defined _MSC_VER
      73             : static HCRYPTPROV _provider = 0;
      74             : 
      75             : void _exit()
      76             : {
      77             :     if (_provider && !CryptReleaseContext(_provider, 0))
      78             :         LBERROR << "Failed to release crypto context: " << sysError
      79             :                 << std::endl;
      80             :     _provider = 0;
      81             : }
      82             : 
      83             : HCRYPTPROV _init()
      84             : {
      85             :     HCRYPTPROV provider = 0;
      86             :     if (CryptAcquireContext(&provider, 0, 0, PROV_RSA_FULL,
      87             :                             CRYPT_VERIFYCONTEXT) ||
      88             :         !provider)
      89             :     {
      90             :         ::atexit(_exit);
      91             :     }
      92             :     else
      93             :     {
      94             :         LBERROR << "Failed to acquire crypto context: " << sysError
      95             :                 << std::endl;
      96             :         return 0;
      97             :     }
      98             : 
      99             :     _provider = provider;
     100             :     return provider;
     101             : }
     102             : #endif
     103             : }
     104             : 
     105        1030 : RNG::RNG()
     106             : {
     107             : #ifdef __APPLE__
     108             :     srandomdev();
     109             : #endif
     110        1030 : }
     111             : 
     112        1030 : RNG::~RNG()
     113             : {
     114        1030 : }
     115             : 
     116      525080 : bool RNG::_get(void* data, const size_t size)
     117             : {
     118             : #ifdef __linux__
     119      525080 :     static int fd = _init();
     120      525080 :     int read = ::read(fd, data, size);
     121      525080 :     LBASSERTINFO(read == ssize_t(size), read << " != " << size << ": "
     122             :                                              << sysError);
     123      525080 :     if (read != ssize_t(size))
     124             :     {
     125           0 :         LBERROR << "random number generator not working" << std::endl;
     126           0 :         return false;
     127             :     }
     128             : 
     129             : #elif defined _MSC_VER
     130             :     static HCRYPTPROV provider = _init();
     131             :     if (!CryptGenRandom(provider, (DWORD)size, (BYTE*)data))
     132             :     {
     133             :         LBERROR << "random number generator not working" << std::endl;
     134             :         return false;
     135             :     }
     136             : #else // __APPLE__
     137             :     uint8_t* ptr = reinterpret_cast<uint8_t*>(data);
     138             :     for (size_t i = 0; i < size; ++i)
     139             :         ptr[i] = (random() & 0xff);
     140             : #endif
     141      525080 :     return true;
     142             : }
     143          75 : }

Generated by: LCOV version 1.11