#ifndef FORTUNA_FORTUNA_H #define FORTUNA_FORTUNA_H #include "accumulator.h" #include "generator.h" #include "pool.h" #include #include #include #include #include #include #include #include #include #include #include namespace fortuna { class Fortuna final { public: static constexpr const char NUM_OF_POOLS{32}; static constexpr const uint64_t two_pow_twenty{1048576}; std::mutex mtx; std::mutex mtx_random_data; std::mutex mtx_p_pools; mutable std::mutex mtx_accu; // used in const fun, too std::mutex print_mtx; std::jthread th_sfm; std::jthread th_urandom; Fortuna(); ~Fortuna() noexcept; [[optimize_for_synchronized]] auto random_data(const uint64_t) -> void; [[optimize_for_synchronized]] auto moar_random_data(const uint64_t&) -> void; auto set_reseed_ctr_to_null() -> void { std::scoped_lock sl(mtx_accu, print_mtx); this->_p_accumulator->set_reseed_ctr_to_null(); fmt::print(stderr, "reseed_ctr set to 0x00\n"); } auto incr_reseed_ctr() -> void { std::scoped_lock sl(mtx, mtx_accu); this->_p_accumulator->incr_reseed_ctr(); } auto get_reseed_ctr() const -> uint64_t { std::lock_guard lg(mtx_accu); return this->_p_accumulator->get_reseed_ctr(); } auto initialize_prng() -> void { try { std::call_once(PRNG_init, [] { ; }); set_reseed_ctr_to_null(); std::scoped_lock sl(mtx_accu, mtx_p_pools); { std::lock_guard lg(print_mtx); R.initialize_pools(); fmt::print(stderr, "[i] fortuna: pools initialized\n"); } this->_p_accumulator->set_pools_ptr(R._p_pools); this->_p_accumulator->set_gen_ptr(R.Gen); this->sync_point.count_down(); } catch (std::exception& e) { std::lock_guard lg(print_mtx); fmt::print( stderr, "{}\n[!] fortuna: fatal error, PRNG initialization FAILED!\n\n", e.what()); throw; } std::lock_guard lg(print_mtx); fmt::print(stderr, "[*] fortuna: PRNG initialized\n"); } auto seed_file_manager_service() -> void; auto urandom_entropy_src_service() -> void; auto stop_running() -> int { try { fmt::print(stderr, "[i] fortuna: received the stop request...\n"); this->continue_running.store(false); } catch (std::exception& e) { throw; } return 0; } // PRNG state class R_state { friend fortuna::Fortuna; public: R_state() noexcept {} ~R_state() noexcept = default; protected: auto initialize_pools() -> void { unsigned int i{accumulator::Accumulator::init_pool_num}; assert(i == 0); for (; i < Fortuna::NUM_OF_POOLS; ++i) { this->_p_pools->at(i).initialize_pool(i); } } private: generator::Generator Gen; // _p_pools points to the array of 32 Pool objects std::shared_ptr> _p_pools{std::make_shared< std::array>()}; std::chrono::steady_clock::time_point last_reseed; }; // class R_state fortuna::Fortuna::R_state R; std::shared_ptr _p_accumulator{ std::make_shared()}; std::latch sync_point{1}; // wait for init before spawning the threads std::latch die_point{2}; // wait for service threads to die std::atomic continue_running{true}; std::once_flag PRNG_init; }; // class Fortuna } // namespace fortuna #endif // FORTUNA_FORTUNA_H