1 /** 2 * Library Internal/Global State 3 * 4 * Copyright: 5 * (C) 1999-2008 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.libstate.libstate; 12 13 public import botan.utils.types; 14 public import botan.algo_factory.algo_factory; 15 public import botan.libstate.lookup; 16 public import botan.libstate.global_state; 17 import botan.rng.rng; 18 import botan.utils.charset; 19 import botan.engine.engine; 20 import botan.utils.cpuid; 21 import botan.asn1.oids; 22 import botan.engine.core_engine; 23 import memutils.dictionarylist; 24 import std.algorithm; 25 import core.sync.mutex; 26 import botan.entropy.entropy_src; 27 import memutils.hashmap; 28 29 import core.thread; 30 31 import botan.constants; 32 static if (BOTAN_HAS_SELFTESTS) 33 import botan.selftest.selftest; 34 // Engines 35 static if (BOTAN_HAS_ENGINE_ASSEMBLER) 36 import botan.engine.asm_engine; 37 static if (BOTAN_HAS_ENGINE_AES_ISA) 38 import botan.engine.aes_isa_engine; 39 static if (BOTAN_HAS_ENGINE_SIMD) 40 import botan.engine.simd_engine; 41 static if (BOTAN_HAS_ENGINE_GNU_MP) 42 import botan.engine.gnump_engine; 43 static if (BOTAN_HAS_ENGINE_OPENSSL) 44 import botan.engine.openssl_engine; 45 // Entropy sources 46 static if (BOTAN_HAS_ENTROPY_SRC_HIGH_RESOLUTION_TIMER) 47 import botan.entropy.hres_timer; 48 static if (BOTAN_HAS_ENTROPY_SRC_RDRAND) 49 import botan.entropy.rdrand; 50 static if (BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM) 51 import botan.entropy.dev_random; 52 static if (BOTAN_HAS_ENTROPY_SRC_EGD) 53 import botan.entropy.es_egd; 54 static if (BOTAN_HAS_ENTROPY_SRC_UNIX_PROCESS_RUNNER) 55 import botan.entropy.unix_procs; 56 static if (BOTAN_HAS_ENTROPY_SRC_BEOS) 57 import botan.entropy.es_beos; 58 static if (BOTAN_HAS_ENTROPY_SRC_CAPI) 59 import botan.entropy.es_capi; 60 static if (BOTAN_HAS_ENTROPY_SRC_WIN32) 61 import botan.entropy.es_win32; 62 static if (BOTAN_HAS_ENTROPY_SRC_PROC_WALKER) 63 import botan.entropy.proc_walk; 64 65 private bool g_modexp_init; 66 67 void modexpInit() { g_modexp_init = true; } 68 69 /** 70 * Global Library State 71 */ 72 final class LibraryState 73 { 74 public: 75 shared static this() 76 { 77 gs_entropy_src_mutex = new Mutex; 78 } 79 80 ~this() { 81 if (m_algorithm_factory) 82 m_algorithm_factory.destroy(); 83 } 84 85 void initialize() 86 { 87 logTrace("LibraryState.initialize()"); 88 if (m_initialized) 89 return; 90 91 if (!g_modexp_init) { 92 SCANToken.setDefaultAliases(); 93 static if (BOTAN_HAS_PUBLIC_KEY_CRYPTO) 94 OIDS.setDefaults(); 95 } 96 97 m_algorithm_factory = new AlgorithmFactory; 98 99 if (g_modexp_init) { 100 static if (BOTAN_HAS_ENGINE_OPENSSL) { 101 logTrace("Loading OpenSSL Engine"); 102 algorithmFactory().addEngine(new OpenSSLEngine); 103 } 104 algorithmFactory().addEngine(new CoreEngine); 105 m_initialized = true; 106 return; 107 } 108 static if (BOTAN_HAS_ENGINE_GNU_MP) { 109 logTrace("Loading GNU MP Engine"); 110 algorithmFactory().addEngine(new GMPEngine); 111 } 112 113 static if (BOTAN_HAS_ENGINE_OPENSSL) { 114 logTrace("Loading OpenSSL Engine"); 115 algorithmFactory().addEngine(new OpenSSLEngine); 116 } 117 118 static if (BOTAN_HAS_ENGINE_AES_ISA) { 119 logTrace("Loading AES ISA Engine"); 120 algorithmFactory().addEngine(new AESISAEngine); 121 } 122 123 static if (BOTAN_HAS_ENGINE_SIMD) { 124 logTrace("Loading SIMD Engine"); 125 algorithmFactory().addEngine(new SIMDEngine); 126 } 127 128 static if (BOTAN_HAS_ENGINE_ASSEMBLER) { 129 logTrace("Loading Assembler Engine"); 130 algorithmFactory().addEngine(new AssemblerEngine); 131 132 } 133 134 algorithmFactory().addEngine(new CoreEngine); 135 136 synchronized(gs_entropy_src_mutex) { 137 if (gs_sources.length == 0) 138 gs_sources = entropySources(); 139 140 if (!gs_global_prng) { 141 gs_ctor = Thread.getThis(); 142 gs_global_prng = new SerializedRNG(); 143 } 144 } 145 logTrace("Done serialized RNG"); 146 static if (BOTAN_HAS_SELFTESTS) { 147 logTrace("Startup Self-Tests"); 148 confirmStartupSelfTests(algorithmFactory()); 149 } 150 logTrace("Done Self Tests"); 151 m_initialized = true; 152 153 } 154 155 /** 156 * Return a reference to the AlgorithmFactory 157 * Returns: global AlgorithmFactory 158 */ 159 AlgorithmFactory algorithmFactory() 160 { 161 if (!m_algorithm_factory) 162 throw new InvalidState("Uninitialized in algorithmFactory"); 163 // logTrace("Algorithm factory: ", cast(void*)*m_algorithm_factory); 164 return m_algorithm_factory; 165 } 166 167 /** 168 * Return a reference to the global PRNG 169 * Returns: global RandomNumberGenerator 170 */ 171 RandomNumberGenerator globalRng() 172 { 173 return cast(RandomNumberGenerator)gs_global_prng; 174 } 175 176 void pollAvailableSources(ref EntropyAccumulator accum) 177 { 178 synchronized(gs_entropy_src_mutex){ 179 if (gs_sources.empty) 180 throw new Exception("No entropy sources enabled at build time, poll failed"); 181 182 size_t poll_attempt = 0; 183 184 while (!accum.pollingGoalAchieved() && poll_attempt < 16) 185 { 186 const size_t src_idx = poll_attempt % gs_sources.length; 187 gs_sources[src_idx].poll(accum); 188 ++poll_attempt; 189 } 190 } 191 } 192 193 private: 194 static Vector!( EntropySource ) entropySources() 195 { 196 Vector!( EntropySource ) sources; 197 198 static if (BOTAN_HAS_ENTROPY_SRC_HIGH_RESOLUTION_TIMER) 199 sources.pushBack(new HighResolutionTimestamp); 200 201 static if (BOTAN_HAS_ENTROPY_SRC_RDRAND) 202 sources.pushBack(new IntelRdrand); 203 204 static if (BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM) version(Posix) 205 sources.pushBack(new DeviceEntropySource( 206 Vector!string([ "/dev/random", "/dev/srandom", "/dev/urandom" ]) 207 )); 208 209 static if (BOTAN_HAS_ENTROPY_SRC_CAPI) version(Windows) 210 sources.pushBack(new Win32CAPIEntropySource); 211 212 213 static if (BOTAN_HAS_ENTROPY_SRC_WIN32) version(Windows) 214 sources.pushBack(new Win32EntropySource); 215 216 static if (BOTAN_HAS_ENTROPY_SRC_BEOS) 217 sources.pushBack(new BeOSEntropySource); 218 219 static if (BOTAN_HAS_ENTROPY_SRC_UNIX_PROCESS_RUNNER) version(Posix) 220 sources.pushBack(new UnixProcessInfoEntropySource); 221 222 static if (BOTAN_HAS_ENTROPY_SRC_PROC_WALKER) version(Posix) 223 sources.pushBack(new ProcWalkingEntropySource("/proc")); 224 225 static if (BOTAN_HAS_ENTROPY_SRC_UNIX_PROCESS_RUNNER) version(Posix) 226 sources.pushBack( 227 new UnixEntropySource( Vector!string( [ "/bin", "/sbin", "/usr/bin", "/usr/sbin" ] ) ) 228 ); 229 230 static if (BOTAN_HAS_ENTROPY_SRC_EGD) version(Posix) 231 sources.pushBack( 232 new EGDEntropySource( Vector!string( [ "/var/run/egd-pool", "/dev/egd-pool" ] ) ) 233 ); 234 235 return sources.move(); 236 } 237 238 AlgorithmFactory m_algorithm_factory; 239 bool m_initialized; 240 } 241 242 __gshared Thread gs_ctor; 243 __gshared SerializedRNG gs_global_prng; 244 __gshared Mutex gs_entropy_src_mutex; 245 __gshared Vector!( EntropySource ) gs_sources;