7#include <botan/processor_rng.h>
9#include <botan/internal/cpuid.h>
10#include <botan/internal/loadstor.h>
11#include <botan/internal/target_info.h>
13#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) && !defined(BOTAN_USE_GCC_INLINE_ASM)
14 #include <immintrin.h>
21#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
26const size_t HWRNG_RETRIES = 10;
28#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
36const size_t HWRNG_RETRIES = 10;
42const size_t HWRNG_RETRIES = 512;
45#if defined(BOTAN_TARGET_ARCH_IS_X86_32)
46typedef uint32_t hwrng_output;
48typedef uint64_t hwrng_output;
51hwrng_output read_hwrng(
bool& success) {
52 hwrng_output output = 0;
55#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
57 #if defined(BOTAN_USE_GCC_INLINE_ASM)
59 asm volatile(
"rdrand %0; adcl $0,%1" :
"=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(
reinterpret_cast<unsigned long long*
>(&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() {
94 for(
size_t i = 0; i < HWRNG_RETRIES; ++i) {
96 hwrng_output output = read_hwrng(success);
103 throw PRNG_Unseeded(
"Processor RNG instruction failed to produce output within expected iterations");
110#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
112#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
120#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
122#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
129void Processor_RNG::fill_bytes_with_input(std::span<uint8_t> out, std::span<const uint8_t> in) {
133 while(out.size() >=
sizeof(hwrng_output)) {
134 const hwrng_output r = read_hwrng();
136 out = out.subspan(
sizeof(hwrng_output));
141 const hwrng_output r = read_hwrng();
142 uint8_t hwrng_bytes[
sizeof(hwrng_output)];
145 for(
size_t i = 0; i != out.size(); ++i) {
146 out[i] = hwrng_bytes[i];
153 throw Invalid_State(
"Current CPU does not support RNG instruction");
159 std::chrono::milliseconds ) {
static bool has(CPUID::Feature feat)
size_t reseed(Entropy_Sources &, size_t, std::chrono::milliseconds) override
std::string name() const override
constexpr auto store_le(ParamTs &&... params)