aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/lib/entropy/rdrand/rdrand.cpp6
-rw-r--r--src/lib/entropy/rdseed/rdseed.cpp3
-rw-r--r--src/lib/ffi/ffi_rng.cpp15
-rw-r--r--src/lib/rng/rdrand_rng/rdrand_rng.cpp8
-rw-r--r--src/lib/rng/rdrand_rng/rdrand_rng.h5
-rw-r--r--src/tests/test_ffi.cpp95
6 files changed, 86 insertions, 46 deletions
diff --git a/src/lib/entropy/rdrand/rdrand.cpp b/src/lib/entropy/rdrand/rdrand.cpp
index 6a5b0f7c4..b8a74ce2f 100644
--- a/src/lib/entropy/rdrand/rdrand.cpp
+++ b/src/lib/entropy/rdrand/rdrand.cpp
@@ -8,12 +8,12 @@
#include <botan/internal/rdrand.h>
#include <botan/rdrand_rng.h>
-#include <botan/cpuid.h>
namespace Botan {
-size_t Intel_Rdrand::poll(RandomNumberGenerator& rng) {
- if(CPUID::has_rdrand() && BOTAN_ENTROPY_INTEL_RNG_POLLS > 0)
+size_t Intel_Rdrand::poll(RandomNumberGenerator& rng)
+ {
+ if(BOTAN_ENTROPY_INTEL_RNG_POLLS > 0 && RDRAND_RNG::available())
{
RDRAND_RNG rdrand_rng;
secure_vector<uint8_t> buf(4 * BOTAN_ENTROPY_INTEL_RNG_POLLS);
diff --git a/src/lib/entropy/rdseed/rdseed.cpp b/src/lib/entropy/rdseed/rdseed.cpp
index fbb8f921e..fccc53f6a 100644
--- a/src/lib/entropy/rdseed/rdseed.cpp
+++ b/src/lib/entropy/rdseed/rdseed.cpp
@@ -15,7 +15,8 @@
namespace Botan {
BOTAN_FUNC_ISA("rdseed")
-size_t Intel_Rdseed::poll(RandomNumberGenerator& rng) {
+size_t Intel_Rdseed::poll(RandomNumberGenerator& rng)
+ {
if(CPUID::has_rdseed())
{
for(size_t p = 0; p != BOTAN_ENTROPY_INTEL_RNG_POLLS; ++p)
diff --git a/src/lib/ffi/ffi_rng.cpp b/src/lib/ffi/ffi_rng.cpp
index 7e185f75d..e193d4123 100644
--- a/src/lib/ffi/ffi_rng.cpp
+++ b/src/lib/ffi/ffi_rng.cpp
@@ -10,6 +10,10 @@
#include <botan/system_rng.h>
#include <botan/auto_rng.h>
+#if defined(BOTAN_HAS_RDRAND_RNG)
+ #include <botan/rdrand_rng.h>
+#endif
+
extern "C" {
using namespace Botan_FFI;
@@ -36,15 +40,22 @@ int botan_rng_init(botan_rng_t* rng_out, const char* rng_type)
{
rng.reset(new Botan::Null_RNG);
}
+#if defined(BOTAN_HAS_RDRAND_RNG)
+ else if(rng_type_s == "rdrand" && Botan::RDRAND_RNG::available())
+ {
+ rng.reset(new Botan::RDRAND_RNG);
+ }
+#endif
#if defined(BOTAN_TARGET_OS_HAS_THREADS)
else if(rng_type_s == "user-threadsafe")
{
rng.reset(new Botan::Serialized_RNG(new Botan::AutoSeeded_RNG));
}
#endif
- else
+
+ if(!rng)
{
- return BOTAN_FFI_ERROR_BAD_PARAMETER;
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
}
*rng_out = new botan_rng_struct(rng.release());
diff --git a/src/lib/rng/rdrand_rng/rdrand_rng.cpp b/src/lib/rng/rdrand_rng/rdrand_rng.cpp
index c365a5f76..a3ea25921 100644
--- a/src/lib/rng/rdrand_rng/rdrand_rng.cpp
+++ b/src/lib/rng/rdrand_rng/rdrand_rng.cpp
@@ -17,11 +17,17 @@ namespace Botan {
RDRAND_RNG::RDRAND_RNG()
{
- if(!CPUID::has_rdrand())
+ if(!RDRAND_RNG::available())
throw Exception("Current CPU does not support RDRAND instruction");
}
//static
+bool RDRAND_RNG::available()
+ {
+ return CPUID::has_rdrand();
+ }
+
+//static
uint32_t RDRAND_RNG::rdrand()
{
for(;;)
diff --git a/src/lib/rng/rdrand_rng/rdrand_rng.h b/src/lib/rng/rdrand_rng/rdrand_rng.h
index 377de419f..3f6a33b64 100644
--- a/src/lib/rng/rdrand_rng/rdrand_rng.h
+++ b/src/lib/rng/rdrand_rng/rdrand_rng.h
@@ -30,6 +30,11 @@ class BOTAN_PUBLIC_API(2,0) RDRAND_RNG final : public Hardware_RNG
static uint32_t rdrand();
/**
+ * Return true if RDRAND is available on the current processor
+ */
+ static bool available();
+
+ /**
* Constructor will throw if CPU does not have RDRAND bit set
*/
RDRAND_RNG();
diff --git a/src/tests/test_ffi.cpp b/src/tests/test_ffi.cpp
index d6824afd1..ee16267a1 100644
--- a/src/tests/test_ffi.cpp
+++ b/src/tests/test_ffi.cpp
@@ -38,51 +38,14 @@ class FFI_Unit_Tests final : public Test
{
Test::Result result("FFI");
- // RNG test and initialization
botan_rng_t rng;
-
- TEST_FFI_FAIL("invalid rng type", botan_rng_init, (&rng, "invalid_type"));
-
- std::vector<uint8_t> outbuf(512);
-
- if(TEST_FFI_OK(botan_rng_init, (&rng, "user-threadsafe")))
- {
- TEST_FFI_OK(botan_rng_get, (rng, outbuf.data(), outbuf.size()));
- TEST_FFI_OK(botan_rng_reseed, (rng, 256));
-
- botan_rng_t null_rng;
- TEST_FFI_OK(botan_rng_init, (&null_rng, "null"));
- TEST_FFI_RC(-20, botan_rng_reseed_from_rng, (rng, null_rng, 256));
- TEST_FFI_RC(-20, botan_rng_get, (null_rng, outbuf.data(), outbuf.size()));
- TEST_FFI_OK(botan_rng_destroy, (null_rng));
-
- TEST_FFI_OK(botan_rng_destroy, (rng));
- }
-
- if(TEST_FFI_OK(botan_rng_init, (&rng, "user")))
+ if(!TEST_FFI_OK(botan_rng_init, (&rng, "user")))
{
- TEST_FFI_OK(botan_rng_get, (rng, outbuf.data(), outbuf.size()));
- TEST_FFI_OK(botan_rng_reseed, (rng, 256));
-
- botan_rng_t system_rng;
- if(TEST_FFI_OK(botan_rng_init, (&system_rng, "system")))
- {
- TEST_FFI_OK(botan_rng_reseed_from_rng, (rng, system_rng, 256));
- TEST_FFI_OK(botan_rng_destroy, (system_rng));
- }
-
- uint8_t not_really_entropy[32] = { 0 };
- TEST_FFI_OK(botan_rng_add_entropy, (rng, not_really_entropy, 32));
-
- // used for the rest of this function and destroyed at the end
- }
- else
- {
- result.test_note("Existing early due to missing FFI RNG");
return {result};
}
std::vector<Test::Result> results;
+ results.push_back(ffi_test_rng());
results.push_back(ffi_test_utils());
results.push_back(ffi_test_errors());
results.push_back(ffi_test_base64());
@@ -209,6 +172,60 @@ class FFI_Unit_Tests final : public Test
return result;
}
+ Test::Result ffi_test_rng()
+ {
+ Test::Result result("FFI RNG");
+
+ // RNG test and initialization
+ botan_rng_t rng;
+ botan_rng_t system_rng;
+ botan_rng_t rdrand_rng = nullptr;
+ botan_rng_t null_rng;
+
+ TEST_FFI_FAIL("invalid rng type", botan_rng_init, (&rng, "invalid_type"));
+
+ REQUIRE_FFI_OK(botan_rng_init, (&system_rng, "system"));
+ REQUIRE_FFI_OK(botan_rng_init, (&null_rng, "null"));
+
+ int rc = botan_rng_init(&rdrand_rng, "rdrand");
+ result.confirm("Either success or not implemented", rc == 0 || rc == BOTAN_FFI_ERROR_NOT_IMPLEMENTED);
+
+ std::vector<uint8_t> outbuf(512);
+
+ if(TEST_FFI_OK(botan_rng_init, (&rng, "user-threadsafe")))
+ {
+ TEST_FFI_OK(botan_rng_get, (rng, outbuf.data(), outbuf.size()));
+ TEST_FFI_OK(botan_rng_reseed, (rng, 256));
+
+ TEST_FFI_RC(-20, botan_rng_reseed_from_rng, (rng, null_rng, 256));
+ if(rdrand_rng)
+ {
+ TEST_FFI_OK(botan_rng_reseed_from_rng, (rng, rdrand_rng, 256));
+ }
+ TEST_FFI_RC(-20, botan_rng_get, (null_rng, outbuf.data(), outbuf.size()));
+
+ TEST_FFI_OK(botan_rng_destroy, (rng));
+ }
+
+ if(TEST_FFI_OK(botan_rng_init, (&rng, "user")))
+ {
+ TEST_FFI_OK(botan_rng_get, (rng, outbuf.data(), outbuf.size()));
+ TEST_FFI_OK(botan_rng_reseed, (rng, 256));
+
+ TEST_FFI_OK(botan_rng_reseed_from_rng, (rng, system_rng, 256));
+
+ uint8_t not_really_entropy[32] = { 0 };
+ TEST_FFI_OK(botan_rng_add_entropy, (rng, not_really_entropy, 32));
+ }
+
+ TEST_FFI_OK(botan_rng_destroy, (rng));
+ TEST_FFI_OK(botan_rng_destroy, (null_rng));
+ TEST_FFI_OK(botan_rng_destroy, (system_rng));
+ TEST_FFI_OK(botan_rng_destroy, (rdrand_rng));
+
+ return result;
+ }
+
Test::Result ffi_test_rsa_cert()
{
Test::Result result("FFI RSA cert");