00001
00002
00003
00004
00005 #include "pch.h"
00006 #include "osrng.h"
00007
00008 #if (defined(_WIN32) && defined(USE_MS_CRYPTOAPI))
00009 #ifndef _WIN32_WINNT
00010 #define _WIN32_WINNT 0x0400
00011 #endif
00012 #include <windows.h>
00013 #include <wincrypt.h>
00014 #elif defined(__FreeBSD__) || defined(__linux__)
00015 #include <fcntl.h>
00016 #include <unistd.h>
00017 #endif
00018
00019 NAMESPACE_BEGIN(CryptoPP)
00020
00021 #ifdef NONBLOCKING_RNG_AVAILABLE
00022
00023 NonblockingRng::NonblockingRng()
00024 {
00025 #ifdef _WIN32
00026 if(!CryptAcquireContext(&m_hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
00027 throw OS_RNG_Err("NonblockingRng: CryptAcquireContext failed");
00028 #else
00029 m_fd = open("/dev/urandom",O_RDONLY);
00030 if (m_fd == -1)
00031 throw OS_RNG_Err("NonblockingRng: could not open /dev/urandom");
00032 #endif
00033 }
00034
00035 NonblockingRng::~NonblockingRng()
00036 {
00037 #ifdef _WIN32
00038 CryptReleaseContext(m_hProvider, 0);
00039 #else
00040 close(m_fd);
00041 #endif
00042 }
00043
00044 byte NonblockingRng::GenerateByte()
00045 {
00046 byte b;
00047 GenerateBlock(&b, 1);
00048 return b;
00049 }
00050
00051 void NonblockingRng::GenerateBlock(byte *output, unsigned int size)
00052 {
00053 #ifdef _WIN32
00054 if (!CryptGenRandom(m_hProvider, size, output))
00055 throw OS_RNG_Err("NonblockingRng: CryptGenRandom failed");
00056 #else
00057 if (read(m_fd, output, size) != size)
00058 throw OS_RNG_Err("NonblockingRng: error reading from /dev/urandom");
00059 #endif
00060 }
00061
00062 #endif
00063
00064
00065
00066 #ifdef BLOCKING_RNG_AVAILABLE
00067
00068 BlockingRng::BlockingRng()
00069 {
00070 m_fd = open("/dev/random",O_RDONLY);
00071 if (m_fd == -1)
00072 throw OS_RNG_Err("BlockingRng: could not open /dev/random");
00073 }
00074
00075 BlockingRng::~BlockingRng()
00076 {
00077 close(m_fd);
00078 }
00079
00080 byte BlockingRng::GenerateByte()
00081 {
00082 byte b;
00083 GenerateBlock(&b, 1);
00084 return b;
00085 }
00086
00087 void BlockingRng::GenerateBlock(byte *output, unsigned int size)
00088 {
00089 while (size)
00090 {
00091
00092
00093 int len = read(m_fd, output, STDMIN(size, (unsigned int)INT_MAX));
00094 if (len == -1)
00095 throw OS_RNG_Err("BlockingRng: error reading from /dev/random");
00096 size -= len;
00097 output += len;
00098 if (size)
00099 sleep(1);
00100 }
00101 }
00102
00103 #endif
00104
00105
00106
00107 #ifdef AUTO_SEEDED_RANDOM_POOL_AVAILABLE
00108
00109 void AutoSeededRandomPool::Reseed(bool blocking, unsigned int seedSize)
00110 {
00111 #ifdef NONBLOCKING_RNG_AVAILABLE
00112 if (blocking)
00113 #endif
00114 {
00115 #ifdef BLOCKING_RNG_AVAILABLE
00116 BlockingRng rng;
00117 SecByteBlock seed(seedSize);
00118 rng.GenerateBlock(seed, seedSize);
00119 Put(seed, seedSize);
00120 #endif
00121 }
00122
00123 #ifdef BLOCKING_RNG_AVAILABLE
00124 if (!blocking)
00125 #endif
00126 {
00127 #ifdef NONBLOCKING_RNG_AVAILABLE
00128 NonblockingRng rng;
00129 SecByteBlock seed(seedSize);
00130 rng.GenerateBlock(seed, seedSize);
00131 Put(seed, seedSize);
00132 #endif
00133 }
00134 }
00135
00136 #endif
00137
00138 NAMESPACE_END