diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2019-12-05 15:12:59 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2019-12-05 15:12:59 +0900 |
commit | b8cf34c691623e4ec329053cbbf68522a855882d (patch) | |
tree | 34da08632a99677f6b79ecb65e5b655a5b69a67f /boost/uuid | |
parent | 3fdc3e5ee96dca5b11d1694975a65200787eab86 (diff) | |
download | boost-b8cf34c691623e4ec329053cbbf68522a855882d.tar.gz boost-b8cf34c691623e4ec329053cbbf68522a855882d.tar.bz2 boost-b8cf34c691623e4ec329053cbbf68522a855882d.zip |
Imported Upstream version 1.67.0upstream/1.67.0
Diffstat (limited to 'boost/uuid')
-rw-r--r-- | boost/uuid/basic_name_generator.hpp | 2 | ||||
-rw-r--r-- | boost/uuid/detail/random_provider.hpp | 75 | ||||
-rw-r--r-- | boost/uuid/detail/random_provider_arc4random.ipp | 32 | ||||
-rw-r--r-- | boost/uuid/detail/random_provider_bcrypt.ipp | 79 | ||||
-rw-r--r-- | boost/uuid/detail/random_provider_detect_platform.hpp | 62 | ||||
-rw-r--r-- | boost/uuid/detail/random_provider_getentropy.ipp | 37 | ||||
-rw-r--r-- | boost/uuid/detail/random_provider_include_platform.hpp | 27 | ||||
-rw-r--r-- | boost/uuid/detail/random_provider_posix.ipp | 95 | ||||
-rw-r--r-- | boost/uuid/detail/random_provider_wincrypt.ipp | 82 | ||||
-rw-r--r-- | boost/uuid/detail/seed_rng.hpp | 320 | ||||
-rw-r--r-- | boost/uuid/entropy_error.hpp | 45 | ||||
-rw-r--r-- | boost/uuid/name_generator.hpp | 2 | ||||
-rw-r--r-- | boost/uuid/name_generator_md5.hpp | 2 | ||||
-rw-r--r-- | boost/uuid/name_generator_sha1.hpp | 2 | ||||
-rw-r--r-- | boost/uuid/random_generator.hpp | 105 | ||||
-rw-r--r-- | boost/uuid/seed_rng.hpp | 16 |
16 files changed, 621 insertions, 362 deletions
diff --git a/boost/uuid/basic_name_generator.hpp b/boost/uuid/basic_name_generator.hpp index c867fbd266..e82b5f92bb 100644 --- a/boost/uuid/basic_name_generator.hpp +++ b/boost/uuid/basic_name_generator.hpp @@ -1,7 +1,7 @@ // Boost basic_name_generator.hpp header file -----------------------// // Copyright 2010 Andy Tompkins. -// Copyright 2017 James E. King, III +// Copyright 2017 James E. King III // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/boost/uuid/detail/random_provider.hpp b/boost/uuid/detail/random_provider.hpp new file mode 100644 index 0000000000..03d8f26f95 --- /dev/null +++ b/boost/uuid/detail/random_provider.hpp @@ -0,0 +1,75 @@ +// +// Copyright (c) 2017 James E. King III +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENCE_1_0.txt) +// +// Platform-specific random entropy provider +// + +#ifndef BOOST_UUID_DETAIL_RANDOM_PROVIDER_HPP +#define BOOST_UUID_DETAIL_RANDOM_PROVIDER_HPP + +#include <boost/core/noncopyable.hpp> +#include <boost/cstdint.hpp> +#include <boost/limits.hpp> +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_integral.hpp> +#include <boost/type_traits/is_unsigned.hpp> +#include <boost/uuid/entropy_error.hpp> +#include <climits> +#include <iterator> + +// Detection of the platform is separated from inclusion of the correct +// header to facilitate mock testing of the provider implementations. + +#include <boost/uuid/detail/random_provider_detect_platform.hpp> +#include <boost/uuid/detail/random_provider_include_platform.hpp> + + +namespace boost { +namespace uuids { +namespace detail { + +//! \brief Contains code common to all random_provider implementations. +//! \note random_provider_base is required to provide this method: +//! void get_random_bytes(void *buf, size_t siz); +//! \note noncopyable because of some base implementations so +//! this makes it uniform across platforms to avoid any +//! porting surprises +class random_provider + : public detail::random_provider_base, + public noncopyable +{ +public: + //! Leverage the provider as a SeedSeq for + //! PseudoRandomNumberGeneration seeing. + //! \note: See Boost.Random documentation for more details + template<class Iter> + void generate(Iter first, Iter last) + { + typedef typename std::iterator_traits<Iter>::value_type value_type; + BOOST_STATIC_ASSERT(is_integral<value_type>::value); + BOOST_STATIC_ASSERT(is_unsigned<value_type>::value); + BOOST_STATIC_ASSERT(sizeof(value_type) * CHAR_BIT >= 32); + + for (; first != last; ++first) + { + get_random_bytes(&*first, sizeof(*first)); + *first &= (std::numeric_limits<boost::uint32_t>::max)(); + } + } + + //! Return the name of the selected provider + const char * name() const + { + return BOOST_UUID_RANDOM_PROVIDER_STRINGIFY(BOOST_UUID_RANDOM_PROVIDER_NAME); + } +}; + +} // detail +} // uuids +} // boost + +#endif // BOOST_UUID_DETAIL_RANDOM_PROVIDER_HPP diff --git a/boost/uuid/detail/random_provider_arc4random.ipp b/boost/uuid/detail/random_provider_arc4random.ipp new file mode 100644 index 0000000000..6facf28718 --- /dev/null +++ b/boost/uuid/detail/random_provider_arc4random.ipp @@ -0,0 +1,32 @@ +// +// Copyright (c) 2017 James E. King III +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENCE_1_0.txt) +// +// "A Replacement Call for Random" +// https://man.openbsd.org/arc4random.3 +// + +#include <stdlib.h> + +namespace boost { +namespace uuids { +namespace detail { + +class random_provider_base +{ + public: + //! Obtain entropy and place it into a memory location + //! \param[in] buf the location to write entropy + //! \param[in] siz the number of bytes to acquire + void get_random_bytes(void *buf, size_t siz) + { + arc4random_buf(buf, siz); + } +}; + +} // detail +} // uuids +} // boost diff --git a/boost/uuid/detail/random_provider_bcrypt.ipp b/boost/uuid/detail/random_provider_bcrypt.ipp new file mode 100644 index 0000000000..8fedf67b53 --- /dev/null +++ b/boost/uuid/detail/random_provider_bcrypt.ipp @@ -0,0 +1,79 @@ +// +// Copyright (c) 2017 James E. King III +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENCE_1_0.txt) +// +// BCrypt provider for entropy +// + +#include <boost/core/ignore_unused.hpp> +#include <boost/numeric/conversion/cast.hpp> +#include <boost/winapi/bcrypt.hpp> +#include <boost/winapi/get_last_error.hpp> +#include <boost/throw_exception.hpp> + +#if defined(BOOST_UUID_FORCE_AUTO_LINK) || (!defined(BOOST_ALL_NO_LIB) && !defined(BOOST_UUID_RANDOM_PROVIDER_NO_LIB)) +# define BOOST_LIB_NAME "bcrypt" +# define BOOST_AUTO_LINK_NOMANGLE +# include <boost/config/auto_link.hpp> +# undef BOOST_AUTO_LINK_NOMANGLE +#endif + +namespace boost { +namespace uuids { +namespace detail { + +class random_provider_base +{ + public: + random_provider_base() + : hProv_(NULL) + { + boost::winapi::NTSTATUS_ status = + boost::winapi::BCryptOpenAlgorithmProvider( + &hProv_, + boost::winapi::BCRYPT_RNG_ALGORITHM_, + NULL, + 0); + + if (status) + { + BOOST_THROW_EXCEPTION(entropy_error(status, "BCryptOpenAlgorithmProvider")); + } + } + + ~random_provider_base() BOOST_NOEXCEPT + { + if (hProv_) + { + ignore_unused(boost::winapi::BCryptCloseAlgorithmProvider(hProv_, 0)); + } + } + + //! Obtain entropy and place it into a memory location + //! \param[in] buf the location to write entropy + //! \param[in] siz the number of bytes to acquire + void get_random_bytes(void *buf, size_t siz) + { + boost::winapi::NTSTATUS_ status = + boost::winapi::BCryptGenRandom( + hProv_, + static_cast<boost::winapi::PUCHAR_>(buf), + boost::numeric_cast<boost::winapi::ULONG_>(siz), + 0); + + if (status) + { + BOOST_THROW_EXCEPTION(entropy_error(status, "BCryptGenRandom")); + } + } + + private: + boost::winapi::BCRYPT_ALG_HANDLE_ hProv_; +}; + +} // detail +} // uuids +} // boost diff --git a/boost/uuid/detail/random_provider_detect_platform.hpp b/boost/uuid/detail/random_provider_detect_platform.hpp new file mode 100644 index 0000000000..497d7f42c1 --- /dev/null +++ b/boost/uuid/detail/random_provider_detect_platform.hpp @@ -0,0 +1,62 @@ +// +// Copyright (c) 2017 James E. King III +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENCE_1_0.txt) +// +// Platform-specific random entropy provider platform detection +// + +#ifndef BOOST_UUID_DETAIL_RANDOM_PROVIDER_PLATFORM_DETECTION_HPP +#define BOOST_UUID_DETAIL_RANDOM_PROVIDER_PLATFORM_DETECTION_HPP + +#include <boost/predef/library/c/cloudabi.h> +#include <boost/predef/library/c/gnu.h> +#include <boost/predef/os/bsd/open.h> +#include <boost/predef/os/windows.h> + +// +// Platform Detection - will load in the correct header and +// will define the class <tt>random_provider_base</tt>. +// + +#if BOOST_OS_BSD_OPEN >= BOOST_VERSION_NUMBER(2, 1, 0) || BOOST_LIB_C_CLOUDABI +# define BOOST_UUID_RANDOM_PROVIDER_ARC4RANDOM +# define BOOST_UUID_RANDOM_PROVIDER_NAME arc4random + +#elif BOOST_OS_WINDOWS +# include <boost/winapi/config.hpp> +# if BOOST_WINAPI_PARTITION_APP_SYSTEM && \ + !defined(BOOST_UUID_RANDOM_PROVIDER_FORCE_WINCRYPT) && \ + !defined(_WIN32_WCE) && \ + (defined(BOOST_WINAPI_IS_MINGW_W64) || \ + (BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6)) +# define BOOST_UUID_RANDOM_PROVIDER_BCRYPT +# define BOOST_UUID_RANDOM_PROVIDER_NAME bcrypt + +# elif BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM +# define BOOST_UUID_RANDOM_PROVIDER_WINCRYPT +# define BOOST_UUID_RANDOM_PROVIDER_NAME wincrypt +# else +# error Unable to find a suitable windows entropy provider +# endif + +#elif BOOST_LIB_C_GNU >= BOOST_VERSION_NUMBER(2, 25, 0) && !defined(BOOST_UUID_RANDOM_PROVIDER_FORCE_POSIX) +# define BOOST_UUID_RANDOM_PROVIDER_GETENTROPY +# define BOOST_UUID_RANDOM_PROVIDER_NAME getentropy + +#else +# define BOOST_UUID_RANDOM_PROVIDER_POSIX +# define BOOST_UUID_RANDOM_PROVIDER_NAME posix + +#endif + +#define BOOST_UUID_RANDOM_PROVIDER_STRINGIFY2(X) #X +#define BOOST_UUID_RANDOM_PROVIDER_STRINGIFY(X) BOOST_UUID_RANDOM_PROVIDER_STRINGIFY2(X) + +#if defined(BOOST_UUID_RANDOM_PROVIDER_SHOW) +#pragma message("BOOST_UUID_RANDOM_PROVIDER_NAME " BOOST_UUID_RANDOM_PROVIDER_STRINGIFY(BOOST_UUID_RANDOM_PROVIDER_NAME)) +#endif + +#endif // BOOST_UUID_DETAIL_RANDOM_PROVIDER_PLATFORM_DETECTION_HPP diff --git a/boost/uuid/detail/random_provider_getentropy.ipp b/boost/uuid/detail/random_provider_getentropy.ipp new file mode 100644 index 0000000000..1379bf709c --- /dev/null +++ b/boost/uuid/detail/random_provider_getentropy.ipp @@ -0,0 +1,37 @@ +// +// Copyright (c) 2017 James E. King III +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENCE_1_0.txt) +// +// getentropy() capable platforms +// + +#include <boost/throw_exception.hpp> +#include <cerrno> +#include <unistd.h> + +namespace boost { +namespace uuids { +namespace detail { + +class random_provider_base +{ + public: + //! Obtain entropy and place it into a memory location + //! \param[in] buf the location to write entropy + //! \param[in] siz the number of bytes to acquire + void get_random_bytes(void *buf, size_t siz) + { + if (-1 == getentropy(buf, siz)) + { + int err = errno; + BOOST_THROW_EXCEPTION(entropy_error(err, "getentropy")); + } + } +}; + +} // detail +} // uuids +} // boost diff --git a/boost/uuid/detail/random_provider_include_platform.hpp b/boost/uuid/detail/random_provider_include_platform.hpp new file mode 100644 index 0000000000..7d14ec94c0 --- /dev/null +++ b/boost/uuid/detail/random_provider_include_platform.hpp @@ -0,0 +1,27 @@ +// +// Copyright (c) 2017 James E. King III +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENCE_1_0.txt) +// +// Platform-specific random entropy provider platform definition +// + +#ifndef BOOST_UUID_DETAIL_RANDOM_PROVIDER_PLATFORM_INCLUDE_HPP +#define BOOST_UUID_DETAIL_RANDOM_PROVIDER_PLATFORM_INCLUDE_HPP + +#if defined(BOOST_UUID_RANDOM_PROVIDER_ARC4RANDOM) +# include <boost/uuid/detail/random_provider_arc4random.ipp> +#elif defined(BOOST_UUID_RANDOM_PROVIDER_BCRYPT) +# include <boost/uuid/detail/random_provider_bcrypt.ipp> +#elif defined(BOOST_UUID_RANDOM_PROVIDER_GETENTROPY) +# include <boost/uuid/detail/random_provider_getentropy.ipp> +#elif defined(BOOST_UUID_RANDOM_PROVIDER_POSIX) +# include <boost/uuid/detail/random_provider_posix.ipp> +#elif defined(BOOST_UUID_RANDOM_PROVIDER_WINCRYPT) +# include <boost/uuid/detail/random_provider_wincrypt.ipp> +#endif + +#endif // BOOST_UUID_DETAIL_RANDOM_PROVIDER_PLATFORM_INCLUDE_HPP + diff --git a/boost/uuid/detail/random_provider_posix.ipp b/boost/uuid/detail/random_provider_posix.ipp new file mode 100644 index 0000000000..726661c89c --- /dev/null +++ b/boost/uuid/detail/random_provider_posix.ipp @@ -0,0 +1,95 @@ +/* boost uuid/detail/random_provider_posix implementation +* +* Copyright Jens Maurer 2000 +* Copyright 2007 Andy Tompkins. +* Copyright Steven Watanabe 2010-2011 +* Copyright 2017 James E. King III +* +* Distributed under the Boost Software License, Version 1.0. (See +* accompanying file LICENSE_1_0.txt or copy at +* http://www.boost.org/LICENSE_1_0.txt) +* +* $Id$ +*/ + +#include <boost/core/ignore_unused.hpp> +#include <boost/throw_exception.hpp> +#include <boost/uuid/entropy_error.hpp> +#include <cerrno> +#include <fcntl.h> // open +#include <sys/stat.h> +#include <sys/types.h> +#if defined(BOOST_HAS_UNISTD_H) +#include <unistd.h> +#endif + +#ifndef BOOST_UUID_RANDOM_PROVIDER_POSIX_IMPL_CLOSE +#define BOOST_UUID_RANDOM_PROVIDER_POSIX_IMPL_CLOSE ::close +#endif +#ifndef BOOST_UUID_RANDOM_PROVIDER_POSIX_IMPL_OPEN +#define BOOST_UUID_RANDOM_PROVIDER_POSIX_IMPL_OPEN ::open +#endif +#ifndef BOOST_UUID_RANDOM_PROVIDER_POSIX_IMPL_READ +#define BOOST_UUID_RANDOM_PROVIDER_POSIX_IMPL_READ ::read +#endif + +namespace boost { +namespace uuids { +namespace detail { + +class random_provider_base +{ + public: + random_provider_base() + : fd_(0) + { + int flags = O_RDONLY; +#if defined(O_CLOEXEC) + flags |= O_CLOEXEC; +#endif + fd_ = BOOST_UUID_RANDOM_PROVIDER_POSIX_IMPL_OPEN("/dev/urandom", flags); + + if (-1 == fd_) + { + int err = errno; + BOOST_THROW_EXCEPTION(entropy_error(err, "open /dev/urandom")); + } + } + + ~random_provider_base() BOOST_NOEXCEPT + { + if (fd_) + { + ignore_unused(BOOST_UUID_RANDOM_PROVIDER_POSIX_IMPL_CLOSE(fd_)); + } + } + + //! Obtain entropy and place it into a memory location + //! \param[in] buf the location to write entropy + //! \param[in] siz the number of bytes to acquire + void get_random_bytes(void *buf, size_t siz) + { + size_t offset = 0; + do + { + ssize_t sz = BOOST_UUID_RANDOM_PROVIDER_POSIX_IMPL_READ( + fd_, static_cast<char *>(buf) + offset, siz - offset); + + if (sz < 1) + { + int err = errno; + BOOST_THROW_EXCEPTION(entropy_error(err, "read")); + } + + offset += sz; + + } while (offset < siz); + } + + private: + int fd_; +}; + +} // detail +} // uuids +} // boost diff --git a/boost/uuid/detail/random_provider_wincrypt.ipp b/boost/uuid/detail/random_provider_wincrypt.ipp new file mode 100644 index 0000000000..806e1e0c8b --- /dev/null +++ b/boost/uuid/detail/random_provider_wincrypt.ipp @@ -0,0 +1,82 @@ +/* boost uuid/detail/random_provider_wincrypt implementation +* +* Copyright Jens Maurer 2000 +* Copyright 2007 Andy Tompkins. +* Copyright Steven Watanabe 2010-2011 +* Copyright 2017 James E. King III +* +* Distributed under the Boost Software License, Version 1.0. (See +* accompanying file LICENSE_1_0.txt or copy at +* http://www.boost.org/LICENSE_1_0.txt) +* +* $Id$ +*/ + +#include <boost/core/ignore_unused.hpp> +#include <boost/numeric/conversion/cast.hpp> +#include <boost/winapi/crypt.hpp> +#include <boost/winapi/get_last_error.hpp> +#include <boost/throw_exception.hpp> + +#if defined(BOOST_UUID_FORCE_AUTO_LINK) || (!defined(BOOST_ALL_NO_LIB) && !defined(BOOST_UUID_RANDOM_PROVIDER_NO_LIB)) +# if defined(_WIN32_WCE) +# define BOOST_LIB_NAME "coredll" +# else +# define BOOST_LIB_NAME "advapi32" +# endif +# define BOOST_AUTO_LINK_NOMANGLE +# include <boost/config/auto_link.hpp> +# undef BOOST_AUTO_LINK_NOMANGLE +#endif + +namespace boost { +namespace uuids { +namespace detail { + +class random_provider_base +{ + public: + random_provider_base() + : hProv_(NULL) + { + if (!boost::winapi::CryptAcquireContextW( + &hProv_, + NULL, + NULL, + boost::winapi::PROV_RSA_FULL_, + boost::winapi::CRYPT_VERIFYCONTEXT_ | boost::winapi::CRYPT_SILENT_)) + { + boost::winapi::DWORD_ err = boost::winapi::GetLastError(); + BOOST_THROW_EXCEPTION(entropy_error(err, "CryptAcquireContext")); + } + } + + ~random_provider_base() BOOST_NOEXCEPT + { + if (hProv_) + { + ignore_unused(boost::winapi::CryptReleaseContext(hProv_, 0)); + } + } + + //! Obtain entropy and place it into a memory location + //! \param[in] buf the location to write entropy + //! \param[in] siz the number of bytes to acquire + void get_random_bytes(void *buf, size_t siz) + { + if (!boost::winapi::CryptGenRandom(hProv_, + boost::numeric_cast<boost::winapi::DWORD_>(siz), + static_cast<boost::winapi::BYTE_ *>(buf))) + { + boost::winapi::DWORD_ err = boost::winapi::GetLastError(); + BOOST_THROW_EXCEPTION(entropy_error(err, "CryptGenRandom")); + } + } + + private: + boost::winapi::HCRYPTPROV_ hProv_; +}; + +} // detail +} // uuids +} // boost diff --git a/boost/uuid/detail/seed_rng.hpp b/boost/uuid/detail/seed_rng.hpp deleted file mode 100644 index 6b7f7808db..0000000000 --- a/boost/uuid/detail/seed_rng.hpp +++ /dev/null @@ -1,320 +0,0 @@ -// Boost seed_rng.hpp header file ----------------------------------------------// - -// Copyright 2007 Andy Tompkins. -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// Revision History -// 09 Nov 2007 - Initial Revision -// 25 Feb 2008 - moved to namespace boost::uuids::detail -// 28 Nov 2009 - disabled deprecated warnings for MSVC -// 28 Jul 2014 - fixed valgrind warnings and better entropy sources for MSVC - -// seed_rng models a UniformRandomNumberGenerator (see Boost.Random). -// Random number generators are hard to seed well. This is intended to provide -// good seed values for random number generators. -// It creates random numbers from a sha1 hash of data from a variary of sources, -// all of which are standard function calls. It produces random numbers slowly. -// Peter Dimov provided the details of sha1_random_digest_(). -// see http://archives.free.net.ph/message/20070507.175609.4c4f503a.en.html - -#ifndef BOOST_UUID_SEED_RNG_HPP -#define BOOST_UUID_SEED_RNG_HPP - -#include <boost/config.hpp> -#include <cstring> // for memcpy -#include <limits> -#include <ctime> // for time_t, time, clock_t, clock -#include <cstdlib> // for rand -#include <cstdio> // for FILE, fopen, fread, fclose -#include <boost/core/noncopyable.hpp> -#include <boost/uuid/detail/sha1.hpp> -//#include <boost/nondet_random.hpp> //forward declare boost::random::random_device - -// can't use boost::generator_iterator since boost::random number seed(Iter&, Iter) -// functions need a last iterator -//#include <boost/generator_iterator.hpp> -# include <boost/iterator/iterator_facade.hpp> - -#if defined(_MSC_VER) -# pragma warning(push) // Save warning settings. -# pragma warning(disable : 4996) // Disable deprecated std::fopen -#if defined(_WIN32_WCE) -# pragma comment(lib, "coredll.lib") -#else -# pragma comment(lib, "advapi32.lib") -#endif -#endif - -#if defined(BOOST_WINDOWS) -# include <boost/winapi/crypt.hpp> // for CryptAcquireContextA, CryptGenRandom, CryptReleaseContext -# include <boost/winapi/timers.hpp> -# include <boost/winapi/get_current_process_id.hpp> -# include <boost/winapi/get_current_thread_id.hpp> -#else -# include <sys/time.h> // for gettimeofday -# include <sys/types.h> // for pid_t -# include <unistd.h> // for getpid() -#endif - -#ifdef BOOST_NO_STDC_NAMESPACE -namespace std { - using ::memcpy; - using ::time_t; - using ::time; - using ::clock_t; - using ::clock; - using ::rand; - using ::FILE; - using ::fopen; - using ::fread; - using ::fclose; -} //namespace std -#endif - -// forward declare random number generators -namespace boost { namespace random { -class random_device; -}} //namespace boost::random - -namespace boost { -namespace uuids { -namespace detail { - -// should this be part of Boost.Random? -class seed_rng: private boost::noncopyable -{ -public: - typedef unsigned int result_type; - BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); - -public: - // note: rd_ intentionally left uninitialized - seed_rng() BOOST_NOEXCEPT - : rd_index_(5) - , random_(0) - { -#if defined(BOOST_WINDOWS) - if (!boost::winapi::CryptAcquireContextW( - &random_, - NULL, - NULL, - boost::winapi::PROV_RSA_FULL_, - boost::winapi::CRYPT_VERIFYCONTEXT_ | boost::winapi::CRYPT_SILENT_)) - { - random_ = 0; - } -#else - random_ = std::fopen( "/dev/urandom", "rb" ); -#endif - - std::memset(rd_, 0, sizeof(rd_)); - } - - ~seed_rng() BOOST_NOEXCEPT - { - if (random_) { -#if defined(BOOST_WINDOWS) - boost::winapi::CryptReleaseContext(random_, 0); -#else - std::fclose(random_); -#endif - } - } - - result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const BOOST_NOEXCEPT - { - return (std::numeric_limits<result_type>::min)(); - } - result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const BOOST_NOEXCEPT - { - return (std::numeric_limits<result_type>::max)(); - } - - result_type operator()() - { - if (rd_index_ >= 5) { - //get new digest - sha1_random_digest_(); - - rd_index_ = 0; - } - - return rd_[rd_index_++]; - } - -private: - BOOST_STATIC_CONSTANT(std::size_t, internal_state_size = 5); - inline void ignore_size(size_t) {} - - static unsigned int * sha1_random_digest_state_() - { - static unsigned int state[ internal_state_size ]; - return state; - } - - void sha1_random_digest_() - { - boost::uuids::detail::sha1 sha; - - - if (random_) - { - // intentionally left uninitialized - unsigned char state[ 20 ]; -#if defined(BOOST_WINDOWS) - boost::winapi::CryptGenRandom(random_, sizeof(state), state); -#else - ignore_size(std::fread( state, 1, sizeof(state), random_ )); -#endif - sha.process_bytes( state, sizeof( state ) ); - } - - { - // Getting enropy from some system specific sources -#if defined(BOOST_WINDOWS) - boost::winapi::DWORD_ procid = boost::winapi::GetCurrentProcessId(); - sha.process_bytes( (unsigned char const*)&procid, sizeof( procid ) ); - - boost::winapi::DWORD_ threadid = boost::winapi::GetCurrentThreadId(); - sha.process_bytes( (unsigned char const*)&threadid, sizeof( threadid ) ); - - boost::winapi::LARGE_INTEGER_ ts; - ts.QuadPart = 0; - boost::winapi::QueryPerformanceCounter( &ts ); - sha.process_bytes( (unsigned char const*)&ts, sizeof( ts ) ); - - std::time_t tm = std::time( 0 ); - sha.process_bytes( (unsigned char const*)&tm, sizeof( tm ) ); -#else - pid_t pid = getpid(); - sha.process_bytes( (unsigned char const*)&pid, sizeof( pid ) ); - - timeval ts; - gettimeofday(&ts, NULL); // We do not use `clock_gettime` to avoid linkage with -lrt - sha.process_bytes( (unsigned char const*)&ts, sizeof( ts ) ); -#endif - } - - - unsigned int * ps = sha1_random_digest_state_(); - sha.process_bytes( ps, internal_state_size * sizeof( unsigned int ) ); - sha.process_bytes( (unsigned char const*)&ps, sizeof( ps ) ); - - { - std::clock_t ck = std::clock(); - sha.process_bytes( (unsigned char const*)&ck, sizeof( ck ) ); - } - - { - unsigned int rn[] = - { static_cast<unsigned int>(std::rand()) - , static_cast<unsigned int>(std::rand()) - , static_cast<unsigned int>(std::rand()) - }; - sha.process_bytes( (unsigned char const*)rn, sizeof( rn ) ); - } - - { - unsigned int * p = new unsigned int; - sha.process_bytes( (unsigned char const*)&p, sizeof( p ) ); - delete p; - - const seed_rng* this_ptr = this; - sha.process_bytes( (unsigned char const*)&this_ptr, sizeof( this_ptr ) ); - } - - sha.process_bytes( (unsigned char const*)rd_, sizeof( rd_ ) ); - - unsigned int digest[ 5 ]; - sha.get_digest( digest ); - - for( int i = 0; i < 5; ++i ) - { - // harmless data race - ps[ i ] ^= digest[ i ]; - rd_[ i ] ^= digest[ i ]; - } - } - -private: - unsigned int rd_[5]; - int rd_index_; - -#if defined(BOOST_WINDOWS) - boost::winapi::HCRYPTPROV_ random_; -#else - std::FILE * random_; -#endif -}; - -// almost a copy of boost::generator_iterator -// but default constructor sets m_g to NULL -template <class Generator> -class generator_iterator - : public iterator_facade< - generator_iterator<Generator> - , typename Generator::result_type - , single_pass_traversal_tag - , typename Generator::result_type const& - > -{ - typedef iterator_facade< - generator_iterator<Generator> - , typename Generator::result_type - , single_pass_traversal_tag - , typename Generator::result_type const& - > super_t; - - public: - generator_iterator() : m_g(NULL), m_value(0) {} - generator_iterator(Generator* g) : m_g(g), m_value((*m_g)()) {} - - void increment() - { - m_value = (*m_g)(); - } - - const typename Generator::result_type& - dereference() const - { - return m_value; - } - - bool equal(generator_iterator const& y) const - { - return this->m_g == y.m_g && this->m_value == y.m_value; - } - - private: - Generator* m_g; - typename Generator::result_type m_value; -}; - -// seed() seeds a random number generator with good seed values - -template <typename UniformRandomNumberGenerator> -inline void seed(UniformRandomNumberGenerator& rng) -{ - seed_rng seed_gen; - generator_iterator<seed_rng> begin(&seed_gen); - generator_iterator<seed_rng> end; - rng.seed(begin, end); -} - -// random_device does not / can not be seeded -template <> -inline void seed<boost::random::random_device>(boost::random::random_device&) {} - -// random_device does not / can not be seeded -template <> -inline void seed<seed_rng>(seed_rng&) {} - -}}} //namespace boost::uuids::detail - -#if defined(_MSC_VER) -#pragma warning(pop) // Restore warnings to previous state. -#endif - -#endif diff --git a/boost/uuid/entropy_error.hpp b/boost/uuid/entropy_error.hpp new file mode 100644 index 0000000000..27f2936e5e --- /dev/null +++ b/boost/uuid/entropy_error.hpp @@ -0,0 +1,45 @@ +// +// Copyright (c) 2017 James E. King III +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENCE_1_0.txt) +// +// Entropy error class +// + +#ifndef BOOST_UUID_RANDOM_ENTROPY_ERROR_HPP +#define BOOST_UUID_RANDOM_ENTROPY_ERROR_HPP + +#include <boost/cstdint.hpp> +#include <stdexcept> +#include <string> + +namespace boost { +namespace uuids { + +//! \brief Given boost::system::system_error is in a module that +//! is not header-only, we define our own exception type +//! to handle entropy provider errors instead, +class entropy_error : public std::runtime_error +{ +public: + entropy_error(boost::intmax_t errCode, const std::string& message) + : std::runtime_error(message) + , m_errcode(errCode) + { + } + + virtual boost::intmax_t errcode() const + { + return m_errcode; + } + +private: + boost::intmax_t m_errcode; +}; + +} // uuids +} // boost + +#endif // BOOST_UUID_RANDOM_ENTROPY_ERROR_HPP diff --git a/boost/uuid/name_generator.hpp b/boost/uuid/name_generator.hpp index dbd1001b8c..ead8174d1c 100644 --- a/boost/uuid/name_generator.hpp +++ b/boost/uuid/name_generator.hpp @@ -1,7 +1,7 @@ // Boost name_generator.hpp header file -----------------------------// // Copyright 2010 Andy Tompkins. -// Copyright 2017 James E. King, III +// Copyright 2017 James E. King III // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/boost/uuid/name_generator_md5.hpp b/boost/uuid/name_generator_md5.hpp index f167584c41..7b13698df2 100644 --- a/boost/uuid/name_generator_md5.hpp +++ b/boost/uuid/name_generator_md5.hpp @@ -1,6 +1,6 @@ // Boost name_generator_md5.hpp header file ------------------------// -// Copyright 2017 James E. King, III +// Copyright 2017 James E. King III // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/boost/uuid/name_generator_sha1.hpp b/boost/uuid/name_generator_sha1.hpp index 849c75fd02..c34425f5b0 100644 --- a/boost/uuid/name_generator_sha1.hpp +++ b/boost/uuid/name_generator_sha1.hpp @@ -1,7 +1,7 @@ // Boost name_generator_sha1.hpp header file ------------------------// // Copyright 2010 Andy Tompkins. -// Copyright 2017 James E. King, III +// Copyright 2017 James E. King III // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/boost/uuid/random_generator.hpp b/boost/uuid/random_generator.hpp index a635ef03f7..c84fc5472c 100644 --- a/boost/uuid/random_generator.hpp +++ b/boost/uuid/random_generator.hpp @@ -1,6 +1,7 @@ // Boost random_generator.hpp header file ----------------------------------------------// // Copyright 2010 Andy Tompkins. +// Copyright 2017 James E. King III // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -8,20 +9,43 @@ #ifndef BOOST_UUID_RANDOM_GENERATOR_HPP #define BOOST_UUID_RANDOM_GENERATOR_HPP -#include <boost/uuid/uuid.hpp> -#include <boost/uuid/detail/seed_rng.hpp> +#include <boost/assert.hpp> +#include <boost/core/enable_if.hpp> +#include <boost/core/null_deleter.hpp> +#include <boost/random/mersenne_twister.hpp> #include <boost/random/uniform_int.hpp> #include <boost/random/variate_generator.hpp> -#include <boost/random/mersenne_twister.hpp> -#include <boost/core/null_deleter.hpp> -#include <boost/assert.hpp> #include <boost/shared_ptr.hpp> +#include <boost/tti/has_member_function.hpp> +#include <boost/uuid/detail/random_provider.hpp> +#include <boost/uuid/uuid.hpp> #include <limits> namespace boost { namespace uuids { -// generate a random-based uuid +namespace detail { + template<class U> + U& set_uuid_random_vv(U& u) + { + // set variant + // must be 0b10xxxxxx + *(u.begin() + 8) &= 0xBF; + *(u.begin() + 8) |= 0x80; + + // set version + // must be 0b0100xxxx + *(u.begin() + 6) &= 0x4F; //0b01001111 + *(u.begin() + 6) |= 0x40; //0b01000000 + + return u; + } + + BOOST_TTI_HAS_MEMBER_FUNCTION(seed) +} + +//! generate a random-based uuid +//! \param[in] UniformRandomNumberGenerator see Boost.Random documentation template <typename UniformRandomNumberGenerator> class basic_random_generator { private: @@ -31,7 +55,9 @@ private: public: typedef uuid result_type; - // default constructor creates the random number generator + // default constructor creates the random number generator and + // if the UniformRandomNumberGenerator is a PseudoRandomNumberGenerator + // then it gets seeded by a random_provider. basic_random_generator() : pURNG(new UniformRandomNumberGenerator) , generator @@ -42,8 +68,8 @@ public: ) ) { - // seed the random number generator - detail::seed(*pURNG); + // seed the random number generator if it is capable + seed(*pURNG); } // keep a reference to a random number generator @@ -74,9 +100,9 @@ public: BOOST_ASSERT(pURNG); } - uuid operator()() + result_type operator()() { - uuid u; + result_type u; int i=0; unsigned long random_value = generator(); @@ -90,26 +116,61 @@ public: *it = static_cast<uuid::value_type>((random_value >> (i*8)) & 0xFF); } - // set variant - // must be 0b10xxxxxx - *(u.begin()+8) &= 0xBF; - *(u.begin()+8) |= 0x80; + return detail::set_uuid_random_vv(u); + } - // set version - // must be 0b0100xxxx - *(u.begin()+6) &= 0x4F; //0b01001111 - *(u.begin()+6) |= 0x40; //0b01000000 +private: + // Detect whether UniformRandomNumberGenerator has a seed() method which indicates that + // it is a PseudoRandomNumberGenerator and needs a seed to initialize it. This allows + // basic_random_generator to take any type of UniformRandomNumberGenerator and still + // meet the post-conditions for the default constructor. + + template<class MaybePseudoRandomNumberGenerator> + typename boost::enable_if<detail::has_member_function_seed<MaybePseudoRandomNumberGenerator, void> >::type + seed(MaybePseudoRandomNumberGenerator& rng) + { + detail::random_provider seeder; + rng.seed(seeder); + } - return u; + template<class MaybePseudoRandomNumberGenerator> + typename boost::disable_if<detail::has_member_function_seed<MaybePseudoRandomNumberGenerator, void> >::type + seed(MaybePseudoRandomNumberGenerator&) + { } -private: shared_ptr<UniformRandomNumberGenerator> pURNG; generator_type generator; }; +//! \brief a far less complex random generator that uses +//! operating system provided entropy which will +//! satisfy the majority of use cases +class random_generator_pure +{ +public: + typedef uuid result_type; + + //! \returns a random, valid uuid + //! \throws entropy_error + result_type operator()() + { + result_type result; + prov_.get_random_bytes(&result, sizeof(result_type)); + return detail::set_uuid_random_vv(result); + } + +private: + detail::random_provider prov_; +}; + +#if defined(BOOST_UUID_RANDOM_GENERATOR_COMPAT) typedef basic_random_generator<mt19937> random_generator; +#else +typedef random_generator_pure random_generator; +typedef basic_random_generator<mt19937> random_generator_mt19937; +#endif }} // namespace boost::uuids -#endif //BOOST_UUID_RANDOM_GENERATOR_HPP +#endif // BOOST_UUID_RANDOM_GENERATOR_HPP diff --git a/boost/uuid/seed_rng.hpp b/boost/uuid/seed_rng.hpp deleted file mode 100644 index 5f603110cb..0000000000 --- a/boost/uuid/seed_rng.hpp +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - */ - -#ifndef BOOST_UUID_SEED_RNG_DEPRECATED_HPP -#define BOOST_UUID_SEED_RNG_DEPRECATED_HPP - -#include <boost/uuid/detail/seed_rng.hpp> - -#if defined(__GNUC__) || defined(_MSC_VER) -#pragma message("This header is implementation detail and provided for backwards compatibility.") -#endif - -#endif // BOOST_UUID_SEED_RNG_DEPRECATED_HPP |