10#include <botan/auto_rng.h>
11#include <botan/system_rng.h>
12#include <botan/internal/ffi_rng.h>
13#include <botan/internal/ffi_util.h>
18#if defined(BOTAN_HAS_HMAC_DRBG)
19 #include <botan/hmac_drbg.h>
22#if defined(BOTAN_HAS_PROCESSOR_RNG)
23 #include <botan/processor_rng.h>
26#if defined(BOTAN_HAS_JITTER_RNG)
27 #include <botan/jitter_rng.h>
30#if defined(BOTAN_HAS_ESDM_RNG)
31 #include <botan/esdm_rng.h>
40 if(rng_out ==
nullptr) {
44 const std::string rng_type_s(rng_type !=
nullptr ? rng_type :
"system");
46 std::unique_ptr<Botan::RandomNumberGenerator> rng;
48 if(rng_type_s ==
"system") {
49 rng = std::make_unique<Botan::System_RNG>();
50 }
else if(rng_type_s ==
"user" || rng_type_s ==
"user-threadsafe") {
51 rng = std::make_unique<Botan::AutoSeeded_RNG>();
52 }
else if(rng_type_s ==
"null") {
53 rng = std::make_unique<Botan::Null_RNG>();
55#if defined(BOTAN_HAS_PROCESSOR_RNG)
57 rng = std::make_unique<Botan::Processor_RNG>();
60#if defined(BOTAN_HAS_JITTER_RNG)
61 else if(rng_type_s ==
"jitter") {
62 rng = std::make_unique<Botan::Jitter_RNG>();
65#if defined(BOTAN_HAS_ESDM_RNG)
66 else if(rng_type_s ==
"esdm-full") {
67 rng = std::make_unique<Botan::ESDM_RNG>(
false);
68 }
else if(rng_type_s ==
"esdm-pr") {
69 rng = std::make_unique<Botan::ESDM_RNG>(
true);
84 int (*get_cb)(
void* context, uint8_t* out,
size_t out_len),
85 int (*add_entropy_cb)(
void* context,
const uint8_t input[],
size_t length),
86 void (*destroy_cb)(
void* context)) {
88 if(rng_out ==
nullptr) {
92 if(rng_name ==
nullptr) {
96 if(get_cb ==
nullptr) {
102 Custom_RNG(std::string_view name,
104 int (*get_cb)(
void* context, uint8_t* out,
size_t out_len),
105 int (*add_entropy_cb)(
void* context,
const uint8_t input[],
size_t length),
106 void (*destroy_cb)(
void* context)) :
110 m_add_entropy_cb(add_entropy_cb),
111 m_destroy_cb(destroy_cb) {}
113 ~Custom_RNG()
override {
115 m_destroy_cb(m_context);
119 Custom_RNG(
const Custom_RNG& other) =
delete;
120 Custom_RNG(Custom_RNG&& other) =
delete;
121 Custom_RNG& operator=(
const Custom_RNG& other) =
delete;
122 Custom_RNG& operator=(Custom_RNG&& other) =
delete;
125 void fill_bytes_with_input(std::span<uint8_t> output, std::span<const uint8_t> input)
override {
126 if(accepts_input() && !input.empty()) {
127 const int rc = m_add_entropy_cb(m_context, input.data(), input.size());
133 if(!output.empty()) {
134 const int rc = m_get_cb(m_context, output.data(), output.size());
142 bool accepts_input()
const override {
return m_add_entropy_cb !=
nullptr; }
144 std::string name()
const override {
return m_name; }
146 void clear()
override {}
148 bool is_seeded()
const override {
return true; }
153 std::function<int(
void* context, uint8_t* out,
size_t out_len)> m_get_cb;
154 std::function<int(
void* context,
const uint8_t input[],
size_t length)> m_add_entropy_cb;
155 std::function<void(
void* context)> m_destroy_cb;
158 auto rng = std::make_unique<Custom_RNG>(rng_name, context, get_cb, add_entropy_cb, destroy_cb);
169 if(out_len > 0 && out ==
nullptr) {
172 return BOTAN_FFI_VISIT(rng, [=](
auto& r) { r.randomize(out, out_len); });
176 if(out_len > 0 && out ==
nullptr) {
190 if(len > 0 && input ==
nullptr) {
193 return BOTAN_FFI_VISIT(rng, [=](
auto& r) { r.add_entropy(input, len); });
202 if(rng_out ==
nullptr || drbg_name ==
nullptr) {
205 if(seed_len > 0 && seed ==
nullptr) {
209 std::unique_ptr<Botan::Stateful_RNG> drbg;
210 const std::string name(drbg_name);
212#if defined(BOTAN_HAS_HMAC_DRBG)
213 if(name.starts_with(
"HMAC_DRBG(") && name.ends_with(
")") && name.size() > 12) {
214 const std::string hash = name.substr(10, name.size() - 11);
215 drbg = std::make_unique<Botan::HMAC_DRBG>(hash);
223 drbg->initialize_with(std::span(seed, seed_len));
225 std::unique_ptr<Botan::RandomNumberGenerator> rng(std::move(drbg));
231 botan_rng_t rng, uint8_t* out,
size_t out_len,
const uint8_t* addl_input,
size_t addl_len) {
232 if(out_len > 0 && out ==
nullptr) {
235 if(addl_len > 0 && addl_input ==
nullptr) {
238 return BOTAN_FFI_VISIT(rng, [=](
auto& r) { r.randomize_with_input({out, out_len}, {addl_input, addl_len}); });
void randomize(std::span< uint8_t > output)
struct botan_rng_struct * botan_rng_t
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
@ BOTAN_FFI_ERROR_NULL_POINTER
int botan_rng_reseed_from_rng(botan_rng_t rng, botan_rng_t source_rng, size_t bits)
int botan_rng_init_drbg(botan_rng_t *rng_out, const char *drbg_name, const uint8_t *seed, size_t seed_len)
int botan_rng_init_custom(botan_rng_t *rng_out, const char *rng_name, void *context, int(*get_cb)(void *context, uint8_t *out, size_t out_len), int(*add_entropy_cb)(void *context, const uint8_t input[], size_t length), void(*destroy_cb)(void *context))
int botan_rng_reseed(botan_rng_t rng, size_t bits)
int botan_rng_add_entropy(botan_rng_t rng, const uint8_t *input, size_t len)
int botan_rng_init(botan_rng_t *rng_out, const char *rng_type)
int botan_system_rng_get(uint8_t *out, size_t out_len)
int botan_rng_get(botan_rng_t rng, uint8_t *out, size_t out_len)
int botan_rng_destroy(botan_rng_t rng)
int botan_rng_generate_with_input(botan_rng_t rng, uint8_t *out, size_t out_len, const uint8_t *addl_input, size_t addl_len)
#define BOTAN_FFI_VISIT(obj, lambda)
#define BOTAN_FFI_CHECKED_DELETE(o)
T & safe_get(botan_struct< T, M > *p)
BOTAN_FFI_ERROR ffi_new_object(T *obj, Args &&... args)
int ffi_guard_thunk(const char *func_name, T thunk)
RandomNumberGenerator & system_rng()