diff options
-rw-r--r-- | src/lib/entropy/rdrand/rdrand.cpp | 6 | ||||
-rw-r--r-- | src/lib/entropy/rdseed/rdseed.cpp | 3 | ||||
-rw-r--r-- | src/lib/ffi/ffi_rng.cpp | 15 | ||||
-rw-r--r-- | src/lib/rng/rdrand_rng/rdrand_rng.cpp | 8 | ||||
-rw-r--r-- | src/lib/rng/rdrand_rng/rdrand_rng.h | 5 | ||||
-rw-r--r-- | src/tests/test_ffi.cpp | 95 |
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"); |