]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/websocket/detail/prng.ipp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / beast / websocket / detail / prng.ipp
1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9
10 #ifndef BOOST_BEAST_WEBSOCKET_DETAIL_PRNG_IPP
11 #define BOOST_BEAST_WEBSOCKET_DETAIL_PRNG_IPP
12
13 #include <boost/beast/websocket/detail/prng.hpp>
14 #include <boost/beast/core/detail/chacha.hpp>
15 #include <boost/beast/core/detail/pcg.hpp>
16 #include <atomic>
17 #include <cstdlib>
18 #include <mutex>
19 #include <random>
20
21 namespace boost {
22 namespace beast {
23 namespace websocket {
24 namespace detail {
25
26 //------------------------------------------------------------------------------
27
28 std::uint32_t const*
29 prng_seed(std::seed_seq* ss)
30 {
31 struct data
32 {
33 std::uint32_t v[8];
34
35 explicit
36 data(std::seed_seq* pss)
37 {
38 if(! pss)
39 {
40 std::random_device g;
41 std::seed_seq ss{
42 g(), g(), g(), g(),
43 g(), g(), g(), g()};
44 ss.generate(v, v+8);
45 }
46 else
47 {
48 pss->generate(v, v+8);
49 }
50 }
51 };
52 static data const d(ss);
53 return d.v;
54 }
55
56 //------------------------------------------------------------------------------
57
58 inline
59 std::uint32_t
60 make_nonce()
61 {
62 static std::atomic<std::uint32_t> nonce{0};
63 return ++nonce;
64 }
65
66 inline
67 beast::detail::pcg make_pcg()
68 {
69 auto const pv = prng_seed();
70 return beast::detail::pcg{
71 ((static_cast<std::uint64_t>(pv[0])<<32)+pv[1]) ^
72 ((static_cast<std::uint64_t>(pv[2])<<32)+pv[3]) ^
73 ((static_cast<std::uint64_t>(pv[4])<<32)+pv[5]) ^
74 ((static_cast<std::uint64_t>(pv[6])<<32)+pv[7]), make_nonce()};
75 }
76
77 #ifdef BOOST_NO_CXX11_THREAD_LOCAL
78
79 inline
80 std::uint32_t
81 secure_generate()
82 {
83 struct generator
84 {
85 std::uint32_t operator()()
86 {
87 std::lock_guard<std::mutex> guard{mtx};
88 return gen();
89 }
90
91 beast::detail::chacha<20> gen;
92 std::mutex mtx;
93 };
94 static generator gen{beast::detail::chacha<20>{prng_seed(), make_nonce()}};
95 return gen();
96 }
97
98 inline
99 std::uint32_t
100 fast_generate()
101 {
102 struct generator
103 {
104 std::uint32_t operator()()
105 {
106 std::lock_guard<std::mutex> guard{mtx};
107 return gen();
108 }
109
110 beast::detail::pcg gen;
111 std::mutex mtx;
112 };
113 static generator gen{make_pcg()};
114 return gen();
115 }
116
117 #else
118
119 inline
120 std::uint32_t
121 secure_generate()
122 {
123 thread_local static beast::detail::chacha<20> gen{prng_seed(), make_nonce()};
124 return gen();
125 }
126
127 inline
128 std::uint32_t
129 fast_generate()
130 {
131 thread_local static beast::detail::pcg gen{make_pcg()};
132 return gen();
133 }
134
135 #endif
136
137 generator
138 make_prng(bool secure)
139 {
140 if (secure)
141 return &secure_generate;
142 else
143 return &fast_generate;
144 }
145
146 } // detail
147 } // websocket
148 } // beast
149 } // boost
150
151 #endif