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