diff options
Diffstat (limited to 'comm/third_party/botan/src/lib/entropy/rdseed')
3 files changed, 144 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/entropy/rdseed/info.txt b/comm/third_party/botan/src/lib/entropy/rdseed/info.txt new file mode 100644 index 0000000000..ee822ad7c0 --- /dev/null +++ b/comm/third_party/botan/src/lib/entropy/rdseed/info.txt @@ -0,0 +1,19 @@ +<defines> +ENTROPY_SRC_RDSEED -> 20151218 +</defines> + +<isa> +rdseed +sse2 # for mm_pause see #2139 +</isa> + +<header:internal> +rdseed.h +</header:internal> + +<cc> +gcc +clang +icc +msvc +</cc> diff --git a/comm/third_party/botan/src/lib/entropy/rdseed/rdseed.cpp b/comm/third_party/botan/src/lib/entropy/rdseed/rdseed.cpp new file mode 100644 index 0000000000..1830edf9de --- /dev/null +++ b/comm/third_party/botan/src/lib/entropy/rdseed/rdseed.cpp @@ -0,0 +1,97 @@ +/* +* Entropy Source Using Intel's rdseed instruction +* (C) 2015 Daniel Neus +* (C) 2015,2019 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/internal/rdseed.h> +#include <botan/cpuid.h> + +#include <immintrin.h> + +namespace Botan { + +namespace { + +BOTAN_FUNC_ISA("rdseed") +bool read_rdseed(secure_vector<uint32_t>& seed) + { + /* + * RDSEED is not guaranteed to generate an output within any specific number + * of attempts. However in testing on a Skylake system, with all hyperthreads + * occupied in tight RDSEED loops, RDSEED will still usually succeed in under + * 150 attempts. The maximum ever seen was 230 attempts until success. When + * idle, RDSEED usually succeeds in 1 or 2 attempts. + * + * We set an upper bound of 512 attempts, because it is possible that due + * to firmware issue RDSEED is simply broken and never succeeds. We do not + * want to loop forever in that case. If we exceed that limit, then we assume + * the hardware is actually just broken, and stop the poll. + */ + const size_t RDSEED_RETRIES = 512; + + for(size_t i = 0; i != RDSEED_RETRIES; ++i) + { + uint32_t r = 0; + int cf = 0; + +#if defined(BOTAN_USE_GCC_INLINE_ASM) + asm("rdseed %0; adcl $0,%1" : + "=r" (r), "=r" (cf) : "0" (r), "1" (cf) : "cc"); +#else + cf = _rdseed32_step(&r); +#endif + + if(1 == cf) + { + seed.push_back(r); + return true; + } + + // Intel suggests pausing if RDSEED fails. + _mm_pause(); + } + + return false; // failed to produce an output after many attempts + } + +} + +size_t Intel_Rdseed::poll(RandomNumberGenerator& rng) + { + const size_t RDSEED_BYTES = 1024; + static_assert(RDSEED_BYTES % 4 == 0, "Bad RDSEED configuration"); + + if(CPUID::has_rdseed()) + { + secure_vector<uint32_t> seed; + seed.reserve(RDSEED_BYTES / 4); + + for(size_t p = 0; p != RDSEED_BYTES / 4; ++p) + { + /* + If at any point we exceed our retry count, we stop the entire seed + gathering process. This situation will only occur in situations of + extremely high RDSEED utilization. If RDSEED is currently so highly + contended, then the rest of the poll is likely to also face contention and + it is better to quit now rather than (presumably) face very high retry + times for the rest of the poll. + */ + if(!read_rdseed(seed)) + break; + } + + if(seed.size() > 0) + { + rng.add_entropy(reinterpret_cast<const uint8_t*>(seed.data()), + seed.size() * sizeof(uint32_t)); + } + } + + // RDSEED is used but not trusted + return 0; + } + +} diff --git a/comm/third_party/botan/src/lib/entropy/rdseed/rdseed.h b/comm/third_party/botan/src/lib/entropy/rdseed/rdseed.h new file mode 100644 index 0000000000..da94bc0a10 --- /dev/null +++ b/comm/third_party/botan/src/lib/entropy/rdseed/rdseed.h @@ -0,0 +1,28 @@ +/* +* Entropy Source Using Intel's rdseed instruction +* (C) 2015 Jack Lloyd, Daniel Neus +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_ENTROPY_SRC_RDSEED_H_ +#define BOTAN_ENTROPY_SRC_RDSEED_H_ + +#include <botan/entropy_src.h> + +namespace Botan { + +/** +* Entropy source using the rdseed instruction first introduced on +* Intel's Broadwell architecture. +*/ +class Intel_Rdseed final : public Entropy_Source + { + public: + std::string name() const override { return "rdseed"; } + size_t poll(RandomNumberGenerator& rng) override; + }; + +} + +#endif |