Skip to content

Commit

Permalink
Let the entropy module be optional
Browse files Browse the repository at this point in the history
It was previously required by the rng module, but this isn't really
necessary, especially for anyone who is just using the system RNG.
(And/or NIST DRBGs seeded with the system RNG.)
  • Loading branch information
randombit committed Jan 11, 2025
1 parent 11f6f62 commit bfd8226
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 bfd8226

Please sign in to comment.