Skip to content

Commit

Permalink
Merge pull request #4525 from randombit/jack/entropy-is-optional
Browse files Browse the repository at this point in the history
Let the entropy module be optional
  • Loading branch information
randombit authored Jan 12, 2025
2 parents 11f6f62 + bfd8226 commit eefd608
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 28 deletions.
10 changes: 9 additions & 1 deletion src/cli/cli_rng.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
*/

#include "cli.h"
#include <botan/entropy_src.h>

#include <botan/hex.h>
#include <botan/rng.h>
#include <botan/internal/parsing.h>

#if defined(BOTAN_HAS_ENTROPY_SOURCE)
#include <botan/entropy_src.h>
#endif

#if defined(BOTAN_HAS_AUTO_SEEDING_RNG)
#include <botan/auto_rng.h>
#endif
Expand Down Expand Up @@ -56,7 +60,11 @@ std::shared_ptr<Botan::RandomNumberGenerator> cli_make_rng(const std::string& rn
std::shared_ptr<Botan::RandomNumberGenerator> rng;

if(rng_type == "entropy") {
#if defined(BOTAN_HAS_ENTROPY_SOURCE)
rng = std::make_shared<Botan::AutoSeeded_RNG>(Botan::Entropy_Sources::global_sources());
#else
throw CLI_Error_Unsupported("Entropy sources not included in this build");
#endif
} else {
rng = std::make_shared<Botan::AutoSeeded_RNG>();
}
Expand Down
12 changes: 9 additions & 3 deletions src/cli/entropy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@
#include "../tests/test_rng.h" // FIXME
#include "cli.h"

#include <botan/entropy_src.h>
#if defined(BOTAN_HAS_ENTROPY_SOURCE)
#include <botan/entropy_src.h>
#endif

#if defined(BOTAN_HAS_COMPRESSION)
#include <botan/compression.h>
#endif

namespace Botan_CLI {

#if defined(BOTAN_HAS_ENTROPY_SOURCE)

class Entropy final : public Command {
public:
Entropy() : Command("entropy --truncate-at=128 source") {}
Expand Down Expand Up @@ -50,7 +54,7 @@ class Entropy final : public Command {
output() << "Polling " << source << " gathered " << sample.size() << " bytes in " << rng.samples()
<< " outputs with estimated entropy " << entropy_estimate << "\n";

#if defined(BOTAN_HAS_COMPRESSION)
#if defined(BOTAN_HAS_COMPRESSION)
if(!sample.empty()) {
auto comp = Botan::Compression_Algorithm::create("zlib");
if(comp) {
Expand All @@ -69,7 +73,7 @@ class Entropy final : public Command {
}
}
}
#endif
#endif

if(sample.size() <= truncate_sample) {
output() << Botan::hex_encode(sample) << "\n";
Expand All @@ -82,4 +86,6 @@ class Entropy final : public Command {

BOTAN_REGISTER_COMMAND("entropy", Entropy);

#endif

} // namespace Botan_CLI
1 change: 0 additions & 1 deletion src/lib/prov/pkcs11/p11_randomgenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#ifndef BOTAN_P11_RNG_H_
#define BOTAN_P11_RNG_H_

#include <botan/entropy_src.h>
#include <botan/p11_types.h>
#include <botan/rng.h>

Expand Down
19 changes: 12 additions & 7 deletions src/lib/rng/auto_rng/auto_rng.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@

#include <botan/auto_rng.h>

#include <botan/entropy_src.h>
#include <botan/hmac_drbg.h>
#include <botan/internal/loadstor.h>

#include <array>
#if defined(BOTAN_HAS_ENTROPY_SOURCE)
#include <botan/entropy_src.h>
#endif

#if defined(BOTAN_HAS_SYSTEM_RNG)
#include <botan/system_rng.h>
Expand All @@ -27,7 +28,7 @@ std::unique_ptr<MessageAuthenticationCode> auto_rng_hmac() {
};

for(const auto& hmac : possible_auto_rng_hmacs) {
if(auto mac = MessageAuthenticationCode::create_or_throw(hmac)) {
if(auto mac = MessageAuthenticationCode::create(hmac)) {
return mac;
}
}
Expand Down Expand Up @@ -60,13 +61,17 @@ AutoSeeded_RNG::AutoSeeded_RNG(RandomNumberGenerator& underlying_rng,
force_reseed();
}

AutoSeeded_RNG::AutoSeeded_RNG(size_t reseed_interval) :
AutoSeeded_RNG::AutoSeeded_RNG(size_t reseed_interval) {
#if defined(BOTAN_HAS_SYSTEM_RNG)
AutoSeeded_RNG(system_rng(), reseed_interval)
m_rng = std::make_unique<HMAC_DRBG>(auto_rng_hmac(), system_rng(), reseed_interval);
#elif defined(BOTAN_HAS_ENTROPY_SOURCE)
m_rng = std::make_unique<HMAC_DRBG>(auto_rng_hmac(), Entropy_Sources::global_sources(), reseed_interval);
#else
AutoSeeded_RNG(Entropy_Sources::global_sources(), reseed_interval)
BOTAN_UNUSED(reseed_interval);
throw Not_Implemented("AutoSeeded_RNG default constructor not available due to no RNG or entropy sources");
#endif
{

force_reseed();
}

void AutoSeeded_RNG::force_reseed() {
Expand Down
4 changes: 0 additions & 4 deletions src/lib/rng/info.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
<requires>
entropy
</requires>

<module_info>
name -> "Random Number Generators"
brief -> "Implementations of Random Number Generators"
Expand Down
13 changes: 10 additions & 3 deletions src/lib/rng/rng.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@

#include <botan/rng.h>

#include <botan/entropy_src.h>
#include <botan/internal/loadstor.h>

#if defined(BOTAN_HAS_ENTROPY_SOURCE)
#include <botan/entropy_src.h>
#endif

#if defined(BOTAN_HAS_SYSTEM_RNG)
#include <botan/system_rng.h>
#endif
Expand Down Expand Up @@ -47,10 +50,14 @@ void RandomNumberGenerator::randomize_with_ts_input(std::span<uint8_t> output) {

size_t RandomNumberGenerator::reseed(Entropy_Sources& srcs, size_t poll_bits, std::chrono::milliseconds poll_timeout) {
if(this->accepts_input()) {
#if defined(BOTAN_HAS_ENTROPY_SOURCE)
return srcs.poll(*this, poll_bits, poll_timeout);
} else {
return 0;
#else
BOTAN_UNUSED(srcs, poll_bits, poll_timeout);
#endif
}

return 0;
}

void RandomNumberGenerator::reseed_from_rng(RandomNumberGenerator& rng, size_t poll_bits) {
Expand Down
13 changes: 10 additions & 3 deletions src/tests/test_entropy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@

#include "test_rng.h"
#include "tests.h"
#include <botan/entropy_src.h>

#if defined(BOTAN_HAS_ENTROPY_SOURCE)
#include <botan/entropy_src.h>
#endif

#if defined(BOTAN_HAS_COMPRESSION)
#include <botan/compression.h>
#endif

namespace Botan_Tests {

#if defined(BOTAN_HAS_ENTROPY_SOURCE)

namespace {

class Entropy_Source_Tests final : public Test {
Expand Down Expand Up @@ -44,7 +49,7 @@ class Entropy_Source_Tests final : public Test {

result.test_note("poll result", rng.seed_material());

#if defined(BOTAN_HAS_COMPRESSION)
#if defined(BOTAN_HAS_COMPRESSION)
if(!rng.seed_material().empty()) {
/*
* Skip bzip2 both due to OS X problem (GH #394) and because bzip2's
Expand Down Expand Up @@ -102,7 +107,7 @@ class Entropy_Source_Tests final : public Test {
}
}
}
#endif
#endif
} catch(std::exception& e) {
result.test_failure("during entropy collection test", e.what());
}
Expand All @@ -119,4 +124,6 @@ BOTAN_REGISTER_TEST("rng", "entropy", Entropy_Source_Tests);

} // namespace

#endif

} // namespace Botan_Tests
6 changes: 6 additions & 0 deletions src/tests/test_pkcs11_high_level.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
#include <botan/der_enc.h>
#endif

#if defined(BOTAN_HAS_ENTROPY_SOURCE)
#include <botan/entropy_src.h>
#endif

#if defined(BOTAN_HAS_PUBLIC_KEY_CRYPTO)
#include <botan/pubkey.h>
#endif
Expand Down Expand Up @@ -1404,9 +1408,11 @@ Test::Result test_rng_add_entropy() {
p11_rng.clear();
result.confirm("RNG ignores call to clear", p11_rng.is_seeded());

#if defined(BOTAN_HAS_ENTROPY_SOURCE)
result.test_eq("RNG ignores calls to reseed",
p11_rng.reseed(Botan::Entropy_Sources::global_sources(), 256, std::chrono::milliseconds(300)),
0);
#endif

auto rng = Test::new_rng(__func__);
auto random = rng->random_vec(20);
Expand Down
26 changes: 20 additions & 6 deletions src/tests/test_rng_behavior.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ class Stateful_RNG_Tests : public Test {
Test::Result test_broken_entropy_input() {
Test::Result result(rng_name() + " Broken Entropy Input");

#if defined(BOTAN_HAS_ENTROPY_SOURCE)
class Broken_Entropy_Source final : public Botan::Entropy_Source {
public:
std::string name() const override { return "Broken Entropy Source"; }
Expand All @@ -161,6 +162,7 @@ class Stateful_RNG_Tests : public Test {

size_t poll(Botan::RandomNumberGenerator& /*rng*/) override { return 0; }
};
#endif

// make sure no output is generated when the entropy input source is broken

Expand All @@ -171,6 +173,8 @@ class Stateful_RNG_Tests : public Test {

result.test_throws("broken underlying rng", [&rng_with_broken_rng]() { rng_with_broken_rng->random_vec(16); });

#if defined(BOTAN_HAS_ENTROPY_SOURCE)

// entropy_sources throw exception
auto broken_entropy_source_1 = std::make_unique<Broken_Entropy_Source>();
auto broken_entropy_source_2 = std::make_unique<Broken_Entropy_Source>();
Expand Down Expand Up @@ -209,6 +213,7 @@ class Stateful_RNG_Tests : public Test {
result.test_throws("underlying rng and entropy sources broken", [&rng_with_broken_rng_and_broken_es]() {
rng_with_broken_rng_and_broken_es->random_vec(16);
});
#endif

return result;
}
Expand Down Expand Up @@ -678,29 +683,32 @@ class AutoSeeded_RNG_Tests final : public Test {
static Test::Result auto_rng_tests() {
Test::Result result("AutoSeeded_RNG");

Botan::Entropy_Sources no_entropy_for_you;
Botan::Null_RNG null_rng;

result.test_eq("Null_RNG is null", null_rng.is_seeded(), false);

try {
Botan::AutoSeeded_RNG rng(no_entropy_for_you);
result.test_failure("AutoSeeded_RNG should have rejected useless entropy source");
Botan::AutoSeeded_RNG rng(null_rng);
} catch(Botan::PRNG_Unseeded&) {
result.test_success("AutoSeeded_RNG rejected empty entropy source");
result.test_success("AutoSeeded_RNG rejected useless RNG");
}

#if defined(BOTAN_HAS_ENTROPY_SOURCE)
Botan::Entropy_Sources no_entropy_for_you;

try {
Botan::AutoSeeded_RNG rng(null_rng);
Botan::AutoSeeded_RNG rng(no_entropy_for_you);
result.test_failure("AutoSeeded_RNG should have rejected useless entropy source");
} catch(Botan::PRNG_Unseeded&) {
result.test_success("AutoSeeded_RNG rejected useless RNG");
result.test_success("AutoSeeded_RNG rejected empty entropy source");
}

try {
Botan::AutoSeeded_RNG rng(null_rng, no_entropy_for_you);
} catch(Botan::PRNG_Unseeded&) {
result.test_success("AutoSeeded_RNG rejected useless RNG+entropy sources");
}
#endif

Botan::AutoSeeded_RNG rng;

Expand All @@ -720,9 +728,11 @@ class AutoSeeded_RNG_Tests final : public Test {
rng.clear();
result.test_eq("AutoSeeded_RNG unseeded after calling clear", rng.is_seeded(), false);

#if defined(BOTAN_HAS_ENTROPY_SOURCE)
const size_t no_entropy_bits = rng.reseed(no_entropy_for_you, 256, std::chrono::milliseconds(300));
result.test_eq("AutoSeeded_RNG can't reseed from nothing", no_entropy_bits, 0);
result.test_eq("AutoSeeded_RNG still unseeded", rng.is_seeded(), false);
#endif

rng.random_vec(16); // generate and discard output
result.confirm("AutoSeeded_RNG can be reseeded", rng.is_seeded());
Expand Down Expand Up @@ -767,7 +777,9 @@ class System_RNG_Tests final : public Test {
rng.clear(); // clear is a noop for system rng
result.confirm("System RNG always seeded", rng.is_seeded());

#if defined(BOTAN_HAS_ENTROPY_SOURCE)
rng.reseed(Botan::Entropy_Sources::global_sources(), 256, std::chrono::milliseconds(100));
#endif

for(size_t i = 0; i != 128; ++i) {
std::vector<uint8_t> out_buf(i);
Expand Down Expand Up @@ -813,8 +825,10 @@ class Processor_RNG_Tests final : public Test {
rng.clear(); // clear is a noop for rdrand
result.confirm("CPU RNG always seeded", rng.is_seeded());

#if defined(BOTAN_HAS_ENTROPY_SOURCE)
size_t reseed_bits = rng.reseed(Botan::Entropy_Sources::global_sources(), 256, std::chrono::seconds(1));
result.test_eq("CPU RNG cannot consume inputs", reseed_bits, size_t(0));
#endif

/*
Processor_RNG ignores add_entropy calls - confirm this by passing
Expand Down

0 comments on commit eefd608

Please sign in to comment.