|
47 | 47 |
|
48 | 48 | #include <openssl/err.h>
|
49 | 49 | #include <openssl/rand.h>
|
| 50 | +#include <openssl/conf.h> |
50 | 51 |
|
51 | 52 | [[noreturn]] static void RandFailure()
|
52 | 53 | {
|
@@ -294,15 +295,46 @@ void GetRandBytes(unsigned char* buf, int num)
|
294 | 295 | }
|
295 | 296 | }
|
296 | 297 |
|
| 298 | +void LockingCallbackOpenSSL(int mode, int i, const char* file, int line); |
| 299 | + |
297 | 300 | namespace {
|
| 301 | + |
298 | 302 | struct RNGState {
|
299 | 303 | Mutex m_mutex;
|
300 | 304 | unsigned char m_state[32] GUARDED_BY(m_mutex) = {0};
|
301 | 305 | uint64_t m_counter GUARDED_BY(m_mutex) = 0;
|
| 306 | + std::unique_ptr<Mutex[]> m_mutex_openssl; |
302 | 307 |
|
303 | 308 | RNGState()
|
304 | 309 | {
|
305 | 310 | InitHardwareRand();
|
| 311 | + |
| 312 | + // Init OpenSSL library multithreading support |
| 313 | + m_mutex_openssl.reset(new Mutex[CRYPTO_num_locks()]); |
| 314 | + CRYPTO_set_locking_callback(LockingCallbackOpenSSL); |
| 315 | + |
| 316 | + // OpenSSL can optionally load a config file which lists optional loadable modules and engines. |
| 317 | + // We don't use them so we don't require the config. However some of our libs may call functions |
| 318 | + // which attempt to load the config file, possibly resulting in an exit() or crash if it is missing |
| 319 | + // or corrupt. Explicitly tell OpenSSL not to try to load the file. The result for our libs will be |
| 320 | + // that the config appears to have been loaded and there are no modules/engines available. |
| 321 | + OPENSSL_no_config(); |
| 322 | + |
| 323 | +#ifdef WIN32 |
| 324 | + // Seed OpenSSL PRNG with current contents of the screen |
| 325 | + RAND_screen(); |
| 326 | +#endif |
| 327 | + |
| 328 | + // Seed OpenSSL PRNG with performance counter |
| 329 | + RandAddSeed(); |
| 330 | + } |
| 331 | + |
| 332 | + ~RNGState() |
| 333 | + { |
| 334 | + // Securely erase the memory used by the OpenSSL PRNG |
| 335 | + RAND_cleanup(); |
| 336 | + // Shutdown OpenSSL library multithreading support |
| 337 | + CRYPTO_set_locking_callback(nullptr); |
306 | 338 | }
|
307 | 339 |
|
308 | 340 | /** Extract up to 32 bytes of entropy from the RNG state, mixing in new entropy from hasher. */
|
@@ -343,6 +375,17 @@ RNGState& GetRNGState()
|
343 | 375 | }
|
344 | 376 | }
|
345 | 377 |
|
| 378 | +void LockingCallbackOpenSSL(int mode, int i, const char* file, int line) NO_THREAD_SAFETY_ANALYSIS |
| 379 | +{ |
| 380 | + RNGState& rng = GetRNGState(); |
| 381 | + |
| 382 | + if (mode & CRYPTO_LOCK) { |
| 383 | + rng.m_mutex_openssl[i].lock(); |
| 384 | + } else { |
| 385 | + rng.m_mutex_openssl[i].unlock(); |
| 386 | + } |
| 387 | +} |
| 388 | + |
346 | 389 | static void AddDataToRng(void* data, size_t len, RNGState& rng);
|
347 | 390 |
|
348 | 391 | void RandAddSeedSleep()
|
|
0 commit comments