File indexing completed on 2025-01-18 09:29:33
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_BEAST_WEBSOCKET_DETAIL_PRNG_IPP
0011 #define BOOST_BEAST_WEBSOCKET_DETAIL_PRNG_IPP
0012
0013 #include <boost/beast/websocket/detail/prng.hpp>
0014 #include <boost/beast/core/detail/chacha.hpp>
0015 #include <boost/beast/core/detail/pcg.hpp>
0016 #include <atomic>
0017 #include <cstdlib>
0018 #include <mutex>
0019 #include <random>
0020
0021 namespace boost {
0022 namespace beast {
0023 namespace websocket {
0024 namespace detail {
0025
0026
0027
0028 std::uint32_t const*
0029 prng_seed(std::seed_seq* ss)
0030 {
0031 struct data
0032 {
0033 std::uint32_t v[8];
0034
0035 explicit
0036 data(std::seed_seq* pss)
0037 {
0038 if(! pss)
0039 {
0040 std::random_device g;
0041 std::seed_seq ss{
0042 g(), g(), g(), g(),
0043 g(), g(), g(), g()};
0044 ss.generate(v, v+8);
0045 }
0046 else
0047 {
0048 pss->generate(v, v+8);
0049 }
0050 }
0051 };
0052 static data const d(ss);
0053 return d.v;
0054 }
0055
0056
0057
0058 inline
0059 std::uint32_t
0060 make_nonce()
0061 {
0062 static std::atomic<std::uint32_t> nonce{0};
0063 return ++nonce;
0064 }
0065
0066 inline
0067 beast::detail::pcg make_pcg()
0068 {
0069 auto const pv = prng_seed();
0070 return beast::detail::pcg{
0071 ((static_cast<std::uint64_t>(pv[0])<<32)+pv[1]) ^
0072 ((static_cast<std::uint64_t>(pv[2])<<32)+pv[3]) ^
0073 ((static_cast<std::uint64_t>(pv[4])<<32)+pv[5]) ^
0074 ((static_cast<std::uint64_t>(pv[6])<<32)+pv[7]), make_nonce()};
0075 }
0076
0077 #ifdef BOOST_NO_CXX11_THREAD_LOCAL
0078
0079 inline
0080 std::uint32_t
0081 secure_generate()
0082 {
0083 struct generator
0084 {
0085 std::uint32_t operator()()
0086 {
0087 std::lock_guard<std::mutex> guard{mtx};
0088 return gen();
0089 }
0090
0091 beast::detail::chacha<20> gen;
0092 std::mutex mtx;
0093 };
0094 static generator gen{beast::detail::chacha<20>{prng_seed(), make_nonce()}};
0095 return gen();
0096 }
0097
0098 inline
0099 std::uint32_t
0100 fast_generate()
0101 {
0102 struct generator
0103 {
0104 std::uint32_t operator()()
0105 {
0106 std::lock_guard<std::mutex> guard{mtx};
0107 return gen();
0108 }
0109
0110 beast::detail::pcg gen;
0111 std::mutex mtx;
0112 };
0113 static generator gen{make_pcg()};
0114 return gen();
0115 }
0116
0117 #else
0118
0119 inline
0120 std::uint32_t
0121 secure_generate()
0122 {
0123 thread_local static beast::detail::chacha<20> gen{prng_seed(), make_nonce()};
0124 return gen();
0125 }
0126
0127 inline
0128 std::uint32_t
0129 fast_generate()
0130 {
0131 thread_local static beast::detail::pcg gen{make_pcg()};
0132 return gen();
0133 }
0134
0135 #endif
0136
0137 generator
0138 make_prng(bool secure)
0139 {
0140 if (secure)
0141 return &secure_generate;
0142 else
0143 return &fast_generate;
0144 }
0145
0146 }
0147 }
0148 }
0149 }
0150
0151 #endif