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 ~this() { 76 if (m_algorithm_factory) 77 m_algorithm_factory.destroy(); 78 } 79 80 void initialize() 81 { 82 logTrace("LibraryState.initialize()"); 83 if (m_initialized) 84 return; 85 86 if (!g_modexp_init) { 87 SCANToken.setDefaultAliases(); 88 static if (BOTAN_HAS_PUBLIC_KEY_CRYPTO) 89 OIDS.setDefaults(); 90 } 91 92 m_algorithm_factory = new AlgorithmFactory; 93 94 if (g_modexp_init) { 95 static if (BOTAN_HAS_ENGINE_OPENSSL) { 96 logTrace("Loading OpenSSL Engine"); 97 algorithmFactory().addEngine(new OpenSSLEngine); 98 } 99 algorithmFactory().addEngine(new CoreEngine); 100 m_initialized = true; 101 return; 102 } 103 static if (BOTAN_HAS_ENGINE_GNU_MP) { 104 logTrace("Loading GNU MP Engine"); 105 algorithmFactory().addEngine(new GMPEngine); 106 } 107 108 static if (BOTAN_HAS_ENGINE_OPENSSL) { 109 logTrace("Loading OpenSSL Engine"); 110 algorithmFactory().addEngine(new OpenSSLEngine); 111 } 112 113 static if (BOTAN_HAS_ENGINE_AES_ISA) { 114 logTrace("Loading AES ISA Engine"); 115 algorithmFactory().addEngine(new AESISAEngine); 116 } 117 118 static if (BOTAN_HAS_ENGINE_SIMD) { 119 logTrace("Loading SIMD Engine"); 120 algorithmFactory().addEngine(new SIMDEngine); 121 } 122 123 static if (BOTAN_HAS_ENGINE_ASSEMBLER) { 124 logTrace("Loading Assembler Engine"); 125 algorithmFactory().addEngine(new AssemblerEngine); 126 127 } 128 129 algorithmFactory().addEngine(new CoreEngine); 130 if (!gs_entropy_src_mutex) 131 gs_entropy_src_mutex = new Mutex; 132 synchronized(gs_entropy_src_mutex) { 133 if (gs_sources.length == 0) 134 gs_sources = entropySources(); 135 136 if (!gs_global_prng) { 137 gs_ctor = Thread.getThis(); 138 gs_global_prng = new SerializedRNG(); 139 } 140 } 141 logTrace("Done serialized RNG"); 142 static if (BOTAN_HAS_SELFTESTS) { 143 logTrace("Startup Self-Tests"); 144 confirmStartupSelfTests(algorithmFactory()); 145 } 146 logTrace("Done Self Tests"); 147 m_initialized = true; 148 149 } 150 151 /** 152 * Return a reference to the AlgorithmFactory 153 * Returns: global AlgorithmFactory 154 */ 155 AlgorithmFactory algorithmFactory() 156 { 157 if (!m_algorithm_factory) 158 throw new InvalidState("Uninitialized in algorithmFactory"); 159 // logTrace("Algorithm factory: ", cast(void*)*m_algorithm_factory); 160 return m_algorithm_factory; 161 } 162 163 /** 164 * Return a reference to the global PRNG 165 * Returns: global RandomNumberGenerator 166 */ 167 RandomNumberGenerator globalRng() 168 { 169 return cast(RandomNumberGenerator)gs_global_prng; 170 } 171 172 void pollAvailableSources(ref EntropyAccumulator accum) 173 { 174 synchronized(gs_entropy_src_mutex){ 175 if (gs_sources.empty) 176 throw new Exception("No entropy sources enabled at build time, poll failed"); 177 178 size_t poll_attempt = 0; 179 180 while (!accum.pollingGoalAchieved() && poll_attempt < 16) 181 { 182 const size_t src_idx = poll_attempt % gs_sources.length; 183 gs_sources[src_idx].poll(accum); 184 ++poll_attempt; 185 } 186 } 187 } 188 189 private: 190 static Vector!( EntropySource ) entropySources() 191 { 192 Vector!( EntropySource ) sources; 193 194 static if (BOTAN_HAS_ENTROPY_SRC_HIGH_RESOLUTION_TIMER) 195 sources.pushBack(new HighResolutionTimestamp); 196 197 static if (BOTAN_HAS_ENTROPY_SRC_RDRAND) 198 sources.pushBack(new IntelRdrand); 199 200 static if (BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM) version(Posix) 201 sources.pushBack(new DeviceEntropySource( 202 Vector!string([ "/dev/random", "/dev/srandom", "/dev/urandom" ]) 203 )); 204 205 static if (BOTAN_HAS_ENTROPY_SRC_CAPI) version(Windows) 206 sources.pushBack(new Win32CAPIEntropySource); 207 208 209 static if (BOTAN_HAS_ENTROPY_SRC_WIN32) version(Windows) 210 sources.pushBack(new Win32EntropySource); 211 212 static if (BOTAN_HAS_ENTROPY_SRC_BEOS) 213 sources.pushBack(new BeOSEntropySource); 214 215 static if (BOTAN_HAS_ENTROPY_SRC_UNIX_PROCESS_RUNNER) version(Posix) 216 sources.pushBack(new UnixProcessInfoEntropySource); 217 218 static if (BOTAN_HAS_ENTROPY_SRC_PROC_WALKER) version(Posix) 219 sources.pushBack(new ProcWalkingEntropySource("/proc")); 220 221 static if (BOTAN_HAS_ENTROPY_SRC_UNIX_PROCESS_RUNNER) version(Posix) 222 sources.pushBack( 223 new UnixEntropySource( Vector!string( [ "/bin", "/sbin", "/usr/bin", "/usr/sbin" ] ) ) 224 ); 225 226 static if (BOTAN_HAS_ENTROPY_SRC_EGD) version(Posix) 227 sources.pushBack( 228 new EGDEntropySource( Vector!string( [ "/var/run/egd-pool", "/dev/egd-pool" ] ) ) 229 ); 230 231 return sources.move(); 232 } 233 234 AlgorithmFactory m_algorithm_factory; 235 bool m_initialized; 236 } 237 238 __gshared Thread gs_ctor; 239 __gshared SerializedRNG gs_global_prng; 240 __gshared Mutex gs_entropy_src_mutex; 241 __gshared Vector!( EntropySource ) gs_sources;