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

Generated on Tue Jul 8 23:34:21 2003 for Crypto++ by doxygen 1.3.2