<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"> <title>Crypto++: osrng.cpp Source File</title> <link href="doxygen.css" rel="stylesheet" type="text/css"> </head><body> <!-- Generated by Doxygen 1.3.7 --> <div class="qindex"><a class="qindex" href="index.html">Main Page</a> | <a class="qindex" href="namespaces.html">Namespace List</a> | <a class="qindex" href="hierarchy.html">Class Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical List</a> | <a class="qindex" href="annotated.html">Class List</a> | <a class="qindex" href="files.html">File List</a> | <a class="qindex" href="namespacemembers.html">Namespace Members</a> | <a class="qindex" href="functions.html">Class Members</a> | <a class="qindex" href="globals.html">File Members</a></div> <h1>osrng.cpp</h1><pre class="fragment"><div>00001 <span class="comment">// osrng.cpp - written and placed in the public domain by Wei Dai</span> 00002 00003 <span class="comment">// Thanks to Leonard Janke for the suggestion for AutoSeededRandomPool.</span> 00004 00005 <span class="preprocessor">#include "pch.h"</span> 00006 00007 <span class="preprocessor">#ifndef CRYPTOPP_IMPORTS</span> 00008 <span class="preprocessor"></span> 00009 <span class="preprocessor">#include "osrng.h"</span> 00010 00011 <span class="preprocessor">#ifdef OS_RNG_AVAILABLE</span> 00012 <span class="preprocessor"></span> 00013 <span class="preprocessor">#include "rng.h"</span> 00014 00015 <span class="preprocessor">#ifdef CRYPTOPP_WIN32_AVAILABLE</span> 00016 <span class="preprocessor"></span><span class="preprocessor">#ifndef _WIN32_WINNT</span> 00017 <span class="preprocessor"></span><span class="preprocessor">#define _WIN32_WINNT 0x0400</span> 00018 <span class="preprocessor"></span><span class="preprocessor">#endif</span> 00019 <span class="preprocessor"></span><span class="preprocessor">#include <windows.h></span> 00020 <span class="preprocessor">#include <wincrypt.h></span> 00021 <span class="preprocessor">#endif</span> 00022 <span class="preprocessor"></span> 00023 <span class="preprocessor">#ifdef CRYPTOPP_UNIX_AVAILABLE</span> 00024 <span class="preprocessor"></span><span class="preprocessor">#include <errno.h></span> 00025 <span class="preprocessor">#include <fcntl.h></span> 00026 <span class="preprocessor">#include <unistd.h></span> 00027 <span class="preprocessor">#endif</span> 00028 <span class="preprocessor"></span> 00029 NAMESPACE_BEGIN(CryptoPP) 00030 00031 #<span class="keywordflow">if</span> defined(NONBLOCKING_RNG_AVAILABLE) || defined(BLOCKING_RNG_AVAILABLE) 00032 <a class="code" href="class_o_s___r_n_g___err.html">OS_RNG_Err</a>::<a class="code" href="class_o_s___r_n_g___err.html">OS_RNG_Err</a>(const std::string &operation) 00033 : <a class="code" href="class_exception.html">Exception</a>(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 <span class="preprocessor">#endif</span> 00043 <span class="preprocessor"></span> 00044 <span class="preprocessor">#ifdef NONBLOCKING_RNG_AVAILABLE</span> 00045 <span class="preprocessor"></span> 00046 <span class="preprocessor">#ifdef CRYPTOPP_WIN32_AVAILABLE</span> 00047 <span class="preprocessor"></span> 00048 MicrosoftCryptoProvider::MicrosoftCryptoProvider() 00049 { 00050 <span class="keywordflow">if</span>(!CryptAcquireContext(&m_hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) 00051 <span class="keywordflow">throw</span> <a class="code" href="class_o_s___r_n_g___err.html">OS_RNG_Err</a>(<span class="stringliteral">"CryptAcquireContext"</span>); 00052 } 00053 00054 MicrosoftCryptoProvider::~MicrosoftCryptoProvider() 00055 { 00056 CryptReleaseContext(m_hProvider, 0); 00057 } 00058 00059 <span class="preprocessor">#endif</span> 00060 <span class="preprocessor"></span> 00061 NonblockingRng::NonblockingRng() 00062 { 00063 <span class="preprocessor">#ifndef CRYPTOPP_WIN32_AVAILABLE</span> 00064 <span class="preprocessor"></span> m_fd = open(<span class="stringliteral">"/dev/urandom"</span>,O_RDONLY); 00065 <span class="keywordflow">if</span> (m_fd == -1) 00066 <span class="keywordflow">throw</span> <a class="code" href="class_o_s___r_n_g___err.html">OS_RNG_Err</a>(<span class="stringliteral">"open /dev/urandom"</span>); 00067 <span class="preprocessor">#endif</span> 00068 <span class="preprocessor"></span>} 00069 00070 NonblockingRng::~NonblockingRng() 00071 { 00072 <span class="preprocessor">#ifndef CRYPTOPP_WIN32_AVAILABLE</span> 00073 <span class="preprocessor"></span> close(m_fd); 00074 <span class="preprocessor">#endif</span> 00075 <span class="preprocessor"></span>} 00076 <a name="l00077"></a><a class="code" href="class_nonblocking_rng.html#_nonblocking_rnga2">00077</a> byte <a class="code" href="class_nonblocking_rng.html#_nonblocking_rnga2">NonblockingRng::GenerateByte</a>() 00078 { 00079 byte b; 00080 <a class="code" href="class_nonblocking_rng.html#_nonblocking_rnga3">GenerateBlock</a>(&b, 1); 00081 <span class="keywordflow">return</span> b; 00082 } 00083 <a name="l00084"></a><a class="code" href="class_nonblocking_rng.html#_nonblocking_rnga3">00084</a> <span class="keywordtype">void</span> <a class="code" href="class_nonblocking_rng.html#_nonblocking_rnga3">NonblockingRng::GenerateBlock</a>(byte *output, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> size) 00085 { 00086 <span class="preprocessor">#ifdef CRYPTOPP_WIN32_AVAILABLE</span> 00087 <span class="preprocessor"></span><span class="preprocessor"># ifdef WORKAROUND_MS_BUG_Q258000</span> 00088 <span class="preprocessor"></span> <span class="keyword">static</span> MicrosoftCryptoProvider m_Provider; 00089 <span class="preprocessor"># endif</span> 00090 <span class="preprocessor"></span> <span class="keywordflow">if</span> (!CryptGenRandom(m_Provider.GetProviderHandle(), size, output)) 00091 <span class="keywordflow">throw</span> <a class="code" href="class_o_s___r_n_g___err.html">OS_RNG_Err</a>(<span class="stringliteral">"CryptGenRandom"</span>); 00092 <span class="preprocessor">#else</span> 00093 <span class="preprocessor"></span> <span class="keywordflow">if</span> (read(m_fd, output, size) != size) 00094 <span class="keywordflow">throw</span> <a class="code" href="class_o_s___r_n_g___err.html">OS_RNG_Err</a>(<span class="stringliteral">"read /dev/urandom"</span>); 00095 <span class="preprocessor">#endif</span> 00096 <span class="preprocessor"></span>} 00097 00098 <span class="preprocessor">#endif</span> 00099 <span class="preprocessor"></span> 00100 <span class="comment">// *************************************************************</span> 00101 00102 <span class="preprocessor">#ifdef BLOCKING_RNG_AVAILABLE</span> 00103 <span class="preprocessor"></span> 00104 BlockingRng::BlockingRng() 00105 { 00106 m_fd = open(<span class="stringliteral">"/dev/random"</span>,O_RDONLY); 00107 <span class="keywordflow">if</span> (m_fd == -1) 00108 <span class="keywordflow">throw</span> <a class="code" href="class_o_s___r_n_g___err.html">OS_RNG_Err</a>(<span class="stringliteral">"open /dev/random"</span>); 00109 } 00110 00111 BlockingRng::~BlockingRng() 00112 { 00113 close(m_fd); 00114 } 00115 <a name="l00116"></a><a class="code" href="class_blocking_rng.html#_blocking_rnga2">00116</a> byte <a class="code" href="class_blocking_rng.html#_blocking_rnga2">BlockingRng::GenerateByte</a>() 00117 { 00118 byte b; 00119 <a class="code" href="class_blocking_rng.html#_blocking_rnga3">GenerateBlock</a>(&b, 1); 00120 <span class="keywordflow">return</span> b; 00121 } 00122 <a name="l00123"></a><a class="code" href="class_blocking_rng.html#_blocking_rnga3">00123</a> <span class="keywordtype">void</span> <a class="code" href="class_blocking_rng.html#_blocking_rnga3">BlockingRng::GenerateBlock</a>(byte *output, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> size) 00124 { 00125 <span class="keywordflow">while</span> (size) 00126 { 00127 <span class="comment">// on some systems /dev/random will block until all bytes</span> 00128 <span class="comment">// are available, on others it will returns immediately</span> 00129 <span class="keywordtype">int</span> len = read(m_fd, output, STDMIN(size, (<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>)INT_MAX)); 00130 <span class="keywordflow">if</span> (len == -1) 00131 <span class="keywordflow">throw</span> <a class="code" href="class_o_s___r_n_g___err.html">OS_RNG_Err</a>(<span class="stringliteral">"read /dev/random"</span>); 00132 size -= len; 00133 output += len; 00134 <span class="keywordflow">if</span> (size) 00135 sleep(1); 00136 } 00137 } 00138 00139 <span class="preprocessor">#endif</span> 00140 <span class="preprocessor"></span> 00141 <span class="comment">// *************************************************************</span> 00142 00143 <span class="keywordtype">void</span> OS_GenerateRandomBlock(<span class="keywordtype">bool</span> blocking, byte *output, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> size) 00144 { 00145 <span class="preprocessor">#ifdef NONBLOCKING_RNG_AVAILABLE</span> 00146 <span class="preprocessor"></span> <span class="keywordflow">if</span> (blocking) 00147 <span class="preprocessor">#endif</span> 00148 <span class="preprocessor"></span> { 00149 <span class="preprocessor">#ifdef BLOCKING_RNG_AVAILABLE</span> 00150 <span class="preprocessor"></span> <a class="code" href="class_blocking_rng.html">BlockingRng</a> rng; 00151 rng.<a class="code" href="class_blocking_rng.html#_blocking_rnga3">GenerateBlock</a>(output, size); 00152 <span class="preprocessor">#endif</span> 00153 <span class="preprocessor"></span> } 00154 00155 <span class="preprocessor">#ifdef BLOCKING_RNG_AVAILABLE</span> 00156 <span class="preprocessor"></span> <span class="keywordflow">if</span> (!blocking) 00157 <span class="preprocessor">#endif</span> 00158 <span class="preprocessor"></span> { 00159 <span class="preprocessor">#ifdef NONBLOCKING_RNG_AVAILABLE</span> 00160 <span class="preprocessor"></span> <a class="code" href="class_nonblocking_rng.html">NonblockingRng</a> rng; 00161 rng.<a class="code" href="class_nonblocking_rng.html#_nonblocking_rnga3">GenerateBlock</a>(output, size); 00162 <span class="preprocessor">#endif</span> 00163 <span class="preprocessor"></span> } 00164 } 00165 00166 <span class="keywordtype">void</span> AutoSeededRandomPool::Reseed(<span class="keywordtype">bool</span> blocking, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> seedSize) 00167 { 00168 <a class="code" href="class_sec_block.html">SecByteBlock</a> seed(seedSize); 00169 OS_GenerateRandomBlock(blocking, seed, seedSize); 00170 <a class="code" href="class_buffered_transformation.html#_zlib_decompressorz1_0">Put</a>(seed, seedSize); 00171 } 00172 00173 NAMESPACE_END 00174 00175 <span class="preprocessor">#endif</span> 00176 <span class="preprocessor"></span> 00177 <span class="preprocessor">#endif</span> </div></pre><hr size="1"><address style="align: right;"><small>Generated on Sun Nov 7 08:23:58 2004 for Crypto++ by <a href="http://www.doxygen.org/index.html"> <img src="doxygen.png" alt="doxygen" align="middle" border=0 ></a> 1.3.7 </small></address> </body> </html>