Botan 3.12.0
Crypto and TLS for C&
ffi_rng.cpp File Reference
#include <botan/ffi.h>
#include <botan/auto_rng.h>
#include <botan/system_rng.h>
#include <botan/internal/ffi_rng.h>
#include <botan/internal/ffi_util.h>
#include <functional>
#include <memory>

Go to the source code of this file.

Functions

int botan_rng_add_entropy (botan_rng_t rng, const uint8_t *input, size_t 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)
int botan_rng_get (botan_rng_t rng, uint8_t *out, size_t out_len)
int botan_rng_init (botan_rng_t *rng_out, const char *rng_type)
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_init_drbg (botan_rng_t *rng_out, const char *drbg_name, const uint8_t *seed, size_t seed_len)
int botan_rng_reseed (botan_rng_t rng, size_t bits)
int botan_rng_reseed_from_rng (botan_rng_t rng, botan_rng_t source_rng, size_t bits)
int botan_system_rng_get (uint8_t *out, size_t out_len)

Function Documentation

◆ botan_rng_add_entropy()

int botan_rng_add_entropy ( botan_rng_t rng,
const uint8_t * entropy,
size_t entropy_len )

Add some seed material to a random number generator

Parameters
Random Number Generatorsrng object
Entropy Collectionthe data to add
entropy_lenlength of entropy buffer
Returns
0 on success, a negative value on failure

Definition at line 189 of file ffi_rng.cpp.

189 {
190 if(len > 0 && input == nullptr) {
192 }
193 return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.add_entropy(input, len); });
194}
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition ffi.h:133
#define BOTAN_FFI_VISIT(obj, lambda)
Definition ffi_util.h:158

References BOTAN_FFI_ERROR_NULL_POINTER, and BOTAN_FFI_VISIT.

◆ botan_rng_destroy()

int botan_rng_destroy ( botan_rng_t rng)

Frees all resources of the random number generator object

Parameters
Random Number Generatorsrng object
Returns
0 if success, error if invalid object handle

Definition at line 164 of file ffi_rng.cpp.

164 {
165 return BOTAN_FFI_CHECKED_DELETE(rng);
166}
#define BOTAN_FFI_CHECKED_DELETE(o)
Definition ffi_util.h:188

References BOTAN_FFI_CHECKED_DELETE.

◆ botan_rng_generate_with_input()

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 )

Generate random bytes from an RNG with additional input.

For a DRBG, the additional input is mixed in before generating. Many other RNG types (eg RDRAND or system RNG) will ignore the input.

Parameters
Random Number Generatorsthe RNG object
outoutput buffer
out_lennumber of bytes to generate
addl_inputadditional input to mix in (may be NULL if addl_len is 0)
addl_lenlength of additional input
Returns
0 on success, negative on failure

Definition at line 230 of file ffi_rng.cpp.

231 {
232 if(out_len > 0 && out == nullptr) {
234 }
235 if(addl_len > 0 && addl_input == nullptr) {
237 }
238 return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.randomize_with_input({out, out_len}, {addl_input, addl_len}); });
239}

References BOTAN_FFI_ERROR_NULL_POINTER, and BOTAN_FFI_VISIT.

◆ botan_rng_get()

int botan_rng_get ( botan_rng_t rng,
uint8_t * out,
size_t out_len )

Get random bytes from a random number generator

Parameters
Random Number Generatorsrng object
outoutput buffer of size out_len
out_lennumber of requested bytes
Returns
0 on success, negative on failure

Definition at line 168 of file ffi_rng.cpp.

168 {
169 if(out_len > 0 && out == nullptr) {
171 }
172 return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.randomize(out, out_len); });
173}

References BOTAN_FFI_ERROR_NULL_POINTER, and BOTAN_FFI_VISIT.

◆ botan_rng_init()

int botan_rng_init ( botan_rng_t * rng,
const char * rng_type )

Initialize a random number generator object

