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

randombit / botan / 11268576238

10 Oct 2024 06:22AM UTC coverage: 90.983% (-0.02%) from 91.007%
11268576238

push

github

web-flow
Merge pull request #4325 from plancksecurity/jitter

Add jitterentropy as RNG

89487 of 98356 relevant lines covered (90.98%)

8933666.37 hits per line

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

92.86
/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

26
extern "C" {
27

28
using namespace Botan_FFI;
29

30
int botan_rng_init(botan_rng_t* rng_out, const char* rng_type) {
73✔
31
   return ffi_guard_thunk(__func__, [=]() -> int {
73✔
32
      if(rng_out == nullptr) {
73✔
33
         return BOTAN_FFI_ERROR_NULL_POINTER;
34
      }
35

36
      const std::string rng_type_s(rng_type ? rng_type : "system");
146✔
37

38
      std::unique_ptr<Botan::RandomNumberGenerator> rng;
73✔
39

40
      if(rng_type_s == "system") {
73✔
41
         rng = std::make_unique<Botan::System_RNG>();
64✔
42
      } else if(rng_type_s == "user" || rng_type_s == "user-threadsafe") {
9✔
43
         rng = std::make_unique<Botan::AutoSeeded_RNG>();
5✔
44
      } else if(rng_type_s == "null") {
4✔
45
         rng = std::make_unique<Botan::Null_RNG>();
1✔
46
      }
47
#if defined(BOTAN_HAS_PROCESSOR_RNG)
48
      else if((rng_type_s == "rdrand" || rng_type_s == "hwrng") && Botan::Processor_RNG::available()) {
3✔
49
         rng = std::make_unique<Botan::Processor_RNG>();
1✔
50
      }
51
#endif
52
#if defined(BOTAN_HAS_JITTER_RNG)
53
      else if(rng_type_s == "jitter") {
2✔
54
         rng = std::make_unique<Botan::Jitter_RNG>();
1✔
55
      }
56
#endif
57

58
      if(!rng) {
73✔
59
         return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
60
      }
61

62
      *rng_out = new botan_rng_struct(std::move(rng));
72✔
63
      return BOTAN_FFI_SUCCESS;
72✔
64
   });
146✔
65
}
66

67
int botan_rng_init_custom(botan_rng_t* rng_out,
1✔
68
                          const char* rng_name,
69
                          void* context,
70
                          int (*get_cb)(void* context, uint8_t* out, size_t out_len),
71
                          int (*add_entropy_cb)(void* context, const uint8_t input[], size_t length),
72
                          void (*destroy_cb)(void* context)) {
73
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
74
      if(rng_out == nullptr) {
1✔
75
         return BOTAN_FFI_ERROR_NULL_POINTER;
76
      }
77

78
      if(rng_name == nullptr) {
1✔
79
         return BOTAN_FFI_ERROR_NULL_POINTER;
80
      }
81

82
      if(get_cb == nullptr) {
1✔
83
         return BOTAN_FFI_ERROR_NULL_POINTER;
84
      }
85

86
      class Custom_RNG : public Botan::RandomNumberGenerator {
1✔
87
         public:
88
            Custom_RNG(std::string_view name,
1✔
89
                       void* context,
90
                       int (*get_cb)(void* context, uint8_t* out, size_t out_len),
91
                       int (*add_entropy_cb)(void* context, const uint8_t input[], size_t length),
92
                       void (*destroy_cb)(void* context)) :
1✔
93
                  m_name(name) {
1✔
94
               m_context = context;
1✔
95
               m_get_cb = get_cb;
1✔
96
               m_add_entropy_cb = add_entropy_cb;
1✔
97
               m_destroy_cb = destroy_cb;
1✔
98
            }
1✔
99

100
            ~Custom_RNG() override {
2✔
101
               if(m_destroy_cb) {
1✔
102
                  m_destroy_cb(m_context);
1✔
103
               }
104
            }
5✔
105

106
            Custom_RNG(const Custom_RNG& other) = delete;
107
            Custom_RNG(Custom_RNG&& other) = delete;
108
            Custom_RNG& operator=(const Custom_RNG& other) = delete;
109
            Custom_RNG& operator=(Custom_RNG&& other) = delete;
110

111
         protected:
112
            void fill_bytes_with_input(std::span<uint8_t> output, std::span<const uint8_t> input) override {
4✔
113
               if(accepts_input() && !input.empty()) {
4✔
114
                  int rc = m_add_entropy_cb(m_context, input.data(), input.size());
3✔
115
                  if(rc) {
3✔
116
                     throw Botan::Invalid_State("Failed to add entropy via C callback, rc=" + std::to_string(rc));
×
117
                  }
118
               }
119

120
               if(!output.empty()) {
4✔
121
                  int rc = m_get_cb(m_context, output.data(), output.size());
1✔
122
                  if(rc) {
1✔
123
                     throw Botan::Invalid_State("Failed to get random from C callback, rc=" + std::to_string(rc));
×
124
                  }
125
               }
126
            }
4✔
127

128
         public:
129
            bool accepts_input() const override { return m_add_entropy_cb != nullptr; }
4✔
130

131
            std::string name() const override { return m_name; }
×
132

133
            void clear() override {}
×
134

135
            bool is_seeded() const override { return true; }
×
136

137
         private:
138
            std::string m_name;
139
            void* m_context;
140
            std::function<int(void* context, uint8_t* out, size_t out_len)> m_get_cb;
141
            std::function<int(void* context, const uint8_t input[], size_t length)> m_add_entropy_cb;
142
            std::function<void(void* context)> m_destroy_cb;
143
      };
144

145
      auto rng = std::make_unique<Custom_RNG>(rng_name, context, get_cb, add_entropy_cb, destroy_cb);
1✔
146

147
      *rng_out = new botan_rng_struct(std::move(rng));
1✔
148
      return BOTAN_FFI_SUCCESS;
1✔
149
   });
2✔
150
}
151

152
int botan_rng_destroy(botan_rng_t rng) {
73✔
153
   return BOTAN_FFI_CHECKED_DELETE(rng);
73✔
154
}
155

156
int botan_rng_get(botan_rng_t rng, uint8_t* out, size_t out_len) {
55✔
157
   return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.randomize(out, out_len); });
110✔
158
}
159

160
int botan_system_rng_get(uint8_t* out, size_t out_len) {
1✔
161
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
162
      Botan::system_rng().randomize(out, out_len);
1✔
163
      return BOTAN_FFI_SUCCESS;
1✔
164
   });
1✔
165
}
166

167
int botan_rng_reseed(botan_rng_t rng, size_t bits) {
3✔
168
   return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.reseed_from_rng(Botan::system_rng(), bits); });
6✔
169
}
170

171
int botan_rng_add_entropy(botan_rng_t rng, const uint8_t* input, size_t len) {
3✔
172
   return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.add_entropy(input, len); });
6✔
173
}
174

175
int botan_rng_reseed_from_rng(botan_rng_t rng, botan_rng_t source_rng, size_t bits) {
5✔
176
   return BOTAN_FFI_VISIT(rng, [=](auto& r) { r.reseed_from_rng(safe_get(source_rng), bits); });
10✔
177
}
178
}
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