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