#ifndef FORTUNA_FORTUNA_H #define FORTUNA_FORTUNA_H #include "accumulator.h" #include "generator.h" #include #include #include #include namespace fortuna { class Fortuna { public: // in microseconds static constexpr const unsigned int reseed_interval{10000}; static constexpr const char num_of_pools{32}; std::mutex mtx; std::mutex print_mtx; std::thread th_gen; std::thread th_accu; std::thread th_sfm; Fortuna(); ~Fortuna() noexcept; auto random_data(unsigned int) -> void; auto set_reseed_ctr_to_null() -> void { Fortuna::R.null_da_ctr(); } auto incr_reseed_ctr() -> void { ++Fortuna::R.reseed_ctr; } auto get_reseed_ctr() const -> uint64_t { return R.reseed_ctr; } auto initialize_prng() -> void { // TODO(me): handle the reseeds here as per Cryptography Engineering, // p. 153 std::lock_guard lg(mtx); set_reseed_ctr_to_null(); try { R.initialize_pools(); fmt::print("pools initialized\n"); accumulator.set_gen(R.Gen); // FIXME: bogus first reseed here, P_0 definitely hasn't collected // enough entropy by now incr_reseed_ctr(); fmt::print("first reseed\n"); R.Gen.reseed("fortuna"); } catch (std::exception& e) { fmt::print("{}\n", e.what()); } fmt::print("PRNG initialized\n"); } auto generator_service(fortuna::generator::Generator*) -> void; auto accumulator_service() -> void; auto seed_file_manager_service() -> void; // PRNG state class R_state { friend fortuna::Fortuna; public: R_state() {} ~R_state() = default; protected: auto null_da_ctr() -> void { reseed_ctr = 0x00; fmt::print("reseed_ctr set to 0x00\n"); } auto initialize_pools() -> void { for (unsigned int i = accumulator::Accumulator::init_pool_num; i < num_of_pools; ++i) { pools[i].initialize_pool(i); } } private: generator::Generator Gen; uint64_t reseed_ctr{0x00}; accumulator::Pool pools[num_of_pools]; std::chrono::steady_clock::time_point last_reseed; }; // class R_state fortuna::Fortuna::R_state R; fortuna::accumulator::Accumulator accumulator; }; // class Fortuna } // namespace fortuna #endif // FORTUNA_FORTUNA_H