aboutsummaryrefslogtreecommitdiffstats
path: root/src/cli
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-08-30 12:18:43 -0400
committerJack Lloyd <[email protected]>2017-08-30 12:18:43 -0400
commit06eefb457eb8e4fadd46d8dbde026a9f163ff4f1 (patch)
treef909c53e6c4e26c003f593178ae2163b50edf49b /src/cli
parent17ef09021892afc4c0e9fe7ba97423bf832e6dc5 (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.h41
-rw-r--r--src/cli/utils.cpp109
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";