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 }