]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/random/src/random_device.cpp
1 /* boost random_device.cpp implementation
3 * Copyright Jens Maurer 2000
4 * Copyright Steven Watanabe 2010-2011
5 * Distributed under the Boost Software License, Version 1.0. (See
6 * accompanying file LICENSE_1_0.txt or copy at
7 * http://www.boost.org/LICENSE_1_0.txt)
13 #define BOOST_RANDOM_SOURCE
15 #include <boost/random/random_device.hpp>
16 #include <boost/config.hpp>
17 #include <boost/throw_exception.hpp>
18 #include <boost/assert.hpp>
19 #include <boost/detail/workaround.hpp>
20 #include <boost/system/system_error.hpp>
21 #include <boost/system/error_code.hpp>
24 #if !defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION) && !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
25 // A definition is required even for integral static constants
26 const bool boost::random::random_device::has_fixed_range
;
30 #if !defined(BOOST_RANDOM_WINDOWS_RUNTIME)
31 # if defined(__cplusplus_winrt)
32 # include <winapifamily.h>
33 # if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
34 # define BOOST_RANDOM_WINDOWS_RUNTIME 1
39 #if defined(BOOST_WINDOWS)
41 #if !defined(BOOST_RANDOM_WINDOWS_RUNTIME)
44 #include <stdexcept> // std::invalid_argument
46 using namespace Platform
;
47 using namespace Windows::Security::Cryptography
;
50 #define BOOST_AUTO_LINK_NOMANGLE
51 #define BOOST_LIB_NAME Advapi32
52 #include <boost/config/auto_link.hpp>
58 // mingw's wincrypt.h appears to be missing some things
76 #if !defined(BOOST_RANDOM_WINDOWS_RUNTIME)
77 const char * const default_token
= MS_DEF_PROV_A
;
79 const char * const default_token
= "";
83 class boost::random::random_device::impl
86 impl(const std::string
& token
) : provider(token
) {
87 #if !defined(BOOST_RANDOM_WINDOWS_RUNTIME)
92 // Find the type of a specific provider
93 for(DWORD i
= 0; ; ++i
) {
95 if(!CryptEnumProvidersA(i
, NULL
, 0, &type
, buffer
, &len
)) {
96 if (GetLastError() == ERROR_NO_MORE_ITEMS
) break;
99 if(buffer
== provider
) {
104 if(!CryptAcquireContextA(&hProv
, NULL
, provider
.c_str(), type
,
105 CRYPT_VERIFYCONTEXT
| CRYPT_SILENT
)) {
106 error("Could not acquire CSP context");
111 #if !defined(BOOST_RANDOM_WINDOWS_RUNTIME)
113 if(!CryptReleaseContext(hProv
, 0)) error("Could not release CSP context");
117 unsigned int next() {
120 #if !defined(BOOST_RANDOM_WINDOWS_RUNTIME)
121 if(!CryptGenRandom(hProv
, sizeof(result
),
122 static_cast<BYTE
*>(static_cast<void*>(&result
)))) {
123 error("error while reading");
126 auto buffer
= CryptographicBuffer::GenerateRandom(sizeof(result
));
127 auto data
= ref
new Array
<unsigned char>(buffer
->Length
);
128 CryptographicBuffer::CopyToByteArray(buffer
, &data
);
129 memcpy(&result
, data
->begin(), data
->end() - data
->begin());
136 #if !defined(BOOST_RANDOM_WINDOWS_RUNTIME)
137 void error(const char * msg
) {
138 DWORD error_code
= GetLastError();
139 boost::throw_exception(
140 boost::system::system_error(
141 error_code
, boost::system::system_category(),
142 std::string("boost::random_device: ") + msg
+
143 " Cryptographic Service Provider " + provider
));
147 const std::string provider
;
153 // the default is the unlimited capacity device, using some secure hash
154 // try "/dev/random" for blocking when the entropy pool has drained
155 const char * const default_token
= "/dev/urandom";
159 * This uses the POSIX interface for unbuffered reading.
160 * Using buffered std::istream would consume entropy which may
161 * not actually be used. Entropy is a precious good we avoid
165 #if defined(__GNUC__) && defined(_CXXRT_STD_NAME)
166 // I have severe difficulty to get the POSIX includes to work with
167 // -fhonor-std and Dietmar Kuhl's standard C++ library. Hack around that
170 static const int O_RDONLY
= 0;
171 extern int open(const char *__file
, int __oflag
, ...);
172 extern int read(int __fd
, __ptr_t __buf
, size_t __nbytes
);
173 extern int close(int __fd
);
176 #include <sys/types.h>
177 #include <sys/stat.h>
178 #include <fcntl.h> // open
179 #include <unistd.h> // read, close
182 #include <errno.h> // errno
183 #include <string.h> // strerror
184 #include <stdexcept> // std::invalid_argument
187 class boost::random::random_device::impl
190 impl(const std::string
& token
) : path(token
) {
191 fd
= open(token
.c_str(), O_RDONLY
);
193 error("cannot open");
196 ~impl() { if(close(fd
) < 0) error("could not close"); }
198 unsigned int next() {
200 std::size_t offset
= 0;
202 long sz
= read(fd
, reinterpret_cast<char *>(&result
) + offset
, sizeof(result
) - offset
);
204 error("error while reading");
207 error("EOF while reading");
210 } while(offset
< sizeof(result
));
215 void error(const char * msg
) {
216 int error_code
= errno
;
217 boost::throw_exception(
218 boost::system::system_error(
219 error_code
, boost::system::system_category(),
220 std::string("boost::random_device: ") + msg
+
221 " random-number pseudo-device " + path
));
223 const std::string path
;
227 #endif // BOOST_WINDOWS
229 BOOST_RANDOM_DECL
boost::random::random_device::random_device()
230 : pimpl(new impl(default_token
))
233 BOOST_RANDOM_DECL
boost::random::random_device::random_device(const std::string
& token
)
234 : pimpl(new impl(token
))
237 BOOST_RANDOM_DECL
boost::random_device::~random_device()
242 BOOST_RANDOM_DECL
double boost::random_device::entropy() const
247 BOOST_RANDOM_DECL
unsigned int boost::random_device::operator()()
249 return pimpl
->next();