Botan 3.9.0
Crypto and TLS for C&
ffi_rng.cpp
Go to the documentation of this file.
1/*
2* (C) 2015,2017 Jack Lloyd
3* (C) 2021 René Fischer
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/ffi.h>
9
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>
14
15#include <functional>
16#include <memory>
17
18#if defined(BOTAN_HAS_PROCESSOR_RNG)
19 #include <botan/processor_rng.h>
20#endif
21
22#if defined(BOTAN_HAS_JITTER_RNG)
23 #include <botan/jitter_rng.h>
24#endif
25#if defined(BOTAN_HAS_ESDM_RNG)
26 #include <botan/esdm_rng.h>
27#endif
28
29extern "C" {
30
31using namespace Botan_FFI;
32
33int botan_rng_init(botan_rng_t* rng_out, const char* rng_type) {
34 return ffi_guard_thunk(__func__, [=]() -> int {
35 if(rng_out == nullptr) {
37 }
38
39 const std::string rng_type_s(rng_type != nullptr ? rng_type : "system");
40
41 std::unique_ptr<Botan::RandomNumberGenerator> rng;
42
43 if(rng_type_s == "system") {
44 rng = std::make_unique<Botan::System_RNG>();
45 } else if(rng_type_s == "user" || rng_type_s == "user-threadsafe") {
46 rng = std::make_unique<Botan::AutoSeeded_RNG>();
47 } else if(rng_type_s == "null") {
48 rng = std::make_unique<Botan::Null_RNG>();
49 }
50#if defined(BOTAN_HAS_PROCESSOR_RNG)
51 else if((rng_type_s == "rdrand" || rng_type_s == "hwrng") && Botan::Processor_RNG::available()) {
52 rng = std::make_unique<Botan::Processor_RNG>();
53 }
54#endif
55#if defined(BOTAN_HAS_JITTER_RNG)
56 else if(rng_type_s == "jitter") {
57 rng = std::make_unique<Botan::Jitter_RNG>();
58 }
59#endif
60#if defined(BOTAN_HAS_ESDM_RNG)
61 else if(rng_type_s == "esdm-full") {
62 rng = std::make_unique<Botan::ESDM_RNG>(false);
63 } else if(rng_type_s == "esdm-pr") {
64 rng = std::make_unique<Botan::ESDM_RNG>(true);
65 }
66#endif
67
68 if(!rng) {
70 }
71
72 return ffi_new_object(rng_out, std::move(rng));
73 });
74}
75
77 const char* rng_name,
78 void* context,
79 int (*get_cb)(void* context, uint8_t* out, size_t out_len),
80 int (*add_entropy_cb)(void* context, const uint8_t input[], size_t length),
81 void (*destroy_cb)(void* context)) {
82 return ffi_guard_thunk(__func__, [=]() -> int {
83 if(rng_out == nullptr) {
85 }
86
87 if(rng_name == nullptr) {
89 }
90
91 if(get_cb == nullptr) {
93 }
94
95 class Custom_RNG : public Botan::RandomNumberGenerator {
96 public:
97 Custom_RNG(std::string_view name,
98 void* context,
99 int (*get_cb)(void* context, uint8_t* out, size_t out_len),
100 int (*add_entropy_cb)(void* context, const uint8_t input[], size_t length),
101 void (*destroy_cb)(void* context)) :
102 m_name(name),
103 m_context(context),
104 m_get_cb(get_cb),
105 m_add_entropy_cb(add_entropy_cb),
106 m_destroy_cb(destroy_cb) {}
107
108 ~Custom_RNG() override {
109 if(m_destroy_cb) {
110 m_destroy_cb(m_context);
111 }
112 }
113
114 Custom_RNG(const Custom_RNG& other) = delete;
115 Custom_RNG(Custom_RNG&& other) = delete;
116 Custom_RNG& operator=(const Custom_RNG& other) = delete;
117 Custom_RNG& operator=(Custom_RNG&& other) = delete;
118
119 protected:
120 void fill_bytes_with_input(std::span<uint8_t> output, std::span<const uint8_t> input) override {
121 if(accepts_input() && !input.empty()) {
122 int rc = m_add_entropy_cb(m_context, input.data(), input.size());
123 if(rc != 0) {
124 throw Botan::Invalid_State("Failed to add entropy via C callback, rc=" + std::to_string(rc));
125 }
126 }
127
128 if(!output.empty()) {
129 int rc = m_get_cb(m_context, output.data(), output.size());
130 if(rc != 0) {
131 throw Botan::Invalid_State("Failed to get random from C callback, rc=" + std::to_string(rc));
132 }
133 }
134 }
135
136 public:
137 bool accepts_input() const override { return m_add_entropy_cb != nullptr; }
138
139 std::string name() const override { return m_name; }
140
141 void clear() override {}
142
143 bool is_seeded() const override { return true; }
144
145 private:
146 std::string m_name;
147 void* m_context;
148 std::function<int(void* context, uint8_t* out, size_t out_len)> m_get_cb;
149 std::function<int(void* context, const uint8_t input[], size_t length)> m_add_entropy_cb;
150 std::function<void(void* context)> m_destroy_cb;
151 };
152
153 auto rng = std::make_unique<Custom_RNG>(rng_name, context, get_cb, add_entropy_cb, destroy_cb);
154
155 return ffi_new_object(rng_out, std::move(rng));
156 });
157}
158
162
163int botan_rng_get(botan_rng_t rng, uint8_t* out, size_t out_len) {
164 return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.randomize(out, out_len); });
165}
166
167int botan_system_rng_get(uint8_t* out, size_t out_len) {
168 return ffi_guard_thunk(__func__, [=]() -> int {
169 Botan::system_rng().randomize(out, out_len);
170 return BOTAN_FFI_SUCCESS;
171 });
172}
173
174int botan_rng_reseed(botan_rng_t rng, size_t bits) {
175 return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.reseed_from_rng(Botan::system_rng(), bits); });
176}
177
178int botan_rng_add_entropy(botan_rng_t rng, const uint8_t* input, size_t len) {
179 return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.add_entropy(input, len); });
180}
181
182int botan_rng_reseed_from_rng(botan_rng_t rng, botan_rng_t source_rng, size_t bits) {
183 return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.reseed_from_rng(safe_get(source_rng), bits); });
184}
185}
void randomize(std::span< uint8_t > output)
Definition rng.h:71
struct botan_rng_struct * botan_rng_t
Definition ffi.h:289
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
Definition ffi.h:138
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition ffi.h:132
@ BOTAN_FFI_SUCCESS
Definition ffi.h:115
int botan_rng_reseed_from_rng(botan_rng_t rng, botan_rng_t source_rng, size_t bits)
Definition ffi_rng.cpp:182
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))
Definition ffi_rng.cpp:76
int botan_rng_reseed(botan_rng_t rng, size_t bits)
Definition ffi_rng.cpp:174
int botan_rng_add_entropy(botan_rng_t rng, const uint8_t *input, size_t len)
Definition ffi_rng.cpp:178
int botan_rng_init(botan_rng_t *rng_out, const char *rng_type)
Definition ffi_rng.cpp:33
int botan_system_rng_get(uint8_t *out, size_t out_len)
Definition ffi_rng.cpp:167
int botan_rng_get(botan_rng_t rng, uint8_t *out, size_t out_len)
Definition ffi_rng.cpp:163
int botan_rng_destroy(botan_rng_t rng)
Definition ffi_rng.cpp:159
#define BOTAN_FFI_VISIT(obj, lambda)
Definition ffi_util.h:158
#define BOTAN_FFI_CHECKED_DELETE(o)
Definition ffi_util.h:185
T & safe_get(botan_struct< T, M > *p)
Definition ffi_util.h:79
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
RandomNumberGenerator & system_rng()