/src/botan/src/lib/rng/stateful_rng/stateful_rng.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * (C) 2016 Jack Lloyd |
3 | | * |
4 | | * Botan is released under the Simplified BSD License (see license.txt) |
5 | | */ |
6 | | |
7 | | #include <botan/stateful_rng.h> |
8 | | #include <botan/internal/os_utils.h> |
9 | | #include <botan/loadstor.h> |
10 | | |
11 | | #if defined(BOTAN_HAS_PROCESSOR_RNG) |
12 | | #include <botan/processor_rng.h> |
13 | | #endif |
14 | | |
15 | | namespace Botan { |
16 | | |
17 | | void Stateful_RNG::clear() |
18 | 7 | { |
19 | 7 | m_reseed_counter = 0; |
20 | 7 | m_last_pid = 0; |
21 | 7 | } |
22 | | |
23 | | void Stateful_RNG::force_reseed() |
24 | 0 | { |
25 | 0 | m_reseed_counter = 0; |
26 | 0 | } |
27 | | |
28 | | bool Stateful_RNG::is_seeded() const |
29 | 541k | { |
30 | 541k | return m_reseed_counter > 0; |
31 | 541k | } |
32 | | |
33 | | void Stateful_RNG::initialize_with(const uint8_t input[], size_t len) |
34 | 0 | { |
35 | 0 | add_entropy(input, len); |
36 | 0 |
|
37 | 0 | if(8*len >= security_level()) |
38 | 0 | { |
39 | 0 | reset_reseed_counter(); |
40 | 0 | } |
41 | 0 | } |
42 | | |
43 | | void Stateful_RNG::randomize_with_ts_input(uint8_t output[], size_t output_len) |
44 | 0 | { |
45 | 0 | uint8_t additional_input[24] = { 0 }; |
46 | 0 |
|
47 | 0 | store_le(OS::get_high_resolution_clock(), additional_input); |
48 | 0 |
|
49 | 0 | #if defined(BOTAN_HAS_PROCESSOR_RNG) |
50 | 0 | if(Processor_RNG::available()) |
51 | 0 | { |
52 | 0 | Processor_RNG hwrng; |
53 | 0 | hwrng.randomize(additional_input + 8, sizeof(additional_input) - 8); |
54 | 0 | } |
55 | 0 | else |
56 | 0 | #endif |
57 | 0 | { |
58 | 0 | store_le(OS::get_system_timestamp_ns(), additional_input + 8); |
59 | 0 | store_le(m_last_pid, additional_input + 16); |
60 | 0 | store_le(static_cast<uint32_t>(m_reseed_counter), additional_input + 20); |
61 | 0 | } |
62 | 0 |
|
63 | 0 | randomize_with_input(output, output_len, additional_input, sizeof(additional_input)); |
64 | 0 | } |
65 | | |
66 | | size_t Stateful_RNG::reseed(Entropy_Sources& srcs, |
67 | | size_t poll_bits, |
68 | | std::chrono::milliseconds poll_timeout) |
69 | 0 | { |
70 | 0 | size_t bits_collected = RandomNumberGenerator::reseed(srcs, poll_bits, poll_timeout); |
71 | 0 |
|
72 | 0 | if(bits_collected >= security_level()) |
73 | 0 | { |
74 | 0 | reset_reseed_counter(); |
75 | 0 | } |
76 | 0 |
|
77 | 0 | return bits_collected; |
78 | 0 | } |
79 | | |
80 | | void Stateful_RNG::reseed_from_rng(RandomNumberGenerator& rng, size_t poll_bits) |
81 | 0 | { |
82 | 0 | RandomNumberGenerator::reseed_from_rng(rng, poll_bits); |
83 | 0 |
|
84 | 0 | if(poll_bits >= security_level()) |
85 | 0 | { |
86 | 0 | reset_reseed_counter(); |
87 | 0 | } |
88 | 0 | } |
89 | | |
90 | | void Stateful_RNG::reseed_check() |
91 | 474k | { |
92 | 474k | const uint32_t cur_pid = OS::get_process_id(); |
93 | 474k | |
94 | 474k | const bool fork_detected = (m_last_pid > 0) && (cur_pid != m_last_pid); |
95 | 474k | |
96 | 474k | if(is_seeded() == false || |
97 | 474k | fork_detected || |
98 | 474k | (m_reseed_interval > 0 && m_reseed_counter >= m_reseed_interval)) |
99 | 0 | { |
100 | 0 | m_reseed_counter = 0; |
101 | 0 | m_last_pid = cur_pid; |
102 | 0 |
|
103 | 0 | if(m_underlying_rng) |
104 | 0 | { |
105 | 0 | reseed_from_rng(*m_underlying_rng, security_level()); |
106 | 0 | } |
107 | 0 |
|
108 | 0 | if(m_entropy_sources) |
109 | 0 | { |
110 | 0 | reseed(*m_entropy_sources, security_level()); |
111 | 0 | } |
112 | 0 |
|
113 | 0 | if(!is_seeded()) |
114 | 0 | { |
115 | 0 | if(fork_detected) |
116 | 0 | throw Invalid_State("Detected use of fork but cannot reseed DRBG"); |
117 | 0 | else |
118 | 0 | throw PRNG_Unseeded(name()); |
119 | 474k | } |
120 | 474k | } |
121 | 474k | else |
122 | 474k | { |
123 | 474k | BOTAN_ASSERT(m_reseed_counter != 0, "RNG is seeded"); |
124 | 474k | m_reseed_counter += 1; |
125 | 474k | } |
126 | 474k | } |
127 | | |
128 | | } |