Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:33

0001 //
0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/beast
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 } // detail
0147 } // websocket
0148 } // beast
0149 } // boost
0150 
0151 #endif