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 }