7#include <botan/processor_rng.h>
8#include <botan/internal/loadstor.h>
9#include <botan/internal/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;
26#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
34 const size_t HWRNG_RETRIES = 10;
40 const size_t HWRNG_RETRIES = 512;
43#if defined(BOTAN_TARGET_ARCH_IS_X86_32)
44 typedef uint32_t hwrng_output;
46 typedef uint64_t hwrng_output;
49hwrng_output read_hwrng(
bool& success)
51 hwrng_output output = 0;
54#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
56#if defined(BOTAN_USE_GCC_INLINE_ASM)
58 asm volatile(
"rdrand %0; adcl $0,%1" :
59 "=r" (output),
"=r" (cf) :
"0" (output),
"1" (cf) :
"cc");
60#elif defined(BOTAN_TARGET_ARCH_IS_X86_32)
61 cf = _rdrand32_step(&output);
63 cf = _rdrand64_step(&output);
67#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
76 asm volatile(
"darn %0, 1" :
"=r" (output));
77 asm volatile(
"darn %0, 1" :
"=r" (output2));
79 if((~output) != 0 && (~output2) != 0)
93hwrng_output read_hwrng()
95 for(
size_t i = 0; i < HWRNG_RETRIES; ++i)
98 hwrng_output output = read_hwrng(success);
104 throw PRNG_Unseeded(
"Processor RNG instruction failed to produce output within expected iterations");
112#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
113 return CPUID::has_rdrand();
114#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
115 return CPUID::has_darn_rng();
123#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
125#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
132void Processor_RNG::fill_bytes_with_input(std::span<uint8_t> out, std::span<const uint8_t> in)
137 while(out.size() >=
sizeof(hwrng_output))
139 const hwrng_output r = read_hwrng();
141 out = out.subspan(
sizeof(hwrng_output));
146 const hwrng_output r = read_hwrng();
147 uint8_t hwrng_bytes[
sizeof(hwrng_output)];
150 for(
size_t i = 0; i != out.size(); ++i)
151 out[i] = hwrng_bytes[i];
158 throw Invalid_State(
"Current CPU does not support RNG instruction");
#define BOTAN_UNUSED(...)
size_t reseed(Entropy_Sources &, size_t, std::chrono::milliseconds) override
std::string name() const override
constexpr void store_le(uint16_t in, uint8_t out[2])