8#include <botan/system_rng.h>
10#if defined(BOTAN_TARGET_OS_HAS_RTLGENRANDOM)
11 #include <botan/dyn_load.h>
16#elif defined(BOTAN_TARGET_OS_HAS_CRYPTO_NG)
19#elif defined(BOTAN_TARGET_OS_HAS_ARC4RANDOM)
22#elif defined(BOTAN_TARGET_OS_HAS_GETRANDOM)
23 #include <sys/random.h>
26#elif defined(BOTAN_TARGET_OS_HAS_DEV_RANDOM)
27 #include <sys/types.h>
38#if defined(BOTAN_TARGET_OS_HAS_RTLGENRANDOM)
40class System_RNG_Impl
final :
public RandomNumberGenerator
43 System_RNG_Impl() : m_advapi(
"advapi32.dll")
46 m_rtlgenrandom = m_advapi.resolve<RtlGenRandom_fptr>(
"SystemFunction036");
49 void randomize(uint8_t buf[],
size_t len)
override
51 bool success = m_rtlgenrandom(buf, ULONG(len)) ==
TRUE;
53 throw System_Error(
"RtlGenRandom failed");
56 void add_entropy(
const uint8_t[],
size_t)
override { }
57 bool is_seeded()
const override {
return true; }
58 bool accepts_input()
const override {
return false; }
59 void clear()
override { }
60 std::string
name()
const override {
return "RtlGenRandom"; }
65 using RtlGenRandom_fptr = BYTE (NTAPI *)(PVOID, ULONG);
67 Dynamically_Loaded_Library m_advapi;
68 RtlGenRandom_fptr m_rtlgenrandom;
71#elif defined(BOTAN_TARGET_OS_HAS_CRYPTO_NG)
73class System_RNG_Impl
final :
public RandomNumberGenerator
78 NTSTATUS ret = ::BCryptOpenAlgorithmProvider(&m_prov,
80 MS_PRIMITIVE_PROVIDER, 0);
81 if(ret != STATUS_SUCCESS)
82 throw System_Error(
"System_RNG failed to acquire crypto provider", ret);
87 ::BCryptCloseAlgorithmProvider(m_prov, 0);
90 void randomize(uint8_t buf[],
size_t len)
override
92 NTSTATUS ret = ::BCryptGenRandom(m_prov,
static_cast<PUCHAR
>(buf),
static_cast<ULONG
>(len), 0);
93 if(ret != STATUS_SUCCESS)
94 throw System_Error(
"System_RNG call to BCryptGenRandom failed", ret);
97 void add_entropy(
const uint8_t in[],
size_t length)
override
105 bool is_seeded()
const override {
return true; }
106 bool accepts_input()
const override {
return false; }
107 void clear()
override { }
108 std::string
name()
const override {
return "crypto_ng"; }
110 BCRYPT_ALG_HANDLE m_prov;
113#elif defined(BOTAN_TARGET_OS_HAS_ARC4RANDOM)
115class System_RNG_Impl
final :
public RandomNumberGenerator
120 void randomize(uint8_t buf[],
size_t len)
override
125 ::arc4random_buf(buf, len);
129 bool accepts_input()
const override {
return false; }
130 void add_entropy(
const uint8_t[],
size_t)
override { }
131 bool is_seeded()
const override {
return true; }
132 void clear()
override { }
133 std::string
name()
const override {
return "arc4random"; }
136#elif defined(BOTAN_TARGET_OS_HAS_GETRANDOM)
138class System_RNG_Impl
final :
public RandomNumberGenerator
143 void randomize(uint8_t buf[],
size_t len)
override
145 const unsigned int flags = 0;
149 const ssize_t got = ::getrandom(buf, len, flags);
155 throw System_Error(
"System_RNG getrandom failed", errno);
163 bool accepts_input()
const override {
return false; }
164 void add_entropy(
const uint8_t[],
size_t)
override { }
165 bool is_seeded()
const override {
return true; }
166 void clear()
override { }
167 std::string
name()
const override {
return "getrandom"; }
171#elif defined(BOTAN_TARGET_OS_HAS_DEV_RANDOM)
175class System_RNG_Impl
final :
public RandomNumberGenerator
184 m_fd = ::open(BOTAN_SYSTEM_RNG_DEVICE, O_RDWR |
O_NOCTTY);
196 m_fd = ::open(BOTAN_SYSTEM_RNG_DEVICE, O_RDONLY |
O_NOCTTY);
201 throw System_Error(
"System_RNG failed to open RNG device", errno);
210 void randomize(uint8_t buf[],
size_t len)
override;
211 void add_entropy(
const uint8_t in[],
size_t length)
override;
212 bool is_seeded()
const override {
return true; }
213 bool accepts_input()
const override {
return m_writable; }
214 void clear()
override { }
215 std::string
name()
const override {
return BOTAN_SYSTEM_RNG_DEVICE; }
221void System_RNG_Impl::randomize(uint8_t buf[],
size_t len)
225 ssize_t got = ::read(m_fd, buf, len);
231 throw System_Error(
"System_RNG read failed", errno);
234 throw System_Error(
"System_RNG EOF on device");
241void System_RNG_Impl::add_entropy(
const uint8_t input[],
size_t len)
248 ssize_t got = ::write(m_fd, input, len);
267 if(errno == EPERM || errno == EBADF)
271 throw System_Error(
"System_RNG write failed", errno);
285 static System_RNG_Impl g_system_rng;
int(* final)(unsigned char *, CTX *)
RandomNumberGenerator & system_rng()