1 /**
2 * RandomNumberGenerator
3 * 
4 * Copyright:
5 * (C) 1999-2009 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 module botan.rng.rng;
12 
13 import botan.entropy.entropy_src;
14 import botan.utils.exceptn;
15 import core.sync.mutex;
16 import botan.rng.hmac_rng;
17 import botan.libstate.libstate;
18 import botan.utils.types : Unique;
19 
20 /**
21 * This class represents a random number (RNG) generator object.
22 */
23 abstract class RandomNumberGenerator
24 {
25 public:
26     /**
27     * Create a seeded and active RNG object for general application use
28     * Added in 1.8.0
29     */
30     static RandomNumberGenerator makeRng()
31     {
32         return makeRng(globalState().algorithmFactory());
33     }
34 
35     /**
36     * Create a seeded and active RNG object for general application use
37     * Added in 1.11.5
38     */
39     static RandomNumberGenerator makeRng(AlgorithmFactory af)
40     {
41         RandomNumberGenerator rng = new HMAC_RNG(af.makeMac("HMAC(SHA-512)"), 
42                                                  af.makeMac("HMAC(SHA-256)"));
43         rng.reseed(256);
44         
45         return rng;
46     }
47     /**
48     * Randomize a ubyte array.
49     *
50     * Params:
51     *  output = the ubyte array to hold the random output.
52     *  length = the length of the ubyte array output.
53     */
54     abstract void randomize(ubyte* output, size_t length);
55 
56     /**
57     * Return a random vector
58     * Params:
59     *  bytes = number of bytes in the result
60     * Returns: randomized vector of length bytes
61     */
62     abstract SecureVector!ubyte randomVec(size_t bytes)
63     {
64         SecureVector!ubyte output = SecureVector!ubyte(bytes);
65         randomize(output.ptr, output.length);
66         return output;
67     }
68 
69     /**
70     * Return a random ubyte
71     * Returns: random ubyte
72     */
73     final ubyte nextByte()
74     {
75         ubyte output;
76         this.randomize(&output, 1);
77         return output;
78     }
79 
80     /**
81     * Check whether this RNG is seeded.
82     * Returns: true if this RNG was already seeded, false otherwise.
83     */
84     abstract bool isSeeded() const;
85 
86     /**
87     * Clear all internally held values of this RNG.
88     */
89     abstract void clear();
90 
91     /**
92     * Return the name of this object
93     */
94     abstract @property string name() const;
95 
96     /**
97     * Seed this RNG using the entropy sources it contains.
98     *
99     * Params:
100     *  bits_to_collect = is the number of bits of entropy to
101                 attempt to gather from the entropy sources
102     */
103     abstract void reseed(size_t bits_to_collect);
104 
105     /**
106     * Add entropy to this RNG.
107     *
108     * Params:
109     *  input = a ubyte array containg the entropy to be added
110     *  length = the length of the ubyte array in
111     */
112     abstract void addEntropy(const(ubyte)* input, size_t length);
113 
114 }
115 
116 /**
117 * Null/stub RNG - fails if you try to use it for anything
118 */
119 class NullRNG : RandomNumberGenerator
120 {
121 public:
122     override void randomize(ubyte*, size_t) { throw new PRNGUnseeded("Null_RNG"); }
123 
124     override void clear() {}
125 
126     override @property string name() const { return "Null_RNG"; }
127 
128     override void reseed(size_t) {}
129     override bool isSeeded() const { return false; }
130     override void addEntropy(const(ubyte)*, size_t) {}
131 }
132 
133 /**
134 * Wraps access to a RNG in a mutex
135 */
136 class SerializedRNG : RandomNumberGenerator
137 {
138 public:
139     override void randomize(ubyte* output, size_t length)
140     {
141         synchronized(m_mtx) m_rng.randomize(output, length);        
142     }
143 
144     override bool isSeeded() const
145     {
146         synchronized(m_mtx) return m_rng.isSeeded();
147     }
148 
149     override void clear()
150     {
151         synchronized(m_mtx) m_rng.clear();
152     }
153 
154     override @property string name() const
155     {
156         synchronized(m_mtx) return m_rng.name;
157     }
158 
159     override void reseed(size_t poll_bits)
160     {
161         synchronized(m_mtx) m_rng.reseed(poll_bits);
162     }
163 
164     override void addEntropy(const(ubyte)* input, size_t len)
165     {
166         synchronized(m_mtx) m_rng.addEntropy(input, len);
167     }
168 
169     override SecureVector!ubyte randomVec(size_t bytes) { return super.randomVec(bytes); }
170 
171     this()
172     {
173         m_mtx = new Mutex;
174         m_rng = RandomNumberGenerator.makeRng();
175     }
176 
177 private:
178     Unique!RandomNumberGenerator m_rng;
179     Mutex m_mtx;
180 }