diff options
author | Jack Lloyd <[email protected]> | 2017-08-30 12:18:43 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-08-30 12:18:43 -0400 |
commit | 06eefb457eb8e4fadd46d8dbde026a9f163ff4f1 (patch) | |
tree | f909c53e6c4e26c003f593178ae2163b50edf49b /src/cli | |
parent | 17ef09021892afc4c0e9fe7ba97423bf832e6dc5 (diff) |
Refactor RNG seeding logic in command line interface
This is needed for LLVM which doesn't have any usable entropy
sources. Also useful for determinsitic private key creation, etc.
Diffstat (limited to 'src/cli')
-rw-r--r-- | src/cli/cli.h | 41 | ||||
-rw-r--r-- | src/cli/utils.cpp | 109 |
2 files changed, 81 insertions, 69 deletions
diff --git a/src/cli/cli.h b/src/cli/cli.h index fcff94870..23cf0ff1c 100644 --- a/src/cli/cli.h +++ b/src/cli/cli.h @@ -11,14 +11,6 @@ #include <botan/parsing.h> #include <botan/rng.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 - #include <fstream> #include <iostream> #include <functional> @@ -30,6 +22,10 @@ namespace Botan_CLI { +/* Declared in utils.cpp */ +std::unique_ptr<Botan::RandomNumberGenerator> +cli_make_rng(const std::string& type, const std::string& hex_drbg_seed); + class CLI_Error : public std::runtime_error { public: @@ -334,11 +330,12 @@ class Command m_spec_opts.insert(std::make_pair("error-output", "")); #if defined(BOTAN_HAS_SYSTEM_RNG) - const auto availableRng = "system"; + const std::string availableRng = "system"; #else - const auto availableRng = "auto"; + const std::string availableRng = "user"; #endif m_spec_opts.insert(std::make_pair("rng-type", availableRng)); + m_spec_opts.insert(std::make_pair("drbg-seed", "")); } /* @@ -493,29 +490,7 @@ class Command { if(m_rng == nullptr) { - const std::string rng_type = get_arg("rng-type"); - - if(rng_type == "system") - { -#if defined(BOTAN_HAS_SYSTEM_RNG) - m_rng.reset(new Botan::System_RNG); -#endif - } - - // TODO --rng-type=drbg - // TODO --drbg-seed=hexstr - - if(rng_type == "auto") - { -#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) - m_rng.reset(new Botan::AutoSeeded_RNG); -#endif - } - - if(!m_rng) - { - throw CLI_Error_Unsupported("rng", rng_type); - } + m_rng = cli_make_rng(get_arg("rng-type"), get_arg("drbg-seed")); } return *m_rng.get(); diff --git a/src/cli/utils.cpp b/src/cli/utils.cpp index 2bf03c760..620ef72a2 100644 --- a/src/cli/utils.cpp +++ b/src/cli/utils.cpp @@ -29,6 +29,10 @@ #include <botan/rdrand_rng.h> #endif +#if defined(BOTAN_HAS_HMAC_DRBG) + #include <botan/hmac_drbg.h> +#endif + #if defined(BOTAN_HAS_HTTP_UTIL) #include <botan/http_util.h> #endif @@ -47,6 +51,64 @@ 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") + { + return std::unique_ptr<Botan::RandomNumberGenerator>(new Botan::System_RNG); + } +#endif + +#if defined(BOTAN_HAS_RDRAND_RNG) + if(rng_type == "rdrand") + { + if(Botan::CPUID::has_rdrand()) + return std::unique_ptr<Botan::RandomNumberGenerator>(new Botan::RDRAND_RNG); + else + throw CLI_Error("RDRAND instruction not supported on this processor"); + } +#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") + { + 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) + if(rng_type == "drbg") + { + std::unique_ptr<Botan::MessageAuthenticationCode> mac = + Botan::MessageAuthenticationCode::create(BOTAN_AUTO_RNG_HMAC); + 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 rng; + } +#endif + + throw CLI_Error_Unsupported("RNG", rng_type); + } + class Config_Info final : public Command { public: @@ -170,49 +232,24 @@ BOTAN_REGISTER_COMMAND("hash", Hash); class RNG final : public Command { public: - RNG() : Command("rng --system --rdrand --entropy *bytes") {} + RNG() : Command("rng --system --rdrand --auto --entropy --drbg --drbg-seed= *bytes") {} void go() override { - std::unique_ptr<Botan::RNG> rng; + std::string type = "auto"; // default - if(flag_set("system")) - { -#if defined(BOTAN_HAS_SYSTEM_RNG) - rng.reset(new Botan::System_RNG); -#else - error_output() << "system_rng disabled in build\n"; - return; -#endif - } - else if(flag_set("rdrand")) + for(std::string flag : { "system", "rdrand", "auto", "entropy", "drbg" }) { -#if defined(BOTAN_HAS_RDRAND_RNG) - rng.reset(new Botan::RDRAND_RNG); -#else - error_output() << "rdrand_rng disabled in build\n"; - return; -#endif - } - else if(flag_set("entropy")) - { -#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) - rng.reset(new Botan::AutoSeeded_RNG(Botan::Entropy_Sources::global_sources())); -#else - error_output() << "auto_rng disabled in build\n"; - return; -#endif - } - else - { -#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) - rng.reset(new Botan::AutoSeeded_RNG); -#else - error_output() << "auto_rng disabled in build\n"; - return; -#endif + if(flag_set(flag)) + { + type = flag; + break; + } } + const std::string drbg_seed = get_arg("drbg-seed"); + std::unique_ptr<Botan::RNG> rng = cli_make_rng(type, drbg_seed); + for(const std::string& req : get_arg_list("bytes")) { output() << Botan::hex_encode(rng->random_vec(Botan::to_u32bit(req))) << "\n"; |