00001
00002
00003
00004
00005
#include "pch.h"
00006
#include "osrng.h"
00007
00008
#ifdef OS_RNG_AVAILABLE
00009
00010
#include "rng.h"
00011
00012
#ifdef CRYPTOPP_WIN32_AVAILABLE
00013
#ifndef _WIN32_WINNT
00014
#define _WIN32_WINNT 0x0400
00015
#endif
00016
#include <windows.h>
00017
#include <wincrypt.h>
00018
#endif
00019
00020
#ifdef CRYPTOPP_UNIX_AVAILABLE
00021
#include <errno.h>
00022
#include <fcntl.h>
00023
#include <unistd.h>
00024
#endif
00025
00026 NAMESPACE_BEGIN(CryptoPP)
00027
00028 #
if defined(NONBLOCKING_RNG_AVAILABLE) || defined(BLOCKING_RNG_AVAILABLE)
00029
OS_RNG_Err::
OS_RNG_Err(const std::string &operation)
00030 :
Exception(OTHER_ERROR, "OS_Rng: " + operation + " operation failed with error " +
00031 #ifdef CRYPTOPP_WIN32_AVAILABLE
00032 "0x" + IntToString(GetLastError(), 16)
00033 #else
00034 IntToString(errno)
00035 #endif
00036 )
00037 {
00038 }
00039
#endif
00040
00041
#ifdef NONBLOCKING_RNG_AVAILABLE
00042
00043
#ifdef CRYPTOPP_WIN32_AVAILABLE
00044
00045 MicrosoftCryptoProvider::MicrosoftCryptoProvider()
00046 {
00047
if(!CryptAcquireContext(&m_hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
00048
throw OS_RNG_Err(
"CryptAcquireContext");
00049 }
00050
00051 MicrosoftCryptoProvider::~MicrosoftCryptoProvider()
00052 {
00053 CryptReleaseContext(m_hProvider, 0);
00054 }
00055
00056
#endif
00057
00058 NonblockingRng::NonblockingRng()
00059 {
00060
#ifndef CRYPTOPP_WIN32_AVAILABLE
00061
m_fd = open(
"/dev/urandom",O_RDONLY);
00062
if (m_fd == -1)
00063
throw OS_RNG_Err(
"open /dev/urandom");
00064
#endif
00065
}
00066
00067 NonblockingRng::~NonblockingRng()
00068 {
00069
#ifndef CRYPTOPP_WIN32_AVAILABLE
00070
close(m_fd);
00071
#endif
00072
}
00073
00074 byte
NonblockingRng::GenerateByte()
00075 {
00076 byte b;
00077
GenerateBlock(&b, 1);
00078
return b;
00079 }
00080
00081 void NonblockingRng::GenerateBlock(byte *output,
unsigned int size)
00082 {
00083
#ifdef CRYPTOPP_WIN32_AVAILABLE
00084
# ifdef WORKAROUND_MS_BUG_Q258000
00085
static MicrosoftCryptoProvider m_Provider;
00086
# endif
00087
if (!CryptGenRandom(m_Provider.GetProviderHandle(), size, output))
00088
throw OS_RNG_Err(
"CryptGenRandom");
00089
#else
00090
if (read(m_fd, output, size) != size)
00091
throw OS_RNG_Err(
"read /dev/urandom");
00092
#endif
00093
}
00094
00095
#endif
00096
00097
00098
00099
#ifdef BLOCKING_RNG_AVAILABLE
00100
00101 BlockingRng::BlockingRng()
00102 {
00103 m_fd = open(
"/dev/random",O_RDONLY);
00104
if (m_fd == -1)
00105
throw OS_RNG_Err(
"open /dev/random");
00106 }
00107
00108 BlockingRng::~BlockingRng()
00109 {
00110 close(m_fd);
00111 }
00112
00113 byte BlockingRng::GenerateByte()
00114 {
00115 byte b;
00116
GenerateBlock(&b, 1);
00117
return b;
00118 }
00119
00120
void BlockingRng::GenerateBlock(byte *output,
unsigned int size)
00121 {
00122
while (size)
00123 {
00124
00125
00126
int len = read(m_fd, output, STDMIN(size, (
unsigned int)INT_MAX));
00127
if (len == -1)
00128
throw OS_RNG_Err(
"read /dev/random");
00129 size -= len;
00130 output += len;
00131
if (size)
00132 sleep(1);
00133 }
00134 }
00135
00136
#endif
00137
00138
00139
00140
void OS_GenerateRandomBlock(
bool blocking, byte *output,
unsigned int size)
00141 {
00142
#ifdef NONBLOCKING_RNG_AVAILABLE
00143
if (blocking)
00144
#endif
00145
{
00146
#ifdef BLOCKING_RNG_AVAILABLE
00147
BlockingRng rng;
00148 rng.GenerateBlock(output, size);
00149
#endif
00150
}
00151
00152
#ifdef BLOCKING_RNG_AVAILABLE
00153
if (!blocking)
00154
#endif
00155
{
00156
#ifdef NONBLOCKING_RNG_AVAILABLE
00157
NonblockingRng rng;
00158 rng.
GenerateBlock(output, size);
00159
#endif
00160
}
00161 }
00162
00163
void AutoSeededRandomPool::Reseed(
bool blocking,
unsigned int seedSize)
00164 {
00165
SecByteBlock seed(seedSize);
00166 OS_GenerateRandomBlock(blocking, seed, seedSize);
00167 Put(seed, seedSize);
00168 }
00169
00170 NAMESPACE_END
00171
00172
#endif