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