Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

osrng.cpp

00001 // osrng.cpp - written and placed in the public domain by Wei Dai
00002 
00003 // Thanks to Leonard Janke for the suggestion for AutoSeededRandomPool.
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                 // on some systems /dev/random will block until all bytes
00125                 // are available, on others it will returns immediately
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

Generated on Mon Apr 19 18:12:31 2004 for Crypto++ by doxygen 1.3.6-20040222