diff options
Diffstat (limited to 'lib/entropy/rdrand')
-rw-r--r-- | lib/entropy/rdrand/info.txt | 22 | ||||
-rw-r--r-- | lib/entropy/rdrand/rdrand.cpp | 60 | ||||
-rw-r--r-- | lib/entropy/rdrand/rdrand.h | 28 |
3 files changed, 110 insertions, 0 deletions
diff --git a/lib/entropy/rdrand/info.txt b/lib/entropy/rdrand/info.txt new file mode 100644 index 000000000..546ab699a --- /dev/null +++ b/lib/entropy/rdrand/info.txt @@ -0,0 +1,22 @@ +define ENTROPY_SRC_RDRAND 20131128 + +need_isa rdrand + +<source> +rdrand.cpp +</source> + +<header:internal> +rdrand.h +</header:internal> + +<arch> +x86_32 +x86_64 +</arch> + +<cc> +gcc +clang +icc +</cc> diff --git a/lib/entropy/rdrand/rdrand.cpp b/lib/entropy/rdrand/rdrand.cpp new file mode 100644 index 000000000..0dae697c8 --- /dev/null +++ b/lib/entropy/rdrand/rdrand.cpp @@ -0,0 +1,60 @@ +/* +* 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> + +#if !defined(BOTAN_USE_GCC_INLINE_ASM) + #include <immintrin.h> +#endif + +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 = 0; + +#if BOTAN_USE_GCC_INLINE_ASM + int cf = 0; + + // Encoding of rdrand %eax + asm(".byte 0x0F, 0xC7, 0xF0; adcl $0,%1" : + "=a" (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/lib/entropy/rdrand/rdrand.h b/lib/entropy/rdrand/rdrand.h new file mode 100644 index 000000000..d7629d37f --- /dev/null +++ b/lib/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 |