7#include <botan/processor_rng.h>
9#include <botan/exceptn.h>
10#include <botan/internal/cpuid.h>
11#include <botan/internal/isa_extn.h>
12#include <botan/internal/loadstor.h>
13#include <botan/internal/target_info.h>
15#if defined(BOTAN_TARGET_ARCH_IS_X86_FAMILY) && !defined(BOTAN_USE_GCC_INLINE_ASM)
16 #include <immintrin.h>
23#if defined(BOTAN_TARGET_ARCH_IS_X86_FAMILY)
28const size_t HWRNG_RETRIES = 10;
30#elif defined(BOTAN_TARGET_ARCH_IS_PPC_FAMILY)
38const size_t HWRNG_RETRIES = 10;
44const size_t HWRNG_RETRIES = 512;
47#if defined(BOTAN_TARGET_ARCH_IS_X86_32)
48typedef uint32_t hwrng_output;
50typedef uint64_t hwrng_output;
53hwrng_output BOTAN_FN_ISA_RNG read_hwrng(
bool& success) {
54 hwrng_output output = 0;
57#if defined(BOTAN_TARGET_ARCH_IS_X86_FAMILY)
59 #if defined(BOTAN_USE_GCC_INLINE_ASM)
62 asm volatile(
"rdrand %0; adcl $0,%1" :
"=r"(output),
"=r"(cf) :
"0"(output),
"1"(cf) :
"cc");
63 #elif defined(BOTAN_TARGET_ARCH_IS_X86_32)
64 cf = _rdrand32_step(&output);
66 cf = _rdrand64_step(
reinterpret_cast<unsigned long long*
>(&output));
70#elif defined(BOTAN_TARGET_ARCH_IS_PPC_FAMILY)
79 asm volatile(
"darn %0, 1" :
"=r"(output));
80 asm volatile(
"darn %0, 1" :
"=r"(output2));
82 if((~output) != 0 && (~output2) != 0) {
96hwrng_output read_hwrng() {
97 for(
size_t i = 0; i < HWRNG_RETRIES; ++i) {
99 const hwrng_output output = read_hwrng(success);
106 throw PRNG_Unseeded(
"Processor RNG instruction failed to produce output within expected iterations");
113#if defined(BOTAN_TARGET_ARCH_IS_X86_FAMILY)
115#elif defined(BOTAN_TARGET_ARCH_IS_PPC_FAMILY)
123#if defined(BOTAN_TARGET_ARCH_IS_X86_FAMILY)
125#elif defined(BOTAN_TARGET_ARCH_IS_PPC_FAMILY)
132void Processor_RNG::fill_bytes_with_input(std::span<uint8_t> out, std::span<const uint8_t> in) {
136 while(out.size() >=
sizeof(hwrng_output)) {
137 const hwrng_output r = read_hwrng();
139 out = out.subspan(
sizeof(hwrng_output));
144 const hwrng_output r = read_hwrng();
145 uint8_t hwrng_bytes[
sizeof(hwrng_output)];
148 for(
size_t i = 0; i != out.size(); ++i) {
149 out[i] = hwrng_bytes[i];
156 throw Invalid_State(
"Current CPU does not support RNG instruction");
static bool has(CPUID::Feature feat)
std::string name() const override
constexpr auto store_le(ParamTs &&... params)