Botan 3.10.0
Crypto and TLS for C&
jitter_rng.cpp
Go to the documentation of this file.
1/*
2* CPU Jitter Random Number Generator
3* (C) 2024 Planck Security S.A.
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/jitter_rng.h>
9
10#include <botan/assert.h>
11
12#include <jitterentropy.h>
13
14namespace Botan {
15
16struct Jitter_RNG_Internal {
17 Jitter_RNG_Internal();
18 ~Jitter_RNG_Internal();
19 void collect_into_buffer(std::span<uint8_t> buf);
20
21 private:
22 rand_data* m_rand_data;
23};
24
25Jitter_RNG_Internal::Jitter_RNG_Internal() {
26 constexpr unsigned int oversampling_rate = 0; // use default oversampling
27 constexpr unsigned int flags = JENT_FORCE_FIPS; // enable health tests
28
29 // if flags and osr are used, use the same values for init and alloc
30 static int result = jent_entropy_init_ex(oversampling_rate, flags);
31
32 // no further details documented regarding the return value
33 BOTAN_ASSERT(result == 0, "JitterRNG: initialization successful");
34
35 m_rand_data = jent_entropy_collector_alloc(oversampling_rate, flags);
36 BOTAN_ASSERT_NONNULL(m_rand_data);
37}
38
39Jitter_RNG_Internal::~Jitter_RNG_Internal() {
40 if(m_rand_data) {
41 jent_entropy_collector_free(m_rand_data);
42 m_rand_data = nullptr;
43 }
44}
45
46void Jitter_RNG_Internal::collect_into_buffer(std::span<uint8_t> buf) {
47 if(buf.empty()) {
48 return;
49 }
50
51 BOTAN_STATE_CHECK(m_rand_data != nullptr);
52
53 ssize_t num_bytes = jent_read_entropy_safe(&m_rand_data, reinterpret_cast<char*>(buf.data()), buf.size());
54 if(num_bytes < 0) {
55 const auto error_msg = [&]() -> std::string_view {
56 switch(num_bytes) {
57 case -1: // should never happen because of the check above
58 return "JitterRNG: Uninitilialized";
59 case -2:
60 return "JitterRNG: SP800-90B repetition count online health test failed";
61 case -3:
62 return "JitterRNG: SP800-90B adaptive proportion online health test failed";
63 case -4:
64 return "JitterRNG: Internal timer generator could not be initialized";
65 case -5:
66 return "JitterRNG: LAG predictor health test failed";
67 case -6:
68 return "JitterRNG: Repetitive count test (RCT) failed permanently";
69 case -7:
70 return "JitterRNG: Adaptive proportion test (APT) failed permanently";
71 case -8:
72 return "JitterRNG: LAG prediction test failed permanently";
73 default:
74 return "JitterRNG: Error reading entropy";
75 }
76 }();
77 throw Internal_Error(error_msg);
78 }
79
80 // According to the docs, `jent_read_entropy` itself runs its logic as often
81 // as necessary to gather the requested number of bytes,
82 // so this should actually never happen.
83 BOTAN_ASSERT(static_cast<size_t>(num_bytes) == buf.size(), "JitterRNG produced the expected number of bytes");
84}
85
86Jitter_RNG::Jitter_RNG() : m_jitter{std::make_unique<Jitter_RNG_Internal>()} {}
87
88Jitter_RNG::~Jitter_RNG() = default;
89
91 m_jitter = std::make_unique<Jitter_RNG_Internal>();
92}
93
94void Jitter_RNG::fill_bytes_with_input(std::span<uint8_t> out, std::span<const uint8_t> in) {
95 BOTAN_UNUSED(in);
96
97 m_jitter->collect_into_buffer(out);
98}
99
100} // namespace Botan
#define BOTAN_UNUSED
Definition assert.h:144
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:114
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:62
void clear() override
Flags flags(Flag flags)
Definition p11.h:845