Botan 3.0.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#include <botan/internal/ffi_util.h>
10#include <botan/internal/ffi_rng.h>
11#include <botan/system_rng.h>
12#include <botan/auto_rng.h>
13
14#include <functional>
15#include <memory>
16
17#if defined(BOTAN_HAS_PROCESSOR_RNG)
18#include <botan/processor_rng.h>
19#endif
20
21extern "C" {
22
23using namespace Botan_FFI;
24
25int botan_rng_init(botan_rng_t* rng_out, const char* rng_type)
26 {
27 return ffi_guard_thunk(__func__, [=]() -> int {
28 if(rng_out == nullptr)
30
31 const std::string rng_type_s(rng_type ? rng_type : "system");
32
33 std::unique_ptr<Botan::RandomNumberGenerator> rng;
34
35 if(rng_type_s == "system")
36 {
37 rng = std::make_unique<Botan::System_RNG>();
38 }
39 else if(rng_type_s == "user" || rng_type_s == "user-threadsafe")
40 {
41 rng = std::make_unique<Botan::AutoSeeded_RNG>();
42 }
43 else if(rng_type_s == "null")
44 {
45 rng = std::make_unique<Botan::Null_RNG>();
46 }
47#if defined(BOTAN_HAS_PROCESSOR_RNG)
48 else if((rng_type_s == "rdrand" || rng_type_s == "hwrng") && Botan::Processor_RNG::available())
49 {
50 rng = std::make_unique<Botan::Processor_RNG>();
51 }
52#endif
53
54 if(!rng)
55 {
57 }
58
59 *rng_out = new botan_rng_struct(std::move(rng));
60 return BOTAN_FFI_SUCCESS;
61 });
62 }
63
64int botan_rng_init_custom(botan_rng_t* rng_out, const char* rng_name, void* context,
65 int(* get_cb)(void* context, uint8_t* out, size_t out_len),
66 int(* add_entropy_cb)(void* context, const uint8_t input[], size_t length),
67 void(* destroy_cb)(void* context))
68 {
69 return ffi_guard_thunk(__func__,[=]() -> int {
70 if(rng_out == nullptr)
72
73 if(rng_name == nullptr)
75
76 if(get_cb == nullptr)
78
79 class Custom_RNG : public Botan::RandomNumberGenerator
80 {
81 public:
82 Custom_RNG(std::string_view name, void* context,
83 int(* get_cb)(void* context, uint8_t* out, size_t out_len),
84 int(* add_entropy_cb)(void* context, const uint8_t input[], size_t length),
85 void(* destroy_cb)(void* context)) :
86 m_name(name)
87 {
88 m_context = context;
89 m_get_cb = get_cb;
90 m_add_entropy_cb = add_entropy_cb;
91 m_destroy_cb = destroy_cb;
92 }
93
94 ~Custom_RNG() override
95 {
96 if(m_destroy_cb)
97 {
98 m_destroy_cb(m_context);
99 }
100 }
101
102 Custom_RNG(const Custom_RNG& other) = delete;
103 Custom_RNG(Custom_RNG&& other) = delete;
104 Custom_RNG& operator=(const Custom_RNG& other) = delete;
105 Custom_RNG& operator=(Custom_RNG&& other) = delete;
106
107 protected:
108 void fill_bytes_with_input(std::span<uint8_t> output, std::span<const uint8_t> input) override
109 {
110 if(accepts_input() && !input.empty())
111 {
112 int rc = m_add_entropy_cb(m_context, input.data(), input.size());
113 if(rc)
114 {
115 throw Botan::Invalid_State("Failed to add entropy via C callback, rc=" + std::to_string(rc));
116 }
117 }
118
119 if(!output.empty())
120 {
121 int rc = m_get_cb(m_context, output.data(), output.size());
122 if(rc)
123 {
124 throw Botan::Invalid_State("Failed to get random from C callback, rc=" + std::to_string(rc));
125 }
126 }
127 }
128
129 public:
130 bool accepts_input() const override
131 {
132 return m_add_entropy_cb != nullptr;
133 }
134
135 std::string name() const override
136 {
137 return m_name;
138 }
139
140 void clear() override
141 {
142 }
143
144 bool is_seeded() const override
145 {
146 return true;
147 }
148
149 private:
150 std::string m_name;
151 void* m_context;
152 std::function<int(void* context, uint8_t* out, size_t out_len)> m_get_cb;
153 std::function<int(void* context, const uint8_t input[], size_t length)> m_add_entropy_cb;
154 std::function<void(void* context)> m_destroy_cb;
155 };
156
157 auto rng = std::make_unique<Custom_RNG>(rng_name, context, get_cb, add_entropy_cb, destroy_cb);
158
159 *rng_out = new botan_rng_struct(std::move(rng));
160 return BOTAN_FFI_SUCCESS;
161 });
162 }
163
165 {
166 return BOTAN_FFI_CHECKED_DELETE(rng);
167 }
168
169int botan_rng_get(botan_rng_t rng, uint8_t* out, size_t out_len)
170 {
171 return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.randomize(out, out_len); });
172 }
173
174int botan_system_rng_get(uint8_t* out, size_t out_len)
175 {
176 return ffi_guard_thunk(__func__, [=]() -> int
177 {
178 Botan::system_rng().randomize(out, out_len);
179 return BOTAN_FFI_SUCCESS;
180 });
181 }
182
183int botan_rng_reseed(botan_rng_t rng, size_t bits)
184 {
185 return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.reseed_from_rng(Botan::system_rng(), bits); });
186 }
187
188int botan_rng_add_entropy(botan_rng_t rng, const uint8_t* input, size_t len)
189 {
190 return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.add_entropy(input, len); });
191 }
192
193int botan_rng_reseed_from_rng(botan_rng_t rng, botan_rng_t source_rng, size_t bits)
194 {
195 return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.reseed_from_rng(safe_get(source_rng), bits); });
196 }
197
198}
static bool available()
void randomize(std::span< uint8_t > output)
Definition: rng.h:53
std::string name
struct botan_rng_struct * botan_rng_t
Definition: ffi.h:229
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
Definition: ffi.h:91
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition: ffi.h:85
@ BOTAN_FFI_SUCCESS
Definition: ffi.h:70
int botan_rng_reseed_from_rng(botan_rng_t rng, botan_rng_t source_rng, size_t bits)
Definition: ffi_rng.cpp:193
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:64
int botan_rng_reseed(botan_rng_t rng, size_t bits)
Definition: ffi_rng.cpp:183
int botan_rng_add_entropy(botan_rng_t rng, const uint8_t *input, size_t len)
Definition: ffi_rng.cpp:188
int botan_rng_init(botan_rng_t *rng_out, const char *rng_type)
Definition: ffi_rng.cpp:25
int botan_system_rng_get(uint8_t *out, size_t out_len)
Definition: ffi_rng.cpp:174
int botan_rng_get(botan_rng_t rng, uint8_t *out, size_t out_len)
Definition: ffi_rng.cpp:169
int botan_rng_destroy(botan_rng_t rng)
Definition: ffi_rng.cpp:164
#define BOTAN_FFI_VISIT(obj, lambda)
Definition: ffi_util.h:126
#define BOTAN_FFI_CHECKED_DELETE(o)
Definition: ffi_util.h:145
T & safe_get(botan_struct< T, M > *p)
Definition: ffi_util.h:69
int ffi_guard_thunk(const char *func_name, const std::function< int()> &thunk)
Definition: ffi.cpp:120
RandomNumberGenerator & system_rng()
Definition: system_rng.cpp:376