random_provider_bcrypt.ipp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. //
  2. // Copyright (c) 2017 James E. King III
  3. //
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt or copy at
  6. // https://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // BCrypt provider for entropy
  9. //
  10. #include <cstddef>
  11. #include <boost/config.hpp>
  12. #include <boost/core/ignore_unused.hpp>
  13. #include <boost/move/core.hpp>
  14. #include <boost/numeric/conversion/cast.hpp>
  15. #include <boost/winapi/bcrypt.hpp>
  16. #include <boost/winapi/get_last_error.hpp>
  17. #include <boost/throw_exception.hpp>
  18. #if defined(BOOST_UUID_FORCE_AUTO_LINK) || (!defined(BOOST_ALL_NO_LIB) && !defined(BOOST_UUID_RANDOM_PROVIDER_NO_LIB))
  19. # define BOOST_LIB_NAME "bcrypt"
  20. # if defined(BOOST_AUTO_LINK_NOMANGLE)
  21. # include <boost/config/auto_link.hpp>
  22. # else
  23. # define BOOST_AUTO_LINK_NOMANGLE
  24. # include <boost/config/auto_link.hpp>
  25. # undef BOOST_AUTO_LINK_NOMANGLE
  26. # endif
  27. #endif
  28. namespace boost {
  29. namespace uuids {
  30. namespace detail {
  31. class random_provider_base
  32. {
  33. BOOST_MOVABLE_BUT_NOT_COPYABLE(random_provider_base)
  34. public:
  35. random_provider_base()
  36. : hProv_(NULL)
  37. {
  38. boost::winapi::NTSTATUS_ status =
  39. boost::winapi::BCryptOpenAlgorithmProvider(
  40. &hProv_,
  41. boost::winapi::BCRYPT_RNG_ALGORITHM_,
  42. NULL,
  43. 0);
  44. if (BOOST_UNLIKELY(status != 0))
  45. {
  46. BOOST_THROW_EXCEPTION(entropy_error(status, "BCryptOpenAlgorithmProvider"));
  47. }
  48. }
  49. random_provider_base(BOOST_RV_REF(random_provider_base) that) BOOST_NOEXCEPT : hProv_(that.hProv_)
  50. {
  51. that.hProv_ = NULL;
  52. }
  53. random_provider_base& operator= (BOOST_RV_REF(random_provider_base) that) BOOST_NOEXCEPT
  54. {
  55. destroy();
  56. hProv_ = that.hProv_;
  57. that.hProv_ = NULL;
  58. return *this;
  59. }
  60. ~random_provider_base() BOOST_NOEXCEPT
  61. {
  62. destroy();
  63. }
  64. //! Obtain entropy and place it into a memory location
  65. //! \param[in] buf the location to write entropy
  66. //! \param[in] siz the number of bytes to acquire
  67. void get_random_bytes(void *buf, std::size_t siz)
  68. {
  69. boost::winapi::NTSTATUS_ status =
  70. boost::winapi::BCryptGenRandom(
  71. hProv_,
  72. static_cast<boost::winapi::PUCHAR_>(buf),
  73. boost::numeric_cast<boost::winapi::ULONG_>(siz),
  74. 0);
  75. if (BOOST_UNLIKELY(status != 0))
  76. {
  77. BOOST_THROW_EXCEPTION(entropy_error(status, "BCryptGenRandom"));
  78. }
  79. }
  80. private:
  81. void destroy() BOOST_NOEXCEPT
  82. {
  83. if (hProv_)
  84. {
  85. boost::ignore_unused(boost::winapi::BCryptCloseAlgorithmProvider(hProv_, 0));
  86. }
  87. }
  88. private:
  89. boost::winapi::BCRYPT_ALG_HANDLE_ hProv_;
  90. };
  91. } // detail
  92. } // uuids
  93. } // boost