8 #include <botan/system_rng.h>
10 #if defined(BOTAN_TARGET_OS_HAS_RTLGENRANDOM)
11 #include <botan/dyn_load.h>
13 #define _WINSOCKAPI_ // stop windows.h including winsock.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)
40 class 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)
73 class 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)
115 class System_RNG_Impl
final :
public RandomNumberGenerator
120 void randomize(uint8_t buf[],
size_t len)
override
122 ::arc4random_buf(buf, len);
125 bool accepts_input()
const override {
return false; }
126 void add_entropy(
const uint8_t[],
size_t)
override { }
127 bool is_seeded()
const override {
return true; }
128 void clear()
override { }
129 std::string
name()
const override {
return "arc4random"; }
132 #elif defined(BOTAN_TARGET_OS_HAS_GETRANDOM)
134 class System_RNG_Impl
final :
public RandomNumberGenerator
139 void randomize(uint8_t buf[],
size_t len)
override
141 const unsigned int flags = 0;
145 const ssize_t got = ::getrandom(buf, len, flags);
151 throw System_Error(
"System_RNG getrandom failed", errno);
159 bool accepts_input()
const override {
return false; }
160 void add_entropy(
const uint8_t[],
size_t)
override { }
161 bool is_seeded()
const override {
return true; }
162 void clear()
override { }
163 std::string
name()
const override {
return "getrandom"; }
167 #elif defined(BOTAN_TARGET_OS_HAS_DEV_RANDOM)
171 class System_RNG_Impl
final :
public RandomNumberGenerator
180 m_fd = ::open(BOTAN_SYSTEM_RNG_DEVICE, O_RDWR |
O_NOCTTY);
192 m_fd = ::open(BOTAN_SYSTEM_RNG_DEVICE, O_RDONLY |
O_NOCTTY);
197 throw System_Error(
"System_RNG failed to open RNG device", errno);
206 void randomize(uint8_t buf[],
size_t len)
override;
207 void add_entropy(
const uint8_t in[],
size_t length)
override;
208 bool is_seeded()
const override {
return true; }
209 bool accepts_input()
const override {
return m_writable; }
210 void clear()
override { }
211 std::string
name()
const override {
return BOTAN_SYSTEM_RNG_DEVICE; }
217 void System_RNG_Impl::randomize(uint8_t buf[],
size_t len)
221 ssize_t got = ::read(m_fd, buf, len);
227 throw System_Error(
"System_RNG read failed", errno);
230 throw System_Error(
"System_RNG EOF on device");
237 void System_RNG_Impl::add_entropy(
const uint8_t input[],
size_t len)
244 ssize_t got = ::write(m_fd, input, len);
263 if(errno == EPERM || errno == EBADF)
267 throw System_Error(
"System_RNG write failed", errno);
281 static System_RNG_Impl g_system_rng;
RandomNumberGenerator & system_rng()
int(* final)(unsigned char *, CTX *)