aboutsummaryrefslogtreecommitdiffstats
path: root/src/cli/utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/cli/utils.cpp')
-rw-r--r--src/cli/utils.cpp109
1 files changed, 73 insertions, 36 deletions
diff --git a/src/cli/utils.cpp b/src/cli/utils.cpp
index 63e0fc7d6..ce461cb65 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 std::unique_ptr<Botan::RandomNumberGenerator>(rng.release());
+ }
+#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";