X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Frand%2Frand_win.c;h=34c2a8b92443655d37817b1647863b584c9f6a9a;hp=46cbe1494c24f9c39e07ceb35246d2449f0a0705;hb=c7504aeb640a88949dfe3146f7e0f275f517464c;hpb=73241290bc15d708bb9ec8bb48891df1e5485e3e diff --git a/crypto/rand/rand_win.c b/crypto/rand/rand_win.c index 46cbe1494c..34c2a8b924 100644 --- a/crypto/rand/rand_win.c +++ b/crypto/rand/rand_win.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -10,62 +10,153 @@ #include "internal/cryptlib.h" #include #include "rand_lcl.h" - +#include "internal/rand_int.h" #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) + +# ifndef OPENSSL_RAND_SEED_OS +# error "Unsupported seeding method configured; must be os" +# endif + # include -# ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0400 +/* On Windows 7 or higher use BCrypt instead of the legacy CryptoAPI */ +# if defined(_MSC_VER) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0601 +# define USE_BCRYPTGENRANDOM # endif -# include +# ifdef USE_BCRYPTGENRANDOM +# include +# pragma comment(lib, "bcrypt.lib") +# ifndef STATUS_SUCCESS +# define STATUS_SUCCESS ((NTSTATUS)0x00000000L) +# endif +# else +# include /* * Intel hardware RNG CSP -- available from * http://developer.intel.com/design/security/rng/redist_license.htm */ -# define PROV_INTEL_SEC 22 -# define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider" - -static void readtimer(void); +# define PROV_INTEL_SEC 22 +# define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider" +# endif -int RAND_poll(void) +size_t rand_pool_acquire_entropy(RAND_POOL *pool) { - MEMORYSTATUS mst; - HCRYPTPROV hProvider = 0; - DWORD w; - BYTE buf[64]; - - /* poll the CryptoAPI PRNG */ - /* The CryptoAPI returns sizeof(buf) bytes of randomness */ - if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { - if (CryptGenRandom(hProvider, sizeof(buf), buf) != 0) { - RAND_add(buf, sizeof(buf), sizeof(buf)); - } - CryptReleaseContext(hProvider, 0); +# ifndef USE_BCRYPTGENRANDOM + HCRYPTPROV hProvider; +# endif + unsigned char *buffer; + size_t bytes_needed; + size_t entropy_available = 0; + + +# ifdef OPENSSL_RAND_SEED_RDTSC + entropy_available = rand_acquire_entropy_from_tsc(pool); + if (entropy_available > 0) + return entropy_available; +# endif + +# ifdef OPENSSL_RAND_SEED_RDCPU + entropy_available = rand_acquire_entropy_from_cpu(pool); + if (entropy_available > 0) + return entropy_available; +# endif + +# ifdef USE_BCRYPTGENRANDOM + bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + buffer = rand_pool_add_begin(pool, bytes_needed); + if (buffer != NULL) { + size_t bytes = 0; + if (BCryptGenRandom(NULL, buffer, bytes_needed, + BCRYPT_USE_SYSTEM_PREFERRED_RNG) == STATUS_SUCCESS) + bytes = bytes_needed; + + rand_pool_add_end(pool, bytes, 8 * bytes); + entropy_available = rand_pool_entropy_available(pool); } + if (entropy_available > 0) + return entropy_available; +# else + bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + buffer = rand_pool_add_begin(pool, bytes_needed); + if (buffer != NULL) { + size_t bytes = 0; + /* poll the CryptoAPI PRNG */ + if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { + if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) + bytes = bytes_needed; + + CryptReleaseContext(hProvider, 0); + } - /* poll the Pentium PRG with CryptoAPI */ - if (CryptAcquireContextW(&hProvider, NULL, INTEL_DEF_PROV, PROV_INTEL_SEC, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { - if (CryptGenRandom(hProvider, sizeof(buf), buf) != 0) { - RAND_add(buf, sizeof(buf), sizeof(buf)); + rand_pool_add_end(pool, bytes, 8 * bytes); + entropy_available = rand_pool_entropy_available(pool); + } + if (entropy_available > 0) + return entropy_available; + + bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + buffer = rand_pool_add_begin(pool, bytes_needed); + if (buffer != NULL) { + size_t bytes = 0; + /* poll the Pentium PRG with CryptoAPI */ + if (CryptAcquireContextW(&hProvider, NULL, + INTEL_DEF_PROV, PROV_INTEL_SEC, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { + if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) + bytes = bytes_needed; + + CryptReleaseContext(hProvider, 0); } - CryptReleaseContext(hProvider, 0); + rand_pool_add_end(pool, bytes, 8 * bytes); + entropy_available = rand_pool_entropy_available(pool); } + if (entropy_available > 0) + return entropy_available; +# endif - /* timer data */ - readtimer(); + return rand_pool_entropy_available(pool); +} - /* memory usage statistics */ - GlobalMemoryStatus(&mst); - RAND_add(&mst, sizeof(mst), 1); - /* process ID */ - w = GetCurrentProcessId(); - RAND_add(&w, sizeof(w), 1); +int rand_pool_add_nonce_data(RAND_POOL *pool) +{ + struct { + DWORD pid; + DWORD tid; + FILETIME time; + } data = { 0 }; + + /* + * Add process id, thread id, and a high resolution timestamp to + * ensure that the nonce is unique whith high probability for + * different process instances. + */ + data.pid = GetCurrentProcessId(); + data.tid = GetCurrentThreadId(); + GetSystemTimeAsFileTime(&data.time); + + return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); +} - return (1); +int rand_pool_add_additional_data(RAND_POOL *pool) +{ + struct { + DWORD tid; + LARGE_INTEGER time; + } data = { 0 }; + + /* + * Add some noise from the thread id and a high resolution timer. + * The thread id adds a little randomness if the drbg is accessed + * concurrently (which is the case for the drbg). + */ + data.tid = GetCurrentThreadId(); + QueryPerformanceCounter(&data.time); + return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); } -#if OPENSSL_API_COMPAT < 0x00101000L +# if OPENSSL_API_COMPAT < 0x10100000L int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam) { RAND_poll(); @@ -76,43 +167,19 @@ void RAND_screen(void) { RAND_poll(); } -#endif +# endif -/* feed timing information to the PRNG */ -static void readtimer(void) +int rand_pool_init(void) { - DWORD w; - LARGE_INTEGER l; - static int have_perfc = 1; -# if defined(_MSC_VER) && defined(_M_X86) - static int have_tsc = 1; - DWORD cyclecount; - - if (have_tsc) { - __try { - __asm { - _emit 0x0f _emit 0x31 mov cyclecount, eax} - RAND_add(&cyclecount, sizeof(cyclecount), 1); - } - __except(EXCEPTION_EXECUTE_HANDLER) { - have_tsc = 0; - } - } -# else -# define have_tsc 0 -# endif + return 1; +} - if (have_perfc) { - if (QueryPerformanceCounter(&l) == 0) - have_perfc = 0; - else - RAND_add(&l, sizeof(l), 0); - } +void rand_pool_cleanup(void) +{ +} - if (!have_tsc && !have_perfc) { - w = GetTickCount(); - RAND_add(&w, sizeof(w), 0); - } +void rand_pool_keep_random_devices_open(int keep) +{ } #endif