160 lines
4.0 KiB
C++
160 lines
4.0 KiB
C++
#ifndef FORTUNA_POOL_CPP
|
|
#define FORTUNA_POOL_CPP
|
|
|
|
#include "pool.h"
|
|
|
|
#include <fmt/core.h>
|
|
#include <fmt/ranges.h>
|
|
|
|
#include <atomic>
|
|
#include <climits>
|
|
#include <cstddef>
|
|
#include <mutex>
|
|
#include <stdexcept>
|
|
#include <utility>
|
|
|
|
namespace fortuna {
|
|
namespace accumulator {
|
|
|
|
auto Pool::set_id(const unsigned int& id) noexcept -> void {
|
|
std::lock_guard<std::mutex> lg(mtx);
|
|
this->pool_id = id;
|
|
}
|
|
|
|
auto Pool::get_id() const noexcept -> unsigned int {
|
|
return this->pool_id;
|
|
}
|
|
|
|
auto Pool::initialize_pool(const unsigned int& id) -> void {
|
|
// ref: https://stackoverflow.com/a/23204682
|
|
std::call_once(init, [this, id] { this->set_id(id); });
|
|
}
|
|
|
|
auto Pool::add_entropy(const unsigned int& source,
|
|
const std::vector<char>& event) -> int {
|
|
std::unique_lock<std::recursive_mutex> ul(ro_mtx_s);
|
|
const size_t event_size{sizeof(char) * event.size()};
|
|
const size_t max_event_size{32};
|
|
std::string event_str;
|
|
std::atomic<bool> all_ok{false};
|
|
|
|
fmt::print(stderr, "\tevent_size (bytes): {}\n", event_size);
|
|
try {
|
|
if (source > 255) {
|
|
throw std::invalid_argument(
|
|
"source number outside of interval <0,255>\n");
|
|
}
|
|
fmt::print(stderr, "\tsource_id: {}\n", source);
|
|
|
|
if (event_size < 1 || event_size > max_event_size) {
|
|
const std::string msg{
|
|
"[!] add_entropy: the length of the event needs to "
|
|
"be from the interval <1,32>"};
|
|
fmt::print(stderr,
|
|
"\tsource: {}\n{}\nevent size: {}\n\tpool_id: {}",
|
|
source,
|
|
msg,
|
|
event_size,
|
|
this->pool_id);
|
|
throw std::invalid_argument(msg);
|
|
}
|
|
else {
|
|
all_ok = true;
|
|
}
|
|
}
|
|
catch (const std::exception& e) {
|
|
fmt::print(stderr, "{}\n", e.what());
|
|
throw;
|
|
}
|
|
|
|
if (all_ok) {
|
|
try {
|
|
{
|
|
// FIXME: check for overflow - std::string size bounding?
|
|
// event_str.assign(event.begin(), event.end());
|
|
|
|
// as per Cryptography Engineering, p. 148 (180/385)
|
|
std::vector<char> fullevent{static_cast<char>(source)};
|
|
fullevent.push_back(static_cast<char>(event_size));
|
|
fullevent.insert(
|
|
std::end(fullevent), std::begin(event), std::end(event));
|
|
fmt::print(
|
|
stderr, "\t[i] add_entropy(fullevent): {}\n", fullevent);
|
|
|
|
// FIXME: check size for overflow
|
|
// also, atm this counts event size but actually what gets
|
|
// appended are digests of 64 characters (hex-encoded 32 bytes)
|
|
size += event_size;
|
|
|
|
{
|
|
const std::string digest(fortuna::Util::do_sha(fullevent));
|
|
|
|
fmt::print(
|
|
stderr, "\t[i] add_entropy(digest): {}\n", digest);
|
|
|
|
append_s(digest);
|
|
}
|
|
}
|
|
|
|
fmt::print(stderr,
|
|
"\t[i] s.length() (simple char count): {}\n"
|
|
"\t[i] get_s_byte_count() (byte count): {}\n"
|
|
"\t[i] pool_id: {}\n"
|
|
"\t[i] s: {}\n",
|
|
this->s.length(),
|
|
this->get_s_byte_count(),
|
|
this->pool_id,
|
|
// "");
|
|
this->s);
|
|
}
|
|
catch (const std::exception& e) {
|
|
fmt::print(stderr, "[!] pool(add_entropy): {}\n", e.what());
|
|
// FIXME: handle this (as all the other unhandled exceptions)
|
|
throw;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
else {
|
|
// everything not ok
|
|
return 1;
|
|
}
|
|
} // add_entropy
|
|
|
|
auto Pool::get_s_byte_count() const -> uint64_t {
|
|
// returns total byte count of (hex-encoded) entropy string contained in
|
|
// the pool. since the string is hex-encoded, we divide its char count by 2
|
|
// to get proper byte count. we need this since we actually don't care about
|
|
// the length of the hex string as it is, rather we care about what it came
|
|
// from (the raw entropy event)
|
|
|
|
std::lock_guard<std::recursive_mutex> lg(ro_mtx_s);
|
|
return this->s.length() / 2;
|
|
}
|
|
|
|
auto Pool::get_s() const -> std::string {
|
|
std::lock_guard<std::recursive_mutex> lg(ro_mtx_s);
|
|
return this->s;
|
|
}
|
|
|
|
auto Pool::clear_pool() -> void {
|
|
std::lock_guard<std::mutex> lg(mtx);
|
|
this->s.clear();
|
|
}
|
|
|
|
auto Pool::append_s(const std::string& entropy_s) -> void {
|
|
std::lock_guard<std::mutex> lg(mtx);
|
|
try {
|
|
this->s.append(entropy_s);
|
|
}
|
|
catch (const std::exception& e) {
|
|
fmt::print(stderr, "{}\n", e.what());
|
|
}
|
|
}
|
|
|
|
|
|
} // namespace accumulator
|
|
} // namespace fortuna
|
|
|
|
#endif // FORTUNA_POOL_CPP
|