diff options
Diffstat (limited to 'comm/third_party/botan/src/cli/cli_rng.cpp')
-rw-r--r-- | comm/third_party/botan/src/cli/cli_rng.cpp | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/cli/cli_rng.cpp b/comm/third_party/botan/src/cli/cli_rng.cpp new file mode 100644 index 0000000000..e3eee0c035 --- /dev/null +++ b/comm/third_party/botan/src/cli/cli_rng.cpp @@ -0,0 +1,146 @@ +/* +* (C) 2015,2017 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "cli.h" +#include <botan/rng.h> +#include <botan/entropy_src.h> +#include <botan/hex.h> +#include <botan/parsing.h> + +#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) + #include <botan/auto_rng.h> +#endif + +#if defined(BOTAN_HAS_SYSTEM_RNG) + #include <botan/system_rng.h> +#endif + +#if defined(BOTAN_HAS_PROCESSOR_RNG) + #include <botan/processor_rng.h> +#endif + +#if defined(BOTAN_HAS_HMAC_DRBG) + #include <botan/hmac_drbg.h> +#endif + +namespace Botan_CLI { + +std::unique_ptr<Botan::RandomNumberGenerator> +cli_make_rng(const std::string& rng_type, const std::string& hex_drbg_seed) + { +#if defined(BOTAN_HAS_SYSTEM_RNG) + if(rng_type == "system" || rng_type.empty()) + { + return std::unique_ptr<Botan::RandomNumberGenerator>(new Botan::System_RNG); + } +#endif + + const std::vector<uint8_t> drbg_seed = Botan::hex_decode(hex_drbg_seed); + +#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) + if(rng_type == "auto" || rng_type == "entropy" || rng_type.empty()) + { + std::unique_ptr<Botan::RandomNumberGenerator> rng; + + if(rng_type == "entropy") + rng.reset(new Botan::AutoSeeded_RNG(Botan::Entropy_Sources::global_sources())); + else + rng.reset(new Botan::AutoSeeded_RNG); + + if(drbg_seed.size() > 0) + rng->add_entropy(drbg_seed.data(), drbg_seed.size()); + return rng; + } +#endif + +#if defined(BOTAN_HAS_HMAC_DRBG) && defined(BOTAN_HAS_SHA2_32) + if(rng_type == "drbg" || (rng_type.empty() && drbg_seed.empty() == false)) + { + std::unique_ptr<Botan::MessageAuthenticationCode> mac = + Botan::MessageAuthenticationCode::create_or_throw("HMAC(SHA-256)"); + std::unique_ptr<Botan::Stateful_RNG> rng(new Botan::HMAC_DRBG(std::move(mac))); + rng->add_entropy(drbg_seed.data(), drbg_seed.size()); + + if(rng->is_seeded() == false) + throw CLI_Error("For " + rng->name() + " a seed of at least " + + std::to_string(rng->security_level()/8) + + " bytes must be provided"); + + return std::unique_ptr<Botan::RandomNumberGenerator>(rng.release()); + } +#endif + +#if defined(BOTAN_HAS_PROCESSOR_RNG) + if(rng_type == "rdrand" || rng_type == "cpu" || rng_type.empty()) + { + if(Botan::Processor_RNG::available()) + return std::unique_ptr<Botan::RandomNumberGenerator>(new Botan::Processor_RNG); + else if(rng_type.empty() == false) + throw CLI_Error("RNG instruction not supported on this processor"); + } +#endif + + if(rng_type.empty()) + throw CLI_Error_Unsupported("No random number generator seems to be available in the current build"); + else + throw CLI_Error_Unsupported("RNG", rng_type); + } + +class RNG final : public Command + { + public: + RNG() : Command("rng --format=hex --system --rdrand --auto --entropy --drbg --drbg-seed= *bytes") {} + + std::string group() const override + { + return "misc"; + } + + std::string description() const override + { + return "Sample random bytes from the specified rng"; + } + + void go() override + { + const std::string format = get_arg("format"); + std::string type = get_arg("rng-type"); + + if(type.empty()) + { + for(std::string flag : { "system", "rdrand", "auto", "entropy", "drbg" }) + { + if(flag_set(flag)) + { + type = flag; + break; + } + } + } + + const std::string drbg_seed = get_arg("drbg-seed"); + std::unique_ptr<Botan::RandomNumberGenerator> rng = cli_make_rng(type, drbg_seed); + + for(const std::string& req : get_arg_list("bytes")) + { + const size_t req_len = Botan::to_u32bit(req); + const auto blob = rng->random_vec(req_len); + + if(format == "binary" || format == "raw") + { + output().write(reinterpret_cast<const char*>(blob.data()), blob.size()); + } + else + { + output() << format_blob(format, blob) << "\n"; + } + } + } + }; + +BOTAN_REGISTER_COMMAND("rng", RNG); + +} |