diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/entropy/rdrand/info.txt | 16 | ||||
-rw-r--r-- | src/lib/entropy/rdrand/rdrand.cpp | 32 | ||||
-rw-r--r-- | src/lib/rng/rdrand_rng/info.txt | 16 | ||||
-rw-r--r-- | src/lib/rng/rdrand_rng/rdrand_rng.cpp | 84 | ||||
-rw-r--r-- | src/lib/rng/rdrand_rng/rdrand_rng.h | 61 |
5 files changed, 170 insertions, 39 deletions
diff --git a/src/lib/entropy/rdrand/info.txt b/src/lib/entropy/rdrand/info.txt index e3e1a2a50..ebc7fb747 100644 --- a/src/lib/entropy/rdrand/info.txt +++ b/src/lib/entropy/rdrand/info.txt @@ -1,6 +1,8 @@ define ENTROPY_SRC_RDRAND 20131128 -need_isa rdrand +<requires> +rdrand_rng +</requires> <source> rdrand.cpp @@ -9,15 +11,3 @@ rdrand.cpp <header:internal> rdrand.h </header:internal> - -<arch> -x86_32 -x86_64 -</arch> - -<cc> -gcc -clang -icc -msvc -</cc> diff --git a/src/lib/entropy/rdrand/rdrand.cpp b/src/lib/entropy/rdrand/rdrand.cpp index fb04d7b78..7fa05c605 100644 --- a/src/lib/entropy/rdrand/rdrand.cpp +++ b/src/lib/entropy/rdrand/rdrand.cpp @@ -7,40 +7,20 @@ */ #include <botan/internal/rdrand.h> +#include <botan/rdrand_rng.h> #include <botan/cpuid.h> #include <botan/build.h> -#if !defined(BOTAN_USE_GCC_INLINE_ASM) - #include <immintrin.h> -#endif - namespace Botan { size_t Intel_Rdrand::poll(RandomNumberGenerator& rng) { - if(CPUID::has_rdrand()) + if(CPUID::has_rdrand() && BOTAN_ENTROPY_INTEL_RNG_POLLS > 0) { - for(size_t p = 0; p != BOTAN_ENTROPY_INTEL_RNG_POLLS; ++p) - { - for(size_t i = 0; i != BOTAN_ENTROPY_RDRAND_RETRIES; ++i) - { - uint32_t r = 0; - -#if defined(BOTAN_USE_GCC_INLINE_ASM) - int cf = 0; + RDRAND_RNG rdrand_rng; + secure_vector<uint8_t> buf(4 * BOTAN_ENTROPY_INTEL_RNG_POLLS); - // 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(1 == cf) - { - rng.add_entropy_T(r); - break; - } - } - } + rdrand_rng.randomize(buf.data(), buf.size()); + rng.add_entropy(buf.data(), buf.size()); } // RDRAND is used but not trusted diff --git a/src/lib/rng/rdrand_rng/info.txt b/src/lib/rng/rdrand_rng/info.txt new file mode 100644 index 000000000..2e597ebec --- /dev/null +++ b/src/lib/rng/rdrand_rng/info.txt @@ -0,0 +1,16 @@ +define RDRAND_RNG 20160619 + +need_isa rdrand + +<arch> +x86_32 +x86_64 +</arch> + +<cc> +gcc +clang +icc +msvc +</cc> + diff --git a/src/lib/rng/rdrand_rng/rdrand_rng.cpp b/src/lib/rng/rdrand_rng/rdrand_rng.cpp new file mode 100644 index 000000000..4d2e51cf8 --- /dev/null +++ b/src/lib/rng/rdrand_rng/rdrand_rng.cpp @@ -0,0 +1,84 @@ +/** +* RDRAND RNG +* (C) 2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/rdrand_rng.h> +#include <botan/loadstor.h> +#include <botan/cpuid.h> + +#if !defined(BOTAN_USE_GCC_INLINE_ASM) + #include <immintrin.h> +#endif + +namespace Botan { + +RDRAND_RNG::RDRAND_RNG() + { + if(!CPUID::has_rdrand()) + throw Exception("Current CPU does not support RDRAND instruction"); + } + +//static +uint32_t RDRAND_RNG::rdrand() + { + bool ok = false; + uint32_t r = rdrand_status(ok); + + while(!ok) + { + r = rdrand_status(ok); + } + + return r; + } + +//static +uint32_t RDRAND_RNG::rdrand_status(bool& ok) + { + ok = false; + uint32_t r = 0; + + for(size_t i = 0; i != BOTAN_ENTROPY_RDRAND_RETRIES; ++i) + { +#if defined(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(1 == cf) + { + ok = true; + return r; + } + } + + return 0; + } + +void RDRAND_RNG::randomize(uint8_t out[], size_t out_len) + { + while(out_len >= 4) + { + uint32_t r = RDRAND_RNG::rdrand(); + + store_le(r, out); + out += 4; + out_len -= 4; + } + + if(out_len) // between 1 and 3 trailing bytes + { + uint32_t r = RDRAND_RNG::rdrand(); + for(size_t i = 0; i != out_len; ++i) + out[i] = get_byte(i, r); + } + } + +} diff --git a/src/lib/rng/rdrand_rng/rdrand_rng.h b/src/lib/rng/rdrand_rng/rdrand_rng.h new file mode 100644 index 000000000..b9445f28e --- /dev/null +++ b/src/lib/rng/rdrand_rng/rdrand_rng.h @@ -0,0 +1,61 @@ +/** +* RDRAND RNG +* (C) 2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_RNG_RDRAND_H_ +#define BOTAN_RNG_RDRAND_H_ + +#include <botan/rng.h> + +namespace Botan { + +class BOTAN_DLL RDRAND_RNG : public Hardware_RNG + { + public: + /** + * On correctly working hardware, RDRAND is always supposed to + * succeed within a set number of retries. If after that many + * retries RDRAND has still not suceeded, sets ok = false and + * returns 0. + */ + static uint32_t rdrand_status(bool& ok); + + /* + * Calls RDRAND until it succeeds, this could hypothetically + * loop forever on broken hardware. + */ + static uint32_t rdrand(); + + /** + * Constructor will throw if CPU does not have RDRAND bit set + */ + RDRAND_RNG(); + + /** + * Uses RDRAND to produce output + */ + void randomize(uint8_t out[], size_t out_len) override; + + /* + * No way to provide entropy to RDRAND generator, so add_entropy is ignored + */ + void add_entropy(const uint8_t[], size_t) override + { /* no op */ } + + size_t reseed_with_sources(Entropy_Sources&, size_t, + std::chrono::milliseconds) override + { return 0; /* no op */ } + + std::string name() const override { return "RDRAND"; } + + bool is_seeded() const override { return true; } + + void clear() override {} + }; + +} + +#endif |