diff options
author | lloyd <[email protected]> | 2012-04-26 13:32:37 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2012-04-26 13:32:37 +0000 |
commit | a062a3f81a283b5f3edabd188eecebbf8acb9967 (patch) | |
tree | 141106e9996590533fb6eb494c5c73bcd9419f37 /src | |
parent | 25f329b8a45b6f84f9a01a0326db48f6853dc59c (diff) |
Add support for the rdrand instruction, added in Intel's Ivy Bridge
processors. Tested using SDE on Linux with GCC 4.6, Intel C++ 11.1,
and Clang 3.0, all using the inline asm variant. I do not know if
current Visual C++ has the intrinsics available or not, so it's only
marked as available for those compilers at the moment.
Diffstat (limited to 'src')
-rw-r--r-- | src/entropy/rdrand/info.txt | 20 | ||||
-rw-r--r-- | src/entropy/rdrand/rdrand.cpp | 55 | ||||
-rw-r--r-- | src/entropy/rdrand/rdrand.h | 28 | ||||
-rw-r--r-- | src/libstate/global_rng.cpp | 8 |
4 files changed, 111 insertions, 0 deletions
diff --git a/src/entropy/rdrand/info.txt b/src/entropy/rdrand/info.txt new file mode 100644 index 000000000..4b9362d61 --- /dev/null +++ b/src/entropy/rdrand/info.txt @@ -0,0 +1,20 @@ +define ENTROPY_SRC_RDRAND + +<source> +rdrand.cpp +</source> + +<header:internal> +rdrand.h +</header:internal> + +<arch> +x86 +x86_64 +</arch> + +<cc> +gcc +clang +icc +</cc> diff --git a/src/entropy/rdrand/rdrand.cpp b/src/entropy/rdrand/rdrand.cpp new file mode 100644 index 000000000..72abd6166 --- /dev/null +++ b/src/entropy/rdrand/rdrand.cpp @@ -0,0 +1,55 @@ +/* +* Entropy Source Using Intel's rdrand instruction +* (C) 2012 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/internal/rdrand.h> +#include <botan/cpuid.h> +#include <immintrin.h> + +namespace Botan { + +/* +* Get the timestamp +*/ +void Intel_Rdrand::poll(Entropy_Accumulator& accum) + { + if(!CPUID::has_rdrand()) + return; + + /* + * Put an upper bound on the total entropy we're willing to claim + * for any one polling of rdrand to prevent it from swamping our + * poll. Internally, the rdrand system is a DRGB that reseeds at a + * somewhat unpredictable rate (the current conditions are + * documented, but that might not be true for different + * implementations, eg on Haswell or a future AMD chip, so I don't + * want to assume). This limit ensures we're going to poll at least + * one other source so we have some diversity in our inputs. + */ + + const size_t POLL_UPPER_BOUND = 96; + const size_t RDRAND_POLLS = 32; + const double ENTROPY_PER_POLL = + static_cast<double>(POLL_UPPER_BOUND) / (RDRAND_POLLS * 4); + + for(size_t i = 0; i != RDRAND_POLLS; ++i) + { + unsigned int r; + +#if BOTAN_USE_GCC_INLINE_ASM + int cf = 0; + asm("rdrand %0; adcl $0,%1" : + "=r" (r), "=r" (cf) : "0" (r), "1" (cf) : "cc"); +#else + int cf = _rdrand32_step(&r); +#endif + + if(cf == 1) + accum.add(r, ENTROPY_PER_POLL); + } + } + +} diff --git a/src/entropy/rdrand/rdrand.h b/src/entropy/rdrand/rdrand.h new file mode 100644 index 000000000..d7629d37f --- /dev/null +++ b/src/entropy/rdrand/rdrand.h @@ -0,0 +1,28 @@ +/* +* Entropy Source Using Intel's rdrand instruction +* (C) 2012 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_ENTROPY_SRC_RDRAND_H__ +#define BOTAN_ENTROPY_SRC_RDRAND_H__ + +#include <botan/entropy_src.h> + +namespace Botan { + +/** +* Entropy source using the rdrand instruction first introduced on +* Intel's Ivy Bridge architecture. +*/ +class Intel_Rdrand : public EntropySource + { + public: + std::string name() const { return "Intel Rdrand"; } + void poll(Entropy_Accumulator& accum); + }; + +} + +#endif diff --git a/src/libstate/global_rng.cpp b/src/libstate/global_rng.cpp index e9ea530ac..7e7976f58 100644 --- a/src/libstate/global_rng.cpp +++ b/src/libstate/global_rng.cpp @@ -24,6 +24,10 @@ #include <botan/internal/hres_timer.h> #endif +#if defined(BOTAN_HAS_ENTROPY_SRC_RDRAND) + #include <botan/internal/rdrand.h> +#endif + #if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM) #include <botan/internal/dev_random.h> #endif @@ -65,6 +69,10 @@ void add_entropy_sources(RandomNumberGenerator* rng) rng->add_entropy_source(new High_Resolution_Timestamp); #endif +#if defined(BOTAN_HAS_ENTROPY_SRC_RDRAND) + rng->add_entropy_source(new Intel_Rdrand); +#endif + #if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM) rng->add_entropy_source( new Device_EntropySource( |