• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 16249365818

13 Jul 2025 12:56PM UTC coverage: 90.618% (+0.002%) from 90.616%
16249365818

Pull #4985

github

web-flow
Merge 34acb0b10 into cf74a5db8
Pull Request #4985: Enable and fix clang-tidy warning cppcoreguidelines-prefer-member-initializer

99527 of 109831 relevant lines covered (90.62%)

12274327.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.96
/src/lib/ffi/ffi_rng.cpp
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

29
extern "C" {
30

31
using namespace Botan_FFI;
32

33
int botan_rng_init(botan_rng_t* rng_out, const char* rng_type) {
92✔
34
   return ffi_guard_thunk(__func__, [=]() -> int {
92✔
35
      if(rng_out == nullptr) {
92✔
36
         return BOTAN_FFI_ERROR_NULL_POINTER;
37
      }
38

39
      const std::string rng_type_s(rng_type ? rng_type : "system");
184✔
40

41
      std::unique_ptr<Botan::RandomNumberGenerator> rng;
92✔
42

43
      if(rng_type_s == "system") {
92✔
44
         rng = std::make_unique<Botan::System_RNG>();
75✔
45
      } else if(rng_type_s == "user" || rng_type_s == "user-threadsafe") {
17✔
46
         rng = std::make_unique<Botan::AutoSeeded_RNG>();
11✔
47
      } else if(rng_type_s == "null") {
6✔
48
         rng = std::make_unique<Botan::Null_RNG>();
1✔
49
      }
50
#if defined(BOTAN_HAS_PROCESSOR_RNG)
51
      else if((rng_type_s == "rdrand" || rng_type_s == "hwrng") && Botan::Processor_RNG::available()) {
5✔
52
         rng = std::make_unique<Botan::Processor_RNG>();
1✔
53
      }
54
#endif
55
#if defined(BOTAN_HAS_JITTER_RNG)
56
      else if(rng_type_s == "jitter") {
4✔
57
         rng = std::make_unique<Botan::Jitter_RNG>();
1✔
58
      }
59
#endif
60
#if defined(BOTAN_HAS_ESDM_RNG)
61
      else if(rng_type_s == "esdm-full") {
3✔
62
         rng = std::make_unique<Botan::ESDM_RNG>(false);
1✔
63
      } else if(rng_type_s == "esdm-pr") {
2✔
64
         rng = std::make_unique<Botan::ESDM_RNG>(true);
1✔
65
      }
66
#endif
67

68
      if(!rng) {
92✔
69
         return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
70
      }
71

72
      return ffi_new_object(rng_out, std::move(rng));
91✔
73
   });
92✔
74
}
75

76
int botan_rng_init_custom(botan_rng_t* rng_out,
1✔
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 {
1✔
83
      if(rng_out == nullptr) {
1✔
84
         return BOTAN_FFI_ERROR_NULL_POINTER;
85
      }
86

87
      if(rng_name == nullptr) {
1✔
88
         return BOTAN_FFI_ERROR_NULL_POINTER;
89
      }
90

91
      if(get_cb == nullptr) {
1✔
92
         return BOTAN_FFI_ERROR_NULL_POINTER;
93
      }
94

95
      class Custom_RNG : public Botan::RandomNumberGenerator {
1✔
96
         public:
97
            Custom_RNG(std::string_view name,
1✔
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)) :
1✔
102
                  m_name(name),
1✔
103
                  m_context(context),
1✔
104
                  m_get_cb(get_cb),
1✔
105
                  m_add_entropy_cb(add_entropy_cb),
1✔
106
                  m_destroy_cb(destroy_cb) {}
2✔
107

108
            ~Custom_RNG() override {
2✔
109
               if(m_destroy_cb) {
1✔
110
                  m_destroy_cb(m_context);
1✔
111
               }
112
            }
5✔
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 {
4✔
121
               if(accepts_input() && !input.empty()) {
4✔
122
                  int rc = m_add_entropy_cb(m_context, input.data(), input.size());
3✔
123
                  if(rc) {
3✔
124
                     throw Botan::Invalid_State("Failed to add entropy via C callback, rc=" + std::to_string(rc));
×
125
                  }
126
               }
127

128
               if(!output.empty()) {
4✔
129
                  int rc = m_get_cb(m_context, output.data(), output.size());
1✔
130
                  if(rc) {
1✔
131
                     throw Botan::Invalid_State("Failed to get random from C callback, rc=" + std::to_string(rc));
×
132
                  }
133
               }
134
            }
4✔
135

136
         public:
137
            bool accepts_input() const override { return m_add_entropy_cb != nullptr; }
4✔
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);
1✔
154

155
      return ffi_new_object(rng_out, std::move(rng));
1✔
156
   });
1✔
157
}
158

159
int botan_rng_destroy(botan_rng_t rng) {
103✔
160
   return BOTAN_FFI_CHECKED_DELETE(rng);
103✔
161
}
162

163
int botan_rng_get(botan_rng_t rng, uint8_t* out, size_t out_len) {
66✔
164
   return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.randomize(out, out_len); });
132✔
165
}
166

167
int botan_system_rng_get(uint8_t* out, size_t out_len) {
1✔
168
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
169
      Botan::system_rng().randomize(out, out_len);
1✔
170
      return BOTAN_FFI_SUCCESS;
1✔
171
   });
1✔
172
}
173

174
int botan_rng_reseed(botan_rng_t rng, size_t bits) {
7✔
175
   return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.reseed_from_rng(Botan::system_rng(), bits); });
14✔
176
}
177

178
int botan_rng_add_entropy(botan_rng_t rng, const uint8_t* input, size_t len) {
8✔
179
   return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.add_entropy(input, len); });
16✔
180
}
181

182
int botan_rng_reseed_from_rng(botan_rng_t rng, botan_rng_t source_rng, size_t bits) {
9✔
183
   return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.reseed_from_rng(safe_get(source_rng), bits); });
18✔
184
}
185
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc