#ifndef FORTUNA_POOL_CPP #define FORTUNA_POOL_CPP #include "pool.h" #include #include #include #include #include #include #include #include namespace fortuna { namespace accumulator { auto Pool::set_id(const unsigned int& id) noexcept -> void { std::lock_guard 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& event) -> int { std::unique_lock 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 all_ok{false}; fmt::print("\tevent_size (bytes): {}\n", event_size); try { if (source > 255) { throw std::invalid_argument( "source number outside of interval <0,255>\n"); } fmt::print("\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("\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("{}\n", e.what()); throw; } if (all_ok) { try { const std::string strsource{std::to_string(source)}; { // 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 fullevent{static_cast(source)}; fullevent.push_back(static_cast(event_size)); fullevent.insert( std::end(fullevent), std::begin(event), std::end(event)); fmt::print("\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("\t[i] add_entropy(digest): {}\n", digest); append_s(digest); } } fmt::print("\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("[!] 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 lg(ro_mtx_s); return this->s.length() / 2; } auto Pool::get_s() const -> std::string { std::lock_guard lg(ro_mtx_s); return this->s; } auto Pool::clear_pool() -> void { std::lock_guard lg(mtx); this->s.clear(); } auto Pool::append_s(const std::string& entropy_s) -> void { std::lock_guard lg(mtx); try { this->s.append(entropy_s); } catch (const std::exception& e) { fmt::print("{}\n", e.what()); } } } // namespace accumulator } // namespace fortuna #endif // FORTUNA_POOL_CPP