Parameters
Random Number Generatorsrng object
rng_typetype of the rng, possible values: "system": system RNG "esdm-full": ESDM RNG (fully seeded) "esdm-pr": ESDM RNG (w. prediction resistance) "user": userspace RNG "user-threadsafe": userspace RNG, with internal locking "rdrand": directly read RDRAND Set rng_type to null to let the library choose some default.

Definition at line 38 of file ffi_rng.cpp.

38 {
39 return ffi_guard_thunk(__func__, [=]() -> int {
40 if(rng_out == nullptr) {
42 }
43
44 const std::string rng_type_s(rng_type != nullptr ? rng_type : "system");
45
46 std::unique_ptr<Botan::RandomNumberGenerator> rng;
47
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>();
54 }
55#if defined(BOTAN_HAS_PROCESSOR_RNG)
56 else if((rng_type_s == "rdrand" || rng_type_s == "hwrng") && Botan::Processor_RNG::available()) {
57 rng = std::make_unique<Botan::Processor_RNG>();
58 }
59#endif
60#if defined(BOTAN_HAS_JITTER_RNG)
61 else if(rng_type_s == "jitter") {
62 rng = std::make_unique<Botan::Jitter_RNG>();
63 }
64#endif
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);
70 }
71#endif
72
73 if(!rng) {
75 }
76
77 return ffi_new_object(rng_out, std::move(rng));
78 });
79}
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
Definition ffi.h:140
BOTAN_FFI_ERROR ffi_new_object(T *obj, Args &&... args)
Definition ffi_util.h:178
int ffi_guard_thunk(const char *func_name, T thunk)
Definition ffi_util.h:95

References Botan::Processor_RNG::available(), BOTAN_FFI_ERROR_NOT_IMPLEMENTED, BOTAN_FFI_ERROR_NULL_POINTER, Botan_FFI::ffi_guard_thunk(), and Botan_FFI::ffi_new_object().

◆ botan_rng_init_custom()

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) )

Initialize a custom random number generator from a set of callback functions

Parameters
rng_outrng object to create
rng_namename of the rng
contextAn application-specific context passed to the callback functions
get_cbCallback for getting random bytes from the rng, return 0 for success
add_entropy_cbCallback for adding entropy to the rng, return 0 for success, may be NULL
destroy_cbCallback called when rng is destroyed, may be NULL

Definition at line 81 of file ffi_rng.cpp.

86 {
87 return ffi_guard_thunk(__func__, [=]() -> int {
88 if(rng_out == nullptr) {
90 }
91
92 if(rng_name == nullptr) {
94 }
95
96 if(get_cb == nullptr) {
98 }
99
100 class Custom_RNG final : public Botan::RandomNumberGenerator {
101 public:
102 Custom_RNG(std::string_view name,
103 void* context,
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)) :
107 m_name(name),
108 m_context(context),
109 m_get_cb(get_cb),
110 m_add_entropy_cb(add_entropy_cb),
111 m_destroy_cb(destroy_cb) {}
112
113 ~Custom_RNG() override {
114 if(m_destroy_cb) {
115 m_destroy_cb(m_context);
116 }
117 }
118
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;
123
124 protected:
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());
128 if(rc != 0) {
129 throw Botan::Invalid_State("Failed to add entropy via C callback, rc=" + std::to_string(rc));
130 }
131 }
132
133 if(!output.empty()) {
134 const int rc = m_get_cb(m_context, output.data(), output.size());
135 if(rc != 0) {
136 throw Botan::Invalid_State("Failed to get random from C callback, rc=" + std::to_string(rc));
137 }
138 }
139 }
140
141 public:
142 bool accepts_input() const override { return m_add_entropy_cb != nullptr; }
143
144 std::string name() const override { return m_name; }
145
146 void clear() override {}
147
148 bool is_seeded() const override { return true; }
149
150 private:
151 std::string m_name;
152 void* m_context;
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;
156 };
157
158 auto rng = std::make_unique<Custom_RNG>(rng_name, context, get_cb, add_entropy_cb, destroy_cb);
159
160 return ffi_new_object(rng_out, std::move(rng));
161 });
162}

