fortuna: properly handle reseeds
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
* move reseed_ctr and related member functions to Accumulator * create a std::shared_ptr<Accumulator> to Fortuna's internal Accumulator object and feed that into SeedFileManager instead of a reference, which used to get copied to a new object in SeedFileManager * make Accumulator non-copyable, since it's only to be created once. instead, a shared_ptr is used to facilitate multiple-access * handle concurrency in Accumulator as the reseed_ctr-related functions can now be accessed from both Fortuna and SeedFileManager, declare mtx as mutable (since it's also used in a const function) * use std::scoped_lock in 'initialize_prng()' to safely lock both mutexes
This commit is contained in:
parent
760fd1bd9c
commit
52de785399
|
@ -28,6 +28,21 @@ Accumulator::Accumulator() noexcept {
|
|||
Accumulator::~Accumulator() noexcept {}
|
||||
|
||||
|
||||
auto Accumulator::set_reseed_ctr_to_null() -> void {
|
||||
std::lock_guard<std::mutex> lg(mtx);
|
||||
this->reseed_ctr = 0x00;
|
||||
}
|
||||
|
||||
auto Accumulator::incr_reseed_ctr() -> void {
|
||||
std::lock_guard<std::mutex> lg(mtx);
|
||||
{ ++this->reseed_ctr; }
|
||||
}
|
||||
|
||||
auto Accumulator::get_reseed_ctr() const -> uint64_t {
|
||||
std::lock_guard<std::mutex> lg(mtx);
|
||||
return this->reseed_ctr;
|
||||
}
|
||||
|
||||
auto Accumulator::_p_pools_equal(
|
||||
std::shared_ptr<std::array<accumulator::Pool, Accumulator::NUM_OF_POOLS>>
|
||||
p_pools) const -> bool {
|
||||
|
@ -84,6 +99,7 @@ auto Accumulator::get_random_data(const unsigned int& n_bytes) -> std::string {
|
|||
|
||||
auto Accumulator::call_reseed(const std::string& seed) -> void {
|
||||
try {
|
||||
incr_reseed_ctr();
|
||||
this->Gen->reseed(seed);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
namespace fortuna {
|
||||
|
@ -22,6 +23,9 @@ private:
|
|||
static constexpr const uint8_t MAX_SOURCES{255};
|
||||
static constexpr const uint8_t NUM_OF_POOLS{32};
|
||||
|
||||
mutable std::mutex mtx; // used in const fun
|
||||
uint64_t reseed_ctr{0x00};
|
||||
|
||||
std::vector<uint8_t> entropy_sources{};
|
||||
fortuna::generator::Generator* Gen;
|
||||
std::shared_ptr<std::array<accumulator::Pool, Accumulator::NUM_OF_POOLS>>
|
||||
|
@ -33,6 +37,12 @@ protected:
|
|||
public:
|
||||
constexpr static const unsigned int init_pool_num{0};
|
||||
|
||||
auto set_reseed_ctr_to_null() -> void;
|
||||
|
||||
auto incr_reseed_ctr() -> void;
|
||||
|
||||
auto get_reseed_ctr() const -> uint64_t;
|
||||
|
||||
auto _p_pools_equal(
|
||||
std::shared_ptr<std::array<accumulator::Pool,
|
||||
Accumulator::NUM_OF_POOLS>> p_pools) const
|
||||
|
@ -82,6 +92,9 @@ public:
|
|||
|
||||
Accumulator() noexcept;
|
||||
~Accumulator() noexcept;
|
||||
Accumulator(const Accumulator&) = delete; // no copy
|
||||
Accumulator(Accumulator&) = delete;
|
||||
Accumulator& operator=(const Accumulator&) = delete;
|
||||
|
||||
}; // class Accumulator
|
||||
|
||||
|
|
12
fortuna.cpp
12
fortuna.cpp
|
@ -86,7 +86,7 @@ auto Fortuna::random_data(unsigned int n_bytes) -> void {
|
|||
// 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->R.reseed_ctr %
|
||||
if (this->get_reseed_ctr() %
|
||||
static_cast<uint64_t>(pow(2, static_cast<double>(i))) ==
|
||||
0) {
|
||||
s.append(fortuna::Util::do_sha(
|
||||
|
@ -101,8 +101,8 @@ auto Fortuna::random_data(unsigned int n_bytes) -> void {
|
|||
s.clear();
|
||||
}
|
||||
|
||||
fmt::print("[i] fortuna: reseed ctr {}\n", R.reseed_ctr);
|
||||
if (R.reseed_ctr == 0) {
|
||||
fmt::print("[i] fortuna: reseed ctr {}\n", get_reseed_ctr());
|
||||
if (get_reseed_ctr() == 0) {
|
||||
fmt::print("[!] ERROR: reseed ctr is 0, PRNG not seeded!\n");
|
||||
throw std::runtime_error("illegal state, PRNG not seeded");
|
||||
}
|
||||
|
@ -179,9 +179,9 @@ auto Fortuna::seed_file_manager_service() -> void {
|
|||
std::unique_lock<std::mutex> mtx_l(mtx);
|
||||
std::unique_lock<std::mutex> a_ul(mtx_accu);
|
||||
|
||||
assert(this->accumulator._p_pools_equal(this->R._p_pools));
|
||||
assert(this->_p_accumulator->_p_pools_equal(this->R._p_pools));
|
||||
|
||||
SeedFileManager sfm(this->accumulator);
|
||||
SeedFileManager sfm(this->_p_accumulator);
|
||||
|
||||
a_ul.unlock();
|
||||
mtx_l.unlock();
|
||||
|
@ -244,7 +244,7 @@ auto Fortuna::urandom_entropy_src_service() -> void {
|
|||
if (this->R._p_pools) {
|
||||
// make sure they're pointing to the same chunk of data
|
||||
// I know, debug-only
|
||||
assert(this->accumulator._p_pools_equal(this->R._p_pools));
|
||||
assert(this->_p_accumulator->_p_pools_equal(this->R._p_pools));
|
||||
|
||||
ues.event(adder);
|
||||
}
|
||||
|
|
61
fortuna.h
61
fortuna.h
|
@ -22,7 +22,7 @@ public:
|
|||
std::mutex mtx;
|
||||
std::mutex mtx_random_data;
|
||||
std::mutex mtx_p_pools;
|
||||
std::mutex mtx_accu;
|
||||
mutable std::mutex mtx_accu; // used in const fun, too
|
||||
std::mutex print_mtx;
|
||||
std::thread th_gen;
|
||||
std::thread th_accu;
|
||||
|
@ -36,53 +36,47 @@ public:
|
|||
[[optimize_for_synchronized]] auto random_data(unsigned int) -> void;
|
||||
|
||||
auto set_reseed_ctr_to_null() -> void {
|
||||
std::lock_guard<std::mutex> lg(mtx);
|
||||
Fortuna::R.null_da_ctr();
|
||||
std::scoped_lock sl(mtx_accu, print_mtx);
|
||||
this->_p_accumulator->set_reseed_ctr_to_null();
|
||||
fmt::print("reseed_ctr set to 0x00\n");
|
||||
}
|
||||
|
||||
auto incr_reseed_ctr() -> void {
|
||||
std::lock_guard<std::mutex> lg(mtx);
|
||||
++Fortuna::R.reseed_ctr;
|
||||
std::scoped_lock sl(mtx, mtx_accu);
|
||||
this->_p_accumulator->incr_reseed_ctr();
|
||||
}
|
||||
|
||||
auto get_reseed_ctr() const -> uint64_t {
|
||||
return R.reseed_ctr;
|
||||
std::lock_guard<std::mutex> lg(mtx_accu);
|
||||
return this->_p_accumulator->get_reseed_ctr();
|
||||
}
|
||||
|
||||
auto initialize_prng() -> void {
|
||||
// TODO(me): handle the reseeds here as per Cryptography Engineering,
|
||||
// p. 153
|
||||
set_reseed_ctr_to_null();
|
||||
std::unique_lock<std::mutex> p_ul(print_mtx);
|
||||
|
||||
std::scoped_lock sl(mtx_accu, mtx_p_pools);
|
||||
try {
|
||||
R.initialize_pools();
|
||||
fmt::print("[i] fortuna: pools initialized\n");
|
||||
p_ul.unlock();
|
||||
accumulator.set_pools_ptr(R._p_pools);
|
||||
accumulator.set_gen(R.Gen);
|
||||
set_reseed_ctr_to_null();
|
||||
|
||||
// FIXME: bogus first reseed here, P_0 definitely hasn't collected
|
||||
// enough entropy by now
|
||||
incr_reseed_ctr();
|
||||
std::scoped_lock sl(mtx_accu, mtx_p_pools);
|
||||
|
||||
p_ul.lock();
|
||||
fmt::print("first reseed\n");
|
||||
p_ul.unlock();
|
||||
{
|
||||
std::lock_guard<std::mutex> lg(print_mtx);
|
||||
|
||||
std::unique_lock<std::mutex> ul(mtx);
|
||||
R.Gen.reseed("fortuna");
|
||||
ul.unlock();
|
||||
R.initialize_pools();
|
||||
fmt::print("[i] fortuna: pools initialized\n");
|
||||
}
|
||||
|
||||
this->_p_accumulator->set_pools_ptr(R._p_pools);
|
||||
this->_p_accumulator->set_gen(R.Gen);
|
||||
|
||||
this->sync_point.count_down();
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
p_ul.try_lock();
|
||||
std::lock_guard<std::mutex> lg(print_mtx);
|
||||
fmt::print(
|
||||
"{}\n[!] fortuna: fatal error, PRNG initialization FAILED!\n\n",
|
||||
e.what());
|
||||
}
|
||||
p_ul.try_lock();
|
||||
this->sync_point.count_down();
|
||||
|
||||
std::lock_guard<std::mutex> lg(print_mtx);
|
||||
fmt::print("[*] fortuna: PRNG initialized\n");
|
||||
}
|
||||
|
||||
|
@ -104,11 +98,6 @@ public:
|
|||
~R_state() noexcept = 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 < Fortuna::NUM_OF_POOLS;
|
||||
|
@ -119,7 +108,6 @@ public:
|
|||
|
||||
private:
|
||||
generator::Generator Gen;
|
||||
uint64_t reseed_ctr{0x00};
|
||||
|
||||
// da_pools is to be used solely for creating a shared_ptr of the
|
||||
// object: _p_pools. any further access to the structure should be
|
||||
|
@ -136,7 +124,8 @@ public:
|
|||
}; // class R_state
|
||||
|
||||
fortuna::Fortuna::R_state R;
|
||||
fortuna::accumulator::Accumulator accumulator;
|
||||
std::shared_ptr<accumulator::Accumulator> _p_accumulator{
|
||||
std::make_shared<accumulator::Accumulator>()};
|
||||
|
||||
}; // class Fortuna
|
||||
|
||||
|
|
|
@ -21,8 +21,9 @@
|
|||
namespace fortuna {
|
||||
|
||||
SeedFileManager::SeedFileManager(
|
||||
const fortuna::accumulator::Accumulator& da_accumulator) noexcept {
|
||||
this->accumulator = da_accumulator;
|
||||
std::shared_ptr<fortuna::accumulator::Accumulator>
|
||||
da_accumulator) noexcept {
|
||||
this->_p_accumulator = da_accumulator;
|
||||
}
|
||||
SeedFileManager::~SeedFileManager() noexcept {
|
||||
set_job_running(false); // RIP, well, yeah, not running when the obj dies
|
||||
|
@ -108,7 +109,7 @@ auto SeedFileManager::update_seed_file() -> void {
|
|||
buff.SizeInBytes() *
|
||||
8); // we need the size in bits
|
||||
|
||||
accumulator.call_reseed(str_buff);
|
||||
this->_p_accumulator->call_reseed(str_buff);
|
||||
write_seed_file();
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
|
@ -123,7 +124,7 @@ auto SeedFileManager::write_seed_file() -> void {
|
|||
|
||||
fortuna::SeedFileManager::IS_RUNNING = true;
|
||||
CryptoPP::SecByteBlock buff{config.seed_f_length};
|
||||
const std::string da_buff{accumulator.get_random_data(
|
||||
const std::string da_buff{this->_p_accumulator->get_random_data(
|
||||
static_cast<unsigned int>(config.seed_f_length))};
|
||||
|
||||
assert(da_buff.length() % 2 == 0);
|
||||
|
|
|
@ -26,8 +26,8 @@ public:
|
|||
auto is_job_running() const -> bool;
|
||||
auto do_stuff() -> void;
|
||||
|
||||
explicit SeedFileManager(
|
||||
const fortuna::accumulator::Accumulator& accumulator) noexcept;
|
||||
explicit SeedFileManager(std::shared_ptr<fortuna::accumulator::Accumulator>
|
||||
accumulator) noexcept;
|
||||
~SeedFileManager() noexcept;
|
||||
|
||||
protected:
|
||||
|
@ -38,7 +38,7 @@ private:
|
|||
mutable std::recursive_mutex mtx;
|
||||
std::atomic<bool> IS_RUNNING{false};
|
||||
DoTask do_task;
|
||||
fortuna::accumulator::Accumulator accumulator;
|
||||
std::shared_ptr<fortuna::accumulator::Accumulator> _p_accumulator;
|
||||
|
||||
auto seed_file_exists() const -> bool;
|
||||
auto write_seed_file() -> void;
|
||||
|
|
Reference in New Issue