aboutsummaryrefslogtreecommitdiffstats
path: root/src/cli/entropy.cpp
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2019-08-27 10:05:49 -0400
committerJack Lloyd <[email protected]>2019-08-27 20:04:21 -0400
commitb4543c801cde2874b982bbaccba471bd14c27810 (patch)
treefd918d86ed4d114203a0c137abbbf19b66739052 /src/cli/entropy.cpp
parentecb22c16531db3023c739fa1436d8f3893fa1081 (diff)
Add a cmdlet which allows sampling/testing raw entropy sources
Diffstat (limited to 'src/cli/entropy.cpp')
-rw-r--r--src/cli/entropy.cpp104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/cli/entropy.cpp b/src/cli/entropy.cpp
new file mode 100644
index 000000000..0404afb99
--- /dev/null
+++ b/src/cli/entropy.cpp
@@ -0,0 +1,104 @@
+/*
+* (C) 2019 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "cli.h"
+#include "../tests/test_rng.h" // FIXME
+
+#include <botan/entropy_src.h>
+
+#if defined(BOTAN_HAS_COMPRESSION)
+#include <botan/compression.h>
+#endif
+
+namespace Botan_CLI {
+
+class Entropy final : public Command
+ {
+ public:
+ Entropy() : Command("entropy --truncate-at=128 source") {}
+
+ std::string group() const override
+ {
+ return "misc";
+ }
+
+ std::string description() const override
+ {
+ return "Sample a raw entropy source";
+ }
+
+ void go() override
+ {
+ const std::string req_source = get_arg("source");
+ const size_t truncate_sample = get_arg_sz("truncate-at");
+
+ auto& entropy_sources = Botan::Entropy_Sources::global_sources();
+
+ std::vector<std::string> sources;
+ if(req_source == "all")
+ sources = entropy_sources.enabled_sources();
+ else
+ sources.push_back(req_source);
+
+ for(std::string source : sources)
+ {
+ Botan_Tests::SeedCapturing_RNG rng;
+ const size_t entropy_estimate = entropy_sources.poll_just(rng, source);
+
+ if(rng.samples() == 0)
+ {
+ output() << "Source " << source << " is unavailable\n";
+ continue;
+ }
+
+ const auto& sample = rng.seed_material();
+
+ output() << "Polling " << source << " gathered " << sample.size()
+ << " bytes in " << rng.samples() << " outputs with estimated entropy "
+ << entropy_estimate << "\n";
+
+#if defined(BOTAN_HAS_COMPRESSION)
+ if(!sample.empty())
+ {
+ std::unique_ptr<Botan::Compression_Algorithm> comp(Botan::make_compressor("zlib"));
+ if(comp)
+ {
+ try
+ {
+ Botan::secure_vector<uint8_t> compressed;
+ compressed.assign(sample.begin(), sample.end());
+ comp->start(9);
+ comp->finish(compressed);
+
+ if(compressed.size() < sample.size())
+ {
+ output() << "Sample from " << source << " was zlib compressed from " << sample.size()
+ << " bytes to " << compressed.size() << " bytes\n";
+ }
+ }
+ catch(std::exception& e)
+ {
+ error_output() << "Error while attempting to compress: " << e.what() << "\n";
+ }
+ }
+ }
+#endif
+
+ if(sample.size() <= truncate_sample)
+ {
+ output() << Botan::hex_encode(sample) << "\n";
+ }
+ else if(truncate_sample > 0)
+ {
+ output() << Botan::hex_encode(&sample[0], truncate_sample) << "...\n";
+ }
+ }
+ }
+ };
+
+BOTAN_REGISTER_COMMAND("entropy", Entropy);
+
+}