aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/rng/rdrand_rng/rdrand_rng.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/rng/rdrand_rng/rdrand_rng.cpp')
-rw-r--r--src/lib/rng/rdrand_rng/rdrand_rng.cpp92
1 files changed, 22 insertions, 70 deletions
diff --git a/src/lib/rng/rdrand_rng/rdrand_rng.cpp b/src/lib/rng/rdrand_rng/rdrand_rng.cpp
index ece3d9f39..fade5a199 100644
--- a/src/lib/rng/rdrand_rng/rdrand_rng.cpp
+++ b/src/lib/rng/rdrand_rng/rdrand_rng.cpp
@@ -6,106 +6,58 @@
*/
#include <botan/rdrand_rng.h>
+#include <botan/processor_rng.h>
#include <botan/loadstor.h>
-#include <botan/cpuid.h>
-
-#if !defined(BOTAN_USE_GCC_INLINE_ASM)
- #include <immintrin.h>
-#endif
namespace Botan {
-namespace {
-
-#if defined(BOTAN_TARGET_ARCH_IS_X86_64)
- typedef uint64_t rdrand_output;
-#else
- typedef uint32_t rdrand_output;
-#endif
-
-#if !defined(BOTAN_USE_GCC_INLINE_ASM)
-BOTAN_FUNC_ISA("rdrnd")
-#endif
-rdrand_output read_rdrand()
- {
- /*
- * According to Intel, RDRAND is guaranteed to generate a random
- * number within 10 retries on a working CPU
- */
- const size_t RDRAND_RETRIES = 10;
-
- for(size_t i = 0; i < RDRAND_RETRIES; ++i)
- {
- rdrand_output r = 0;
- int cf = 0;
-
-#if defined(BOTAN_USE_GCC_INLINE_ASM)
- // same asm seq works for 32 and 64 bit
- asm("rdrand %0; adcl $0,%1" :
- "=r" (r), "=r" (cf) : "0" (r), "1" (cf) : "cc");
-#elif defined(BOTAN_TARGET_ARCH_IS_X86_64)
- cf = _rdrand64_step(&r);
-#else
- cf = _rdrand32_step(&r);
-#endif
- if(1 == cf)
- {
- return r;
- }
- }
-
- throw PRNG_Unseeded("RDRAND read failed");
- }
-
-}
-
void RDRAND_RNG::randomize(uint8_t out[], size_t out_len)
{
- while(out_len >= sizeof(rdrand_output))
- {
- const rdrand_output r = read_rdrand();
- store_le(r, out);
- out += sizeof(rdrand_output);
- out_len -= sizeof(rdrand_output);
- }
-
- if(out_len > 0) // at most sizeof(rdrand_output)-1
- {
- const rdrand_output r = read_rdrand();
- for(size_t i = 0; i != out_len; ++i)
- out[i] = get_byte(i, r);
- }
+ Processor_RNG rng;
+ rng.randomize(out, out_len);
}
RDRAND_RNG::RDRAND_RNG()
{
- if(!RDRAND_RNG::available())
- throw Invalid_State("Current CPU does not support RDRAND instruction");
+ // Will throw if instruction is not available
+ Processor_RNG rng;
}
//static
bool RDRAND_RNG::available()
{
- return CPUID::has_rdrand();
+ return Processor_RNG::available();
}
//static
uint32_t RDRAND_RNG::rdrand()
{
- return static_cast<uint32_t>(read_rdrand());
+ Processor_RNG rng;
+
+ for(;;)
+ {
+ try
+ {
+ uint8_t out[4];
+ rng.randomize(out, 4);
+ return load_le<uint32_t>(out, 0);
+ }
+ catch(PRNG_Unseeded&) {}
+ }
}
//static
-BOTAN_FUNC_ISA("rdrnd")
uint32_t RDRAND_RNG::rdrand_status(bool& ok)
{
ok = false;
+ Processor_RNG rng;
try
{
- const uint32_t r = static_cast<uint32_t>(read_rdrand());
+ uint8_t out[4];
+ rng.randomize(out, 4);
ok = true;
- return r;
+ return load_le<uint32_t>(out, 0);
}
catch(PRNG_Unseeded&) {}