random_provider_bcrypt.ipp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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. // http://www.boost.org/LICENCE_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. # define BOOST_AUTO_LINK_NOMANGLE
  21. # include <boost/config/auto_link.hpp>
  22. # undef BOOST_AUTO_LINK_NOMANGLE
  23. #endif
  24. namespace boost {
  25. namespace uuids {
  26. namespace detail {
  27. class random_provider_base
  28. {
  29. BOOST_MOVABLE_BUT_NOT_COPYABLE(random_provider_base)
  30. public:
  31. random_provider_base()
  32. : hProv_(NULL)
  33. {
  34. boost::winapi::NTSTATUS_ status =
  35. boost::winapi::BCryptOpenAlgorithmProvider(
  36. &hProv_,
  37. boost::winapi::BCRYPT_RNG_ALGORITHM_,
  38. NULL,
  39. 0);
  40. if (BOOST_UNLIKELY(status != 0))
  41. {
  42. BOOST_THROW_EXCEPTION(entropy_error(status, "BCryptOpenAlgorithmProvider"));
  43. }
  44. }
  45. random_provider_base(BOOST_RV_REF(random_provider_base) that) BOOST_NOEXCEPT : hProv_(that.hProv_)
  46. {
  47. that.hProv_ = NULL;
  48. }
  49. random_provider_base& operator= (BOOST_RV_REF(random_provider_base) that) BOOST_NOEXCEPT
  50. {
  51. destroy();
  52. hProv_ = that.hProv_;
  53. that.hProv_ = NULL;
  54. return *this;
  55. }
  56. ~random_provider_base() BOOST_NOEXCEPT
  57. {
  58. destroy();
  59. }
  60. //! Obtain entropy and place it into a memory location
  61. //! \param[in] buf the location to write entropy
  62. //! \param[in] siz the number of bytes to acquire
  63. void get_random_bytes(void *buf, std::size_t siz)
  64. {
  65. boost::winapi::NTSTATUS_ status =
  66. boost::winapi::BCryptGenRandom(
  67. hProv_,
  68. static_cast<boost::winapi::PUCHAR_>(buf),
  69. boost::numeric_cast<boost::winapi::ULONG_>(siz),
  70. 0);
  71. if (BOOST_UNLIKELY(status != 0))
  72. {
  73. BOOST_THROW_EXCEPTION(entropy_error(status, "BCryptGenRandom"));
  74. }
  75. }
  76. private:
  77. void destroy() BOOST_NOEXCEPT
  78. {
  79. if (hProv_)
  80. {
  81. boost::ignore_unused(boost::winapi::BCryptCloseAlgorithmProvider(hProv_, 0));
  82. }
  83. }
  84. private:
  85. boost::winapi::BCRYPT_ALG_HANDLE_ hProv_;
  86. };
  87. } // detail
  88. } // uuids
  89. } // boost