References BOTAN_FFI_ERROR_NULL_POINTER, Botan_FFI::ffi_guard_thunk(), and Botan_FFI::ffi_new_object().

◆ botan_rng_init_drbg()

int botan_rng_init_drbg ( botan_rng_t * rng_out,
const char * drbg_name,
const uint8_t * seed,
size_t seed_len )

Create and seed a DRBG

Parameters
rng_outthe new DRBG object
drbg_namethe name of the DRBG (e.g. "HMAC_DRBG(SHA-256)")
SEEDthe seed material (entropy || nonce || personalization_string)
seed_lenlength of seed in bytes
Returns
0 on success, negative on failure

Definition at line 200 of file ffi_rng.cpp.

200 {
201 return ffi_guard_thunk(__func__, [=]() -> int {
202 if(rng_out == nullptr || drbg_name == nullptr) {
204 }
205 if(seed_len > 0 && seed == nullptr) {
207 }
208
209 std::unique_ptr<Botan::Stateful_RNG> drbg;
210 const std::string name(drbg_name);
211
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);
216 }
217#endif
218
219 if(!drbg) {
221 }
222
223 drbg->initialize_with(std::span(seed, seed_len));
224 // Upcast to RandomNumberGenerator for the FFI object
225 std::unique_ptr<Botan::RandomNumberGenerator> rng(std::move(drbg));
226 return ffi_new_object(rng_out, std::move(rng));
227 });
228}

References BOTAN_FFI_ERROR_NOT_IMPLEMENTED, BOTAN_FFI_ERROR_NULL_POINTER, Botan_FFI::ffi_guard_thunk(), and Botan_FFI::ffi_new_object().

◆ botan_rng_reseed()

int botan_rng_reseed ( botan_rng_t rng,
size_t bits )

Reseed a random number generator Uses the System_RNG as a seed generator.

Parameters
Random Number Generatorsrng object
bitsnumber of bits to reseed with
Returns
0 on success, a negative value on failure

Definition at line 185 of file ffi_rng.cpp.

185 {
186 return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.reseed_from_rng(Botan::system_rng(), bits); });
187}
RandomNumberGenerator & system_rng()

References BOTAN_FFI_VISIT, and Botan::system_rng().

◆ botan_rng_reseed_from_rng()

int botan_rng_reseed_from_rng ( botan_rng_t rng,
botan_rng_t source_rng,
size_t bits )

Reseed a random number generator

Parameters
Random Number Generatorsrng object
source_rngthe rng that will be read from
bitsnumber of bits to reseed with
Returns
0 on success, a negative value on failure

Definition at line 196 of file ffi_rng.cpp.

196 {
197 return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.reseed_from_rng(safe_get(source_rng), bits); });
198}
T & safe_get(botan_struct< T, M > *p)
Definition ffi_util.h:79

References BOTAN_FFI_VISIT, and Botan_FFI::safe_get().

◆ botan_system_rng_get()

int botan_system_rng_get ( uint8_t * out,
size_t out_len )

Get random bytes from system random number generator

Parameters
outoutput buffer of size out_len
out_lennumber of requested bytes
Returns
0 on success, negative on failure

Definition at line 175 of file ffi_rng.cpp.

175 {
176 if(out_len > 0 && out == nullptr) {
178 }
179 return ffi_guard_thunk(__func__, [=]() -> int {
180 Botan::system_rng().randomize(out, out_len);
181 return BOTAN_FFI_SUCCESS;
182 });
183}
void randomize(std::span< uint8_t > output)
Definition rng.h:75
@ BOTAN_FFI_SUCCESS
Definition ffi.h:116

References BOTAN_FFI_ERROR_NULL_POINTER, BOTAN_FFI_SUCCESS, Botan_FFI::ffi_guard_thunk(), Botan::RandomNumberGenerator::randomize(), and Botan::system_rng().