7#include <botan/processor_rng.h>
8#include <botan/loadstor.h>
9#include <botan/cpuid.h>
11#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) && !defined(BOTAN_USE_GCC_INLINE_ASM)
12 #include <immintrin.h>
19#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
24 const size_t HWRNG_RETRIES = 10;
30 const size_t HWRNG_RETRIES = 512;
33#if defined(BOTAN_TARGET_ARCH_IS_X86_32)
34 typedef uint32_t hwrng_output;
36 typedef uint64_t hwrng_output;
39hwrng_output read_hwrng(
bool& success)
41 hwrng_output output = 0;
44#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
46#if defined(BOTAN_USE_GCC_INLINE_ASM)
48 asm volatile(
"rdrand %0; adcl $0,%1" :
49 "=r" (output),
"=r" (cf) :
"0" (output),
"1" (cf) :
"cc");
50#elif defined(BOTAN_TARGET_ARCH_IS_X86_32)
51 cf = _rdrand32_step(&output);
53 cf = _rdrand64_step(&output);
57#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
66 asm volatile(
"darn %0, 1" :
"=r" (output));
67 asm volatile(
"darn %0, 1" :
"=r" (output2));
69 if((~output) != 0 && (~output2) != 0)
83hwrng_output read_hwrng()
85 for(
size_t i = 0; i < HWRNG_RETRIES; ++i)
88 hwrng_output output = read_hwrng(success);
94 throw PRNG_Unseeded(
"Processor RNG instruction failed to produce output within expected iterations");
102#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
103 return CPUID::has_rdrand();
104#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
105 return CPUID::has_darn_rng();
113#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
115#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
124 while(out_len >=
sizeof(hwrng_output))
126 const hwrng_output r = read_hwrng();
128 out +=
sizeof(hwrng_output);
129 out_len -=
sizeof(hwrng_output);
134 const hwrng_output r = read_hwrng();
135 for(
size_t i = 0; i != out_len; ++i)
143 throw Invalid_State(
"Current CPU does not support RNG instruction");
void randomize(uint8_t out[], size_t out_len) override
void add_entropy(const uint8_t[], size_t) override
size_t reseed(Entropy_Sources &, size_t, std::chrono::milliseconds) override
std::string name() const override
void store_le(uint16_t in, uint8_t out[2])
constexpr uint8_t get_byte(size_t byte_num, T input)