This repository has been archived on 2022-02-10. You can view files and clone it, but cannot push or open issues or pull requests.
fortuna/fortuna.cpp

227 lines
6.1 KiB
C++
Raw Normal View History

#ifndef FORTUNA_FORTUNA_CPP
#define FORTUNA_FORTUNA_CPP
2021-11-10 23:55:58 +01:00
#include "fortuna.h"
#include "event_adder_impl.h"
#include "pool.h"
#include "seed_file_management.h"
#include "urandom_entropy_src.h"
#include "util.h"
2021-11-10 23:55:58 +01:00
#include <cryptopp/cryptlib.h>
#include <fmt/chrono.h>
#include <cassert>
#include <chrono>
#include <cstdint>
#include <exception>
#include <memory>
#include <mutex>
#include <thread>
2021-11-10 23:55:58 +01:00
namespace fortuna {
2022-01-04 06:57:36 +01:00
static constexpr const unsigned int min_pool_size{64};
auto now{std::chrono::steady_clock::now()};
2022-01-04 06:57:36 +01:00
Fortuna::Fortuna() {
try {
initialize_prng();
2022-01-21 06:27:06 +01:00
this->sync_point.wait(); // wait for init
th_sfm = std::jthread(&Fortuna::seed_file_manager_service, this);
th_urandom = std::jthread(&Fortuna::urandom_entropy_src_service, this);
2022-01-10 04:25:03 +01:00
}
catch (CryptoPP::Exception& e) {
2022-01-04 06:57:36 +01:00
fmt::print(stderr, "{}\n", e.what());
// perhaps die on error
2021-11-10 23:55:58 +01:00
}
2022-01-04 06:57:36 +01:00
}
Fortuna::~Fortuna() noexcept {
this->die_point.wait();
fmt::print("[*] Fortuna says goodbye!\n");
2022-01-04 06:57:36 +01:00
}
auto Fortuna::random_data(unsigned int n_bytes) -> void {
2022-01-20 07:55:21 +01:00
std::lock_guard<std::mutex> lg(mtx_random_data);
2022-01-04 06:57:36 +01:00
const auto start{std::chrono::system_clock::now()};
fmt::print("random_data starting - {}\n", start);
2022-01-10 04:25:03 +01:00
auto elapsed{std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch() -
now.time_since_epoch())};
2022-01-14 05:20:52 +01:00
fmt::print("[i] fortuna: last_reseed: {} ago\n", elapsed);
2022-01-04 06:57:36 +01:00
now = std::chrono::steady_clock::now();
2022-01-20 06:06:07 +01:00
try {
std::string s;
// synchronise reads and writes to the between
// {generator,accumulator,fortuna} service threads -> in member
// functions
const int pools_to_use{ffsll(static_cast<int>(get_reseed_ctr()))};
fmt::print("[*] fortuna: current p0 length: {}\n",
this->R._p_pools->at(0).get_s_byte_count());
if (R.Gen.time_to_reseed(R._p_pools->at(0).get_s_byte_count(),
min_pool_size,
elapsed,
R.Gen.reseed_interval)) {
// if (R.pools[0].get_s_byte_count() >= min_pool_size &&
// elapsed > R.Gen.reseed_interval) {
for (int i = 0; i < static_cast<int>(pools_to_use); ++i) {
if (this->get_reseed_ctr() %
2022-01-20 06:06:07 +01:00
static_cast<uint64_t>(pow(2, static_cast<double>(i))) ==
0) {
s.append(fortuna::Util::do_sha(
this->R._p_pools->at(static_cast<uint64_t>(i))
.get_s()));
this->R._p_pools->at(static_cast<uint64_t>(i)).clear_pool();
2022-01-10 04:25:03 +01:00
}
}
2022-01-20 06:06:07 +01:00
incr_reseed_ctr();
R.Gen.reseed(s);
R.last_reseed = std::chrono::steady_clock::now();
s.clear();
2022-01-03 07:49:53 +01:00
}
fmt::print("[i] fortuna: reseed ctr {}\n", get_reseed_ctr());
if (get_reseed_ctr() == 0) {
2022-01-20 06:06:07 +01:00
fmt::print("[!] ERROR: reseed ctr is 0, PRNG not seeded!\n");
throw std::runtime_error("illegal state, PRNG not seeded");
}
else {
const std::string n{R.Gen.generate_random_data(n_bytes)};
fmt::print(
"got you {} proper bytes from generate_random_data -> {}\n",
n_bytes,
n);
}
2022-01-10 04:25:03 +01:00
}
2022-01-20 06:06:07 +01:00
catch (std::exception& e) {
fmt::print("{}\n", e.what());
2022-01-03 07:49:53 +01:00
}
2022-01-04 06:57:36 +01:00
const auto end{std::chrono::system_clock::now()};
const std::chrono::duration<float> diff = end - start;
2022-01-04 06:57:36 +01:00
fmt::print("random_data done - {}\n", end);
fmt::print("getting random data took {:.{}f}s\n", diff.count(), 12);
2022-01-10 04:25:03 +01:00
} // random_data
2022-01-04 06:57:36 +01:00
2022-01-04 06:57:36 +01:00
auto Fortuna::seed_file_manager_service() -> void {
static constexpr const std::chrono::seconds checkup_interval{10};
{
std::lock_guard<std::mutex> p_ul(print_mtx);
fmt::print("[i] fortuna: starting seed file manager service\n");
fmt::print("[*] sfm: checkup interval {}\n", checkup_interval);
}
auto right_now{fortuna::Util::current_time()};
std::unique_lock<std::mutex> mtx_l(mtx);
2022-01-20 08:14:40 +01:00
std::unique_lock<std::mutex> a_ul(mtx_accu);
assert(this->_p_accumulator->_p_pools_equal(this->R._p_pools));
2022-01-20 08:14:40 +01:00
SeedFileManager sfm(this->_p_accumulator);
2022-01-20 08:14:40 +01:00
a_ul.unlock();
mtx_l.unlock();
2022-01-04 06:57:36 +01:00
2022-01-10 04:25:03 +01:00
while (true) {
right_now = fortuna::Util::current_time();
{
std::lock_guard<std::mutex> p_ul(print_mtx);
fmt::print("[*] sfm: checkup time @{}\n", right_now);
}
2022-01-10 04:25:03 +01:00
if (!sfm.is_job_running()) {
{
std::lock_guard<std::mutex> p_ul(print_mtx);
fmt::print("[*] sfm: job not running, starting\n");
}
try {
sfm.do_stuff();
2022-01-10 04:25:03 +01:00
}
catch (std::exception& e) {
{
std::lock_guard<std::mutex> p_ul(print_mtx);
fmt::print(
stderr, "[!] sfm: exception caught: {}\n", e.what());
}
}
2022-01-10 04:25:03 +01:00
}
else {
std::lock_guard<std::mutex> p_ul(print_mtx);
fmt::print("[*] sfm: job running\n");
}
std::this_thread::sleep_until(right_now +
2022-01-10 04:25:03 +01:00
std::chrono::seconds(checkup_interval));
}
std::lock_guard<std::mutex> p_ul(print_mtx);
fmt::print("[*] sfm: stopping, goodbye!\n\n");
this->die_point.count_down();
2022-01-04 06:57:36 +01:00
}
auto Fortuna::urandom_entropy_src_service() -> void {
static constexpr const std::chrono::milliseconds wakeup_interval{50};
{
std::lock_guard<std::mutex> p_ul(print_mtx);
fmt::print("[i] fortuna: starting urandom entropy src service\n");
fmt::print("[*] ues: wakeup interval {}\n", wakeup_interval);
}
auto right_now{fortuna::Util::current_time()};
std::unique_lock<std::mutex> mtx_l(mtx);
accumulator::UrandomEntropySrc ues;
static constexpr const uint8_t src_id{0};
accumulator::EventAdderImpl adder(src_id, this->R._p_pools);
mtx_l.unlock();
while (true) {
try {
std::lock_guard<std::mutex> p_ul(print_mtx);
fmt::print("[i] now: {}\n", fortuna::Util::current_time());
// check if ptr still valid
if (this->R._p_pools) {
// make sure they're pointing to the same chunk of data
// I know, debug-only
assert(this->_p_accumulator->_p_pools_equal(this->R._p_pools));
ues.event(adder);
}
}
catch (std::exception& e) {
{
std::lock_guard<std::mutex> p_ul(print_mtx);
fmt::print("[!] ues exception: {}\n", e.what());
}
}
right_now = fortuna::Util::current_time();
std::this_thread::sleep_until(
right_now + std::chrono::milliseconds(wakeup_interval));
mtx_l.lock();
{
std::lock_guard<std::mutex> p_ul(print_mtx);
fmt::print("[*] fortuna: current p0 length: {}\n\n",
this->R._p_pools->at(0).get_s_byte_count());
}
mtx_l.unlock();
}
std::lock_guard<std::mutex> p_ul(print_mtx);
fmt::print("[*] ues: stopping, goodbye!\n\n");
this->die_point.count_down();
}
2021-11-10 23:55:58 +01:00
} // namespace fortuna
2022-01-10 04:25:03 +01:00
#endif // FORTUNA_FORTUNA_CPP