Coverage Report

Created: 2020-05-23 13:54

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