1 /* 2 * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include "internal/cryptlib.h" 11 #include <openssl/rand.h> 12 #include "crypto/rand_pool.h" 13 #include "crypto/rand.h" 14 #include "prov/seeding.h" 15 16 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) 17 18 # ifndef OPENSSL_RAND_SEED_OS 19 # error "Unsupported seeding method configured; must be os" 20 # endif 21 22 # include <windows.h> 23 /* On Windows Vista or higher use BCrypt instead of the legacy CryptoAPI */ 24 # if defined(_MSC_VER) && _MSC_VER > 1500 /* 1500 = Visual Studio 2008 */ \ 25 && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 26 # define USE_BCRYPTGENRANDOM 27 # endif 28 29 # ifdef USE_BCRYPTGENRANDOM 30 # include <bcrypt.h> 31 # ifdef _MSC_VER 32 # pragma comment(lib, "bcrypt.lib") 33 # endif 34 # ifndef STATUS_SUCCESS 35 # define STATUS_SUCCESS ((NTSTATUS)0x00000000L) 36 # endif 37 # else 38 # include <wincrypt.h> 39 /* 40 * Intel hardware RNG CSP -- available from 41 * http://developer.intel.com/design/security/rng/redist_license.htm 42 */ 43 # define PROV_INTEL_SEC 22 44 # define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider" 45 # endif 46 47 size_t ossl_pool_acquire_entropy(RAND_POOL *pool) 48 { 49 # ifndef USE_BCRYPTGENRANDOM 50 HCRYPTPROV hProvider; 51 # endif 52 unsigned char *buffer; 53 size_t bytes_needed; 54 size_t entropy_available = 0; 55 56 57 # ifdef OPENSSL_RAND_SEED_RDTSC 58 entropy_available = ossl_prov_acquire_entropy_from_tsc(pool); 59 if (entropy_available > 0) 60 return entropy_available; 61 # endif 62 63 # ifdef OPENSSL_RAND_SEED_RDCPU 64 entropy_available = ossl_prov_acquire_entropy_from_cpu(pool); 65 if (entropy_available > 0) 66 return entropy_available; 67 # endif 68 69 # ifdef USE_BCRYPTGENRANDOM 70 bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); 71 buffer = ossl_rand_pool_add_begin(pool, bytes_needed); 72 if (buffer != NULL) { 73 size_t bytes = 0; 74 if (BCryptGenRandom(NULL, buffer, bytes_needed, 75 BCRYPT_USE_SYSTEM_PREFERRED_RNG) == STATUS_SUCCESS) 76 bytes = bytes_needed; 77 78 ossl_rand_pool_add_end(pool, bytes, 8 * bytes); 79 entropy_available = ossl_rand_pool_entropy_available(pool); 80 } 81 if (entropy_available > 0) 82 return entropy_available; 83 # else 84 bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); 85 buffer = ossl_rand_pool_add_begin(pool, bytes_needed); 86 if (buffer != NULL) { 87 size_t bytes = 0; 88 /* poll the CryptoAPI PRNG */ 89 if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, 90 CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { 91 if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) 92 bytes = bytes_needed; 93 94 CryptReleaseContext(hProvider, 0); 95 } 96 97 ossl_rand_pool_add_end(pool, bytes, 8 * bytes); 98 entropy_available = ossl_rand_pool_entropy_available(pool); 99 } 100 if (entropy_available > 0) 101 return entropy_available; 102 103 bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); 104 buffer = ossl_rand_pool_add_begin(pool, bytes_needed); 105 if (buffer != NULL) { 106 size_t bytes = 0; 107 /* poll the Pentium PRG with CryptoAPI */ 108 if (CryptAcquireContextW(&hProvider, NULL, 109 INTEL_DEF_PROV, PROV_INTEL_SEC, 110 CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { 111 if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) 112 bytes = bytes_needed; 113 114 CryptReleaseContext(hProvider, 0); 115 } 116 ossl_rand_pool_add_end(pool, bytes, 8 * bytes); 117 entropy_available = ossl_rand_pool_entropy_available(pool); 118 } 119 if (entropy_available > 0) 120 return entropy_available; 121 # endif 122 123 return ossl_rand_pool_entropy_available(pool); 124 } 125 126 127 int ossl_pool_add_nonce_data(RAND_POOL *pool) 128 { 129 struct { 130 DWORD pid; 131 DWORD tid; 132 FILETIME time; 133 } data; 134 135 /* Erase the entire structure including any padding */ 136 memset(&data, 0, sizeof(data)); 137 138 /* 139 * Add process id, thread id, and a high resolution timestamp to 140 * ensure that the nonce is unique with high probability for 141 * different process instances. 142 */ 143 data.pid = GetCurrentProcessId(); 144 data.tid = GetCurrentThreadId(); 145 GetSystemTimeAsFileTime(&data.time); 146 147 return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); 148 } 149 150 int ossl_rand_pool_add_additional_data(RAND_POOL *pool) 151 { 152 struct { 153 DWORD tid; 154 LARGE_INTEGER time; 155 } data; 156 157 /* Erase the entire structure including any padding */ 158 memset(&data, 0, sizeof(data)); 159 160 /* 161 * Add some noise from the thread id and a high resolution timer. 162 * The thread id adds a little randomness if the drbg is accessed 163 * concurrently (which is the case for the <master> drbg). 164 */ 165 data.tid = GetCurrentThreadId(); 166 QueryPerformanceCounter(&data.time); 167 return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); 168 } 169 170 int ossl_rand_pool_init(void) 171 { 172 return 1; 173 } 174 175 void ossl_rand_pool_cleanup(void) 176 { 177 } 178 179 void ossl_rand_pool_keep_random_devices_open(int keep) 180 { 181 } 182 183 #endif 184